aboutsummaryrefslogtreecommitdiff
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/cmake/caches/Fuchsia-stage2-instrumented.cmake3
-rw-r--r--clang/cmake/caches/Fuchsia.cmake3
-rw-r--r--clang/docs/ClangFormatStyleOptions.rst12
-rw-r--r--clang/docs/ClangTools.rst43
-rw-r--r--clang/docs/HIPSupport.rst68
-rw-r--r--clang/docs/LanguageExtensions.rst26
-rw-r--r--clang/docs/OpenMPSupport.rst5
-rw-r--r--clang/docs/ReleaseNotes.rst1084
-rw-r--r--clang/docs/StandardCPlusPlusModules.rst16
-rw-r--r--clang/docs/UsersManual.rst16
-rw-r--r--clang/docs/analyzer/checkers.rst11
-rw-r--r--clang/include/clang-c/Index.h2
-rw-r--r--clang/include/clang/Analysis/Analyses/LifetimeSafety.h101
-rw-r--r--clang/include/clang/Basic/Builtins.td12
-rw-r--r--clang/include/clang/Basic/BuiltinsAMDGPU.def11
-rw-r--r--clang/include/clang/Basic/CodeGenOptions.def3
-rw-r--r--clang/include/clang/Basic/Diagnostic.h5
-rw-r--r--clang/include/clang/Basic/DiagnosticDriverKinds.td2
-rw-r--r--clang/include/clang/Basic/DiagnosticIDs.h5
-rw-r--r--clang/include/clang/Basic/DiagnosticLexKinds.td3
-rw-r--r--clang/include/clang/Basic/DiagnosticParseKinds.td3
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td10
-rw-r--r--clang/include/clang/Basic/LangOptions.def2
-rw-r--r--clang/include/clang/Basic/Specifiers.h2
-rw-r--r--clang/include/clang/Basic/TargetInfo.h4
-rw-r--r--clang/include/clang/Basic/arm_neon.td4
-rw-r--r--clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h6
-rw-r--r--clang/include/clang/CIR/Dialect/IR/CIROps.td77
-rw-r--r--clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td8
-rw-r--r--clang/include/clang/CIR/Dialect/Passes.h1
-rw-r--r--clang/include/clang/CIR/MissingFeatures.h4
-rw-r--r--clang/include/clang/Driver/Driver.h19
-rw-r--r--clang/include/clang/Driver/Options.td28
-rw-r--r--clang/include/clang/Driver/ToolChain.h7
-rw-r--r--clang/include/clang/Format/Format.h14
-rw-r--r--clang/include/clang/Lex/DependencyDirectivesScanner.h9
-rw-r--r--clang/include/clang/Parse/ParseHLSLRootSignature.h6
-rw-r--r--clang/include/clang/Sema/Sema.h14
-rw-r--r--clang/include/clang/Sema/SemaARM.h5
-rw-r--r--clang/include/clang/Sema/SemaRISCV.h5
-rw-r--r--clang/include/clang/Sema/SemaX86.h4
-rw-r--r--clang/include/clang/StaticAnalyzer/Checkers/Checkers.td4
-rw-r--r--clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h63
-rw-r--r--clang/include/clang/Tooling/Inclusions/IncludeStyle.h4
-rw-r--r--clang/lib/AST/ByteCode/ByteCodeEmitter.cpp2
-rw-r--r--clang/lib/AST/ByteCode/Compiler.cpp201
-rw-r--r--clang/lib/AST/ByteCode/Compiler.h14
-rw-r--r--clang/lib/AST/ByteCode/Context.cpp43
-rw-r--r--clang/lib/AST/ByteCode/Context.h8
-rw-r--r--clang/lib/AST/ByteCode/Descriptor.h2
-rw-r--r--clang/lib/AST/ByteCode/EvalEmitter.cpp2
-rw-r--r--clang/lib/AST/ByteCode/EvaluationResult.cpp2
-rw-r--r--clang/lib/AST/ByteCode/Interp.h76
-rw-r--r--clang/lib/AST/ByteCode/InterpBuiltin.cpp27
-rw-r--r--clang/lib/AST/ByteCode/Opcodes.td1
-rw-r--r--clang/lib/AST/ByteCode/Pointer.cpp25
-rw-r--r--clang/lib/AST/ByteCode/Pointer.h19
-rw-r--r--clang/lib/AST/ByteCode/PrimType.h33
-rw-r--r--clang/lib/AST/ByteCode/Program.cpp24
-rw-r--r--clang/lib/AST/ExprConstant.cpp10
-rw-r--r--clang/lib/AST/TextNodeDumper.cpp5
-rw-r--r--clang/lib/Analysis/LifetimeSafety.cpp311
-rw-r--r--clang/lib/Analysis/plugins/CheckerDependencyHandling/CheckerDependencyHandling.cpp13
-rw-r--r--clang/lib/Analysis/plugins/CheckerOptionHandling/CheckerOptionHandling.cpp13
-rw-r--r--clang/lib/Analysis/plugins/SampleAnalyzer/MainCallChecker.cpp18
-rw-r--r--clang/lib/Basic/TargetInfo.cpp2
-rw-r--r--clang/lib/Basic/Targets.cpp3
-rw-r--r--clang/lib/Basic/Targets/AArch64.cpp3
-rw-r--r--clang/lib/Basic/Targets/AArch64.h2
-rw-r--r--clang/lib/Basic/Targets/ARM.cpp4
-rw-r--r--clang/lib/Basic/Targets/Mips.h6
-rw-r--r--clang/lib/Basic/Targets/OSTargets.h1
-rw-r--r--clang/lib/Basic/Targets/RISCV.cpp9
-rw-r--r--clang/lib/Basic/Targets/RISCV.h2
-rw-r--r--clang/lib/Basic/Targets/X86.cpp8
-rw-r--r--clang/lib/Basic/Targets/X86.h2
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp7
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenCXXABI.h5
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp23
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenClass.cpp132
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenCleanup.cpp69
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenDecl.cpp97
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExpr.cpp59
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp156
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp40
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenFunction.cpp176
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenFunction.h120
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp26
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenStmt.cpp3
-rw-r--r--clang/lib/CIR/CodeGen/CMakeLists.txt1
-rw-r--r--clang/lib/CIR/CodeGen/EHScopeStack.h99
-rw-r--r--clang/lib/CIR/Dialect/IR/CIRDialect.cpp98
-rw-r--r--clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp186
-rw-r--r--clang/lib/CIR/Lowering/CIRPasses.cpp2
-rw-r--r--clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp12
-rw-r--r--clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h10
-rw-r--r--clang/lib/CodeGen/ABIInfo.cpp4
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp16
-rw-r--r--clang/lib/CodeGen/CGCall.cpp36
-rw-r--r--clang/lib/CodeGen/CGDebugInfo.cpp5
-rw-r--r--clang/lib/CodeGen/CGExprCXX.cpp27
-rw-r--r--clang/lib/CodeGen/CGOpenMPRuntime.cpp157
-rw-r--r--clang/lib/CodeGen/CGStmt.cpp11
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp7
-rw-r--r--clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp42
-rw-r--r--clang/lib/CodeGen/TargetBuiltins/ARM.cpp4
-rw-r--r--clang/lib/Driver/Driver.cpp772
-rw-r--r--clang/lib/Driver/ToolChain.cpp68
-rw-r--r--clang/lib/Driver/ToolChains/AMDGPU.cpp149
-rw-r--r--clang/lib/Driver/ToolChains/AMDGPU.h2
-rw-r--r--clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp10
-rw-r--r--clang/lib/Driver/ToolChains/AMDGPUOpenMP.h3
-rw-r--r--clang/lib/Driver/ToolChains/Arch/Sparc.cpp31
-rw-r--r--clang/lib/Driver/ToolChains/Arch/Sparc.h3
-rw-r--r--clang/lib/Driver/ToolChains/BareMetal.cpp3
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp82
-rw-r--r--clang/lib/Driver/ToolChains/CommonArgs.cpp2
-rw-r--r--clang/lib/Driver/ToolChains/Cuda.cpp2
-rw-r--r--clang/lib/Driver/ToolChains/Flang.cpp1
-rw-r--r--clang/lib/Driver/ToolChains/HIPAMD.cpp8
-rw-r--r--clang/lib/Driver/ToolChains/HIPAMD.h3
-rw-r--r--clang/lib/Driver/ToolChains/HIPSPV.cpp7
-rw-r--r--clang/lib/Driver/ToolChains/HIPSPV.h3
-rw-r--r--clang/lib/Driver/ToolChains/MSVC.cpp4
-rw-r--r--clang/lib/Driver/ToolChains/MinGW.cpp2
-rw-r--r--clang/lib/Driver/ToolChains/OpenBSD.cpp2
-rw-r--r--clang/lib/Driver/ToolChains/ROCm.h30
-rw-r--r--clang/lib/Driver/ToolChains/Solaris.cpp6
-rw-r--r--clang/lib/Driver/ToolChains/UEFI.cpp4
-rw-r--r--clang/lib/Format/BreakableToken.cpp4
-rw-r--r--clang/lib/Format/ContinuationIndenter.cpp4
-rw-r--r--clang/lib/Format/Format.cpp6
-rw-r--r--clang/lib/Format/FormatTokenLexer.cpp35
-rw-r--r--clang/lib/Format/IntegerLiteralSeparatorFixer.cpp8
-rw-r--r--clang/lib/Format/IntegerLiteralSeparatorFixer.h4
-rw-r--r--clang/lib/Format/ObjCPropertyAttributeOrderFixer.cpp2
-rw-r--r--clang/lib/Format/TokenAnnotator.cpp3
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp6
-rw-r--r--clang/lib/Interpreter/Interpreter.cpp12
-rw-r--r--clang/lib/Interpreter/InterpreterValuePrinter.cpp2
-rw-r--r--clang/lib/Lex/LiteralSupport.cpp2
-rw-r--r--clang/lib/Lex/Pragma.cpp12
-rw-r--r--clang/lib/Parse/ParseDecl.cpp3
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp7
-rw-r--r--clang/lib/Parse/ParseHLSLRootSignature.cpp7
-rw-r--r--clang/lib/Sema/AnalysisBasedWarnings.cpp7
-rw-r--r--clang/lib/Sema/SemaARM.cpp91
-rw-r--r--clang/lib/Sema/SemaAvailability.cpp6
-rw-r--r--clang/lib/Sema/SemaChecking.cpp2
-rw-r--r--clang/lib/Sema/SemaConcept.cpp3
-rw-r--r--clang/lib/Sema/SemaDecl.cpp15
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp304
-rw-r--r--clang/lib/Sema/SemaOpenACCAtomic.cpp16
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp37
-rw-r--r--clang/lib/Sema/SemaRISCV.cpp110
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp21
-rw-r--r--clang/lib/Sema/SemaX86.cpp62
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp14
-rw-r--r--clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp83
-rw-r--r--clang/lib/Tooling/Inclusions/HeaderIncludes.cpp3
-rw-r--r--clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp4
-rw-r--r--clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes4
-rw-r--r--clang/test/APINotes/Inputs/Headers/SwiftImportAs.h6
-rw-r--r--clang/test/APINotes/swift-import-as.cpp15
-rw-r--r--clang/test/AST/ByteCode/builtin-bit-cast.cpp4
-rw-r--r--clang/test/AST/ByteCode/unions.cpp72
-rw-r--r--clang/test/AST/ast-dump-APValue-lvalue.cpp8
-rw-r--r--clang/test/Analysis/malloc.c18
-rw-r--r--clang/test/C/C2y/n3353.c11
-rw-r--r--clang/test/CIR/CodeGen/array-ctor.cpp106
-rw-r--r--clang/test/CIR/CodeGen/bitfields.c48
-rw-r--r--clang/test/CIR/CodeGen/builtin_call.cpp16
-rw-r--r--clang/test/CIR/CodeGen/cleanup.cpp83
-rw-r--r--clang/test/CIR/CodeGen/complex-cast.cpp358
-rw-r--r--clang/test/CIR/CodeGen/destructors.cpp4
-rw-r--r--clang/test/CIR/CodeGen/dtor-alias.cpp75
-rw-r--r--clang/test/CIR/IR/array-ctor.cir29
-rw-r--r--clang/test/ClangScanDeps/modules-full-named-modules.cppm66
-rw-r--r--clang/test/CodeGen/AArch64/neon-intrinsics.c12
-rw-r--r--clang/test/CodeGen/PowerPC/ppc-dmf-future-builtin-err.c15
-rw-r--r--clang/test/CodeGen/PowerPC/ppc-dmf-mma-builtin-err.c2
-rw-r--r--clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/non-overloaded/vcompress.c74
-rw-r--r--clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/non-overloaded/vrgather.c272
-rw-r--r--clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/overloaded/vcompress.c74
-rw-r--r--clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/overloaded/vrgather.c272
-rw-r--r--clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/non-overloaded/vcompress.c68
-rw-r--r--clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/non-overloaded/vrgather.c488
-rw-r--r--clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/overloaded/vcompress.c76
-rw-r--r--clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/overloaded/vrgather.c576
-rw-r--r--clang/test/CodeGen/X86/prefetchi-error.c7
-rw-r--r--clang/test/CodeGen/builtin-maximumnum-minimumnum.c171
-rw-r--r--clang/test/CodeGenCXX/builtin-amdgcn-fence.cpp4
-rw-r--r--clang/test/CodeGenCXX/delete.cpp32
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-eh-async.cpp209
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-eh-disabled.cpp140
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-eh-ip2state.cpp242
-rw-r--r--clang/test/CodeGenHLSL/BasicFeatures/ArrayOutputArguments.hlsl12
-rw-r--r--clang/test/CodeGenOpenCL/amdgpu-features.cl2
-rw-r--r--clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250-load-monitor.cl66
-rw-r--r--clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250-wmma-w32.cl12
-rw-r--r--clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250.cl19
-rw-r--r--clang/test/DebugInfo/KeyInstructions/asm.c59
-rw-r--r--clang/test/DebugInfo/KeyInstructions/goto.c30
-rw-r--r--clang/test/Driver/amdgpu-hip-system-arch.c6
-rw-r--r--clang/test/Driver/baremetal.cpp16
-rw-r--r--clang/test/Driver/cuda-phases.cu10
-rw-r--r--clang/test/Driver/hip-inputs.hip4
-rw-r--r--clang/test/Driver/hip-invalid-target-id.hip8
-rw-r--r--clang/test/Driver/hip-options.hip5
-rw-r--r--clang/test/Driver/hip-phases.hip22
-rw-r--r--clang/test/Driver/invalid-offload-options.cpp22
-rw-r--r--clang/test/Driver/module-fgen-reduced-bmi.cppm3
-rw-r--r--clang/test/Driver/module-output.cppm13
-rw-r--r--clang/test/Driver/modules.cpp2
-rw-r--r--clang/test/Driver/nvptx-cuda-system-arch.c6
-rw-r--r--clang/test/Driver/offload-target.c22
-rw-r--r--clang/test/Driver/openbsd.c5
-rw-r--r--clang/test/Driver/openmp-offload.c11
-rw-r--r--clang/test/Driver/openmp-system-arch.c8
-rw-r--r--clang/test/Driver/print-multi-selection-flags.c17
-rw-r--r--clang/test/Driver/sparc-target-features.c9
-rw-r--r--clang/test/Interpreter/fail.cpp7
-rw-r--r--clang/test/Interpreter/pretty-print.c2
-rw-r--r--clang/test/Interpreter/pretty-print.cpp3
-rw-r--r--clang/test/Layout/ms-no-unique-address.cpp1
-rw-r--r--clang/test/Misc/time-passes.c6
-rw-r--r--clang/test/Modules/mingw-exceptions.cppm3
-rw-r--r--clang/test/OpenMP/copy-gaps-1.cpp52
-rw-r--r--clang/test/OpenMP/copy-gaps-2.cpp52
-rw-r--r--clang/test/OpenMP/copy-gaps-3.cpp46
-rw-r--r--clang/test/OpenMP/copy-gaps-4.cpp48
-rw-r--r--clang/test/OpenMP/copy-gaps-5.cpp50
-rw-r--r--clang/test/OpenMP/copy-gaps-6.cpp87
-rw-r--r--clang/test/OpenMP/declare_variant_clauses_ast_print.cpp26
-rw-r--r--clang/test/OpenMP/declare_variant_clauses_messages.cpp12
-rw-r--r--clang/test/OpenMP/target_map_array_section_no_length_codegen.cpp361
-rw-r--r--clang/test/OpenMP/target_map_codegen_35.cpp29
-rw-r--r--clang/test/OpenMP/target_map_messages.cpp24
-rw-r--r--clang/test/Preprocessor/arm-acle-6.4.c31
-rw-r--r--clang/test/Preprocessor/init-mips.c64
-rw-r--r--clang/test/Preprocessor/pragma-pushpop-macro-diag.c4
-rw-r--r--clang/test/Preprocessor/pragma-pushpop-macro.c3
-rw-r--r--clang/test/Preprocessor/stdint.c10
-rw-r--r--clang/test/Sema/builtins-elementwise-math.c90
-rw-r--r--clang/test/Sema/implicit-special-member-deprecated.cpp24
-rw-r--r--clang/test/Sema/unsupported-arm-streaming.cpp3
-rw-r--r--clang/test/Sema/warn-fortify-source.c5
-rw-r--r--clang/test/Sema/warn-lifetime-safety-dataflow.cpp87
-rw-r--r--clang/test/SemaCXX/attr-target-clones-riscv.cpp3
-rw-r--r--clang/test/SemaCXX/constant-expression-p2280r4.cpp14
-rw-r--r--clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp1
-rw-r--r--clang/test/SemaCXX/wreturn-always-throws.cpp21
-rw-r--r--clang/test/SemaOpenACC/atomic-construct.cpp52
-rw-r--r--clang/test/SemaOpenCL/builtins-amdgcn-error-gfx1250-param.cl19
-rw-r--r--clang/test/SemaOpenCL/builtins-amdgcn-error-gfx1250-wmma-w32-param.cl7
-rw-r--r--clang/test/SemaTemplate/concepts.cpp8
-rw-r--r--clang/test/SemaTemplate/deduction-guide.cpp16
-rw-r--r--clang/tools/driver/cc1_main.cpp2
-rw-r--r--clang/unittests/Analysis/CMakeLists.txt1
-rw-r--r--clang/unittests/Analysis/LifetimeSafetyTest.cpp710
-rw-r--r--clang/unittests/Format/BracesInserterTest.cpp6
-rw-r--r--clang/unittests/Format/ConfigParseTest.cpp1
-rw-r--r--clang/unittests/Format/FormatTest.cpp109
-rw-r--r--clang/unittests/Format/FormatTestComments.cpp10
-rw-r--r--clang/unittests/Format/FormatTestJava.cpp12
-rw-r--r--clang/unittests/Format/FormatTestSelective.cpp23
-rw-r--r--clang/unittests/Format/IntegerLiteralSeparatorTest.cpp26
-rw-r--r--clang/unittests/Format/SortIncludesTest.cpp4
-rw-r--r--clang/unittests/Format/TokenAnnotatorTest.cpp4
-rw-r--r--clang/unittests/Interpreter/InterpreterTest.cpp7
-rw-r--r--clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp199
-rw-r--r--clang/unittests/StaticAnalyzer/BlockEntranceCallbackTest.cpp6
-rw-r--r--clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp2
-rw-r--r--clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp4
-rw-r--r--clang/unittests/StaticAnalyzer/CallEventTest.cpp2
-rw-r--r--clang/unittests/StaticAnalyzer/ConflictingEvalCallsTest.cpp6
-rw-r--r--clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp8
-rw-r--r--clang/unittests/StaticAnalyzer/FalsePositiveRefutationBRVisitorTest.cpp4
-rw-r--r--clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp2
-rw-r--r--clang/unittests/StaticAnalyzer/NoStateChangeFuncVisitorTest.cpp4
-rw-r--r--clang/unittests/StaticAnalyzer/ObjcBug-124477.cpp2
-rw-r--r--clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp24
-rw-r--r--clang/unittests/StaticAnalyzer/SValSimplifyerTest.cpp3
-rw-r--r--clang/unittests/StaticAnalyzer/SValTest.cpp6
-rw-r--r--clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp6
285 files changed, 9483 insertions, 3374 deletions
diff --git a/clang/cmake/caches/Fuchsia-stage2-instrumented.cmake b/clang/cmake/caches/Fuchsia-stage2-instrumented.cmake
index ecd478a..b328f3d 100644
--- a/clang/cmake/caches/Fuchsia-stage2-instrumented.cmake
+++ b/clang/cmake/caches/Fuchsia-stage2-instrumented.cmake
@@ -43,3 +43,6 @@ set(CLANG_BOOTSTRAP_CMAKE_ARGS
${EXTRA_ARGS}
-C ${CMAKE_CURRENT_LIST_DIR}/Fuchsia-stage2.cmake
CACHE STRING "")
+
+# Do not use LLVM build for generating PGO data.
+set(CLANG_PGO_TRAINING_USE_LLVM_BUILD OFF CACHE BOOL "")
diff --git a/clang/cmake/caches/Fuchsia.cmake b/clang/cmake/caches/Fuchsia.cmake
index ee1d681..a3f86f6 100644
--- a/clang/cmake/caches/Fuchsia.cmake
+++ b/clang/cmake/caches/Fuchsia.cmake
@@ -76,6 +76,9 @@ foreach(variable ${_FUCHSIA_BOOTSTRAP_PASSTHROUGH})
get_property(value CACHE ${variable} PROPERTY VALUE)
get_property(type CACHE ${variable} PROPERTY TYPE)
set(BOOTSTRAP_${variable} "${value}" CACHE ${type} "")
+ if(FUCHSIA_ENABLE_PGO)
+ set(BOOTSTRAP_BOOTSTRAP_${variable} "${value}" CACHE ${type} "")
+ endif()
endif()
endforeach()
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index bfc8094..7f970f6 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -4201,8 +4201,8 @@ the configuration (without a prefix: ``Auto``).
* ``""`` means "arbitrary suffix"
* ``"$"`` means "no suffix"
- For example, if configured to ``"(_test)?$"``, then a header a.h would be seen
- as the "main" include in both a.cc and a_test.cc.
+ For example, if configured to ``"(_test)?$"``, then a header a.h would be
+ seen as the "main" include in both a.cc and a_test.cc.
.. _IncludeIsMainSourceRegex:
@@ -6400,6 +6400,14 @@ the configuration (without a prefix: ``Auto``).
IF (...) vs. IF(...)
<conditional-body> <conditional-body>
+ * ``bool AfterNot`` If ``true``, put a space between alternative operator ``not`` and the
+ opening parenthesis.
+
+ .. code-block:: c++
+
+ true: false:
+ return not (a || b); vs. return not(a || b);
+
* ``bool AfterOverloadedOperator`` If ``true``, put a space between operator overloading and opening
parentheses.
diff --git a/clang/docs/ClangTools.rst b/clang/docs/ClangTools.rst
index 60e2159..3216328 100644
--- a/clang/docs/ClangTools.rst
+++ b/clang/docs/ClangTools.rst
@@ -89,13 +89,50 @@ they'll be tracked here. The focus of this documentation is on the scope
and features of the tools for other tool developers; each tool should
provide its own user-focused documentation.
-``clang-tidy``
+``Clang-Doc``
+-------------
+
+`Clang-Doc <https://clang.llvm.org/extra/clang-doc.html>`_ is a tool for
+generating C and C++ documentation from source code and comments.
+
+``Clang-Include-Fixer``
+-----------------------
+
+`Clang-Include-Fixer <https://clang.llvm.org/extra/clang-include-fixer.html>`_
+is a tool to automate the addition of missing ``#include`` directives in a C++
+file. It adds missing namespace qualifiers to unidentified symbols when
+necessary and also removes unused headers.
+
+``Clang-Tidy``
--------------
-`clang-tidy <https://clang.llvm.org/extra/clang-tidy/>`_ is a clang-based C++
+`Clang-Tidy <https://clang.llvm.org/extra/clang-tidy/>`_ is a Clang-based C++
linter tool. It provides an extensible framework for building compiler-based
static analyses detecting and fixing bug-prone patterns, performance,
-portability and maintainability issues.
+portability and maintainability issues. It also has checks for modernizing code
+to newer language standards.
+
+``Clangd``
+----------
+
+`Clangd <https://clangd.llvm.org/>`_ is a language server that can work with
+many editors via a plugin. It understands your C++ code and adds smart
+features to your editor: code completion, compile errors, go-to-definition and
+more.
+
+``Modularize``
+--------------
+
+`Modularize <https://clang.llvm.org/extra/modularize.html>`_ is a standalone
+tool that checks whether a set of headers provides the consistent definitions
+required to use modules.
+
+``pp-trace``
+------------
+
+`pp-trace <https://clang.llvm.org/extra/pp-trace.html>`_ is a standalone tool
+that traces preprocessor activity. It’s also used as a test of Clang’s
+``PPCallbacks`` interface.
Ideas for new Tools
diff --git a/clang/docs/HIPSupport.rst b/clang/docs/HIPSupport.rst
index 406e1c8..b4a671e 100644
--- a/clang/docs/HIPSupport.rst
+++ b/clang/docs/HIPSupport.rst
@@ -545,37 +545,22 @@ The following restrictions imposed on user code apply to both modes:
1. Pointers to function, and all associated features, such as e.g. dynamic
polymorphism, cannot be used (directly or transitively) by the user provided
callable passed to an algorithm invocation;
-2. Global / namespace scope / ``static`` / ``thread`` storage duration variables
- cannot be used (directly or transitively) in name by the user provided
- callable;
-
- - When executing in **HMM Mode** they can be used in address e.g.:
-
- .. code-block:: C++
-
- namespace { int foo = 42; }
-
- bool never(const std::vector<int>& v) {
- return std::any_of(std::execution::par_unseq, std::cbegin(v), std::cend(v), [](auto&& x) {
- return x == foo;
- });
- }
-
- bool only_in_hmm_mode(const std::vector<int>& v) {
- return std::any_of(std::execution::par_unseq, std::cbegin(v), std::cend(v),
- [p = &foo](auto&& x) { return x == *p; });
- }
-
-3. Only algorithms that are invoked with the ``parallel_unsequenced_policy`` are
+2. ``static`` (except for program-wide unique ones) / ``thread`` storage
+ duration variables cannot be used (directly or transitively) in name by the
+ user provided callable;
+3. User code must be compiled in ``-fgpu-rdc`` mode in order for global /
+ namespace scope variables / program-wide unique ``static`` storage duration
+ variables to be usable in name by the user provided callable;
+4. Only algorithms that are invoked with the ``parallel_unsequenced_policy`` are
candidates for offload;
-4. Only algorithms that are invoked with iterator arguments that model
+5. Only algorithms that are invoked with iterator arguments that model
`random_access_iterator <https://en.cppreference.com/w/cpp/iterator/random_access_iterator>`_
are candidates for offload;
-5. `Exceptions <https://en.cppreference.com/w/cpp/language/exceptions>`_ cannot
+6. `Exceptions <https://en.cppreference.com/w/cpp/language/exceptions>`_ cannot
be used by the user provided callable;
-6. Dynamic memory allocation (e.g. ``operator new``) cannot be used by the user
+7. Dynamic memory allocation (e.g. ``operator new``) cannot be used by the user
provided callable;
-7. Selective offload is not possible i.e. it is not possible to indicate that
+8. Selective offload is not possible i.e. it is not possible to indicate that
only some algorithms invoked with the ``parallel_unsequenced_policy`` are to
be executed on the accelerator.
@@ -585,15 +570,6 @@ additional restrictions:
1. All code that is expected to interoperate has to be recompiled with the
``--hipstdpar-interpose-alloc`` flag i.e. it is not safe to compose libraries
that have been independently compiled;
-2. automatic storage duration (i.e. stack allocated) variables cannot be used
- (directly or transitively) by the user provided callable e.g.
-
- .. code-block:: c++
-
- bool never(const std::vector<int>& v, int n) {
- return std::any_of(std::execution::par_unseq, std::cbegin(v), std::cend(v),
- [p = &n](auto&& x) { return x == *p; });
- }
Current Support
===============
@@ -626,17 +602,12 @@ Linux operating system. Support is synthesised in the following table:
The minimum Linux kernel version for running in HMM mode is 6.4.
-The forwarding header can be obtained from
-`its GitHub repository <https://github.com/ROCm/roc-stdpar>`_.
-It will be packaged with a future `ROCm <https://rocm.docs.amd.com/en/latest/>`_
-release. Because accelerated algorithms are provided via
-`rocThrust <https://rocm.docs.amd.com/projects/rocThrust/en/latest/>`_, a
-transitive dependency on
-`rocPrim <https://rocm.docs.amd.com/projects/rocPRIM/en/latest/>`_ exists. Both
-can be obtained either by installing their associated components of the
-`ROCm <https://rocm.docs.amd.com/en/latest/>`_ stack, or from their respective
-repositories. The list algorithms that can be offloaded is available
-`here <https://github.com/ROCm/roc-stdpar#algorithm-support-status>`_.
+The forwarding header is packaged by
+`ROCm <https://rocm.docs.amd.com/en/latest/>`_, and is obtainable by installing
+the `hipstdpar` packege. The list algorithms that can be offloaded is available
+`here <https://github.com/ROCm/roc-stdpar#algorithm-support-status>`_. More
+details are available via the dedicated blog
+`<https://rocm.blogs.amd.com/software-tools-optimization/hipstdpar/README.html>`_.
HIP Specific Elements
---------------------
@@ -690,9 +661,8 @@ HIP Specific Elements
Open Questions / Future Developments
====================================
-1. The restriction on the use of global / namespace scope / ``static`` /
- ``thread`` storage duration variables in offloaded algorithms will be lifted
- in the future, when running in **HMM Mode**;
+1. The restriction on the use of ``static`` / ``thread`` storage duration
+ variables in offloaded algorithms might be lifted;
2. The restriction on the use of dynamic memory allocation in offloaded
algorithms will be lifted in the future.
3. The restriction on the use of pointers to function, and associated features
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index f448a9a..34e1bf1 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -138,7 +138,7 @@ for support for non-standardized features, i.e. features not prefixed ``c_``,
``cxx_`` or ``objc_``.
Another use of ``__has_feature`` is to check for compiler features not related
-to the language standard, such as e.g. :doc:`AddressSanitizer
+to the language standard, such as :doc:`AddressSanitizer
<AddressSanitizer>`.
If the ``-pedantic-errors`` option is given, ``__has_extension`` is equivalent
@@ -377,8 +377,8 @@ Builtin Macros
``__FILE_NAME__``
Clang-specific extension that functions similar to ``__FILE__`` but only
- renders the last path component (the filename) instead of an invocation
- dependent full path to that file.
+ renders the last path component (the filename) instead of an
+ invocation-dependent full path to that file.
``__COUNTER__``
Defined to an integer value that starts at zero and is incremented each time
@@ -716,7 +716,7 @@ See also :ref:`langext-__builtin_shufflevector`, :ref:`langext-__builtin_convert
a NEON vector or an SVE vector, it's only available in C++ and uses normal bool
conversions (that is, != 0).
If it's an extension (OpenCL) vector, it's only available in C and OpenCL C.
- And it selects base on signedness of the condition operands (OpenCL v1.1 s6.3.9).
+ And it selects based on signedness of the condition operands (OpenCL v1.1 s6.3.9).
.. [#] sizeof can only be used on vector length specific SVE types.
.. [#] Clang does not allow the address of an element to be taken while GCC
allows this. This is intentional for vectors with a boolean element type and
@@ -848,6 +848,14 @@ of different sizes and signs is forbidden in binary and ternary builtins.
semantics, see `LangRef
<http://llvm.org/docs/LangRef.html#llvm-min-intrinsics-comparation>`_
for the comparison.
+ T __builtin_elementwise_maximumnum(T x, T y) return x or y, whichever is larger. Follows IEEE 754-2019 floating point types
+ semantics, see `LangRef
+ <http://llvm.org/docs/LangRef.html#llvm-min-intrinsics-comparation>`_
+ for the comparison.
+ T __builtin_elementwise_minimumnum(T x, T y) return x or y, whichever is smaller. Follows IEEE 754-2019 floating point types
+ semantics, see `LangRef
+ <http://llvm.org/docs/LangRef.html#llvm-min-intrinsics-comparation>`_
+ for the comparison.
============================================== ====================================================================== =========================================
@@ -857,7 +865,7 @@ Each builtin returns a scalar equivalent to applying the specified
operation(x, y) as recursive even-odd pairwise reduction to all vector
elements. ``operation(x, y)`` is repeatedly applied to each non-overlapping
even-odd element pair with indices ``i * 2`` and ``i * 2 + 1`` with
-``i in [0, Number of elements / 2)``. If the numbers of elements is not a
+``i in [0, Number of elements / 2)``. If the number of elements is not a
power of 2, the vector is widened with neutral elements for the reduction
at the end to the next power of 2.
@@ -1491,7 +1499,7 @@ C++14 digit separators
Use ``__cpp_digit_separators`` to determine if support for digit separators
using single quotes (for instance, ``10'000``) is enabled. At this time, there
-is no corresponding ``__has_feature`` name
+is no corresponding ``__has_feature`` name.
C++14 generalized lambda capture
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1545,7 +1553,7 @@ C++ type aware allocators
^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_extension(cxx_type_aware_allocators)`` to determine the existence of
-support for the future C++2d type aware allocator feature. For full details see
+support for the future C++2d type aware allocator feature. For full details, see
:doc:`C++ Type Aware Allocators <CXXTypeAwareAllocators>` for additional details.
C11
@@ -1643,7 +1651,7 @@ Modules
Use ``__has_feature(modules)`` to determine if Modules have been enabled.
For example, compiling code with ``-fmodules`` enables the use of Modules.
-More information could be found `here <https://clang.llvm.org/docs/Modules.html>`_.
+More information can be found `here <https://clang.llvm.org/docs/Modules.html>`_.
Language Extensions Back-ported to Previous Standards
=====================================================
@@ -1878,7 +1886,7 @@ The following type trait primitives are supported by Clang. Those traits marked
C++26 relocatable types, and types which
were made trivially relocatable via the ``clang::trivial_abi`` attribute.
This trait is deprecated and should be replaced by
- ``__builtin_is_cpp_trivially_relocatable``. Note however that it is generally
+ ``__builtin_is_cpp_trivially_relocatable``. Note, however, that it is generally
unsafe to relocate a C++-relocatable type with ``memcpy`` or ``memmove``;
use ``__builtin_trivially_relocate``.
* ``__builtin_is_cpp_trivially_relocatable`` (C++): Returns true if an object
diff --git a/clang/docs/OpenMPSupport.rst b/clang/docs/OpenMPSupport.rst
index 986aaab..fc44f4c 100644
--- a/clang/docs/OpenMPSupport.rst
+++ b/clang/docs/OpenMPSupport.rst
@@ -443,7 +443,7 @@ implementation.
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
| Traits for default device envirable | :none:`unclaimed` | :none:`unclaimed` | |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
-| Optionally omit array length expression | :none:`unclaimed` | :none:`unclaimed` | |
+| Optionally omit array length expression | :good:`done` | :none:`unclaimed` | https://github.com/llvm/llvm-project/pull/148048 |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
| Canonical loop sequences | :none:`unclaimed` | :none:`unclaimed` | |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
@@ -467,6 +467,9 @@ implementation.
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
| Non-const do_not_sync for nowait/nogroup | :none:`unclaimed` | :none:`unclaimed` | |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| need_device_addr modifier for adjust_args clause | :part:`partial` | :none:`unclaimed` | Parsing/Sema: https://github.com/llvm/llvm-project/pull/143442 |
+| | | | https://github.com/llvm/llvm-project/pull/149586 |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
OpenMP Extensions
=================
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 46a7767..ec51ffd 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -34,72 +34,26 @@ latest release, please see the `Clang Web Site <https://clang.llvm.org>`_ or the
Potentially Breaking Changes
============================
-- The Objective-C ARC migrator (ARCMigrate) has been removed.
-- Fix missing diagnostics for uses of declarations when performing typename access,
- such as when performing member access on a ``[[deprecated]]`` type alias.
- (#GH58547)
-- For ARM targets when compiling assembly files, the features included in the selected CPU
- or Architecture's FPU are included. If you wish not to use a specific feature,
- the relevant ``+no`` option will need to be amended to the command line option.
-- When compiling with branch target enforcement, ``asm goto``
- statements will no longer guarantee to place a ``bti`` or
- ``endbr64`` instruction at the labels named as possible branch
- destinations, so it is not safe to use a register-controlled branch
- instruction to branch to one. (In line with gcc.)
-- Added a sugar type `PredefinedSugarType` to improve diagnostic messages. (#GH143653)
-
C/C++ Language Potentially Breaking Changes
-------------------------------------------
-- New LLVM optimizations have been implemented that optimize pointer arithmetic on
- null pointers more aggressively. As part of this, clang has implemented a special
- case for old-style offsetof idioms like ``((int)(&(((struct S *)0)->field)))``, to
- ensure they are not caught by these optimizations. It is also possible to use
- ``-fwrapv-pointer`` or ``-fno-delete-null-pointer-checks`` to make pointer arithmetic
- on null pointers well-defined. (#GH130734, #GH130742, #GH130952)
-
C++ Specific Potentially Breaking Changes
-----------------------------------------
-
-- The type trait builtin ``__is_referenceable`` has been removed, since it has
- very few users and all the type traits that could benefit from it in the
- standard library already have their own bespoke builtins.
-- A workaround for libstdc++4.7 has been removed. Note that 4.8.3 remains the oldest
- supported libstdc++ version.
-- Added ``!nonnull/!align`` metadata to load of references for better codegen.
-- Checking for integer to enum conversions in constant expressions is more
- strict; in particular, ``const E x = (E)-1;`` is not treated as a constant
- if it's out of range. The Boost numeric_conversion library is impacted by
- this; it was fixed in Boost 1.81. (#GH143034)
-
-- Fully implemented `CWG400 Using-declarations and the `
- `"struct hack" <https://wg21.link/CWG400>`_. Invalid member using-declaration
- whose nested-name-specifier doesn't refer to a base class such as
- ``using CurrentClass::Foo;`` is now rejected in C++98 mode.
+- For C++20 modules, the Reduced BMI mode will be the default option. This may introduce
+ regressions if your build system supports two-phase compilation model but haven't support
+ reduced BMI or it is a compiler bug or a bug in users code.
ABI Changes in This Version
---------------------------
-- Return larger CXX records in memory instead of using AVX registers. Code compiled with older clang will be incompatible with newer version of the clang unless -fclang-abi-compat=20 is provided. (#GH120670)
-
AST Dumping Potentially Breaking Changes
----------------------------------------
-- Added support for dumping template arguments of structural value kinds.
-
Clang Frontend Potentially Breaking Changes
-------------------------------------------
-- The ``-Wglobal-constructors`` flag now applies to ``[[gnu::constructor]]`` and
- ``[[gnu::destructor]]`` attributes.
-
Clang Python Bindings Potentially Breaking Changes
--------------------------------------------------
-- ``Cursor.from_location`` now returns ``None`` instead of a null cursor.
- This eliminates the last known source of null cursors.
-- Almost all ``Cursor`` methods now assert that they are called on non-null cursors.
- Most of the time null cursors were mapped to ``None``,
- so no widespread breakages are expected.
What's New in Clang |release|?
==============================
@@ -107,45 +61,14 @@ What's New in Clang |release|?
C++ Language Changes
--------------------
-- Added a :ref:`__builtin_structured_binding_size <builtin_structured_binding_size-doc>` (T)
- builtin that returns the number of structured bindings that would be produced by destructuring ``T``.
-
-- Similarly to GCC, Clang now supports constant expressions in
- the strings of a GNU ``asm`` statement.
-
- .. code-block:: c++
-
- int foo() {
- asm((std::string_view("nop")) ::: (std::string_view("memory")));
- }
-
-- Clang now implements the changes to overload resolution proposed by section 1 and 2 of
- `P3606 <https://wg21.link/P3606R0>`_. If a non-template candidate exists in an overload set that is
- a perfect match (all conversion sequences are identity conversions) template candidates are not instantiated.
- Diagnostics that would have resulted from the instantiation of these template candidates are no longer
- produced. This aligns Clang closer to the behavior of GCC, and fixes (#GH62096), (#GH74581), and (#GH74581).
-
C++2c Feature Support
^^^^^^^^^^^^^^^^^^^^^
-- Implemented `P1061R10 Structured Bindings can introduce a Pack <https://wg21.link/P1061R10>`_.
-- Implemented `P2786R13 Trivial Relocatability <https://wg21.link/P2786R13>`_.
-
-
-- Implemented `P0963R3 Structured binding declaration as a condition <https://wg21.link/P0963R3>`_.
-
-- Implemented `P3618R0 Allow attaching main to the global module <https://wg21.link/P3618>`_.
-
C++23 Feature Support
^^^^^^^^^^^^^^^^^^^^^
C++20 Feature Support
^^^^^^^^^^^^^^^^^^^^^
-- Fixed a crash with a defaulted spaceship (``<=>``) operator when the class
- contains a member declaration of vector type. Vector types cannot yet be
- compared directly, so this causes the operator to be deleted. (#GH137452)
-- Implement constant evaluation of lambdas that capture structured bindings.
- (#GH145956)
C++17 Feature Support
^^^^^^^^^^^^^^^^^^^^^
@@ -153,564 +76,37 @@ C++17 Feature Support
Resolutions to C++ Defect Reports
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- The flag `-frelaxed-template-template-args`
- and its negation have been removed, having been deprecated since the previous
- two releases. The improvements to template template parameter matching implemented
- in the previous release, as described in P3310 and P3579, made this flag unnecessary.
-
-- Implemented `CWG2918 Consideration of constraints for address of overloaded `
- `function <https://cplusplus.github.io/CWG/issues/2918.html>`_
-
-- Bumped the ``__cpp_constexpr`` feature-test macro to ``202002L`` in C++20 mode as indicated in
- `P2493R0 <https://wg21.link/P2493R0>`_.
-
-- Implemented `CWG2517 Useless restriction on use of parameter in `
- `constraint-expression <https://cplusplus.github.io/CWG/issues/2517.html>`_.
-- Implemented `CWG3005 Function parameters should never be name-independent <https://wg21.link/CWG3005>`_.
-
-- Implemented `CWG2496 ref-qualifiers and virtual overriding <https://wg21.link/CWG2496>`_.
-
C Language Changes
------------------
-- Clang now allows an ``inline`` specifier on a typedef declaration of a
- function type in Microsoft compatibility mode. #GH124869
-- Clang now allows ``restrict`` qualifier for array types with pointer elements (#GH92847).
-- Clang now diagnoses ``const``-qualified object definitions without an
- initializer. If the object is a variable or field which is zero-initialized,
- it will be diagnosed under the new warning ``-Wdefault-const-init-var`` or
- ``-Wdefault-const-init-field``, respectively. Similarly, if the variable or
- field is not zero-initialized, it will be diagnosed under the new diagnostic
- ``-Wdefault-const-init-var-unsafe`` or ``-Wdefault-const-init-field-unsafe``,
- respectively. The unsafe diagnostic variants are grouped under a new
- diagnostic ``-Wdefault-const-init-unsafe``, which itself is grouped under the
- new diagnostic ``-Wdefault-const-init``. Finally, ``-Wdefault-const-init`` is
- grouped under ``-Wc++-compat`` because these constructs are not compatible
- with C++. #GH19297
-- Added ``-Wimplicit-void-ptr-cast``, grouped under ``-Wc++-compat``, which
- diagnoses implicit conversion from ``void *`` to another pointer type as
- being incompatible with C++. (#GH17792)
-- Added ``-Wc++-keyword``, grouped under ``-Wc++-compat``, which diagnoses when
- a C++ keyword is used as an identifier in C. (#GH21898)
-- Added ``-Wc++-hidden-decl``, grouped under ``-Wc++-compat``, which diagnoses
- use of tag types which are visible in C but not visible in C++ due to scoping
- rules. e.g.,
-
- .. code-block:: c
-
- struct S {
- struct T {
- int x;
- } t;
- };
- struct T t; // Invalid C++, valid C, now diagnosed
-- Added ``-Wimplicit-int-enum-cast``, grouped under ``-Wc++-compat``, which
- diagnoses implicit conversion from integer types to an enumeration type in C,
- which is not compatible with C++. #GH37027
-- Split "implicit conversion from enum type to different enum type" diagnostic
- from ``-Wenum-conversion`` into its own diagnostic group,
- ``-Wimplicit-enum-enum-cast``, which is grouped under both
- ``-Wenum-conversion`` and ``-Wimplicit-int-enum-cast``. This conversion is an
- int-to-enum conversion because the enumeration on the right-hand side is
- promoted to ``int`` before the assignment.
-- Added ``-Wtentative-definition-compat``, grouped under ``-Wc++-compat``,
- which diagnoses tentative definitions in C with multiple declarations as
- being incompatible with C++. e.g.,
-
- .. code-block:: c
-
- // File scope
- int i;
- int i; // Vaild C, invalid C++, now diagnosed
-- Added ``-Wunterminated-string-initialization``, grouped under ``-Wextra``,
- which diagnoses an initialization from a string literal where only the null
- terminator cannot be stored. e.g.,
-
- .. code-block:: c
-
-
- char buf1[3] = "foo"; // -Wunterminated-string-initialization
- char buf2[3] = "flarp"; // -Wexcess-initializers
- char buf3[3] = "fo\0"; // This is fine, no warning.
-
- This diagnostic can be suppressed by adding the new ``nonstring`` attribute
- to the field or variable being initialized. #GH137705
-- Added ``-Wc++-unterminated-string-initialization``, grouped under
- ``-Wc++-compat``, which also diagnoses the same cases as
- ``-Wunterminated-string-initialization``. However, this diagnostic is not
- silenced by the ``nonstring`` attribute as these initializations are always
- incompatible with C++.
-- Added ``-Wjump-misses-init``, which is off by default and grouped under
- ``-Wc++-compat``. It diagnoses when a jump (``goto`` to its label, ``switch``
- to its ``case``) will bypass the initialization of a local variable, which is
- invalid in C++.
-- Added the existing ``-Wduplicate-decl-specifier`` diagnostic, which is on by
- default, to ``-Wc++-compat`` because duplicated declaration specifiers are
- not valid in C++.
-- The ``[[clang::assume()]]`` attribute is now correctly recognized in C. The
- ``__attribute__((assume()))`` form has always been supported, so the fix is
- specific to the attribute syntax used.
-- The ``clang-cl`` driver now recognizes ``/std:clatest`` and sets the language
- mode to C23. (#GH147233)
-
C2y Feature Support
^^^^^^^^^^^^^^^^^^^
-- Implement `WG14 N3409 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3409.pdf>`_
- which removes UB around use of ``void`` expressions. In practice, this means
- that ``_Generic`` selection associations may now have ``void`` type, but it
- also removes UB with code like ``(void)(void)1;``.
-- Implemented `WG14 N3411 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3411.pdf>`_
- which allows a source file to not end with a newline character. Note,
- ``-pedantic`` will no longer diagnose this in either C or C++ modes. This
- feature was adopted as applying to obsolete versions of C in WG14 and as a
- defect report in WG21 (CWG787).
-- Implemented `WG14 N3353 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3353.htm>`_
- which adds the new ``0o`` and ``0O`` ocal literal prefixes and deprecates
- octal literals other than ``0`` which do not start with the new prefix. This
- feature is exposed in earlier language modes and in C++ as an extension. The
- paper also introduced octal and hexadecimal delimited escape sequences (e.g.,
- ``"\x{12}\o{12}"``) which are also supported as an extension in older C
- language modes.
-- Implemented `WG14 N3369 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3369.pdf>`_
- which introduces the ``_Lengthof`` operator, and `WG14 N3469 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3469.htm>`_
- which renamed ``_Lengthof`` to ``_Countof``. This feature is implemented as
- a conforming extension in earlier C language modes, but not in C++ language
- modes (``std::extent`` and ``std::size`` already provide the same
- functionality but with more granularity). The feature can be tested via
- ``__has_feature(c_countof)`` or ``__has_extension(c_countof)``. This also
- adds the ``<stdcountof.h>`` header file which exposes the ``countof`` macro
- which expands to ``_Countof``.
C23 Feature Support
^^^^^^^^^^^^^^^^^^^
-- Clang now accepts ``-std=iso9899:2024`` as an alias for C23.
-- Added ``__builtin_c23_va_start()`` for compatibility with GCC and to enable
- better diagnostic behavior for the ``va_start()`` macro in C23 and later.
- This also updates the definition of ``va_start()`` in ``<stdarg.h>`` to use
- the new builtin. Fixes #GH124031.
-- Implemented `WG14 N2819 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2819.pdf>`_
- which clarified that a compound literal used within a function prototype is
- treated as if the compound literal were within the body rather than at file
- scope.
-- Fixed a bug where you could not cast a null pointer constant to type
- ``nullptr_t``. Fixes #GH133644.
-- Implemented `WG14 N3037 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3037.pdf>`_
- which allows tag types to be redefined within the same translation unit so
- long as both definitions are structurally equivalent (same tag types, same
- tag names, same tag members, etc). As a result of this paper, ``-Wvisibility``
- is no longer diagnosed in C23 if the parameter is a complete tag type (it
- does still fire when the parameter is an incomplete tag type as that cannot
- be completed).
-- Fixed a failed assertion with an invalid parameter to the ``#embed``
- directive. Fixes #GH126940.
-- Fixed a crash when a declaration of a ``constexpr`` variable with an invalid
- type. Fixes #GH140887
-- Documented `WG14 N3006 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3006.htm>`_
- which clarified how Clang is handling underspecified object declarations.
-- Clang now accepts single variadic parameter in type-name. It's a part of
- `WG14 N2975 <https://open-std.org/JTC1/SC22/WG14/www/docs/n2975.pdf>`_
-- Fixed a bug with handling the type operand form of ``typeof`` when it is used
- to specify a fixed underlying type for an enumeration. #GH146351
-- Fixed a rejects-valid bug where Clang would reject an enumeration with an
- ``_Atomic`` underlying type. The underlying type is the non-atomic,
- unqualified version of the specified type. Due to the perhaps surprising lack
- of atomic behavior, this is diagnosed under
- ``-Wunderlying-atomic-qualifier-ignored``, which defaults to an error. This
- can be downgraded with ``-Wno-underlying-atomic-qualifier-ignored`` or
- ``-Wno-error=underlying-atomic-qualifier-ignored``. Clang now also diagnoses
- cv-qualifiers as being ignored, but that warning does not default to an error.
- It can be controlled by ``-Wunderlying-cv-qualifier-ignore``. (#GH147736)
-
-C11 Feature Support
-^^^^^^^^^^^^^^^^^^^
-- Implemented `WG14 N1285 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1285.htm>`_
- which introduces the notion of objects with a temporary lifetime. When an
- expression resulting in an rvalue with structure or union type and that type
- contains a member of array type, the expression result is an automatic storage
- duration object with temporary lifetime which begins when the expression is
- evaluated and ends at the evaluation of the containing full expression. This
- functionality is also implemented for earlier C language modes because the
- C99 semantics will never be implemented (it would require dynamic allocations
- of memory which leaks, which users would not appreciate).
Non-comprehensive list of changes in this release
-------------------------------------------------
+- Added ``__builtin_elementwise_minnumnum`` and ``__builtin_elementwise_maxnumnum``.
-- Support parsing the `cc` operand modifier and alias it to the `c` modifier (#GH127719).
-- Added `__builtin_elementwise_exp10`.
-- For AMDPGU targets, added `__builtin_v_cvt_off_f32_i4` that maps to the `v_cvt_off_f32_i4` instruction.
-- Added `__builtin_elementwise_minnum` and `__builtin_elementwise_maxnum`.
-- No longer crashing on invalid Objective-C categories and extensions when
- dumping the AST as JSON. (#GH137320)
-- Clang itself now uses split stacks instead of threads for allocating more
- stack space when running on Apple AArch64 based platforms. This means that
- stack traces of Clang from debuggers, crashes, and profilers may look
- different than before.
-- Fixed a crash when a VLA with an invalid size expression was used within a
- ``sizeof`` or ``typeof`` expression. (#GH138444)
-- ``__builtin_invoke`` has been added to improve the compile time of ``std::invoke``.
-- Deprecation warning is emitted for the deprecated ``__reference_binds_to_temporary`` intrinsic.
- ``__reference_constructs_from_temporary`` should be used instead. (#GH44056)
-- Added `__builtin_get_vtable_pointer` to directly load the primary vtable pointer from a
- polymorphic object.
-- ``libclang`` receives a family of new bindings to query basic facts about
- GCC-style inline assembly blocks, including whether the block is ``volatile``
- and its template string following the LLVM IR ``asm`` format. (#GH143424)
-- Clang no longer rejects reinterpret_cast conversions between indirect
- ARC-managed pointers and other pointer types. The prior behavior was overly
- strict and inconsistent with the ARC specification.
New Compiler Flags
------------------
-- New option ``-Wundef-true`` added and enabled by default to warn when `true` is used in the C preprocessor without being defined before C23.
-
-- New option ``-fprofile-continuous`` added to enable continuous profile syncing to file (#GH124353, `docs <https://clang.llvm.org/docs/UsersManual.html#cmdoption-fprofile-continuous>`_).
- The feature has `existed <https://clang.llvm.org/docs/SourceBasedCodeCoverage.html#running-the-instrumented-program>`_)
- for a while and this is just a user facing option.
-
-- New option ``-ftime-report-json`` added which outputs the same timing data as ``-ftime-report`` but formatted as JSON.
-
-- New option ``-Wnrvo`` added and disabled by default to warn about missed NRVO opportunities.
-
-- New option ``-ignore-pch`` added to disable precompiled headers. It overrides ``-emit-pch`` and ``-include-pch``. (#GH142409, `PCHDocs <https://clang.llvm.org/docs/UsersManual.html#ignoring-a-pch-file>`_).
-
-- New options ``-g[no-]key-instructions`` added, disabled by default. Reduces jumpiness of debug stepping for optimized code in some debuggers (not LLDB at this time). Not recommended for use without optimizations. DWARF only. Note both the positive and negative flags imply ``-g``.
-
Deprecated Compiler Flags
-------------------------
Modified Compiler Flags
-----------------------
-- The ARM AArch32 ``-mtp`` option accepts and defaults to ``auto``, a value of ``auto`` uses the best available method of providing the frame pointer supported by the hardware. This matches
- the behavior of ``-mtp`` in gcc. This changes the default behavior for ARM targets that provide the ``TPIDRURO`` register as this will be used instead of a call to the ``__aeabi_read_tp``.
- Programs that use ``__aeabi_read_tp`` but do not use the ``TPIDRURO`` register must use ``-mtp=soft``. Fixes #123864
-
-- The compiler flag `-fbracket-depth` default value is increased from 256 to 2048. (#GH94728)
-
-- `-Wpadded` option implemented for the `x86_64-windows-msvc` target. Fixes #61702
-
-- The ``-mexecute-only`` and ``-mpure-code`` flags are now accepted for AArch64 targets. (#GH125688)
-
-- The ``-fchar8_t`` flag is no longer considered in non-C++ languages modes. (#GH55373)
-
-- The ``-fveclib=libmvec`` option now supports AArch64 targets (requires GLIBC 2.40 or newer).
-
-- The ``-Og`` optimization flag now sets ``-fextend-variable-liveness``,
- reducing performance slightly while reducing the number of optimized-out
- variables. (#GH118026)
-
Removed Compiler Flags
-------------------------
Attribute Changes in Clang
--------------------------
-Adding [[clang::unsafe_buffer_usage]] attribute to a method definition now turns off all -Wunsafe-buffer-usage
-related warnings within the method body.
-
-- The ``no_sanitize`` attribute now accepts both ``gnu`` and ``clang`` names.
-- The ``ext_vector_type(n)`` attribute can now be used as a generic type attribute.
-- Clang now diagnoses use of declaration attributes on void parameters. (#GH108819)
-- Clang now allows ``__attribute__((model("small")))`` and
- ``__attribute__((model("large")))`` on non-TLS globals in x86-64 compilations.
- This forces the global to be considered small or large in regards to the
- x86-64 code model, regardless of the code model specified for the compilation.
-- Clang now emits a warning ``-Wreserved-init-priority`` instead of a hard error
- when ``__attribute__((init_priority(n)))`` is used with values of n in the
- reserved range [0, 100]. The warning will be treated as an error by default.
-
-- There is a new ``format_matches`` attribute to complement the existing
- ``format`` attribute. ``format_matches`` allows the compiler to verify that
- a format string argument is equivalent to a reference format string: it is
- useful when a function accepts a format string without its accompanying
- arguments to format. For instance:
-
- .. code-block:: c
-
- static int status_code;
- static const char *status_string;
-
- void print_status(const char *fmt) {
- fprintf(stderr, fmt, status_code, status_string);
- // ^ warning: format string is not a string literal [-Wformat-nonliteral]
- }
-
- void stuff(void) {
- print_status("%s (%#08x)\n");
- // order of %s and %x is swapped but there is no diagnostic
- }
-
- Before the introducion of ``format_matches``, this code cannot be verified
- at compile-time. ``format_matches`` plugs that hole:
-
- .. code-block:: c
-
- __attribute__((format_matches(printf, 1, "%x %s")))
- void print_status(const char *fmt) {
- fprintf(stderr, fmt, status_code, status_string);
- // ^ `fmt` verified as if it was "%x %s" here; no longer triggers
- // -Wformat-nonliteral, would warn if arguments did not match "%x %s"
- }
-
- void stuff(void) {
- print_status("%s (%#08x)\n");
- // warning: format specifier 's' is incompatible with 'x'
- // warning: format specifier 'x' is incompatible with 's'
- }
-
- Like with ``format``, the first argument is the format string flavor and the
- second argument is the index of the format string parameter.
- ``format_matches`` accepts an example valid format string as its third
- argument. For more information, see the Clang attributes documentation.
-
-- Introduced a new statement attribute ``[[clang::atomic]]`` that enables
- fine-grained control over atomic code generation on a per-statement basis.
- Supported options include ``[no_]remote_memory``,
- ``[no_]fine_grained_memory``, and ``[no_]ignore_denormal_mode``. These are
- particularly relevant for AMDGPU targets, where they map to corresponding IR
- metadata.
-
-- Clang now disallows the use of attributes applied before an
- ``extern template`` declaration (#GH79893).
-
-- Clang will print the "reason" string argument passed on to
- ``[[clang::warn_unused_result("reason")]]`` as part of the warning diagnostic.
Improvements to Clang's diagnostics
-----------------------------------
-
-- Improve the diagnostics for deleted default constructor errors for C++ class
- initializer lists that don't explicitly list a class member and thus attempt
- to implicitly default construct that member.
-- The ``-Wunique-object-duplication`` warning has been added to warn about objects
- which are supposed to only exist once per program, but may get duplicated when
- built into a shared library.
-- Fixed a bug where Clang's Analysis did not correctly model the destructor behavior of ``union`` members (#GH119415).
-- A statement attribute applied to a ``case`` label no longer suppresses
- 'bypassing variable initialization' diagnostics (#84072).
-- The ``-Wunsafe-buffer-usage`` warning has been updated to warn
- about unsafe libc function calls. Those new warnings are emitted
- under the subgroup ``-Wunsafe-buffer-usage-in-libc-call``.
-- Diagnostics on chained comparisons (``a < b < c``) are now an error by default. This can be disabled with
- ``-Wno-error=parentheses``.
-- Similarly, fold expressions over a comparison operator are now an error by default.
-- Clang now better preserves the sugared types of pointers to member.
-- Clang now better preserves the presence of the template keyword with dependent
- prefixes.
-- Clang now in more cases avoids printing 'type-parameter-X-X' instead of the name of
- the template parameter.
-- Clang now respects the current language mode when printing expressions in
- diagnostics. This fixes a bunch of `bool` being printed as `_Bool`, and also
- a bunch of HLSL types being printed as their C++ equivalents.
-- Clang now consistently quotes expressions in diagnostics.
-- When printing types for diagnostics, clang now doesn't suppress the scopes of
- template arguments contained within nested names.
-- The ``-Wshift-bool`` warning has been added to warn about shifting a boolean. (#GH28334)
-- Fixed diagnostics adding a trailing ``::`` when printing some source code
- constructs, like base classes.
-- The :doc:`ThreadSafetyAnalysis` now supports ``-Wthread-safety-pointer``,
- which enables warning on passing or returning pointers to guarded variables
- as function arguments or return value respectively. Note that
- :doc:`ThreadSafetyAnalysis` still does not perform alias analysis. The
- feature will be default-enabled with ``-Wthread-safety`` in a future release.
-- The :doc:`ThreadSafetyAnalysis` now supports reentrant capabilities.
-- Clang will now do a better job producing common nested names, when producing
- common types for ternary operator, template argument deduction and multiple return auto deduction.
-- The ``-Wsign-compare`` warning now treats expressions with bitwise not(~) and minus(-) as signed integers
- except for the case where the operand is an unsigned integer
- and throws warning if they are compared with unsigned integers (##18878).
-- The ``-Wunnecessary-virtual-specifier`` warning (included in ``-Wextra``) has
- been added to warn about methods which are marked as virtual inside a
- ``final`` class, and hence can never be overridden.
-
-- Improve the diagnostics for chained comparisons to report actual expressions and operators (#GH129069).
-
-- Improve the diagnostics for shadows template parameter to report correct location (#GH129060).
-
-- Improve the ``-Wundefined-func-template`` warning when a function template is not instantiated due to being unreachable in modules.
-
-- Fixed an assertion when referencing an out-of-bounds parameter via a function
- attribute whose argument list refers to parameters by index and the function
- is variadic. e.g.,
-
- .. code-block:: c
-
- __attribute__ ((__format_arg__(2))) void test (int i, ...) { }
-
- Fixes #GH61635
-
-- Split diagnosing base class qualifiers from the ``-Wignored-Qualifiers`` diagnostic group into a new ``-Wignored-base-class-qualifiers`` diagnostic group (which is grouped under ``-Wignored-qualifiers``). Fixes #GH131935.
-
-- ``-Wc++98-compat`` no longer diagnoses use of ``__auto_type`` or
- ``decltype(auto)`` as though it was the extension for ``auto``. (#GH47900)
-- Clang now issues a warning for missing return in ``main`` in C89 mode. (#GH21650)
-
-- Now correctly diagnose a tentative definition of an array with static
- storage duration in pedantic mode in C. (#GH50661)
-- No longer diagnosing idiomatic function pointer casts on Windows under
- ``-Wcast-function-type-mismatch`` (which is enabled by ``-Wextra``). Clang
- would previously warn on this construct, but will no longer do so on Windows:
-
- .. code-block:: c
-
- typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
- HMODULE Lib = LoadLibrary("kernel32");
- PGNSI FnPtr = (PGNSI)GetProcAddress(Lib, "GetNativeSystemInfo");
-
-
-- An error is now emitted when a ``musttail`` call is made to a function marked with the ``not_tail_called`` attribute. (#GH133509).
-
-- ``-Whigher-precision-for-complex-divison`` warns when:
-
- - The divisor is complex.
- - When the complex division happens in a higher precision type due to arithmetic promotion.
- - When using the divide and assign operator (``/=``).
-
- Fixes #GH131127
-
-- ``-Wuninitialized`` now diagnoses when a class does not declare any
- constructors to initialize their non-modifiable members. The diagnostic is
- not new; being controlled via a warning group is what's new. Fixes #GH41104
-
-- Analysis-based diagnostics (like ``-Wconsumed`` or ``-Wunreachable-code``)
- can now be correctly controlled by ``#pragma clang diagnostic``. #GH42199
-
-- Improved Clang's error recovery for invalid function calls.
-
-- Improved bit-field diagnostics to consider the type specified by the
- ``preferred_type`` attribute. These diagnostics are controlled by the flags
- ``-Wpreferred-type-bitfield-enum-conversion`` and
- ``-Wpreferred-type-bitfield-width``. These warnings are on by default as they
- they're only triggered if the authors are already making the choice to use
- ``preferred_type`` attribute.
-
-- ``-Winitializer-overrides`` and ``-Wreorder-init-list`` are now grouped under
- the ``-Wc99-designator`` diagnostic group, as they also are about the
- behavior of the C99 feature as it was introduced into C++20. Fixes #GH47037
-- ``-Wreserved-identifier`` now fires on reserved parameter names in a function
- declaration which is not a definition.
-- Clang now prints the namespace for an attribute, if any,
- when emitting an unknown attribute diagnostic.
-
-- ``-Wvolatile`` now warns about volatile-qualified class return types
- as well as volatile-qualified scalar return types. Fixes #GH133380
-
-- Several compatibility diagnostics that were incorrectly being grouped under
- ``-Wpre-c++20-compat`` are now part of ``-Wc++20-compat``. (#GH138775)
-
-- Improved the ``-Wtautological-overlap-compare`` diagnostics to warn about overlapping and non-overlapping ranges involving character literals and floating-point literals.
- The warning message for non-overlapping cases has also been improved (#GH13473).
-
-- Fixed a duplicate diagnostic when performing typo correction on function template
- calls with explicit template arguments. (#GH139226)
-
-- Explanatory note is printed when ``assert`` fails during evaluation of a
- constant expression. Prior to this, the error inaccurately implied that assert
- could not be used at all in a constant expression (#GH130458)
-
-- A new off-by-default warning ``-Wms-bitfield-padding`` has been added to alert to cases where bit-field
- packing may differ under the MS struct ABI (#GH117428).
-
-- ``-Watomic-access`` no longer fires on unreachable code. e.g.,
-
- .. code-block:: c
-
- _Atomic struct S { int a; } s;
- void func(void) {
- if (0)
- s.a = 12; // Previously diagnosed with -Watomic-access, now silenced
- s.a = 12; // Still diagnosed with -Watomic-access
- return;
- s.a = 12; // Previously diagnosed, now silenced
- }
-
-
-- A new ``-Wcharacter-conversion`` warns where comparing or implicitly converting
- between different Unicode character types (``char8_t``, ``char16_t``, ``char32_t``).
- This warning only triggers in C++ as these types are aliases in C. (#GH138526)
-
-- Fixed a crash when checking a ``__thread``-specified variable declaration
- with a dependent type in C++. (#GH140509)
-
-- Clang now suggests corrections for unknown attribute names.
-
-- ``-Wswitch`` will now diagnose unhandled enumerators in switches also when
- the enumerator is deprecated. Warnings about using deprecated enumerators in
- switch cases have moved behind a new ``-Wdeprecated-declarations-switch-case``
- flag.
-
- For example:
-
- .. code-block:: c
-
- enum E {
- Red,
- Green,
- Blue [[deprecated]]
- };
- void example(enum E e) {
- switch (e) {
- case Red: // stuff...
- case Green: // stuff...
- }
- }
-
- will result in a warning about ``Blue`` not being handled in the switch.
-
- The warning can be fixed either by adding a ``default:``, or by adding
- ``case Blue:``. Since the enumerator is deprecated, the latter approach will
- trigger a ``'Blue' is deprecated`` warning, which can be turned off with
- ``-Wno-deprecated-declarations-switch-case``.
-
-- Split diagnosis of implicit integer comparison on negation to a new
- diagnostic group ``-Wimplicit-int-comparison-on-negation``, grouped under
- ``-Wimplicit-int-conversion``, so user can turn it off independently.
-
-- Improved the FixIts for unused lambda captures.
-
-- Delayed typo correction was removed from the compiler; immediate typo
- correction behavior remains the same. Delayed typo correction facilities were
- fragile and unmaintained, and the removal closed the following issues:
- #GH142457, #GH139913, #GH138850, #GH137867, #GH137860, #GH107840, #GH93308,
- #GH69470, #GH59391, #GH58172, #GH46215, #GH45915, #GH45891, #GH44490,
- #GH36703, #GH32903, #GH23312, #GH69874.
-
-- Clang no longer emits a spurious -Wdangling-gsl warning in C++23 when
- iterating over an element of a temporary container in a range-based
- for loop.(#GH109793, #GH145164)
-
-- Fixed false positives in ``-Wformat-truncation`` and ``-Wformat-overflow``
- diagnostics when floating-point numbers had both width field and plus or space
- prefix specified. (#GH143951)
-
-- A warning is now emitted when ``main`` is attached to a named module,
- which can be turned off with ``-Wno-main-attached-to-named-module``. (#GH146247)
-
-- Clang now avoids issuing `-Wreturn-type` warnings in some cases where
- the final statement of a non-void function is a `throw` expression, or
- a call to a function that is trivially known to always throw (i.e., its
- body consists solely of a `throw` statement). This avoids certain
- false positives in exception-heavy code, though only simple patterns
- are currently recognized.
-
-- Clang now accepts ``@tparam`` comments on variable template partial
- specializations. (#GH144775)
-
-- Fixed a bug that caused diagnostic line wrapping to not function correctly on
- some systems. (#GH139499)
-
-- Clang now tries to avoid printing file paths that contain ``..``, instead preferring
- the canonical file path if it ends up being shorter.
-
-- Improve the diagnostics for placement new expression when const-qualified
- object was passed as the storage argument. (#GH143708)
-
-- Clang now does not issue a warning about returning from a function declared with
- the ``[[noreturn]]`` attribute when the function body is ended with a call via
- pointer, provided it can be proven that the pointer only points to
- ``[[noreturn]]`` functions.
-
- Added a separate diagnostic group ``-Wfunction-effect-redeclarations``, for the more pedantic
diagnostics for function effects (``[[clang::nonblocking]]`` and ``[[clang::nonallocating]]``).
Moved the warning for a missing (though implied) attribute on a redeclaration into this group.
@@ -725,283 +121,30 @@ Improvements to Coverage Mapping
Bug Fixes in This Version
-------------------------
-
-- Clang now outputs correct values when #embed data contains bytes with negative
- signed char values (#GH102798).
-- Fixed a crash when merging named enumerations in modules (#GH114240).
-- Fixed rejects-valid problem when #embed appears in std::initializer_list or
- when it can affect template argument deduction (#GH122306).
-- Fix crash on code completion of function calls involving partial order of function templates
- (#GH125500).
-- Fixed clang crash when #embed data does not fit into an array
- (#GH128987).
-- Non-local variable and non-variable declarations in the first clause of a ``for`` loop in C are no longer incorrectly
- considered an error in C23 mode and are allowed as an extension in earlier language modes.
-
-- Remove the ``static`` specifier for the value of ``_FUNCTION_`` for static functions, in MSVC compatibility mode.
-- Fixed a modules crash where exception specifications were not propagated properly (#GH121245, relanded in #GH129982)
-- Fixed a problematic case with recursive deserialization within ``FinishedDeserializing()`` where
- ``PassInterestingDeclsToConsumer()`` was called before the declarations were safe to be passed. (#GH129982)
-- Fixed a modules crash where an explicit Constructor was deserialized. (#GH132794)
-- Defining an integer literal suffix (e.g., ``LL``) before including
- ``<stdint.h>`` in a freestanding build no longer causes invalid token pasting
- when using the ``INTn_C`` macros. (#GH85995)
-- Fixed an assertion failure in the expansion of builtin macros like ``__has_embed()`` with line breaks before the
- closing paren. (#GH133574)
-- Fixed a crash in error recovery for expressions resolving to templates. (#GH135621)
-- Clang no longer accepts invalid integer constants which are too large to fit
- into any (standard or extended) integer type when the constant is unevaluated.
- Merely forming the token is sufficient to render the program invalid. Code
- like this was previously accepted and is now rejected (#GH134658):
- .. code-block:: c
-
- #if 1 ? 1 : 999999999999999999999
- #endif
-- ``#embed`` directive now diagnoses use of a non-character file (device file)
- such as ``/dev/urandom`` as an error. This restriction may be relaxed in the
- future. See (#GH126629).
-- Fixed a clang 20 regression where diagnostics attached to some calls to member functions
- using C++23 "deducing this" did not have a diagnostic location (#GH135522)
-
-- Fixed a crash when a ``friend`` function is redefined as deleted. (#GH135506)
-- Fixed a crash when ``#embed`` appears as a part of a failed constant
- evaluation. The crashes were happening during diagnostics emission due to
- unimplemented statement printer. (#GH132641)
-- Fixed visibility calculation for template functions. (#GH103477)
-- Fixed a bug where an attribute before a ``pragma clang attribute`` or
- ``pragma clang __debug`` would cause an assertion. Instead, this now diagnoses
- the invalid attribute location appropriately. (#GH137861)
-- Fixed a crash when a malformed ``_Pragma`` directive appears as part of an
- ``#include`` directive. (#GH138094)
-- Fixed a crash during constant evaluation involving invalid lambda captures
- (#GH138832)
-- Fixed compound literal is not constant expression inside initializer list
- (#GH87867)
-- Fixed a crash when instantiating an invalid dependent friend template specialization.
- (#GH139052)
-- Fixed a crash with an invalid member function parameter list with a default
- argument which contains a pragma. (#GH113722)
-- Fixed assertion failures when generating name lookup table in modules. (#GH61065, #GH134739)
-- Fixed an assertion failure in constant compound literal statements. (#GH139160)
-- Fix crash due to unknown references and pointer implementation and handling of
- base classes. (GH139452)
-- Fixed an assertion failure in serialization of constexpr structs containing unions. (#GH140130)
-- Fixed duplicate entries in TableGen that caused the wrong attribute to be selected. (GH#140701)
-- Fixed type mismatch error when 'builtin-elementwise-math' arguments have different qualifiers, this should be well-formed. (#GH141397)
-- Constant evaluation now correctly runs the destructor of a variable declared in
- the second clause of a C-style ``for`` loop. (#GH139818)
-- Fixed a bug with constexpr evaluation for structs containing unions in case of C++ modules. (#GH143168)
-- Fixed incorrect token location when emitting diagnostics for tokens expanded from macros. (#GH143216)
-- Fixed an infinite recursion when checking constexpr destructors. (#GH141789)
-- Fixed a crash when a malformed using declaration appears in a ``constexpr`` function. (#GH144264)
-- Fixed a bug when use unicode character name in macro concatenation. (#GH145240)
-- Clang doesn't erroneously inject a ``static_assert`` macro in ms-compatibility and
- -std=c99 mode. This resulted in deletion of ``-W/Wno-microsoft-static-assert``
- flag and diagnostic because the macro injection was used to emit this warning.
- Unfortunately there is no other good way to diagnose usage of ``static_assert``
- macro without inclusion of ``<assert.h>``.
-- In C23, something like ``[[/*possible attributes*/]];`` is an attribute
- declaration, not a statement. So it is not allowed by the syntax in places
- where a statement is required, specifically as the secondary block of a
- selection or iteration statement. This differs from C++, since C++ allows
- declaration statements. Clang now emits a warning for these patterns. (#GH141659)
-- Fixed false positives for redeclaration errors of using enum in
- nested scopes. (#GH147495)
-- Fixed a failed assertion with an operator call expression which comes from a
- macro expansion when performing analysis for nullability attributes. (#GH138371)
-- Fixed a concept equivalent checking crash due to untransformed constraint expressions. (#GH146614)
+- Fix a crash when marco name is empty in ``#pragma push_macro("")`` or
+ ``#pragma pop_macro("")``. (#GH149762).
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- The behaviour of ``__add_pointer`` and ``__remove_pointer`` for Objective-C++'s ``id`` and interfaces has been fixed.
-
-- The signature for ``__builtin___clear_cache`` was changed from
- ``void(char *, char *)`` to ``void(void *, void *)`` to match GCC's signature
- for the same builtin. (#GH47833)
-
-- ``__has_unique_object_representations(Incomplete[])`` is no longer accepted, per
- `LWG4113 <https://cplusplus.github.io/LWG/issue4113>`_.
-
-- ``__builtin_is_cpp_trivially_relocatable``, ``__builtin_is_replaceable`` and
- ``__builtin_trivially_relocate`` have been added to support standard C++26 relocation.
-
-- ``__is_trivially_relocatable`` has been deprecated, and uses should be replaced by
- ``__builtin_is_cpp_trivially_relocatable``.
- Note that, it is generally unsafe to ``memcpy`` non-trivially copyable types that
- are ``__builtin_is_cpp_trivially_relocatable``. It is recommended to use
- ``__builtin_trivially_relocate`` instead.
-
-- ``__reference_binds_to_temporary``, ``__reference_constructs_from_temporary``
- and ``__reference_converts_from_temporary`` intrinsics no longer consider
- function references can bind to temporary objects. (#GH114344)
-
-- ``__reference_constructs_from_temporary`` and
- ``__reference_converts_from_temporary`` intrinsics detect reference binding
- to prvalue instead of xvalue now if the second operand is an object type, per
- `LWG3819 <https://cplusplus.github.io/LWG/issue3819>`_.
-
Bug Fixes to Attribute Support
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- - Fixed crash when a parameter to the ``clang::annotate`` attribute evaluates to ``void``. See #GH119125
-
-- Clang now emits a warning instead of an error when using the one or two
- argument form of GCC 11's ``__attribute__((malloc(deallocator)))``
- or ``__attribute__((malloc(deallocator, ptr-index)))``
- (`#51607 <https://github.com/llvm/llvm-project/issues/51607>`_).
-
-- Corrected the diagnostic for the ``callback`` attribute when passing too many
- or too few attribute argument indicies for the specified callback function.
- (#GH47451)
-
-- No longer crashing on ``__attribute__((align_value(N)))`` during template
- instantiation when the function parameter type is not a pointer or reference.
- (#GH26612)
-- Now allowing the ``[[deprecated]]``, ``[[maybe_unused]]``, and
- ``[[nodiscard]]`` to be applied to a redeclaration after a definition in both
- C and C++ mode for the standard spellings (other spellings, such as
- ``__attribute__((unused))`` are still ignored after the definition, though
- this behavior may be relaxed in the future). (#GH135481)
-
-- Clang will warn if a complete type specializes a deprecated partial specialization.
- (#GH44496)
Bug Fixes to C++ Support
^^^^^^^^^^^^^^^^^^^^^^^^
-
-- Clang now supports implicitly defined comparison operators for friend declarations. (#GH132249)
-- Clang now diagnoses copy constructors taking the class by value in template instantiations. (#GH130866)
-- Clang is now better at keeping track of friend function template instance contexts. (#GH55509)
-- Clang now prints the correct instantiation context for diagnostics suppressed
- by template argument deduction.
-- Errors that occur during evaluation of certain type traits and builtins are
- no longer incorrectly emitted when they are used in an SFINAE context. The
- type traits are:
-
- - ``__is_constructible`` and variants,
- - ``__is_convertible`` and variants,
- - ``__is_assignable`` and variants,
- - ``__reference_binds_to_temporary``,
- ``__reference_constructs_from_temporary``,
- ``__reference_converts_from_temporary``,
- - ``__is_trivially_equality_comparable``.
-
- The builtin is ``__builtin_common_type``. (#GH132044)
-- Clang is now better at instantiating the function definition after its use inside
- of a constexpr lambda. (#GH125747)
-- Fixed a local class member function instantiation bug inside dependent lambdas. (#GH59734), (#GH132208)
-- Clang no longer crashes when trying to unify the types of arrays with
- certain differences in qualifiers (this could happen during template argument
- deduction or when building a ternary operator). (#GH97005)
-- Fixed type alias CTAD issues involving default template arguments. (#GH133132), (#GH134471)
-- Fixed CTAD issues when initializing anonymous fields with designated initializers. (#GH67173)
-- The initialization kind of elements of structured bindings
- direct-list-initialized from an array is corrected to direct-initialization.
-- Clang no longer crashes when a coroutine is declared ``[[noreturn]]``. (#GH127327)
-- Clang now uses the parameter location for abbreviated function templates in ``extern "C"``. (#GH46386)
-- Clang will emit an error instead of crash when use co_await or co_yield in
- C++26 braced-init-list template parameter initialization. (#GH78426)
-- Improved fix for an issue with pack expansions of type constraints, where this
- now also works if the constraint has non-type or template template parameters.
- (#GH131798)
-- Fixes to partial ordering of non-type template parameter packs. (#GH132562)
-- Fix crash when evaluating the trailing requires clause of generic lambdas which are part of
- a pack expansion.
-- Fixes matching of nested template template parameters. (#GH130362)
-- Correctly diagnoses template template parameters which have a pack parameter
- not in the last position.
-- Disallow overloading on struct vs class on dependent types, which is IFNDR, as
- this makes the problem diagnosable.
-- Improved preservation of the presence or absence of typename specifier when
- printing types in diagnostics.
-- Clang now correctly parses ``if constexpr`` expressions in immediate function context. (#GH123524)
-- Fixed an assertion failure affecting code that uses C++23 "deducing this". (#GH130272)
-- Clang now properly instantiates destructors for initialized members within non-delegating constructors. (#GH93251)
-- Correctly diagnoses if unresolved using declarations shadows template parameters (#GH129411)
-- Fixed C++20 aggregate initialization rules being incorrectly applied in certain contexts. (#GH131320)
-- Clang was previously coalescing volatile writes to members of volatile base class subobjects.
- The issue has been addressed by propagating qualifiers during derived-to-base conversions in the AST. (#GH127824)
-- Correctly propagates the instantiated array type to the ``DeclRefExpr`` that refers to it. (#GH79750), (#GH113936), (#GH133047)
-- Fixed a Clang regression in C++20 mode where unresolved dependent call expressions were created inside non-dependent contexts (#GH122892)
-- Clang now emits the ``-Wunused-variable`` warning when some structured bindings are unused
- and the ``[[maybe_unused]]`` attribute is not applied. (#GH125810)
-- Fixed ``static_cast`` not performing access or ambiguity checks when converting to an rvalue reference to a base class. (#GH121429)
-- Declarations using class template argument deduction with redundant
- parentheses around the declarator are no longer rejected. (#GH39811)
-- Fixed a crash caused by invalid declarations of ``std::initializer_list``. (#GH132256)
-- Clang no longer crashes when establishing subsumption between some constraint expressions. (#GH122581)
-- Clang now issues an error when placement new is used to modify a const-qualified variable
- in a ``constexpr`` function. (#GH131432)
-- Fixed an incorrect TreeTransform for calls to ``consteval`` functions if a conversion template is present. (#GH137885)
-- Clang now emits a warning when class template argument deduction for alias templates is used in C++17. (#GH133806)
-- Fixed a missed initializer instantiation bug for variable templates. (#GH134526), (#GH138122)
-- Fix a crash when checking the template template parameters of a dependent lambda appearing in an alias declaration.
- (#GH136432), (#GH137014), (#GH138018)
-- Fixed an assertion when trying to constant-fold various builtins when the argument
- referred to a reference to an incomplete type. (#GH129397)
-- Fixed a crash when a cast involved a parenthesized aggregate initialization in dependent context. (#GH72880)
-- No longer crashes when instantiating invalid variable template specialization
- whose type depends on itself. (#GH51347), (#GH55872)
-- Improved parser recovery of invalid requirement expressions. In turn, this
- fixes crashes from follow-on processing of the invalid requirement. (#GH138820)
-- Fixed the handling of pack indexing types in the constraints of a member function redeclaration. (#GH138255)
-- Clang now correctly parses arbitrary order of ``[[]]``, ``__attribute__`` and ``alignas`` attributes for declarations (#GH133107)
-- Fixed a crash when forming an invalid function type in a dependent context. (#GH138657) (#GH115725) (#GH68852)
-- Fixed a function declaration mismatch that caused inconsistencies between concepts and variable template declarations. (#GH139476)
-- Fixed an out-of-line declaration mismatch involving nested template parameters. (#GH145521)
-- Clang no longer segfaults when there is a configuration mismatch between modules and their users (http://crbug.com/400353616).
-- Fix an incorrect deduction when calling an explicit object member function template through an overload set address.
-- Fixed bug in constant evaluation that would allow using the value of a
- reference in its own initializer in C++23 mode (#GH131330).
-- Clang could incorrectly instantiate functions in discarded contexts (#GH140449)
-- Fix instantiation of default-initialized variable template specialization. (#GH140632) (#GH140622)
-- Clang modules now allow a module and its user to differ on TrivialAutoVarInit*
-- Fixed an access checking bug when initializing non-aggregates in default arguments (#GH62444), (#GH83608)
-- Fixed a pack substitution bug in deducing class template partial specializations. (#GH53609)
-- Fixed a crash when constant evaluating some explicit object member assignment operators. (#GH142835)
-- Fixed an access checking bug when substituting into concepts (#GH115838)
-- Fix a bug where private access specifier of overloaded function not respected. (#GH107629)
-- Correctly handles calling an explicit object member function template overload set
- through its address (``(&Foo::bar<baz>)()``).
-- Fix a crash when using an explicit object parameter in a non-member function. (#GH113185)
-- Fix a crash when forming an invalid call to an operator with an explicit object member. (#GH147121)
-- Correctly handle allocations in the condition of a ``if constexpr``.(#GH120197) (#GH134820)
-- Fixed a crash when handling invalid member using-declaration in C++20+ mode. (#GH63254)
-- Fixed parsing of lambda expressions that appear after ``*`` or ``&`` in contexts where a declaration can appear. (#GH63880)
-- Fix name lookup in lambda appearing in the body of a requires expression. (#GH147650)
-- Fix a crash when trying to instantiate an ambiguous specialization. (#GH51866)
-- Improved handling of variables with ``consteval`` constructors, to
- consistently treat the initializer as manifestly constant-evaluated.
- (#GH135281)
-- Fix a crash in the presence of invalid base classes. (#GH147186)
-- Fix a crash with NTTP when instantiating local class.
-- Fixed a crash involving list-initialization of an empty class with a
- non-empty initializer list. (#GH147949)
-- Fixed constant evaluation of equality comparisons of constexpr-unknown references. (#GH147663)
- Diagnose binding a reference to ``*nullptr`` during constant evaluation. (#GH48665)
+- Suppress ``-Wdeprecated-declarations`` in implicitly generated functions. (#GH147293)
+- Fix a crash when deleting a pointer to an incomplete array (#GH150359).
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
-- Fixed type checking when a statement expression ends in an l-value of atomic type. (#GH106576)
-- Fixed uninitialized use check in a lambda within CXXOperatorCallExpr. (#GH129198)
-- Fixed a malformed printout of ``CXXParenListInitExpr`` in certain contexts.
-- Fixed a malformed printout of certain calling convention function attributes. (#GH143160)
-- Fixed dependency calculation for TypedefTypes (#GH89774)
-- The ODR checker now correctly hashes the names of conversion operators. (#GH143152)
-- Fixed the right parenthesis source location of ``CXXTemporaryObjectExpr``. (#GH143711)
-- Fixed a crash when performing an ``IgnoreUnlessSpelledInSource`` traversal of ASTs containing ``catch(...)`` statements. (#GH146103)
Miscellaneous Bug Fixes
^^^^^^^^^^^^^^^^^^^^^^^
-- HTML tags in comments that span multiple lines are now parsed correctly by Clang's comment parser. (#GH120843)
-
Miscellaneous Clang Crashes Fixed
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- Fixed crash when ``-print-stats`` is enabled in compiling IR files. (#GH131608)
-- Fix code completion crash involving PCH serialized templates. (#GH139019)
-
OpenACC Specific Changes
------------------------
@@ -1011,123 +154,30 @@ Target Specific Changes
AMDGPU Support
^^^^^^^^^^^^^^
-- Bump the default code object version to 6. ROCm 6.3 is required to run any program compiled with COV6.
-
NVPTX Support
^^^^^^^^^^^^^^
-Hexagon Support
-^^^^^^^^^^^^^^^
-
-- The default compilation target has been changed from V60 to V68.
-
X86 Support
^^^^^^^^^^^
-- The 256-bit maximum vector register size control was removed from
- `AVX10 whitepaper <https://cdrdv2.intel.com/v1/dl/getContent/784343>_`.
- * Re-target ``m[no-]avx10.1`` to enable AVX10.1 with 512-bit maximum vector register size.
- * Emit warning for ``mavx10.x-256``, noting AVX10/256 is not supported.
- * Emit warning for ``mavx10.x-512``, noting to use ``m[no-]avx10.x`` instead.
- * Emit warning for ``m[no-]evex512``, noting AVX10/256 is not supported.
- * The features avx10.x-256/512 keep unchanged and will be removed in the next release.
-
Arm and AArch64 Support
^^^^^^^^^^^^^^^^^^^^^^^
-- Implementation of modal 8-bit floating point intrinsics in accordance with
- the Arm C Language Extensions (ACLE)
- `as specified here <https://github.com/ARM-software/acle/blob/main/main/acle.md#modal-8-bit-floating-point-extensions>`_
- is now available.
-- Support has been added for the following processors (command-line identifiers in parentheses):
-
- - Arm Cortex-A320 (``cortex-a320``)
-
-- For ARM targets, cc1as now considers the FPU's features for the selected CPU or Architecture.
-- The ``+nosimd`` attribute is now fully supported for ARM. Previously, this had no effect when being used with
- ARM targets, however this will now disable NEON instructions being generated. The ``simd`` option is
- also now printed when the ``--print-supported-extensions`` option is used.
-- When a feature that depends on NEON (``simd``) is used, NEON is now automatically enabled.
-- When NEON is disabled (``+nosimd``), all features that depend on NEON will now be disabled.
-
-- Pointer authentication
-
- - Support for __ptrauth type qualifier has been added.
- - Objective-C adoption of pointer authentication
-
- - ``isa`` and ``super`` pointers are protected with address diversity and separate
- usage specific discriminators.
- - methodlist pointers and content are protected with address diversity and methodlist
- pointers have a usage specific discriminator.
- - ``class_ro_t`` pointers are protected with address diversity and usage specific
- discriminators.
- - ``SEL`` typed ivars are protected with address diversity and usage specific
- discriminators.
-
-- For AArch64, added support for generating executable-only code sections by using the
- ``-mexecute-only`` or ``-mpure-code`` compiler flags. (#GH125688)
-- Added ``-msve-streaming-vector-bits=`` flag, which allows specifying the
- SVE vector width in streaming mode.
-
Android Support
^^^^^^^^^^^^^^^
Windows Support
^^^^^^^^^^^^^^^
-- Clang now defines ``_CRT_USE_BUILTIN_OFFSETOF`` macro in MSVC-compatible mode,
- which makes ``offsetof`` provided by Microsoft's ``<stddef.h>`` to be defined
- correctly. (#GH59689)
-
-- Clang now can process the `i128` and `ui128` integral suffixes when MSVC
- extensions are enabled. This allows for properly processing ``intsafe.h`` in
- the Windows SDK.
-
LoongArch Support
^^^^^^^^^^^^^^^^^
-- Add support for OHOS on loongarch64.
-
-- Add target attribute support for function. Supported formats include:
- * `arch=<arch>` strings - specifies architecture features for a function (equivalent to `-march=<arch>`).
- * `tune=<cpu>` strings - specifies the tune CPU for a function (equivalent to `-mtune`).
- * `<feature>`/`no-<feature>` - enables/disables specific features.
-
-- Add support for the `_Float16` type. And fix incorrect ABI lowering of `_Float16`
- in the case of structs containing fp16 that are eligible for passing via `GPR+FPR`
- or `FPR+FPR`. Also fix `int16` -> `__fp16` conversion code gen, which uses generic LLVM
- IR rather than `llvm.convert.to.fp16` intrinsics.
-
-- Add support for the `__bf16` type.
-
-- Fix incorrect _BitInt(N>64) alignment. Now consistently uses 16-byte alignment for all
- `_BitInt(N)` where N > 64.
-
RISC-V Support
^^^^^^^^^^^^^^
-- Add support for `-mtune=generic-ooo` (a generic out-of-order model).
-- Adds support for `__attribute__((interrupt("SiFive-CLIC-preemptible")))` and
- `__attribute__((interrupt("SiFive-CLIC-stack-swap")))`. The former
- automatically saves some interrupt CSRs before re-enabling interrupts in the
- function prolog, the latter swaps `sp` with the value in a CSR before it is
- used or modified. These two can also be combined, and can be combined with
- `interrupt("machine")`.
-
-- Adds support for `__attribute__((interrupt("qci-nest")))` and
- `__attribute__((interrupt("qci-nonest")))`. These use instructions from
- Qualcomm's `Xqciint` extension to save and restore some GPRs in interrupt
- service routines.
-
-- `Zicsr` / `Zifencei` are allowed to be duplicated in the presence of `g` in `-march`.
-
-- Add support for the `__builtin_riscv_pause()` intrinsic from the `Zihintpause` extension.
-
CUDA/HIP Language Changes
^^^^^^^^^^^^^^^^^^^^^^^^^
-* Provide a __device__ version of std::__glibcxx_assert_fail() in a header wrapper.
-
CUDA Support
^^^^^^^^^^^^
@@ -1154,164 +204,54 @@ Fixed Point Support in Clang
AST Matchers
------------
-
- Ensure ``hasBitWidth`` doesn't crash on bit widths that are dependent on template
parameters.
-- Ensure ``isDerivedFrom`` matches the correct base in case more than one alias exists.
-- Extend ``templateArgumentCountIs`` to support function and variable template
- specialization.
clang-format
------------
-- Adds ``BreakBeforeTemplateCloser`` option.
-- Adds ``BinPackLongBracedList`` option to override bin packing options in
- long (20 item or more) braced list initializer lists.
-- Add the C language instead of treating it like C++.
-- Allow specifying the language (C, C++, or Objective-C) for a ``.h`` file by
- adding a special comment (e.g. ``// clang-format Language: ObjC``) near the
- top of the file.
-- Add ``EnumTrailingComma`` option for inserting/removing commas at the end of
- ``enum`` enumerator lists.
-- Add ``OneLineFormatOffRegex`` option for turning formatting off for one line.
-- Add ``SpaceAfterOperatorKeyword`` option.
-- Add ``MacrosSkippedByRemoveParentheses`` option so that their invocations are
- skipped by ``RemoveParentheses``.
-
-clang-refactor
---------------
-- Reject `0` as column or line number in 1-based command-line source locations.
- Fixes crash caused by `0` input in `-selection=<file>:<line>:<column>[-<line>:<column>]`. (#GH139457)
-
libclang
--------
-- Fixed a bug in ``clang_File_isEqual`` that sometimes led to different
- in-memory files to be considered as equal.
-- Added ``clang_visitCXXMethods``, which allows visiting the methods
- of a class.
-- Added ``clang_getFullyQualifiedName``, which provides fully qualified type names as
- instructed by a PrintingPolicy.
-
-- Fixed a buffer overflow in ``CXString`` implementation. The fix may result in
- increased memory allocation.
-
-- Deprecate ``clang_Cursor_GetBinaryOpcode`` and ``clang_Cursor_getBinaryOpcodeStr``
- implementations, which are duplicates of ``clang_getCursorBinaryOperatorKind``
- and ``clang_getBinaryOperatorKindSpelling`` respectively.
Code Completion
---------------
-- Reject `0` as column or line number in 1-based command-line source locations.
- Fixes crash caused by `0` input in `-code-completion-at=<file>:<line>:<column>`. (#GH139457)
Static Analyzer
---------------
-- Fixed a crash when C++20 parenthesized initializer lists are used. This issue
- was causing a crash in clang-tidy. (#GH136041)
- The Clang Static Analyzer now handles parenthesized initialization.
(#GH148875)
New features
^^^^^^^^^^^^
-- A new flag - `-static-libclosure` was introduced to support statically linking
- the runtime for the Blocks extension on Windows. This flag currently only
- changes the code generation, and even then, only on Windows. This does not
- impact the linker behaviour like the other `-static-*` flags.
-- OpenACC support, enabled via `-fopenacc` has reached a level of completeness
- to finally be at least notionally usable. Currently, the OpenACC 3.4
- specification has been completely implemented for Sema and AST creation, so
- nodes will show up in the AST after having been properly checked. Lowering is
- currently a work in progress, with compute, loop, and combined constructs
- partially implemented, plus a handful of data and executable constructs
- implemented. Lowering will only work in Clang-IR mode (so only with a compiler
- built with Clang-IR enabled, and with `-fclangir` used on the command line).
- However, note that the Clang-IR implementation status is also quite partial,
- so frequent 'not yet implemented' diagnostics should be expected. Also, the
- ACC MLIR dialect does not currently implement any lowering to LLVM-IR, so no
- code generation is possible for OpenACC.
-- Implemented `P2719R5 Type-aware allocation and deallocation functions <https://wg21.link/P2719>`_
- as an extension in all C++ language modes.
-
-
Crash and bug fixes
^^^^^^^^^^^^^^^^^^^
-- Fixed a crash in ``UnixAPIMisuseChecker`` and ``MallocChecker`` when analyzing
- code with non-standard ``getline`` or ``getdelim`` function signatures. (#GH144884)
-
Improvements
^^^^^^^^^^^^
-- The checker option ``optin.cplusplus.VirtualCall:PureOnly`` was removed,
- because it had been deprecated since 2019 and it is completely useless (it
- was kept only for compatibility with pre-2019 versions, setting it to true is
- equivalent to completely disabling the checker).
-
Moved checkers
^^^^^^^^^^^^^^
-- After lots of improvements, the checker ``alpha.security.ArrayBoundV2`` is
- renamed to ``security.ArrayBound``. As this checker is stable now, the old
- checker ``alpha.security.ArrayBound`` (which was searching for the same kind
- of bugs with an different, simpler and less accurate algorithm) is removed.
-
.. _release-notes-sanitizers:
Sanitizers
----------
-- ``-fsanitize=vptr`` is no longer a part of ``-fsanitize=undefined``.
-- Sanitizer ignorelists now support the syntax ``src:*=sanitize``,
- ``type:*=sanitize``, ``fun:*=sanitize``, ``global:*=sanitize``,
- and ``mainfile:*=sanitize``.
-
Python Binding Changes
----------------------
-- Made ``Cursor`` hashable.
-- Added ``Cursor.has_attrs``, a binding for ``clang_Cursor_hasAttrs``, to check
- whether a cursor has any attributes.
-- Added ``Cursor.specialized_template``, a binding for
- ``clang_getSpecializedCursorTemplate``, to retrieve the primary template that
- the cursor is a specialization of.
-- Added ``Type.get_methods``, a binding for ``clang_visitCXXMethods``, which
- allows visiting the methods of a class.
-- Added ``Type.get_fully_qualified_name``, which provides fully qualified type names as
- instructed by a PrintingPolicy.
-- Add equality comparison operators for ``File`` type
OpenMP Support
--------------
-- Added support 'no_openmp_constructs' assumption clause.
-- Added support for 'self_maps' in map and requirement clause.
-- Added support for 'omp stripe' directive.
-- Fixed a crashing bug with ``omp unroll partial`` if the argument to
- ``partial`` was an invalid expression. (#GH139267)
-- Fixed a crashing bug with ``omp tile sizes`` if the argument to ``sizes`` was
- an invalid expression. (#GH139073)
-- Fixed a crashing bug with ``omp simd collapse`` if the argument to
- ``collapse`` was an invalid expression. (#GH138493)
-- Fixed a crashing bug with a malformed ``cancel`` directive. (#GH139360)
-- Fixed a crashing bug with ``omp distribute dist_schedule`` if the argument to
- ``dist_schedule`` was not strictly positive. (#GH139266)
-- Fixed two crashing bugs with a malformed ``metadirective`` directive. One was
- a crash if the next token after ``metadirective`` was a paren, bracket, or
- brace. The other was if the next token after the meta directive was not an
- open parenthesis. (#GH139665)
-- An error is now emitted when OpenMP ``collapse`` and ``ordered`` clauses have
- an argument larger than what can fit within a 64-bit integer.
-- Added support for private variable reduction.
-- Fixed mapping of arrays of structs containing nested structs with user defined
- mappers, by using compiler-generated default mappers for the outer structs for
- such maps.
-- Deprecation warning has been emitted for deprecated delimited form of ``declare target``.
+- Added parsing and semantic analysis support for the ``need_device_addr``
+ modifier in the ``adjust_args`` clause.
+- Allow array length to be omitted in array section subscript expression.
Improvements
^^^^^^^^^^^^
Additional Information
-
-===================
+======================
A wide variety of additional information is available on the `Clang web
page <https://clang.llvm.org/>`_. The web page contains versions of the
diff --git a/clang/docs/StandardCPlusPlusModules.rst b/clang/docs/StandardCPlusPlusModules.rst
index 933a57f..31d0a5e 100644
--- a/clang/docs/StandardCPlusPlusModules.rst
+++ b/clang/docs/StandardCPlusPlusModules.rst
@@ -687,16 +687,12 @@ fails to instantiate. For such issues, users can add references to ``N::g`` in
the `module purview <https://eel.is/c++draft/module.unit#5>`_ of ``M.cppm`` to
ensure it is reachable, e.g. ``using N::g;``.
-Support for Reduced BMIs is still experimental, but it may become the default
-in the future. The expected roadmap for Reduced BMIs as of Clang 19.x is:
-
-1. ``-fexperimental-modules-reduced-bmi`` was introduced in v19.x
-2. For v20.x, ``-fmodules-reduced-bmi`` is introduced as an equivalent non-experimental
- option. It is expected to stay opt-in for 1~2 releases, though the period depends
- on user feedback and may be extended.
-3. Finally, ``-fmodules-reduced-bmi`` will be the default. When that time
- comes, the term BMI will refer to the Reduced BMI and the Full BMI will only
- be meaningful to build systems which elect to support two-phase compilation.
+As of Clang 22.x, the Reduced BMI is enabled by default. You may still want to
+use Full BMI with ``-fno-modules-reduced-bmi`` in the following case:
+1. Your build system uses two-phase compilation but it haven't adjusted the
+implementation for reduced BMI.
+2. You meet a regression with Reduced BMI that you cannot work around. Please
+report an issue for this case.
Experimental Non-Cascading Changes
----------------------------------
diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
index 284a404..af0a874 100644
--- a/clang/docs/UsersManual.rst
+++ b/clang/docs/UsersManual.rst
@@ -319,7 +319,7 @@ output format of the diagnostics that it generates.
This option, which defaults to "none", controls whether or not Clang
prints the category associated with a diagnostic when emitting it.
- Each diagnostic may or many not have an associated category, if it
+ Each diagnostic may or may not have an associated category, if it
has one, it is listed in the diagnostic categorization field of the
diagnostic line (in the []'s).
@@ -737,7 +737,7 @@ control the crash diagnostics.
crash diagnostics files, but with lower precedence than the option.
Clang is also capable of generating preprocessed source file(s) and associated
-run script(s) even without a crash. This is specially useful when trying to
+run script(s) even without a crash. This is especially useful when trying to
generate a reproducer for warnings or errors while using modules.
.. option:: -gen-reproducer
@@ -1061,7 +1061,7 @@ In this way, the user may only need to specify a root configuration file with
Usually, config file options are placed before command-line options, regardless
of the actual operation to be performed. The exception is being made for the
-options prefixed with the ``$`` character. These will be used only when linker
+options prefixed with the ``$`` character. These will be used only when the linker
is being invoked, and added after all of the command-line specified linker
inputs. Here is some example of ``$``-prefixed options:
@@ -1222,7 +1222,7 @@ existed.
The push and pop pragmas will save and restore the full diagnostic state
of the compiler, regardless of how it was set. It should be noted that while Clang
supports the GCC pragma, Clang and GCC do not support the exact same set
-of warnings, so even when using GCC compatible #pragmas there is no
+of warnings, so even when using GCC-compatible #pragmas there is no
guarantee that they will have identical behaviour on both compilers.
Clang also doesn't yet support GCC behavior for ``#pragma diagnostic pop``
@@ -1681,7 +1681,7 @@ for more details.
* ``preserve-sign`` - the sign of a flushed-to-zero number is preserved in the sign of 0
* ``positive-zero`` - denormals are flushed to positive zero
- The default value depends on the target. For most targets, defaults to
+ The default value depends on the target. For most targets, it defaults to
``ieee``.
.. option:: -f[no-]strict-float-cast-overflow
@@ -1730,7 +1730,7 @@ for more details.
the C and C++ standards but can be enabled using ``-ffp-contract=fast``.
Fusion can be controlled with the ``FP_CONTRACT`` and ``clang fp contract``
- pragmas. Please note that pragmas will be ingored with
+ pragmas. Please note that pragmas will be ignored with
``-ffp-contract=fast``, and refer to the pragma documentation for a
description of how the pragmas interact with the different ``-ffp-contract``
option values.
@@ -1984,11 +1984,11 @@ for more details.
call to runtime library functions (generally the case, but the BE might
sometimes replace the library call if it knows enough about the potential
range of the inputs). Overflow and non-finite values are handled by the
- library implementation. For the case of multiplication overflow will occur in
+ library implementation. For the case of multiplication, overflow will occur in
accordance with normal floating-point rules. This is the default value.
* ``promoted`` Implementation of complex division using algebraic formulas at
higher precision. Overflow is handled. Non-finite values are handled in some
- cases. If the target does not have native support for a higher precision
+ cases. If the target does not have native support for a higher-precision
data type, the implementation for the complex operation using the Smith
algorithm will be used. Overflow may still occur in some cases. NaN and
infinite values are not handled.
diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 26c5028..4e8b318 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -1103,7 +1103,16 @@ To override this threshold to e.g. 4 bytes, use the
optin.portability.UnixAPI
"""""""""""""""""""""""""
-Finds implementation-defined behavior in UNIX/Posix functions.
+Reports situations where 0 is passed as the "size" argument of various
+allocation functions ( ``calloc``, ``malloc``, ``realloc``, ``reallocf``,
+``alloca``, ``__builtin_alloca``, ``__builtin_alloca_with_align``, ``valloc``).
+
+Note that similar functionality is also supported by :ref:`unix-Malloc` which
+reports code that *uses* memory allocated with size zero.
+
+(The name of this checker is motivated by the fact that it was originally
+introduced with the vague goal that it "Finds implementation-defined behavior
+in UNIX/Posix functions.")
optin.taint
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index b929585..be038d9 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -6953,7 +6953,7 @@ clang_getCursorUnaryOperatorKind(CXCursor cursor);
* @}
*/
-CINDEX_DEPRECATED
+/* CINDEX_DEPRECATED - disabled to silence MSVC deprecation warnings */
typedef void *CXRemapping;
CINDEX_DEPRECATED CINDEX_LINKAGE CXRemapping clang_getRemappings(const char *);
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety.h
index 9998702..1c00558 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety.h
@@ -17,14 +17,105 @@
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
-#include "clang/AST/DeclBase.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
-namespace clang {
+#include "llvm/ADT/ImmutableSet.h"
+#include "llvm/ADT/StringMap.h"
+#include <memory>
-void runLifetimeSafetyAnalysis(const DeclContext &DC, const CFG &Cfg,
- AnalysisDeclContext &AC);
+namespace clang::lifetimes {
-} // namespace clang
+/// The main entry point for the analysis.
+void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC);
+
+namespace internal {
+// Forward declarations of internal types.
+class Fact;
+class FactManager;
+class LoanPropagationAnalysis;
+class ExpiredLoansAnalysis;
+struct LifetimeFactory;
+
+/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
+/// Used for giving ID to loans and origins.
+template <typename Tag> struct ID {
+ uint32_t Value = 0;
+
+ bool operator==(const ID<Tag> &Other) const { return Value == Other.Value; }
+ bool operator!=(const ID<Tag> &Other) const { return !(*this == Other); }
+ bool operator<(const ID<Tag> &Other) const { return Value < Other.Value; }
+ ID<Tag> operator++(int) {
+ ID<Tag> Tmp = *this;
+ ++Value;
+ return Tmp;
+ }
+ void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
+ IDBuilder.AddInteger(Value);
+ }
+};
+template <typename Tag>
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID<Tag> ID) {
+ return OS << ID.Value;
+}
+
+using LoanID = ID<struct LoanTag>;
+using OriginID = ID<struct OriginTag>;
+
+// Using LLVM's immutable collections is efficient for dataflow analysis
+// as it avoids deep copies during state transitions.
+// TODO(opt): Consider using a bitset to represent the set of loans.
+using LoanSet = llvm::ImmutableSet<LoanID>;
+using OriginSet = llvm::ImmutableSet<OriginID>;
+
+/// A `ProgramPoint` identifies a location in the CFG by pointing to a specific
+/// `Fact`. identified by a lifetime-related event (`Fact`).
+///
+/// A `ProgramPoint` has "after" semantics: it represents the location
+/// immediately after its corresponding `Fact`.
+using ProgramPoint = const Fact *;
+
+/// Running the lifetime safety analysis and querying its results. It
+/// encapsulates the various dataflow analyses.
+class LifetimeSafetyAnalysis {
+public:
+ LifetimeSafetyAnalysis(AnalysisDeclContext &AC);
+ ~LifetimeSafetyAnalysis();
+
+ void run();
+
+ /// Returns the set of loans an origin holds at a specific program point.
+ LoanSet getLoansAtPoint(OriginID OID, ProgramPoint PP) const;
+
+ /// Returns the set of loans that have expired at a specific program point.
+ LoanSet getExpiredLoansAtPoint(ProgramPoint PP) const;
+
+ /// Finds the OriginID for a given declaration.
+ /// Returns a null optional if not found.
+ std::optional<OriginID> getOriginIDForDecl(const ValueDecl *D) const;
+
+ /// Finds the LoanID's for the loan created with the specific variable as
+ /// their Path.
+ std::vector<LoanID> getLoanIDForVar(const VarDecl *VD) const;
+
+ /// Retrieves program points that were specially marked in the source code
+ /// for testing.
+ ///
+ /// The analysis recognizes special function calls of the form
+ /// `void("__lifetime_test_point_<name>")` as test points. This method returns
+ /// a map from the annotation string (<name>) to the corresponding
+ /// `ProgramPoint`. This allows test harnesses to query the analysis state at
+ /// user-defined locations in the code.
+ /// \note This is intended for testing only.
+ llvm::StringMap<ProgramPoint> getTestPoints() const;
+
+private:
+ AnalysisDeclContext &AC;
+ std::unique_ptr<LifetimeFactory> Factory;
+ std::unique_ptr<FactManager> FactMgr;
+ std::unique_ptr<LoanPropagationAnalysis> LoanPropagation;
+ std::unique_ptr<ExpiredLoansAnalysis> ExpiredLoans;
+};
+} // namespace internal
+} // namespace clang::lifetimes
#endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 5ebb821..c81714e 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -1334,6 +1334,18 @@ def ElementwiseMinimum : Builtin {
let Prototype = "void(...)";
}
+def ElementwiseMaximumNum : Builtin {
+ let Spellings = ["__builtin_elementwise_maximumnum"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def ElementwiseMinimumNum : Builtin {
+ let Spellings = ["__builtin_elementwise_minimumnum"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
def ElementwiseCeil : Builtin {
let Spellings = ["__builtin_elementwise_ceil"];
let Attributes = [NoThrow, Const, CustomTypeChecking];
diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def b/clang/include/clang/Basic/BuiltinsAMDGPU.def
index d4fef5d..945e11b 100644
--- a/clang/include/clang/Basic/BuiltinsAMDGPU.def
+++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def
@@ -642,6 +642,16 @@ TARGET_BUILTIN(__builtin_amdgcn_cvt_sr_f16_f32, "V2hV2hfUiIb", "nc", "f32-to-f16
// GFX1250+ only builtins.
//===----------------------------------------------------------------------===//
+TARGET_BUILTIN(__builtin_amdgcn_flat_prefetch, "vvC*0Ii", "nc", "vmem-pref-insts")
+TARGET_BUILTIN(__builtin_amdgcn_global_prefetch, "vvC*1Ii", "nc", "vmem-pref-insts")
+
+TARGET_BUILTIN(__builtin_amdgcn_global_load_monitor_b32, "ii*1Ii", "nc", "gfx1250-insts")
+TARGET_BUILTIN(__builtin_amdgcn_global_load_monitor_b64, "V2iV2i*1Ii", "nc", "gfx1250-insts")
+TARGET_BUILTIN(__builtin_amdgcn_global_load_monitor_b128, "V4iV4i*1Ii", "nc", "gfx1250-insts")
+TARGET_BUILTIN(__builtin_amdgcn_flat_load_monitor_b32, "ii*0Ii", "nc", "gfx1250-insts")
+TARGET_BUILTIN(__builtin_amdgcn_flat_load_monitor_b64, "V2iV2i*0Ii", "nc", "gfx1250-insts")
+TARGET_BUILTIN(__builtin_amdgcn_flat_load_monitor_b128, "V4iV4i*0Ii", "nc", "gfx1250-insts")
+
TARGET_BUILTIN(__builtin_amdgcn_tensor_load_to_lds, "vV4iV8iV4iV4iIi", "nc", "gfx1250-insts")
TARGET_BUILTIN(__builtin_amdgcn_tensor_load_to_lds_d2, "vV4iV8iIi", "nc", "gfx1250-insts")
TARGET_BUILTIN(__builtin_amdgcn_tensor_store_from_lds, "vV4iV8iV4iV4iIi", "nc", "gfx1250-insts")
@@ -705,6 +715,7 @@ TARGET_BUILTIN(__builtin_amdgcn_wmma_f16_16x16x128_fp8_fp8, "V8hV16iV16iIsV8hIbI
TARGET_BUILTIN(__builtin_amdgcn_wmma_f16_16x16x128_fp8_bf8, "V8hV16iV16iIsV8hIbIb", "nc", "gfx1250-insts,wavefrontsize32")
TARGET_BUILTIN(__builtin_amdgcn_wmma_f16_16x16x128_bf8_fp8, "V8hV16iV16iIsV8hIbIb", "nc", "gfx1250-insts,wavefrontsize32")
TARGET_BUILTIN(__builtin_amdgcn_wmma_f16_16x16x128_bf8_bf8, "V8hV16iV16iIsV8hIbIb", "nc", "gfx1250-insts,wavefrontsize32")
+TARGET_BUILTIN(__builtin_amdgcn_wmma_f32_16x16x128_f8f6f4, "V8fIiV16iIiV16iIsV8f", "nc", "gfx1250-insts,wavefrontsize32")
TARGET_BUILTIN(__builtin_amdgcn_wmma_f32_16x16x128_fp8_fp8, "V8fV16iV16iIsV8fIbIb", "nc", "gfx1250-insts,wavefrontsize32")
TARGET_BUILTIN(__builtin_amdgcn_wmma_f32_16x16x128_fp8_bf8, "V8fV16iV16iIsV8fIbIb", "nc", "gfx1250-insts,wavefrontsize32")
TARGET_BUILTIN(__builtin_amdgcn_wmma_f32_16x16x128_bf8_fp8, "V8fV16iV16iIsV8fIbIb", "nc", "gfx1250-insts,wavefrontsize32")
diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index cfffeb7..e137738 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -313,9 +313,10 @@ CODEGENOPT(SpeculativeLoadHardening, 1, 0, Benign) ///< Enable speculative load
CODEGENOPT(FineGrainedBitfieldAccesses, 1, 0, Benign) ///< Enable fine-grained bitfield accesses.
CODEGENOPT(StrictEnums , 1, 0, Benign) ///< Optimize based on strict enum definition.
CODEGENOPT(StrictVTablePointers, 1, 0, Benign) ///< Optimize based on the strict vtable pointers
-CODEGENOPT(TimePasses , 1, 0, Benign) ///< Set when -ftime-report or -ftime-report= or -ftime-report-json is enabled.
+CODEGENOPT(TimePasses , 1, 0, Benign) ///< Set when -ftime-report, -ftime-report=, -ftime-report-json, or -stats-file-timers is enabled.
CODEGENOPT(TimePassesPerRun , 1, 0, Benign) ///< Set when -ftime-report=per-pass-run is enabled.
CODEGENOPT(TimePassesJson , 1, 0, Benign) ///< Set when -ftime-report-json is enabled.
+CODEGENOPT(TimePassesStatsFile , 1, 0, Benign) ///< Set when -stats-file-timers is enabled.
CODEGENOPT(TimeTrace , 1, 0, Benign) ///< Set when -ftime-trace is enabled.
VALUE_CODEGENOPT(TimeTraceGranularity, 32, 500, Benign) ///< Minimum time granularity (in microseconds),
///< traced by time profiler
diff --git a/clang/include/clang/Basic/Diagnostic.h b/clang/include/clang/Basic/Diagnostic.h
index c7a6276..cee5bed 100644
--- a/clang/include/clang/Basic/Diagnostic.h
+++ b/clang/include/clang/Basic/Diagnostic.h
@@ -895,7 +895,10 @@ public:
/// \param FormatString A fixed diagnostic format string that will be hashed
/// and mapped to a unique DiagID.
template <unsigned N>
- // TODO: Deprecate this once all uses are removed from Clang.
+ // FIXME: this API should almost never be used; custom diagnostics do not
+ // have an associated diagnostic group and thus cannot be controlled by users
+ // like other diagnostics. The number of times this API is used in Clang
+ // should only ever be reduced, not increased.
// [[deprecated("Use a CustomDiagDesc instead of a Level")]]
unsigned getCustomDiagID(Level L, const char (&FormatString)[N]) {
return Diags->getCustomDiagID((DiagnosticIDs::Level)L,
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 34b6c0d..759ba04 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -116,6 +116,8 @@ def err_drv_cuda_host_arch : Error<
"unsupported architecture '%0' for host compilation">;
def err_drv_mix_cuda_hip : Error<
"mixed CUDA and HIP compilation is not supported">;
+def err_drv_mix_offload : Error<
+ "mixed %0 and %1 offloading compilation is not supported">;
def err_drv_bad_target_id : Error<
"invalid target ID '%0'; format is a processor name followed by an optional "
"colon-delimited list of features followed by an enable/disable sign (e.g., "
diff --git a/clang/include/clang/Basic/DiagnosticIDs.h b/clang/include/clang/Basic/DiagnosticIDs.h
index 2b095f0..f07a003 100644
--- a/clang/include/clang/Basic/DiagnosticIDs.h
+++ b/clang/include/clang/Basic/DiagnosticIDs.h
@@ -283,7 +283,10 @@ public:
// writing, nearly all callers of this function were invalid.
unsigned getCustomDiagID(CustomDiagDesc Diag);
- // TODO: Deprecate this once all uses are removed from LLVM
+ // FIXME: this API should almost never be used; custom diagnostics do not
+ // have an associated diagnostic group and thus cannot be controlled by users
+ // like other diagnostics. The number of times this API is used in Clang
+ // should only ever be reduced, not increased.
// [[deprecated("Use a CustomDiagDesc instead of a Level")]]
unsigned getCustomDiagID(Level Level, StringRef Message) {
return getCustomDiagID([&]() -> CustomDiagDesc {
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 723f5d4..c7fe6e1d 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -694,6 +694,9 @@ def err_pragma_push_pop_macro_malformed : Error<
def warn_pragma_pop_macro_no_push : Warning<
"pragma pop_macro could not pop '%0', no matching push_macro">,
InGroup<IgnoredPragmas>;
+def warn_pargma_push_pop_macro_empty_string : Warning<
+ "'#pragma %select{push_macro|pop_macro}0' expected a non-empty string">,
+ InGroup<IgnoredPragmas>;
def warn_pragma_message : Warning<"%0">,
InGroup<PoundPragmaMessage>, DefaultWarnNoWerror;
def err_pragma_message : Error<"%0">;
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 35903af..165f015 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1594,6 +1594,9 @@ def err_omp_unknown_adjust_args_op
def err_omp_declare_variant_wrong_clause : Error<
"expected %select{'match'|'match', 'adjust_args', or 'append_args'}0 clause "
"on 'omp declare variant' directive">;
+def err_omp_non_by_ref_need_device_addr_modifier_argument
+ : Error<"expected reference type argument on 'adjust_args' clause with "
+ "'need_device_addr' modifier">;
def err_omp_declare_variant_duplicate_nested_trait : Error<
"nested OpenMP context selector contains duplicated trait '%0'"
" in selector '%1' and set '%2' with different score">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b2ea65a..4a21321 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13438,13 +13438,13 @@ def note_acc_atomic_mismatch_operand
: Note<"left hand side of assignment operation(%0) must match one side "
"of the sub-operation on the right hand side(%1 and %2)">;
def note_acc_atomic_mismatch_compound_operand
- : Note<"variable %select{|in unary expression|on right hand side of "
+ : Note<"sub-expression %select{|in unary expression|on right hand side of "
"assignment|on left hand side of assignment|on left hand side of "
"compound assignment|on left hand side of assignment}2(%3) must "
- "match variable used %select{|in unary expression|on right hand "
- "side of assignment|<not possible>|on left hand side of compound "
- "assignment|on left hand side of assignment}0(%1) from the first "
- "statement">;
+ "match sub-expression used %select{|in unary expression|on right "
+ "hand side of assignment|<not possible>|on left hand side of "
+ "compound assignment|on left hand side of assignment}0(%1) from the "
+ "first statement">;
def err_acc_declare_required_clauses
: Error<"no valid clauses specified in OpenACC 'declare' directive">;
def err_acc_declare_clause_at_global
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index 6ac8d49..08d98a7 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -491,6 +491,8 @@ LANGOPT(CheckConstexprFunctionBodies, 1, 1, Benign,
LANGOPT(BoundsSafety, 1, 0, NotCompatible, "Bounds safety extension for C")
+LANGOPT(EnableLifetimeSafety, 1, 0, NotCompatible, "Experimental lifetime safety analysis for C++")
+
LANGOPT(PreserveVec3Type, 1, 0, NotCompatible, "Preserve 3-component vector type")
#undef LANGOPT
diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h
index 698fd9d..005f261 100644
--- a/clang/include/clang/Basic/Specifiers.h
+++ b/clang/include/clang/Basic/Specifiers.h
@@ -120,7 +120,7 @@ namespace clang {
/// A C++ access specifier (public, private, protected), plus the
/// special value "none" which means different things in different contexts.
- enum AccessSpecifier {
+ enum AccessSpecifier : uint8_t {
AS_public,
AS_protected,
AS_private,
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index 8b66c73..abfbdfa 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -1551,8 +1551,8 @@ public:
// Return the target-specific priority for features/cpus/vendors so
// that they can be properly sorted for checking.
- virtual uint64_t getFMVPriority(ArrayRef<StringRef> Features) const {
- return 0;
+ virtual llvm::APInt getFMVPriority(ArrayRef<StringRef> Features) const {
+ return llvm::APInt::getZero(32);
}
// Validate the contents of the __builtin_cpu_is(const char*)
diff --git a/clang/include/clang/Basic/arm_neon.td b/clang/include/clang/Basic/arm_neon.td
index 0daef4a..ef19610 100644
--- a/clang/include/clang/Basic/arm_neon.td
+++ b/clang/include/clang/Basic/arm_neon.td
@@ -964,11 +964,11 @@ def SLI_N : WInst<"vsli_n", "...I", "PlQPl", [ImmCheck<2, ImmCheckShiftLeft, 0>]
// Right shift narrow high
def SHRN_HIGH_N : IOpInst<"vshrn_high_n", "<(<q).I",
"HsHiHlHUsHUiHUl", OP_NARROW_HI>;
-def QSHRUN_HIGH_N : SOpInst<"vqshrun_high_n", "<(<q).I",
+def QSHRUN_HIGH_N : SOpInst<"vqshrun_high_n", "(<U)(<Uq).I",
"HsHiHl", OP_NARROW_HI>;
def RSHRN_HIGH_N : IOpInst<"vrshrn_high_n", "<(<q).I",
"HsHiHlHUsHUiHUl", OP_NARROW_HI>;
-def QRSHRUN_HIGH_N : SOpInst<"vqrshrun_high_n", "<(<q).I",
+def QRSHRUN_HIGH_N : SOpInst<"vqrshrun_high_n", "(<U)(<Uq).I",
"HsHiHl", OP_NARROW_HI>;
def QSHRN_HIGH_N : SOpInst<"vqshrn_high_n", "<(<q).I",
"HsHiHlHUsHUiHUl", OP_NARROW_HI>;
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 25baf27..5c04d59 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -75,6 +75,12 @@ public:
return getConstant(loc, cir::IntAttr::get(ty, value));
}
+ mlir::Value getUnsignedInt(mlir::Location loc, uint64_t val,
+ unsigned numBits) {
+ auto type = cir::IntType::get(getContext(), numBits, /*isSigned=*/false);
+ return getConstAPInt(loc, type, llvm::APInt(numBits, val));
+ }
+
// Creates constant null value for integral type ty.
cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc) {
return getConstant(loc, getZeroInitAttr(ty));
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 01c50554..32bb900 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -128,12 +128,12 @@ def CIR_CastKind : CIR_I32EnumAttr<"CastKind", "cast kind", [
// CK_BlockPointerToObjCPointerCast
// CK_AnyPointerToBlockPointerCast
// CK_ObjCObjectLValueCast
- // I32EnumAttrCase<"float_to_complex", 44>,
- // I32EnumAttrCase<"float_complex_to_real", 45>,
- // I32EnumAttrCase<"float_complex_to_bool", 46>,
+ I32EnumAttrCase<"float_to_complex", 44>,
+ I32EnumAttrCase<"float_complex_to_real", 45>,
+ I32EnumAttrCase<"float_complex_to_bool", 46>,
I32EnumAttrCase<"float_complex", 47>,
- // I32EnumAttrCase<"float_complex_to_int_complex", 48>,
- // I32EnumAttrCase<"int_to_complex", 49>,
+ I32EnumAttrCase<"float_complex_to_int_complex", 48>,
+ I32EnumAttrCase<"int_to_complex", 49>,
I32EnumAttrCase<"int_complex_to_real", 50>,
I32EnumAttrCase<"int_complex_to_bool", 51>,
I32EnumAttrCase<"int_complex", 52>,
@@ -607,7 +607,7 @@ def CIR_ConditionOp : CIR_Op<"condition", [
//===----------------------------------------------------------------------===//
defvar CIR_YieldableScopes = [
- "CaseOp", "DoWhileOp", "ForOp", "IfOp", "ScopeOp", "SwitchOp",
+ "ArrayCtor", "CaseOp", "DoWhileOp", "ForOp", "IfOp", "ScopeOp", "SwitchOp",
"TernaryOp", "WhileOp"
];
@@ -2229,6 +2229,50 @@ def CIR_TrapOp : CIR_Op<"trap", [Terminator]> {
}
//===----------------------------------------------------------------------===//
+// ArrayCtor
+//===----------------------------------------------------------------------===//
+
+class CIR_ArrayInitDestroy<string mnemonic> : CIR_Op<mnemonic> {
+ let arguments = (ins
+ Arg<CIR_PtrToArray, "array address", [MemWrite, MemRead]>:$addr
+ );
+
+ let regions = (region SizedRegion<1>:$body);
+ let assemblyFormat = [{
+ $addr `:` qualified(type($addr)) $body attr-dict
+ }];
+
+ let builders = [
+ OpBuilder<(ins "mlir::Value":$addr,
+ "llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)>":$regionBuilder), [{
+ assert(regionBuilder && "builder callback expected");
+ mlir::OpBuilder::InsertionGuard guard($_builder);
+ mlir::Region *r = $_state.addRegion();
+ $_state.addOperands(ValueRange{addr});
+ $_builder.createBlock(r);
+ regionBuilder($_builder, $_state.location);
+ }]>
+ ];
+}
+
+def CIR_ArrayCtor : CIR_ArrayInitDestroy<"array.ctor"> {
+ let summary = "Initialize array elements with C++ constructors";
+ let description = [{
+ Initialize each array element using the same C++ constructor. This
+ operation has one region, with one single block. The block has an
+ incoming argument for the current array index to initialize.
+
+ ```mlir
+ cir.array.ctor(%0 : !cir.ptr<!cir.array<!rec_S x 42>>) {
+ ^bb0(%arg0: !cir.ptr<!rec_S>):
+ cir.call @some_ctor(%arg0) : (!cir.ptr<!rec_S>) -> ()
+ cir.yield
+ }
+ ```
+ }];
+}
+
+//===----------------------------------------------------------------------===//
// VecCreate
//===----------------------------------------------------------------------===//
@@ -3004,6 +3048,27 @@ def CIR_AssumeOp : CIR_Op<"assume"> {
}];
}
+def CIR_AssumeSepStorageOp : CIR_Op<"assume_separate_storage", [
+ SameTypeOperands
+]> {
+ let summary =
+ "Tell the optimizer that two pointers point to different allocations";
+ let description = [{
+ The `cir.assume_separate_storage` operation takes two pointers as arguments,
+ and the operation tells the optimizer that these two pointers point to
+ different allocations.
+
+ This operation corresponds to the `__builtin_assume_separate_storage`
+ builtin function.
+ }];
+
+ let arguments = (ins CIR_VoidPtrType:$ptr1, CIR_VoidPtrType:$ptr2);
+
+ let assemblyFormat = [{
+ $ptr1 `,` $ptr2 `:` qualified(type($ptr1)) attr-dict
+ }];
+}
+
//===----------------------------------------------------------------------===//
// Branch Probability Operations
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
index 2bf7758..d7d55df 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
@@ -166,6 +166,12 @@ def CIR_AnyIntOrFloatType : AnyTypeOf<[CIR_AnyFloatType, CIR_AnyIntType],
def CIR_AnyComplexType : CIR_TypeBase<"::cir::ComplexType", "complex type">;
//===----------------------------------------------------------------------===//
+// Array Type predicates
+//===----------------------------------------------------------------------===//
+
+def CIR_AnyArrayType : CIR_TypeBase<"::cir::ArrayType", "array type">;
+
+//===----------------------------------------------------------------------===//
// Pointer Type predicates
//===----------------------------------------------------------------------===//
@@ -216,6 +222,8 @@ def CIR_PtrToIntOrFloatType : CIR_PtrToType<CIR_AnyIntOrFloatType>;
def CIR_PtrToComplexType : CIR_PtrToType<CIR_AnyComplexType>;
+def CIR_PtrToArray : CIR_PtrToType<CIR_AnyArrayType>;
+
//===----------------------------------------------------------------------===//
// Vector Type predicates
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/Passes.h b/clang/include/clang/CIR/Dialect/Passes.h
index 02210ec..7a202b1 100644
--- a/clang/include/clang/CIR/Dialect/Passes.h
+++ b/clang/include/clang/CIR/Dialect/Passes.h
@@ -25,6 +25,7 @@ std::unique_ptr<Pass> createCIRFlattenCFGPass();
std::unique_ptr<Pass> createCIRSimplifyPass();
std::unique_ptr<Pass> createHoistAllocasPass();
std::unique_ptr<Pass> createLoweringPreparePass();
+std::unique_ptr<Pass> createLoweringPreparePass(clang::ASTContext *astCtx);
void populateCIRPreLoweringPasses(mlir::OpPassManager &pm);
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 182e4b6..e1a5c3d 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -196,6 +196,8 @@ struct MissingFeatures {
static bool cxxRecordStaticMembers() { return false; }
static bool dataLayoutTypeAllocSize() { return false; }
static bool deferredCXXGlobalInit() { return false; }
+ static bool ehCleanupFlags() { return false; }
+ static bool ehstackBranches() { return false; }
static bool emitCheckedInBoundsGEP() { return false; }
static bool emitCondLikelihoodViaExpectIntrinsic() { return false; }
static bool emitLifetimeMarkers() { return false; }
@@ -252,9 +254,9 @@ struct MissingFeatures {
static bool writebacks() { return false; }
static bool appleKext() { return false; }
static bool dtorCleanups() { return false; }
- static bool completeDtors() { return false; }
static bool vtableInitialization() { return false; }
static bool msvcBuiltins() { return false; }
+ static bool vlas() { return false; }
// Missing types
static bool dataMemberType() { return false; }
diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h
index d9e328f..4d32552 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -337,6 +337,10 @@ private:
/// "clang" as it's first argument.
const char *PrependArg;
+ /// The default value of -fuse-ld= option. An empty string means the default
+ /// system linker.
+ std::string PreferredLinker;
+
/// Whether to check that input files exist when constructing compilation
/// jobs.
LLVM_PREFERRED_TYPE(bool)
@@ -355,6 +359,9 @@ public:
phases::ID getFinalPhase(const llvm::opt::DerivedArgList &DAL,
llvm::opt::Arg **FinalPhaseArg = nullptr) const;
+ llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
+ executeProgram(llvm::ArrayRef<llvm::StringRef> Args) const;
+
private:
/// Certain options suppress the 'no input files' warning.
LLVM_PREFERRED_TYPE(bool)
@@ -367,10 +374,6 @@ private:
/// stored in it, and will clean them up when torn down.
mutable llvm::StringMap<std::unique_ptr<ToolChain>> ToolChains;
- /// The associated offloading architectures with each toolchain.
- llvm::DenseMap<const ToolChain *, llvm::SmallVector<llvm::StringRef>>
- OffloadArchs;
-
private:
/// TranslateInputArgs - Create a new derived argument list from the input
/// arguments, after applying the standard argument translations.
@@ -450,6 +453,11 @@ public:
return ClangExecutable.c_str();
}
+ StringRef getPreferredLinker() const { return PreferredLinker; }
+ void setPreferredLinker(std::string Value) {
+ PreferredLinker = std::move(Value);
+ }
+
bool isSaveTempsEnabled() const { return SaveTemps != SaveTempsNone; }
bool isSaveTempsObj() const { return SaveTemps == SaveTempsObj; }
@@ -537,8 +545,7 @@ public:
/// empty string.
llvm::SmallVector<StringRef>
getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,
- Action::OffloadKind Kind, const ToolChain *TC,
- bool SpecificToolchain = true) const;
+ Action::OffloadKind Kind, const ToolChain &TC) const;
/// Check that the file referenced by Value exists. If it doesn't,
/// issue a diagnostic and return false.
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 6c22f06..916400e 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1156,7 +1156,7 @@ def offload_arch_EQ : CommaJoined<["--"], "offload-arch=">,
"If 'native' is used the compiler will detect locally installed architectures. "
"For HIP offloading, the device architecture can be followed by target ID features "
"delimited by a colon (e.g. gfx908:xnack+:sramecc-). May be specified more than once.">;
-def no_offload_arch_EQ : Joined<["--"], "no-offload-arch=">,
+def no_offload_arch_EQ : CommaJoined<["--"], "no-offload-arch=">,
Visibility<[ClangOption, FlangOption]>,
HelpText<"Remove CUDA/HIP offloading device architecture (e.g. sm_35, gfx906) from the list of devices to compile for. "
"'all' resets the list to its default value.">;
@@ -1624,7 +1624,7 @@ defm auto_import : BoolFOption<"auto-import",
// In the future this option will be supported by other offloading
// languages and accept other values such as CPU/GPU architectures,
// offload kinds and target aliases.
-def offload_EQ : CommaJoined<["--"], "offload=">, Flags<[NoXarchOption]>,
+def offload_EQ : CommaJoined<["--"], "offload=">, Flags<[NoXarchOption]>, Alias<offload_targets_EQ>,
HelpText<"Specify comma-separated list of offloading target triples (CUDA and HIP only)">;
// C++ Coroutines
@@ -1904,6 +1904,14 @@ defm bounds_safety : BoolFOption<
BothFlags<[], [CC1Option],
" experimental bounds safety extension for C">>;
+defm lifetime_safety : BoolFOption<
+ "experimental-lifetime-safety",
+ LangOpts<"EnableLifetimeSafety">, DefaultFalse,
+ PosFlag<SetTrue, [], [CC1Option], "Enable">,
+ NegFlag<SetFalse, [], [CC1Option], "Disable">,
+ BothFlags<[], [CC1Option],
+ " experimental lifetime safety for C++">>;
+
defm addrsig : BoolFOption<"addrsig",
CodeGenOpts<"Addrsig">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Emit">,
@@ -3257,13 +3265,14 @@ defm skip_odr_check_in_gmf : BoolOption<"f", "skip-odr-check-in-gmf",
"Perform ODR checks for decls in the global module fragment.">>,
Group<f_Group>;
-def modules_reduced_bmi : Flag<["-"], "fmodules-reduced-bmi">,
- Group<f_Group>, Visibility<[ClangOption, CC1Option]>,
- HelpText<"Generate the reduced BMI">,
- MarshallingInfoFlag<FrontendOpts<"GenReducedBMI">>;
+defm modules_reduced_bmi : BoolOption<"f", "modules-reduced-bmi",
+ FrontendOpts<"GenReducedBMI">, DefaultFalse,
+ NegFlag<SetFalse>,
+ PosFlag<SetTrue, [], [ClangOption, CC1Option],
+ "Generate the reduced BMI">>;
def experimental_modules_reduced_bmi : Flag<["-"], "fexperimental-modules-reduced-bmi">,
- Group<f_Group>, Visibility<[ClangOption, CC1Option]>, Alias<modules_reduced_bmi>;
+ Group<f_Group>, Visibility<[ClangOption, CC1Option]>, Alias<fmodules_reduced_bmi>;
def fmodules_embed_all_files : Joined<["-"], "fmodules-embed-all-files">,
Visibility<[ClangOption, CC1Option, CLOption]>,
@@ -7129,6 +7138,8 @@ def fintrinsic_modules_path : Separate<["-"], "fintrinsic-modules-path">, Group
HelpText<"Specify where to find the compiled intrinsic modules">,
DocBrief<[{This option specifies the location of pre-compiled intrinsic modules,
if they are not in the default location expected by the compiler.}]>;
+def fintrinsic_modules_path_EQ : Joined<["-"], "fintrinsic-modules-path=">,
+ Group<f_Group>, Alias<fintrinsic_modules_path>;
defm backslash : OptInFC1FFlag<"backslash", "Specify that backslash in string introduces an escape character">;
defm xor_operator : OptInFC1FFlag<"xor-operator", "Enable .XOR. as a synonym of .NEQV.">;
@@ -8250,6 +8261,9 @@ def stats_file : Joined<["-"], "stats-file=">,
def stats_file_append : Flag<["-"], "stats-file-append">,
HelpText<"If stats should be appended to stats-file instead of overwriting it">,
MarshallingInfoFlag<FrontendOpts<"AppendStats">>;
+def stats_file_timers : Flag<["-"], "stats-file-timers">,
+ HelpText<"If stats should include timers.">,
+ MarshallingInfoFlag<CodeGenOpts<"TimePassesStatsFile">>;
def fdump_record_layouts_simple : Flag<["-"], "fdump-record-layouts-simple">,
HelpText<"Dump record layout information in a simple form used for testing">,
MarshallingInfoFlag<LangOpts<"DumpRecordLayoutsSimple">>;
diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h
index b8899e7..2430563 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -202,10 +202,6 @@ protected:
ToolChain(const Driver &D, const llvm::Triple &T,
const llvm::opt::ArgList &Args);
- /// Executes the given \p Executable and returns the stdout.
- llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
- executeToolChainProgram(StringRef Executable) const;
-
void setTripleEnvironment(llvm::Triple::EnvironmentType Env);
virtual Tool *buildAssembler() const;
@@ -806,7 +802,8 @@ public:
/// Get paths for device libraries.
virtual llvm::SmallVector<BitCodeLibraryInfo, 12>
- getDeviceLibs(const llvm::opt::ArgList &Args) const;
+ getDeviceLibs(const llvm::opt::ArgList &Args,
+ const Action::OffloadKind DeviceOffloadingKind) const;
/// Add the system specific linker arguments to use
/// for the given HIP runtime library type.
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 7677604..a54ab19 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -4704,6 +4704,13 @@ struct FormatStyle {
/// <conditional-body> <conditional-body>
/// \endcode
bool AfterIfMacros;
+ /// If ``true``, put a space between alternative operator ``not`` and the
+ /// opening parenthesis.
+ /// \code
+ /// true: false:
+ /// return not (a || b); vs. return not(a || b);
+ /// \endcode
+ bool AfterNot;
/// If ``true``, put a space between operator overloading and opening
/// parentheses.
/// \code
@@ -4752,9 +4759,9 @@ struct FormatStyle {
: AfterControlStatements(false), AfterForeachMacros(false),
AfterFunctionDeclarationName(false),
AfterFunctionDefinitionName(false), AfterIfMacros(false),
- AfterOverloadedOperator(false), AfterPlacementOperator(true),
- AfterRequiresInClause(false), AfterRequiresInExpression(false),
- BeforeNonEmptyParentheses(false) {}
+ AfterNot(false), AfterOverloadedOperator(false),
+ AfterPlacementOperator(true), AfterRequiresInClause(false),
+ AfterRequiresInExpression(false), BeforeNonEmptyParentheses(false) {}
bool operator==(const SpaceBeforeParensCustom &Other) const {
return AfterControlStatements == Other.AfterControlStatements &&
@@ -4763,6 +4770,7 @@ struct FormatStyle {
Other.AfterFunctionDeclarationName &&
AfterFunctionDefinitionName == Other.AfterFunctionDefinitionName &&
AfterIfMacros == Other.AfterIfMacros &&
+ AfterNot == Other.AfterNot &&
AfterOverloadedOperator == Other.AfterOverloadedOperator &&
AfterPlacementOperator == Other.AfterPlacementOperator &&
AfterRequiresInClause == Other.AfterRequiresInClause &&
diff --git a/clang/include/clang/Lex/DependencyDirectivesScanner.h b/clang/include/clang/Lex/DependencyDirectivesScanner.h
index acdc9e2..f9fec39 100644
--- a/clang/include/clang/Lex/DependencyDirectivesScanner.h
+++ b/clang/include/clang/Lex/DependencyDirectivesScanner.h
@@ -47,11 +47,10 @@ struct Token {
bool is(tok::TokenKind K) const { return Kind == K; }
bool isNot(tok::TokenKind K) const { return Kind != K; }
- bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const {
- return is(K1) || is(K2);
- }
- template <typename... Ts> bool isOneOf(tok::TokenKind K1, Ts... Ks) const {
- return is(K1) || isOneOf(Ks...);
+ template <typename... Ts> bool isOneOf(Ts... Ks) const {
+ static_assert(sizeof...(Ts) > 0,
+ "requires at least one tok::TokenKind specified");
+ return (is(Ks) || ...);
}
};
diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h
index ad66a26..a49bdfd 100644
--- a/clang/include/clang/Parse/ParseHLSLRootSignature.h
+++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h
@@ -30,7 +30,6 @@ namespace hlsl {
class RootSignatureParser {
public:
RootSignatureParser(llvm::dxbc::RootSignatureVersion Version,
- SmallVector<RootSignatureElement> &Elements,
StringLiteral *Signature, Preprocessor &PP);
/// Consumes tokens from the Lexer and constructs the in-memory
@@ -40,6 +39,9 @@ public:
/// Returns true if a parsing error is encountered.
bool parse();
+ /// Return all elements that have been parsed.
+ ArrayRef<RootSignatureElement> getElements() { return Elements; }
+
private:
DiagnosticsEngine &getDiags() { return PP.getDiagnostics(); }
@@ -226,7 +228,7 @@ private:
private:
llvm::dxbc::RootSignatureVersion Version;
- SmallVector<RootSignatureElement> &Elements;
+ SmallVector<RootSignatureElement> Elements;
StringLiteral *Signature;
RootSignatureLexer Lexer;
Preprocessor &PP;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index b331acb..73eb730 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -834,6 +834,13 @@ enum class CCEKind {
///< message.
};
+/// Enums for the diagnostics of target, target_version and target_clones.
+namespace DiagAttrParams {
+enum DiagType { Unsupported, Duplicate, Unknown };
+enum Specifier { None, CPU, Tune };
+enum AttrName { Target, TargetClones, TargetVersion };
+} // end namespace DiagAttrParams
+
void inferNoReturnAttr(Sema &S, const Decl *D);
/// Sema - This implements semantic analysis and AST building for C.
@@ -4922,13 +4929,6 @@ public:
// handled later in the process, once we know how many exist.
bool checkTargetAttr(SourceLocation LiteralLoc, StringRef Str);
- /// Check Target Version attrs
- bool checkTargetVersionAttr(SourceLocation Loc, Decl *D, StringRef Str);
- bool checkTargetClonesAttrString(
- SourceLocation LiteralLoc, StringRef Str, const StringLiteral *Literal,
- Decl *D, bool &HasDefault, bool &HasCommas, bool &HasNotDefault,
- SmallVectorImpl<SmallString<64>> &StringsBuffer);
-
ErrorAttr *mergeErrorAttr(Decl *D, const AttributeCommonInfo &CI,
StringRef NewUserDiagnostic);
FormatAttr *mergeFormatAttr(Decl *D, const AttributeCommonInfo &CI,
diff --git a/clang/include/clang/Sema/SemaARM.h b/clang/include/clang/Sema/SemaARM.h
index 788a7ab..e77d65f 100644
--- a/clang/include/clang/Sema/SemaARM.h
+++ b/clang/include/clang/Sema/SemaARM.h
@@ -91,6 +91,11 @@ public:
/// Return true if the given vector types are lax-compatible SVE vector types,
/// false otherwise.
bool areLaxCompatibleSveTypes(QualType FirstType, QualType SecondType);
+
+ bool checkTargetVersionAttr(const StringRef Str, const SourceLocation Loc);
+ bool checkTargetClonesAttr(SmallVectorImpl<StringRef> &Params,
+ SmallVectorImpl<SourceLocation> &Locs,
+ SmallVectorImpl<SmallString<64>> &NewParams);
};
SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD);
diff --git a/clang/include/clang/Sema/SemaRISCV.h b/clang/include/clang/Sema/SemaRISCV.h
index 8d2e1c6..844cc3c 100644
--- a/clang/include/clang/Sema/SemaRISCV.h
+++ b/clang/include/clang/Sema/SemaRISCV.h
@@ -55,6 +55,11 @@ public:
bool DeclareAndesVectorBuiltins = false;
std::unique_ptr<sema::RISCVIntrinsicManager> IntrinsicManager;
+
+ bool checkTargetVersionAttr(const StringRef Param, const SourceLocation Loc);
+ bool checkTargetClonesAttr(SmallVectorImpl<StringRef> &Params,
+ SmallVectorImpl<SourceLocation> &Locs,
+ SmallVectorImpl<SmallString<64>> &NewParams);
};
std::unique_ptr<sema::RISCVIntrinsicManager>
diff --git a/clang/include/clang/Sema/SemaX86.h b/clang/include/clang/Sema/SemaX86.h
index b5a23f1..20783e3 100644
--- a/clang/include/clang/Sema/SemaX86.h
+++ b/clang/include/clang/Sema/SemaX86.h
@@ -37,6 +37,10 @@ public:
void handleAnyInterruptAttr(Decl *D, const ParsedAttr &AL);
void handleForceAlignArgPointerAttr(Decl *D, const ParsedAttr &AL);
+
+ bool checkTargetClonesAttr(SmallVectorImpl<StringRef> &Params,
+ SmallVectorImpl<SourceLocation> &Locs,
+ SmallVectorImpl<SmallString<64>> &NewParams);
};
} // namespace clang
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 2234143..38584c9 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -1656,8 +1656,8 @@ def CloneChecker : Checker<"CloneChecker">,
let ParentPackage = PortabilityOptIn in {
def UnixAPIPortabilityChecker : Checker<"UnixAPI">,
- HelpText<"Finds implementation-defined behavior in UNIX/Posix functions">,
- Documentation<NotDocumented>;
+ HelpText<"Finds dynamic memory allocation with size zero">,
+ Documentation<HasDocumentation>;
} // end optin.portability
diff --git a/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h b/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
index 43dbfb1..da3efd7 100644
--- a/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
+++ b/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
@@ -38,29 +38,29 @@
// function clang_registerCheckers. For example:
//
// extern "C"
-// void clang_registerCheckers (CheckerRegistry &registry) {
-// registry.addChecker<MainCallChecker>("example.MainCallChecker",
-// "Disallows calls to functions called main");
+// void clang_registerCheckers(CheckerRegistry &Registry) {
+// Registry.addChecker<MainCallChecker>(
+// "example.MainCallChecker",
+// "Disallows calls to functions called main");
// }
//
-// The first method argument is the full name of the checker, including its
-// enclosing package. By convention, the registered name of a checker is the
-// name of the associated class (the template argument).
-// The second method argument is a short human-readable description of the
-// checker.
+// The first argument of this templated method is the full name of the checker
+// (including its package), while the second argument is a short description
+// that is printed by `-analyzer-checker-help`.
//
-// The clang_registerCheckers function may add any number of checkers to the
-// registry. If any checkers require additional initialization, use the three-
-// argument form of CheckerRegistry::addChecker.
+// A plugin may register several separate checkers by calling `addChecker()`
+// multiple times. If a checker requires custom registration functions (e.g.
+// checker option handling) use the non-templated overload of `addChecker` that
+// takes two callback functions as the first two parameters.
//
// To load a checker plugin, specify the full path to the dynamic library as
// the argument to the -load option in the cc1 frontend. You can then enable
// your custom checker using the -analyzer-checker:
//
-// clang -cc1 -load </path/to/plugin.dylib> -analyze
-// -analyzer-checker=<example.MainCallChecker>
+// clang -cc1 -load /path/to/plugin.dylib -analyze
+// -analyzer-checker=example.MainCallChecker
//
-// For a complete working example, see examples/analyzer-plugin.
+// For complete examples, see clang/lib/Analysis/plugins/SampleAnalyzer
#ifndef CLANG_ANALYZER_API_VERSION_STRING
// FIXME: The Clang version string is not particularly granular;
@@ -108,30 +108,25 @@ private:
mgr.template registerChecker<T>();
}
- template <typename T> static bool returnTrue(const CheckerManager &mgr) {
- return true;
- }
+ static bool returnTrue(const CheckerManager &) { return true; }
public:
- /// Adds a checker to the registry. Use this non-templated overload when your
- /// checker requires custom initialization.
- void addChecker(RegisterCheckerFn Fn, ShouldRegisterFunction sfn,
- StringRef FullName, StringRef Desc, StringRef DocsUri,
- bool IsHidden);
-
- /// Adds a checker to the registry. Use this templated overload when your
- /// checker does not require any custom initialization.
- /// This function isn't really needed and probably causes more headaches than
- /// the tiny convenience that it provides, but external plugins might use it,
- /// and there isn't a strong incentive to remove it.
+ /// Adds a checker to the registry.
+ /// Use this for a checker defined in a plugin if it requires custom
+ /// registration functions (e.g. for handling checker options).
+ /// NOTE: As of now `DocsUri` is never queried from the checker registry.
+ void addChecker(RegisterCheckerFn Fn, ShouldRegisterFunction Sfn,
+ StringRef FullName, StringRef Desc,
+ StringRef DocsUri = "NoDocsUri", bool IsHidden = false);
+
+ /// Adds a checker to the registry.
+ /// Use this for a checker defined in a plugin if it doesn't require custom
+ /// registration functions.
template <class T>
- void addChecker(StringRef FullName, StringRef Desc, StringRef DocsUri,
- bool IsHidden = false) {
- // Avoid MSVC's Compiler Error C2276:
- // http://msdn.microsoft.com/en-us/library/850cstw1(v=VS.80).aspx
+ void addChecker(StringRef FullName, StringRef Desc,
+ StringRef DocsUri = "NoDocsUri", bool IsHidden = false) {
addChecker(&CheckerRegistry::initializeManager<CheckerManager, T>,
- &CheckerRegistry::returnTrue<T>, FullName, Desc, DocsUri,
- IsHidden);
+ &CheckerRegistry::returnTrue, FullName, Desc, DocsUri, IsHidden);
}
/// Makes the checker with the full name \p fullName depend on the checker
diff --git a/clang/include/clang/Tooling/Inclusions/IncludeStyle.h b/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
index fba90d8..bf06061 100644
--- a/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
+++ b/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
@@ -126,8 +126,8 @@ struct IncludeStyle {
/// * ``""`` means "arbitrary suffix"
/// * ``"$"`` means "no suffix"
///
- /// For example, if configured to ``"(_test)?$"``, then a header a.h would be seen
- /// as the "main" include in both a.cc and a_test.cc.
+ /// For example, if configured to ``"(_test)?$"``, then a header a.h would be
+ /// seen as the "main" include in both a.cc and a_test.cc.
/// \version 3.9
std::string IncludeIsMainRegex;
diff --git a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
index 965e235..3288585 100644
--- a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
+++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp
@@ -62,7 +62,7 @@ void ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl,
(Func->hasThisPointer() && !Func->isThisPointerExplicit());
for (auto ParamOffset : llvm::drop_begin(Func->ParamOffsets, Drop)) {
const ParmVarDecl *PD = FuncDecl->parameters()[ParamIndex];
- std::optional<PrimType> T = Ctx.classify(PD->getType());
+ OptPrimType T = Ctx.classify(PD->getType());
this->Params.insert({PD, {ParamOffset, T != std::nullopt}});
++ParamIndex;
}
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 952a43a..63ac536 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -25,34 +25,6 @@ using APSInt = llvm::APSInt;
namespace clang {
namespace interp {
-static bool refersToUnion(const Expr *E) {
- for (;;) {
- if (const auto *ME = dyn_cast<MemberExpr>(E)) {
- if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
- FD && FD->getParent()->isUnion())
- return true;
- E = ME->getBase();
- continue;
- }
-
- if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
- E = ASE->getBase()->IgnoreImplicit();
- continue;
- }
-
- if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E);
- ICE && (ICE->getCastKind() == CK_NoOp ||
- ICE->getCastKind() == CK_DerivedToBase ||
- ICE->getCastKind() == CK_UncheckedDerivedToBase)) {
- E = ICE->getSubExpr();
- continue;
- }
-
- break;
- }
- return false;
-}
-
static std::optional<bool> getBoolValue(const Expr *E) {
if (const auto *CE = dyn_cast_if_present<ConstantExpr>(E);
CE && CE->hasAPValueResult() &&
@@ -237,7 +209,7 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
if (SubExpr->getType().isVolatileQualified())
return this->emitInvalidCast(CastKind::Volatile, /*Fatal=*/true, CE);
- std::optional<PrimType> SubExprT = classify(SubExpr->getType());
+ OptPrimType SubExprT = classify(SubExpr->getType());
// Prepare storage for the result.
if (!Initializing && !SubExprT) {
std::optional<unsigned> LocalIndex = allocateLocal(SubExpr);
@@ -388,7 +360,7 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
const Descriptor *Desc = nullptr;
const QualType PointeeType = CE->getType()->getPointeeType();
if (!PointeeType.isNull()) {
- if (std::optional<PrimType> T = classify(PointeeType))
+ if (OptPrimType T = classify(PointeeType))
Desc = P.createDescriptor(SubExpr, *T);
else
Desc = P.createDescriptor(SubExpr, PointeeType.getTypePtr(),
@@ -436,7 +408,7 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
PrimType T = classifyPrim(IntType);
QualType PtrType = CE->getType();
const Descriptor *Desc;
- if (std::optional<PrimType> T = classify(PtrType->getPointeeType()))
+ if (OptPrimType T = classify(PtrType->getPointeeType()))
Desc = P.createDescriptor(SubExpr, *T);
else if (PtrType->getPointeeType()->isVoidType())
Desc = nullptr;
@@ -473,12 +445,12 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true, CE);
}
QualType SubExprTy = SubExpr->getType();
- std::optional<PrimType> FromT = classify(SubExprTy);
+ OptPrimType FromT = classify(SubExprTy);
// Casts from integer/vector to vector.
if (CE->getType()->isVectorType())
return this->emitBuiltinBitCast(CE);
- std::optional<PrimType> ToT = classify(CE->getType());
+ OptPrimType ToT = classify(CE->getType());
if (!FromT || !ToT)
return false;
@@ -504,7 +476,7 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
case CK_IntegralToBoolean:
case CK_FixedPointToBoolean: {
// HLSL uses this to cast to one-element vectors.
- std::optional<PrimType> FromT = classify(SubExpr->getType());
+ OptPrimType FromT = classify(SubExpr->getType());
if (!FromT)
return false;
@@ -517,8 +489,8 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
case CK_BooleanToSignedIntegral:
case CK_IntegralCast: {
- std::optional<PrimType> FromT = classify(SubExpr->getType());
- std::optional<PrimType> ToT = classify(CE->getType());
+ OptPrimType FromT = classify(SubExpr->getType());
+ OptPrimType ToT = classify(CE->getType());
if (!FromT || !ToT)
return false;
@@ -688,7 +660,7 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
case CK_HLSLVectorTruncation: {
assert(SubExpr->getType()->isVectorType());
- if (std::optional<PrimType> ResultT = classify(CE)) {
+ if (OptPrimType ResultT = classify(CE)) {
assert(!DiscardResult);
// Result must be either a float or integer. Take the first element.
if (!this->visit(SubExpr))
@@ -872,9 +844,9 @@ bool Compiler<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
}
// Typecheck the args.
- std::optional<PrimType> LT = classify(LHS);
- std::optional<PrimType> RT = classify(RHS);
- std::optional<PrimType> T = classify(BO->getType());
+ OptPrimType LT = classify(LHS);
+ OptPrimType RT = classify(RHS);
+ OptPrimType T = classify(BO->getType());
// Special case for C++'s three-way/spaceship operator <=>, which
// returns a std::{strong,weak,partial}_ordering (which is a class, so doesn't
@@ -995,8 +967,8 @@ bool Compiler<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) {
(!LHS->getType()->isPointerType() && !RHS->getType()->isPointerType()))
return false;
- std::optional<PrimType> LT = classify(LHS);
- std::optional<PrimType> RT = classify(RHS);
+ OptPrimType LT = classify(LHS);
+ OptPrimType RT = classify(RHS);
if (!LT || !RT)
return false;
@@ -1068,7 +1040,7 @@ bool Compiler<Emitter>::VisitLogicalBinOp(const BinaryOperator *E) {
BinaryOperatorKind Op = E->getOpcode();
const Expr *LHS = E->getLHS();
const Expr *RHS = E->getRHS();
- std::optional<PrimType> T = classify(E->getType());
+ OptPrimType T = classify(E->getType());
if (Op == BO_LOr) {
// Logical OR. Visit LHS and only evaluate RHS if LHS was FALSE.
@@ -1648,7 +1620,7 @@ bool Compiler<Emitter>::VisitImplicitValueInitExpr(
const ImplicitValueInitExpr *E) {
QualType QT = E->getType();
- if (std::optional<PrimType> T = classify(QT))
+ if (OptPrimType T = classify(QT))
return this->visitZeroInitializer(*T, QT, E);
if (QT->isRecordType()) {
@@ -1734,7 +1706,7 @@ bool Compiler<Emitter>::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
if (!Success)
return false;
- std::optional<PrimType> IndexT = classify(Index->getType());
+ OptPrimType IndexT = classify(Index->getType());
// In error-recovery cases, the index expression has a dependent type.
if (!IndexT)
return this->emitError(E);
@@ -1776,7 +1748,7 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
}
// Primitive values.
- if (std::optional<PrimType> T = classify(QT)) {
+ if (OptPrimType T = classify(QT)) {
assert(!DiscardResult);
if (Inits.size() == 0)
return this->visitZeroInitializer(*T, QT, E);
@@ -1840,7 +1812,7 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
FToInit = cast<CXXParenListInitExpr>(E)->getInitializedFieldInUnion();
const Record::Field *FieldToInit = R->getField(FToInit);
- if (std::optional<PrimType> T = classify(Init)) {
+ if (OptPrimType T = classify(Init)) {
if (!initPrimitiveField(FieldToInit, Init, *T, /*Activate=*/true))
return false;
} else {
@@ -1859,7 +1831,7 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
R->getField(InitIndex)->isUnnamedBitField())
++InitIndex;
- if (std::optional<PrimType> T = classify(Init)) {
+ if (OptPrimType T = classify(Init)) {
const Record::Field *FieldToInit = R->getField(InitIndex);
if (!initPrimitiveField(FieldToInit, Init, *T))
return false;
@@ -1899,7 +1871,7 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
if (!this->emitCheckArraySize(NumElems, E))
return false;
- std::optional<PrimType> InitT = classify(CAT->getElementType());
+ OptPrimType InitT = classify(CAT->getElementType());
unsigned ElementIndex = 0;
for (const Expr *Init : Inits) {
if (const auto *EmbedS =
@@ -2013,7 +1985,7 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
/// this.
template <class Emitter>
bool Compiler<Emitter>::visitArrayElemInit(unsigned ElemIndex, const Expr *Init,
- std::optional<PrimType> InitT) {
+ OptPrimType InitT) {
if (InitT) {
// Visit the primitive element like normal.
if (!this->visit(Init))
@@ -2042,7 +2014,7 @@ bool Compiler<Emitter>::visitCallArgs(ArrayRef<const Expr *> Args,
unsigned ArgIndex = 0;
for (const Expr *Arg : Args) {
- if (std::optional<PrimType> T = classify(Arg)) {
+ if (OptPrimType T = classify(Arg)) {
if (!this->visit(Arg))
return false;
} else {
@@ -2097,7 +2069,7 @@ bool Compiler<Emitter>::VisitSubstNonTypeTemplateParmExpr(
template <class Emitter>
bool Compiler<Emitter>::VisitConstantExpr(const ConstantExpr *E) {
- std::optional<PrimType> T = classify(E->getType());
+ OptPrimType T = classify(E->getType());
if (T && E->hasAPValueResult()) {
// Try to emit the APValue directly, without visiting the subexpr.
// This will only fail if we can't emit the APValue, so won't emit any
@@ -2292,7 +2264,7 @@ bool Compiler<Emitter>::VisitMemberExpr(const MemberExpr *E) {
const auto maybeLoadValue = [&]() -> bool {
if (E->isGLValue())
return true;
- if (std::optional<PrimType> T = classify(E))
+ if (OptPrimType T = classify(E))
return this->emitLoadPop(*T, E);
return false;
};
@@ -2357,7 +2329,7 @@ bool Compiler<Emitter>::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) {
// Investigate compiling this to a loop.
const Expr *SubExpr = E->getSubExpr();
size_t Size = E->getArraySize().getZExtValue();
- std::optional<PrimType> SubExprT = classify(SubExpr);
+ OptPrimType SubExprT = classify(SubExpr);
// So, every iteration, we execute an assignment here
// where the LHS is on the stack (the target array)
@@ -2589,8 +2561,8 @@ bool Compiler<Emitter>::VisitFloatCompoundAssignOperator(
QualType LHSType = LHS->getType();
QualType LHSComputationType = E->getComputationLHSType();
QualType ResultType = E->getComputationResultType();
- std::optional<PrimType> LT = classify(LHSComputationType);
- std::optional<PrimType> RT = classify(ResultType);
+ OptPrimType LT = classify(LHSComputationType);
+ OptPrimType RT = classify(ResultType);
assert(ResultType->isFloatingType());
@@ -2659,8 +2631,8 @@ bool Compiler<Emitter>::VisitPointerCompoundAssignOperator(
BinaryOperatorKind Op = E->getOpcode();
const Expr *LHS = E->getLHS();
const Expr *RHS = E->getRHS();
- std::optional<PrimType> LT = classify(LHS->getType());
- std::optional<PrimType> RT = classify(RHS->getType());
+ OptPrimType LT = classify(LHS->getType());
+ OptPrimType RT = classify(RHS->getType());
if (Op != BO_AddAssign && Op != BO_SubAssign)
return false;
@@ -2698,11 +2670,10 @@ bool Compiler<Emitter>::VisitCompoundAssignOperator(
const Expr *LHS = E->getLHS();
const Expr *RHS = E->getRHS();
- std::optional<PrimType> LHSComputationT =
- classify(E->getComputationLHSType());
- std::optional<PrimType> LT = classify(LHS->getType());
- std::optional<PrimType> RT = classify(RHS->getType());
- std::optional<PrimType> ResultT = classify(E->getType());
+ OptPrimType LHSComputationT = classify(E->getComputationLHSType());
+ OptPrimType LT = classify(LHS->getType());
+ OptPrimType RT = classify(RHS->getType());
+ OptPrimType ResultT = classify(E->getType());
if (!Ctx.getLangOpts().CPlusPlus14)
return this->visit(RHS) && this->visit(LHS) && this->emitError(E);
@@ -2837,7 +2808,7 @@ bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(
// When we're initializing a global variable *or* the storage duration of
// the temporary is explicitly static, create a global variable.
- std::optional<PrimType> SubExprT = classify(SubExpr);
+ OptPrimType SubExprT = classify(SubExpr);
bool IsStatic = E->getStorageDuration() == SD_Static;
if (IsStatic) {
std::optional<unsigned> GlobalIndex = P.createGlobal(E);
@@ -2931,7 +2902,7 @@ bool Compiler<Emitter>::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
return this->visitInitializer(Init) && this->emitFinishInit(E);
}
- std::optional<PrimType> T = classify(E->getType());
+ OptPrimType T = classify(E->getType());
if (E->isFileScope()) {
// Avoid creating a variable if this is a primitive RValue anyway.
if (T && !E->isLValue())
@@ -3014,7 +2985,7 @@ bool Compiler<Emitter>::VisitLambdaExpr(const LambdaExpr *E) {
continue;
++CaptureInitIt;
- if (std::optional<PrimType> T = classify(Init)) {
+ if (OptPrimType T = classify(Init)) {
if (!this->visit(Init))
return false;
@@ -3061,21 +3032,21 @@ bool Compiler<Emitter>::VisitCXXReinterpretCastExpr(
const CXXReinterpretCastExpr *E) {
const Expr *SubExpr = E->getSubExpr();
- std::optional<PrimType> FromT = classify(SubExpr);
- std::optional<PrimType> ToT = classify(E);
+ OptPrimType FromT = classify(SubExpr);
+ OptPrimType ToT = classify(E);
if (!FromT || !ToT)
return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true, E);
if (FromT == PT_Ptr || ToT == PT_Ptr) {
// Both types could be PT_Ptr because their expressions are glvalues.
- std::optional<PrimType> PointeeFromT;
+ OptPrimType PointeeFromT;
if (SubExpr->getType()->isPointerOrReferenceType())
PointeeFromT = classify(SubExpr->getType()->getPointeeType());
else
PointeeFromT = classify(SubExpr->getType());
- std::optional<PrimType> PointeeToT;
+ OptPrimType PointeeToT;
if (E->getType()->isPointerOrReferenceType())
PointeeToT = classify(E->getType()->getPointeeType());
else
@@ -3344,7 +3315,7 @@ bool Compiler<Emitter>::VisitCXXScalarValueInitExpr(
if (DiscardResult || Ty->isVoidType())
return true;
- if (std::optional<PrimType> T = classify(Ty))
+ if (OptPrimType T = classify(Ty))
return this->visitZeroInitializer(*T, Ty, E);
if (const auto *CT = Ty->getAs<ComplexType>()) {
@@ -3457,7 +3428,7 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
assert(classifyPrim(E->getType()) == PT_Ptr);
const Expr *Init = E->getInitializer();
QualType ElementType = E->getAllocatedType();
- std::optional<PrimType> ElemT = classify(ElementType);
+ OptPrimType ElemT = classify(ElementType);
unsigned PlacementArgs = E->getNumPlacementArgs();
const FunctionDecl *OperatorNew = E->getOperatorNew();
const Expr *PlacementDest = nullptr;
@@ -3645,7 +3616,7 @@ bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
if (!this->emitStorePop(InitT, E))
return false;
} else if (DynamicInit) {
- if (std::optional<PrimType> InitT = classify(DynamicInit)) {
+ if (OptPrimType InitT = classify(DynamicInit)) {
if (!this->visit(DynamicInit))
return false;
if (!this->emitStorePop(*InitT, E))
@@ -4154,7 +4125,7 @@ bool Compiler<Emitter>::visitInitializer(const Expr *E) {
}
template <class Emitter> bool Compiler<Emitter>::visitBool(const Expr *E) {
- std::optional<PrimType> T = classify(E->getType());
+ OptPrimType T = classify(E->getType());
if (!T) {
// Convert complex values to bool.
if (E->getType()->isAnyComplexType()) {
@@ -4309,7 +4280,7 @@ bool Compiler<Emitter>::visitZeroArrayInitializer(QualType T, const Expr *E) {
QualType ElemType = AT->getElementType();
size_t NumElems = cast<ConstantArrayType>(AT)->getZExtSize();
- if (std::optional<PrimType> ElemT = classify(ElemType)) {
+ if (OptPrimType ElemT = classify(ElemType)) {
for (size_t I = 0; I != NumElems; ++I) {
if (!this->visitZeroInitializer(*ElemT, ElemType, E))
return false;
@@ -4602,7 +4573,7 @@ bool Compiler<Emitter>::visitExpr(const Expr *E, bool DestroyToplevelScope) {
}
// Expressions with a primitive return type.
- if (std::optional<PrimType> T = classify(E)) {
+ if (OptPrimType T = classify(E)) {
if (!visit(E))
return false;
@@ -4679,7 +4650,7 @@ bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl *VD,
if (!this->visitVarDecl(VD, /*Toplevel=*/true))
return false;
- std::optional<PrimType> VarT = classify(VD->getType());
+ OptPrimType VarT = classify(VD->getType());
if (Context::shouldBeGloballyIndexed(VD)) {
auto GlobalIndex = P.getGlobal(VD);
assert(GlobalIndex); // visitVarDecl() didn't return false.
@@ -4736,7 +4707,7 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,
return VarCreationState::NotCreated();
const Expr *Init = VD->getInit();
- std::optional<PrimType> VarT = classify(VD->getType());
+ OptPrimType VarT = classify(VD->getType());
if (Init && Init->isValueDependent())
return false;
@@ -4868,7 +4839,7 @@ bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val,
const Record::Field *RF = R->getField(I);
QualType FieldType = RF->Decl->getType();
- if (std::optional<PrimType> PT = classify(FieldType)) {
+ if (OptPrimType PT = classify(FieldType)) {
if (!this->visitAPValue(F, *PT, E))
return false;
if (!this->emitInitField(*PT, RF->Offset, E))
@@ -4898,7 +4869,7 @@ bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val,
QualType ElemType = ArrType->getElementType();
for (unsigned A = 0, AN = Val.getArraySize(); A != AN; ++A) {
const APValue &Elem = Val.getArrayInitializedElt(A);
- if (std::optional<PrimType> ElemT = classify(ElemType)) {
+ if (OptPrimType ElemT = classify(ElemType)) {
if (!this->visitAPValue(Elem, *ElemT, E))
return false;
if (!this->emitInitElem(*ElemT, A, E))
@@ -4958,7 +4929,7 @@ bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E,
}
QualType ReturnType = E->getType();
- std::optional<PrimType> ReturnT = classify(E);
+ OptPrimType ReturnT = classify(E);
// Non-primitive return type. Prepare storage.
if (!Initializing && !ReturnT && !ReturnType->isVoidType()) {
@@ -5032,7 +5003,7 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
BlockScope<Emitter> CallScope(this, ScopeKind::Call);
QualType ReturnType = E->getCallReturnType(Ctx.getASTContext());
- std::optional<PrimType> T = classify(ReturnType);
+ OptPrimType T = classify(ReturnType);
bool HasRVO = !ReturnType->isVoidType() && !T;
if (HasRVO) {
@@ -5402,6 +5373,53 @@ bool Compiler<Emitter>::maybeEmitDeferredVarInit(const VarDecl *VD) {
return true;
}
+static bool hasTrivialDefaultCtorParent(const FieldDecl *FD) {
+ assert(FD);
+ assert(FD->getParent()->isUnion());
+ const auto *CXXRD = dyn_cast<CXXRecordDecl>(FD->getParent());
+ return !CXXRD || CXXRD->hasTrivialDefaultConstructor();
+}
+
+template <class Emitter> bool Compiler<Emitter>::refersToUnion(const Expr *E) {
+ for (;;) {
+ if (const auto *ME = dyn_cast<MemberExpr>(E)) {
+ if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
+ FD && FD->getParent()->isUnion() && hasTrivialDefaultCtorParent(FD))
+ return true;
+ E = ME->getBase();
+ continue;
+ }
+
+ if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
+ E = ASE->getBase()->IgnoreImplicit();
+ continue;
+ }
+
+ if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E);
+ ICE && (ICE->getCastKind() == CK_NoOp ||
+ ICE->getCastKind() == CK_DerivedToBase ||
+ ICE->getCastKind() == CK_UncheckedDerivedToBase)) {
+ E = ICE->getSubExpr();
+ continue;
+ }
+
+ if (const auto *This = dyn_cast<CXXThisExpr>(E)) {
+ const auto *ThisRecord =
+ This->getType()->getPointeeType()->getAsRecordDecl();
+ if (!ThisRecord->isUnion())
+ return false;
+ // Otherwise, always activate if we're in the ctor.
+ if (const auto *Ctor =
+ dyn_cast_if_present<CXXConstructorDecl>(CompilingFunction))
+ return Ctor->getParent() == ThisRecord;
+ return false;
+ }
+
+ break;
+ }
+ return false;
+}
+
template <class Emitter>
bool Compiler<Emitter>::visitDeclStmt(const DeclStmt *DS,
bool EvaluateConditionDecl) {
@@ -5933,17 +5951,16 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
if (InitExpr->getType().isNull())
return false;
- if (std::optional<PrimType> T = this->classify(InitExpr)) {
+ if (OptPrimType T = this->classify(InitExpr)) {
+ if (Activate && !this->emitActivateThisField(FieldOffset, InitExpr))
+ return false;
+
if (!this->visit(InitExpr))
return false;
bool BitField = F->isBitField();
- if (BitField && Activate)
- return this->emitInitThisBitFieldActivate(*T, F, FieldOffset, InitExpr);
if (BitField)
return this->emitInitThisBitField(*T, F, FieldOffset, InitExpr);
- if (Activate)
- return this->emitInitThisFieldActivate(*T, FieldOffset, InitExpr);
return this->emitInitThisField(*T, FieldOffset, InitExpr);
}
// Non-primitive case. Get a pointer to the field-to-initialize
@@ -6189,7 +6206,7 @@ bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
return this->VisitVectorUnaryOperator(E);
if (SubExpr->getType()->isFixedPointType())
return this->VisitFixedPointUnaryOperator(E);
- std::optional<PrimType> T = classify(SubExpr->getType());
+ OptPrimType T = classify(SubExpr->getType());
switch (E->getOpcode()) {
case UO_PostInc: { // x++
@@ -6415,7 +6432,7 @@ bool Compiler<Emitter>::VisitComplexUnaryOperator(const UnaryOperator *E) {
if (DiscardResult)
return this->discard(SubExpr);
- std::optional<PrimType> ResT = classify(E);
+ OptPrimType ResT = classify(E);
auto prepareResult = [=]() -> bool {
if (!ResT && !Initializing) {
std::optional<unsigned> LocalIndex = allocateLocal(SubExpr);
@@ -6637,7 +6654,7 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
if (std::optional<unsigned> Index = P.getOrCreateGlobal(D)) {
if (!this->emitGetPtrGlobal(*Index, E))
return false;
- if (std::optional<PrimType> T = classify(E->getType())) {
+ if (OptPrimType T = classify(E->getType())) {
if (!this->visitAPValue(TPOD->getValue(), *T, E))
return false;
return this->emitInitGlobal(*T, *Index, E);
@@ -7136,7 +7153,7 @@ bool Compiler<Emitter>::emitBuiltinBitCast(const CastExpr *E) {
const Expr *SubExpr = E->getSubExpr();
QualType FromType = SubExpr->getType();
QualType ToType = E->getType();
- std::optional<PrimType> ToT = classify(ToType);
+ OptPrimType ToT = classify(ToType);
assert(!ToType->isReferenceType());
@@ -7157,7 +7174,7 @@ bool Compiler<Emitter>::emitBuiltinBitCast(const CastExpr *E) {
if (SubExpr->isGLValue() || FromType->isVectorType()) {
if (!this->visit(SubExpr))
return false;
- } else if (std::optional<PrimType> FromT = classify(SubExpr)) {
+ } else if (OptPrimType FromT = classify(SubExpr)) {
unsigned TempOffset =
allocateLocalPrimitive(SubExpr, *FromT, /*IsConst=*/true);
if (!this->visit(SubExpr))
diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h
index debee672..3a26342 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -254,12 +254,8 @@ protected:
/// If the function does not exist yet, it is compiled.
const Function *getFunction(const FunctionDecl *FD);
- std::optional<PrimType> classify(const Expr *E) const {
- return Ctx.classify(E);
- }
- std::optional<PrimType> classify(QualType Ty) const {
- return Ctx.classify(Ty);
- }
+ OptPrimType classify(const Expr *E) const { return Ctx.classify(E); }
+ OptPrimType classify(QualType Ty) const { return Ctx.classify(Ty); }
/// Classifies a known primitive type.
PrimType classifyPrim(QualType Ty) const {
@@ -306,7 +302,7 @@ protected:
bool visitInitList(ArrayRef<const Expr *> Inits, const Expr *ArrayFiller,
const Expr *E);
bool visitArrayElemInit(unsigned ElemIndex, const Expr *Init,
- std::optional<PrimType> InitT);
+ OptPrimType InitT);
bool visitCallArgs(ArrayRef<const Expr *> Args, const FunctionDecl *FuncDecl,
bool Activate);
@@ -405,6 +401,8 @@ private:
bool checkLiteralType(const Expr *E);
bool maybeEmitDeferredVarInit(const VarDecl *VD);
+ bool refersToUnion(const Expr *E);
+
protected:
/// Variable to storage mapping.
llvm::DenseMap<const ValueDecl *, Scope::Local> Locals;
@@ -435,7 +433,7 @@ protected:
bool InitStackActive = false;
/// Type of the expression returned by the function.
- std::optional<PrimType> ReturnType;
+ OptPrimType ReturnType;
/// Switch case mapping.
CaseMap CaseLabels;
diff --git a/clang/lib/AST/ByteCode/Context.cpp b/clang/lib/AST/ByteCode/Context.cpp
index ead6e4a..aaeb52e 100644
--- a/clang/lib/AST/ByteCode/Context.cpp
+++ b/clang/lib/AST/ByteCode/Context.cpp
@@ -235,6 +235,43 @@ bool Context::evaluateCharRange(State &Parent, const Expr *SizeExpr,
return evaluateStringRepr(Parent, SizeExpr, PtrExpr, Result);
}
+bool Context::evaluateStrlen(State &Parent, const Expr *E, uint64_t &Result) {
+ assert(Stk.empty());
+ Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
+
+ auto PtrRes = C.interpretAsPointer(E, [&](const Pointer &Ptr) {
+ const Descriptor *FieldDesc = Ptr.getFieldDesc();
+ if (!FieldDesc->isPrimitiveArray())
+ return false;
+
+ unsigned N = Ptr.getNumElems();
+ if (Ptr.elemSize() == 1) {
+ Result = strnlen(reinterpret_cast<const char *>(Ptr.getRawAddress()), N);
+ return Result != N;
+ }
+
+ PrimType ElemT = FieldDesc->getPrimType();
+ Result = 0;
+ for (unsigned I = Ptr.getIndex(); I != N; ++I) {
+ INT_TYPE_SWITCH(ElemT, {
+ auto Elem = Ptr.elem<T>(I);
+ if (Elem.isZero())
+ return true;
+ ++Result;
+ });
+ }
+ // We didn't find a 0 byte.
+ return false;
+ });
+
+ if (PtrRes.isInvalid()) {
+ C.cleanup();
+ Stk.clear();
+ return false;
+ }
+ return true;
+}
+
const LangOptions &Context::getLangOpts() const { return Ctx.getLangOpts(); }
static PrimType integralTypeToPrimTypeS(unsigned BitWidth) {
@@ -269,7 +306,7 @@ static PrimType integralTypeToPrimTypeU(unsigned BitWidth) {
llvm_unreachable("Unhandled BitWidth");
}
-std::optional<PrimType> Context::classify(QualType T) const {
+OptPrimType Context::classify(QualType T) const {
if (const auto *BT = dyn_cast<BuiltinType>(T.getCanonicalType())) {
auto Kind = BT->getKind();
@@ -505,7 +542,7 @@ const Function *Context::getOrCreateFunction(const FunctionDecl *FuncDecl) {
// Assign descriptors to all parameters.
// Composite objects are lowered to pointers.
for (const ParmVarDecl *PD : FuncDecl->parameters()) {
- std::optional<PrimType> T = classify(PD->getType());
+ OptPrimType T = classify(PD->getType());
PrimType PT = T.value_or(PT_Ptr);
Descriptor *Desc = P->createDescriptor(PD, PT);
ParamDescriptors.insert({ParamOffset, {PT, Desc}});
@@ -533,7 +570,7 @@ const Function *Context::getOrCreateObjCBlock(const BlockExpr *E) {
// Assign descriptors to all parameters.
// Composite objects are lowered to pointers.
for (const ParmVarDecl *PD : BD->parameters()) {
- std::optional<PrimType> T = classify(PD->getType());
+ OptPrimType T = classify(PD->getType());
PrimType PT = T.value_or(PT_Ptr);
Descriptor *Desc = P->createDescriptor(PD, PT);
ParamDescriptors.insert({ParamOffset, {PT, Desc}});
diff --git a/clang/lib/AST/ByteCode/Context.h b/clang/lib/AST/ByteCode/Context.h
index acf7504..62ef529 100644
--- a/clang/lib/AST/ByteCode/Context.h
+++ b/clang/lib/AST/ByteCode/Context.h
@@ -66,6 +66,10 @@ public:
bool evaluateCharRange(State &Parent, const Expr *SizeExpr,
const Expr *PtrExpr, std::string &Result);
+ /// Evalute \param E and if it can be evaluated to a string literal,
+ /// run strlen() on it.
+ bool evaluateStrlen(State &Parent, const Expr *E, uint64_t &Result);
+
/// Returns the AST context.
ASTContext &getASTContext() const { return Ctx; }
/// Returns the language options.
@@ -78,10 +82,10 @@ public:
uint32_t getBitWidth(QualType T) const { return Ctx.getIntWidth(T); }
/// Classifies a type.
- std::optional<PrimType> classify(QualType T) const;
+ OptPrimType classify(QualType T) const;
/// Classifies an expression.
- std::optional<PrimType> classify(const Expr *E) const {
+ OptPrimType classify(const Expr *E) const {
assert(E);
if (E->isGLValue())
return PT_Ptr;
diff --git a/clang/lib/AST/ByteCode/Descriptor.h b/clang/lib/AST/ByteCode/Descriptor.h
index 0227e4c..4c925f6 100644
--- a/clang/lib/AST/ByteCode/Descriptor.h
+++ b/clang/lib/AST/ByteCode/Descriptor.h
@@ -164,7 +164,7 @@ public:
/// The primitive type this descriptor was created for,
/// or the primitive element type in case this is
/// a primitive array.
- const std::optional<PrimType> PrimT = std::nullopt;
+ const OptPrimType PrimT = std::nullopt;
/// Flag indicating if the block is mutable.
const bool IsConst = false;
/// Flag indicating if a field is mutable.
diff --git a/clang/lib/AST/ByteCode/EvalEmitter.cpp b/clang/lib/AST/ByteCode/EvalEmitter.cpp
index 6e511bc..81ebc56 100644
--- a/clang/lib/AST/ByteCode/EvalEmitter.cpp
+++ b/clang/lib/AST/ByteCode/EvalEmitter.cpp
@@ -324,7 +324,7 @@ void EvalEmitter::updateGlobalTemporaries() {
const Pointer &Ptr = P.getPtrGlobal(*GlobalIndex);
APValue *Cached = Temp->getOrCreateValue(true);
- if (std::optional<PrimType> T = Ctx.classify(E->getType())) {
+ if (OptPrimType T = Ctx.classify(E->getType())) {
TYPE_SWITCH(
*T, { *Cached = Ptr.deref<T>().toAPValue(Ctx.getASTContext()); });
} else {
diff --git a/clang/lib/AST/ByteCode/EvaluationResult.cpp b/clang/lib/AST/ByteCode/EvaluationResult.cpp
index f59612b..b11531f 100644
--- a/clang/lib/AST/ByteCode/EvaluationResult.cpp
+++ b/clang/lib/AST/ByteCode/EvaluationResult.cpp
@@ -204,7 +204,7 @@ static void collectBlocks(const Pointer &Ptr,
} else if (Desc->isPrimitiveArray() && Desc->getPrimType() == PT_Ptr) {
for (unsigned I = 0; I != Desc->getNumElems(); ++I) {
- const Pointer &ElemPointee = Ptr.atIndex(I).deref<Pointer>();
+ const Pointer &ElemPointee = Ptr.elem<Pointer>(I);
if (isUsefulPtr(ElemPointee) && !Blocks.contains(ElemPointee.block()))
collectBlocks(ElemPointee, Blocks);
}
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 7ba6e21..9012442 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -468,10 +468,10 @@ inline bool Mulc(InterpState &S, CodePtr OpPC) {
const Pointer &Result = S.Stk.peek<Pointer>();
if constexpr (std::is_same_v<T, Floating>) {
- APFloat A = LHS.atIndex(0).deref<Floating>().getAPFloat();
- APFloat B = LHS.atIndex(1).deref<Floating>().getAPFloat();
- APFloat C = RHS.atIndex(0).deref<Floating>().getAPFloat();
- APFloat D = RHS.atIndex(1).deref<Floating>().getAPFloat();
+ APFloat A = LHS.elem<Floating>(0).getAPFloat();
+ APFloat B = LHS.elem<Floating>(1).getAPFloat();
+ APFloat C = RHS.elem<Floating>(0).getAPFloat();
+ APFloat D = RHS.elem<Floating>(1).getAPFloat();
APFloat ResR(A.getSemantics());
APFloat ResI(A.getSemantics());
@@ -480,20 +480,20 @@ inline bool Mulc(InterpState &S, CodePtr OpPC) {
// Copy into the result.
Floating RA = S.allocFloat(A.getSemantics());
RA.copy(ResR);
- Result.atIndex(0).deref<Floating>() = RA; // Floating(ResR);
+ Result.elem<Floating>(0) = RA; // Floating(ResR);
Result.atIndex(0).initialize();
Floating RI = S.allocFloat(A.getSemantics());
RI.copy(ResI);
- Result.atIndex(1).deref<Floating>() = RI; // Floating(ResI);
+ Result.elem<Floating>(1) = RI; // Floating(ResI);
Result.atIndex(1).initialize();
Result.initialize();
} else {
// Integer element type.
- const T &LHSR = LHS.atIndex(0).deref<T>();
- const T &LHSI = LHS.atIndex(1).deref<T>();
- const T &RHSR = RHS.atIndex(0).deref<T>();
- const T &RHSI = RHS.atIndex(1).deref<T>();
+ const T &LHSR = LHS.elem<T>(0);
+ const T &LHSI = LHS.elem<T>(1);
+ const T &RHSR = RHS.elem<T>(0);
+ const T &RHSI = RHS.elem<T>(1);
unsigned Bits = LHSR.bitWidth();
// real(Result) = (real(LHS) * real(RHS)) - (imag(LHS) * imag(RHS))
@@ -503,7 +503,7 @@ inline bool Mulc(InterpState &S, CodePtr OpPC) {
T B;
if (T::mul(LHSI, RHSI, Bits, &B))
return false;
- if (T::sub(A, B, Bits, &Result.atIndex(0).deref<T>()))
+ if (T::sub(A, B, Bits, &Result.elem<T>(0)))
return false;
Result.atIndex(0).initialize();
@@ -512,7 +512,7 @@ inline bool Mulc(InterpState &S, CodePtr OpPC) {
return false;
if (T::mul(LHSI, RHSR, Bits, &B))
return false;
- if (T::add(A, B, Bits, &Result.atIndex(1).deref<T>()))
+ if (T::add(A, B, Bits, &Result.elem<T>(1)))
return false;
Result.atIndex(1).initialize();
Result.initialize();
@@ -528,10 +528,10 @@ inline bool Divc(InterpState &S, CodePtr OpPC) {
const Pointer &Result = S.Stk.peek<Pointer>();
if constexpr (std::is_same_v<T, Floating>) {
- APFloat A = LHS.atIndex(0).deref<Floating>().getAPFloat();
- APFloat B = LHS.atIndex(1).deref<Floating>().getAPFloat();
- APFloat C = RHS.atIndex(0).deref<Floating>().getAPFloat();
- APFloat D = RHS.atIndex(1).deref<Floating>().getAPFloat();
+ APFloat A = LHS.elem<Floating>(0).getAPFloat();
+ APFloat B = LHS.elem<Floating>(1).getAPFloat();
+ APFloat C = RHS.elem<Floating>(0).getAPFloat();
+ APFloat D = RHS.elem<Floating>(1).getAPFloat();
APFloat ResR(A.getSemantics());
APFloat ResI(A.getSemantics());
@@ -540,21 +540,21 @@ inline bool Divc(InterpState &S, CodePtr OpPC) {
// Copy into the result.
Floating RA = S.allocFloat(A.getSemantics());
RA.copy(ResR);
- Result.atIndex(0).deref<Floating>() = RA; // Floating(ResR);
+ Result.elem<Floating>(0) = RA; // Floating(ResR);
Result.atIndex(0).initialize();
Floating RI = S.allocFloat(A.getSemantics());
RI.copy(ResI);
- Result.atIndex(1).deref<Floating>() = RI; // Floating(ResI);
+ Result.elem<Floating>(1) = RI; // Floating(ResI);
Result.atIndex(1).initialize();
Result.initialize();
} else {
// Integer element type.
- const T &LHSR = LHS.atIndex(0).deref<T>();
- const T &LHSI = LHS.atIndex(1).deref<T>();
- const T &RHSR = RHS.atIndex(0).deref<T>();
- const T &RHSI = RHS.atIndex(1).deref<T>();
+ const T &LHSR = LHS.elem<T>(0);
+ const T &LHSI = LHS.elem<T>(1);
+ const T &RHSR = RHS.elem<T>(0);
+ const T &RHSI = RHS.elem<T>(1);
unsigned Bits = LHSR.bitWidth();
const T Zero = T::from(0, Bits);
@@ -581,8 +581,8 @@ inline bool Divc(InterpState &S, CodePtr OpPC) {
}
// real(Result) = ((real(LHS) * real(RHS)) + (imag(LHS) * imag(RHS))) / Den
- T &ResultR = Result.atIndex(0).deref<T>();
- T &ResultI = Result.atIndex(1).deref<T>();
+ T &ResultR = Result.elem<T>(0);
+ T &ResultI = Result.elem<T>(1);
if (T::mul(LHSR, RHSR, Bits, &A) || T::mul(LHSI, RHSI, Bits, &B))
return false;
@@ -1983,6 +1983,16 @@ static inline bool Activate(InterpState &S, CodePtr OpPC) {
return true;
}
+static inline bool ActivateThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
+ if (S.checkingPotentialConstantExpression())
+ return false;
+
+ const Pointer &Ptr = S.Current->getThis();
+ assert(Ptr.atField(I).canBeInitialized());
+ Ptr.atField(I).activate();
+ return true;
+}
+
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool StoreActivate(InterpState &S, CodePtr OpPC) {
const T &Value = S.Stk.pop<T>();
@@ -3103,7 +3113,7 @@ inline bool ArrayElem(InterpState &S, CodePtr OpPC, uint32_t Index) {
return false;
assert(Ptr.atIndex(Index).getFieldDesc()->getPrimType() == Name);
- S.Stk.push<T>(Ptr.atIndex(Index).deref<T>());
+ S.Stk.push<T>(Ptr.elem<T>(Index));
return true;
}
@@ -3115,7 +3125,7 @@ inline bool ArrayElemPop(InterpState &S, CodePtr OpPC, uint32_t Index) {
return false;
assert(Ptr.atIndex(Index).getFieldDesc()->getPrimType() == Name);
- S.Stk.push<T>(Ptr.atIndex(Index).deref<T>());
+ S.Stk.push<T>(Ptr.elem<T>(Index));
return true;
}
@@ -3557,12 +3567,22 @@ inline bool BitCastPrim(InterpState &S, CodePtr OpPC, bool TargetIsUCharOrByte,
Floating Result = S.allocFloat(*Sem);
Floating::bitcastFromMemory(Buff.data(), *Sem, &Result);
S.Stk.push<Floating>(Result);
-
- // S.Stk.push<Floating>(T::bitcastFromMemory(Buff.data(), *Sem));
} else if constexpr (needsAlloc<T>()) {
T Result = S.allocAP<T>(ResultBitWidth);
T::bitcastFromMemory(Buff.data(), ResultBitWidth, &Result);
S.Stk.push<T>(Result);
+ } else if constexpr (std::is_same_v<T, Boolean>) {
+ // Only allow to cast single-byte integers to bool if they are either 0
+ // or 1.
+ assert(FullBitWidth.getQuantity() == 8);
+ auto Val = static_cast<unsigned int>(Buff[0]);
+ if (Val > 1) {
+ S.FFDiag(S.Current->getSource(OpPC),
+ diag::note_constexpr_bit_cast_unrepresentable_value)
+ << S.getASTContext().BoolTy << Val;
+ return false;
+ }
+ S.Stk.push<T>(T::bitcastFromMemory(Buff.data(), ResultBitWidth));
} else {
assert(!Sem);
S.Stk.push<T>(T::bitcastFromMemory(Buff.data(), ResultBitWidth));
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 462b9a1..19d4c0c 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -53,7 +53,7 @@ static APSInt popToAPSInt(InterpStack &Stk, PrimType T) {
static void pushInteger(InterpState &S, const APSInt &Val, QualType QT) {
assert(QT->isSignedIntegerOrEnumerationType() ||
QT->isUnsignedIntegerOrEnumerationType());
- std::optional<PrimType> T = S.getContext().classify(QT);
+ OptPrimType T = S.getContext().classify(QT);
assert(T);
unsigned BitWidth = S.getASTContext().getTypeSize(QT);
@@ -1098,9 +1098,9 @@ static bool interp__builtin_complex(InterpState &S, CodePtr OpPC,
const Floating &Arg1 = S.Stk.pop<Floating>();
Pointer &Result = S.Stk.peek<Pointer>();
- Result.atIndex(0).deref<Floating>() = Arg1;
+ Result.elem<Floating>(0) = Arg1;
Result.atIndex(0).initialize();
- Result.atIndex(1).deref<Floating>() = Arg2;
+ Result.elem<Floating>(1) = Arg2;
Result.atIndex(1).initialize();
Result.initialize();
@@ -1530,7 +1530,7 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
return false;
bool IsArray = NumElems.ugt(1);
- std::optional<PrimType> ElemT = S.getContext().classify(ElemType);
+ OptPrimType ElemT = S.getContext().classify(ElemType);
DynamicAllocator &Allocator = S.getAllocator();
if (ElemT) {
Block *B =
@@ -1644,10 +1644,10 @@ static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC,
unsigned NumElems = Arg.getNumElems();
INT_TYPE_SWITCH_NO_BOOL(ElemT, {
- T Result = Arg.atIndex(0).deref<T>();
+ T Result = Arg.elem<T>(0);
unsigned BitWidth = Result.bitWidth();
for (unsigned I = 1; I != NumElems; ++I) {
- T Elem = Arg.atIndex(I).deref<T>();
+ T Elem = Arg.elem<T>(I);
T PrevResult = Result;
if (ID == Builtin::BI__builtin_reduce_add) {
@@ -1723,11 +1723,10 @@ static bool interp__builtin_elementwise_popcount(InterpState &S, CodePtr OpPC,
for (unsigned I = 0; I != NumElems; ++I) {
INT_TYPE_SWITCH_NO_BOOL(ElemT, {
if (BuiltinID == Builtin::BI__builtin_elementwise_popcount) {
- Dst.atIndex(I).deref<T>() =
- T::from(Arg.atIndex(I).deref<T>().toAPSInt().popcount());
+ Dst.elem<T>(I) = T::from(Arg.elem<T>(I).toAPSInt().popcount());
} else {
- Dst.atIndex(I).deref<T>() = T::from(
- Arg.atIndex(I).deref<T>().toAPSInt().reverseBits().getZExtValue());
+ Dst.elem<T>(I) =
+ T::from(Arg.elem<T>(I).toAPSInt().reverseBits().getZExtValue());
}
Dst.atIndex(I).initialize();
});
@@ -2296,8 +2295,8 @@ static bool interp__builtin_elementwise_sat(InterpState &S, CodePtr OpPC,
APSInt Elem1;
APSInt Elem2;
INT_TYPE_SWITCH_NO_BOOL(ElemT, {
- Elem1 = LHS.atIndex(I).deref<T>().toAPSInt();
- Elem2 = RHS.atIndex(I).deref<T>().toAPSInt();
+ Elem1 = LHS.elem<T>(I).toAPSInt();
+ Elem2 = RHS.elem<T>(I).toAPSInt();
});
APSInt Result;
@@ -2880,7 +2879,7 @@ static bool copyRecord(InterpState &S, CodePtr OpPC, const Pointer &Src,
auto copyField = [&](const Record::Field &F, bool Activate) -> bool {
Pointer DestField = Dest.atField(F.Offset);
- if (std::optional<PrimType> FT = S.Ctx.classify(F.Decl->getType())) {
+ if (OptPrimType FT = S.Ctx.classify(F.Decl->getType())) {
TYPE_SWITCH(*FT, {
DestField.deref<T>() = Src.atField(F.Offset).deref<T>();
if (Src.atField(F.Offset).isInitialized())
@@ -2942,7 +2941,7 @@ static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src,
for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) {
Pointer DestElem = Dest.atIndex(I);
TYPE_SWITCH(ET, {
- DestElem.deref<T>() = Src.atIndex(I).deref<T>();
+ DestElem.deref<T>() = Src.elem<T>(I);
DestElem.initialize();
});
}
diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td
index 80703ad..abfed77 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -510,6 +510,7 @@ def StoreBitFieldActivate : StoreBitFieldOpcode {}
def StoreBitFieldActivatePop : StoreBitFieldOpcode {}
def Activate : Opcode {}
+def ActivateThisField : Opcode { let Args = [ArgUint32]; }
// [Pointer, Value] -> []
def Init : StoreOpcode {}
diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp
index 2f9ecf9..4019b74 100644
--- a/clang/lib/AST/ByteCode/Pointer.cpp
+++ b/clang/lib/AST/ByteCode/Pointer.cpp
@@ -665,7 +665,7 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,
return false;
// Primitive values.
- if (std::optional<PrimType> T = Ctx.classify(Ty)) {
+ if (OptPrimType T = Ctx.classify(Ty)) {
TYPE_SWITCH(*T, R = Ptr.deref<T>().toAPValue(ASTCtx));
return true;
}
@@ -682,7 +682,7 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,
const Pointer &FP = Ptr.atField(F.Offset);
QualType FieldTy = F.Decl->getType();
if (FP.isActive()) {
- if (std::optional<PrimType> T = Ctx.classify(FieldTy)) {
+ if (OptPrimType T = Ctx.classify(FieldTy)) {
TYPE_SWITCH(*T, Value = FP.deref<T>().toAPValue(ASTCtx));
} else {
Ok &= Composite(FieldTy, FP, Value);
@@ -705,7 +705,7 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,
const Pointer &FP = Ptr.atField(FD->Offset);
APValue &Value = R.getStructField(I);
- if (std::optional<PrimType> T = Ctx.classify(FieldTy)) {
+ if (OptPrimType T = Ctx.classify(FieldTy)) {
TYPE_SWITCH(*T, Value = FP.deref<T>().toAPValue(ASTCtx));
} else {
Ok &= Composite(FieldTy, FP, Value);
@@ -743,7 +743,7 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,
for (unsigned I = 0; I < NumElems; ++I) {
APValue &Slot = R.getArrayInitializedElt(I);
const Pointer &EP = Ptr.atIndex(I);
- if (std::optional<PrimType> T = Ctx.classify(ElemTy)) {
+ if (OptPrimType T = Ctx.classify(ElemTy)) {
TYPE_SWITCH(*T, Slot = EP.deref<T>().toAPValue(ASTCtx));
} else {
Ok &= Composite(ElemTy, EP.narrow(), Slot);
@@ -757,17 +757,17 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,
QualType ElemTy = CT->getElementType();
if (ElemTy->isIntegerType()) {
- std::optional<PrimType> ElemT = Ctx.classify(ElemTy);
+ OptPrimType ElemT = Ctx.classify(ElemTy);
assert(ElemT);
INT_TYPE_SWITCH(*ElemT, {
- auto V1 = Ptr.atIndex(0).deref<T>();
- auto V2 = Ptr.atIndex(1).deref<T>();
+ auto V1 = Ptr.elem<T>(0);
+ auto V2 = Ptr.elem<T>(1);
R = APValue(V1.toAPSInt(), V2.toAPSInt());
return true;
});
} else if (ElemTy->isFloatingType()) {
- R = APValue(Ptr.atIndex(0).deref<Floating>().getAPFloat(),
- Ptr.atIndex(1).deref<Floating>().getAPFloat());
+ R = APValue(Ptr.elem<Floating>(0).getAPFloat(),
+ Ptr.elem<Floating>(1).getAPFloat());
return true;
}
return false;
@@ -782,9 +782,8 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,
SmallVector<APValue> Values;
Values.reserve(VT->getNumElements());
for (unsigned I = 0; I != VT->getNumElements(); ++I) {
- TYPE_SWITCH(ElemT, {
- Values.push_back(Ptr.atIndex(I).deref<T>().toAPValue(ASTCtx));
- });
+ TYPE_SWITCH(ElemT,
+ { Values.push_back(Ptr.elem<T>(I).toAPValue(ASTCtx)); });
}
assert(Values.size() == VT->getNumElements());
@@ -804,7 +803,7 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,
return toAPValue(ASTCtx);
// Just load primitive types.
- if (std::optional<PrimType> T = Ctx.classify(ResultType)) {
+ if (OptPrimType T = Ctx.classify(ResultType)) {
TYPE_SWITCH(*T, return this->deref<T>().toAPValue(ASTCtx));
}
diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h
index da74013..d17eba5 100644
--- a/clang/lib/AST/ByteCode/Pointer.h
+++ b/clang/lib/AST/ByteCode/Pointer.h
@@ -693,6 +693,25 @@ public:
return *reinterpret_cast<T *>(asBlockPointer().Pointee->rawData() + Offset);
}
+ /// Dereferences the element at index \p I.
+ /// This is equivalent to atIndex(I).deref<T>().
+ template <typename T> T &elem(unsigned I) const {
+ assert(isLive() && "Invalid pointer");
+ assert(isBlockPointer());
+ assert(asBlockPointer().Pointee);
+ assert(isDereferencable());
+ assert(getFieldDesc()->isPrimitiveArray());
+
+ unsigned ElemByteOffset = I * getFieldDesc()->getElemSize();
+ if (isArrayRoot())
+ return *reinterpret_cast<T *>(asBlockPointer().Pointee->rawData() +
+ asBlockPointer().Base + sizeof(InitMapPtr) +
+ ElemByteOffset);
+
+ return *reinterpret_cast<T *>(asBlockPointer().Pointee->rawData() + Offset +
+ ElemByteOffset);
+ }
+
/// Whether this block can be read from at all. This is only true for
/// block pointers that point to a valid location inside that block.
bool isDereferencable() const {
diff --git a/clang/lib/AST/ByteCode/PrimType.h b/clang/lib/AST/ByteCode/PrimType.h
index a156ccc..38c29b9 100644
--- a/clang/lib/AST/ByteCode/PrimType.h
+++ b/clang/lib/AST/ByteCode/PrimType.h
@@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_AST_INTERP_TYPE_H
#define LLVM_CLANG_AST_INTERP_TYPE_H
+#include "clang/Basic/UnsignedOrNone.h"
#include "llvm/Support/raw_ostream.h"
#include <climits>
#include <cstddef>
@@ -49,6 +50,38 @@ enum PrimType : unsigned {
PT_MemberPtr = 14,
};
+// Like std::optional<PrimType>, but only sizeof(PrimType).
+class OptPrimType final {
+ unsigned V = ~0u;
+
+public:
+ OptPrimType() = default;
+ OptPrimType(std::nullopt_t) {}
+ OptPrimType(PrimType T) : V(static_cast<unsigned>(T)) {}
+
+ explicit constexpr operator bool() const { return V != ~0u; }
+ PrimType operator*() const {
+ assert(operator bool());
+ return static_cast<PrimType>(V);
+ }
+
+ PrimType value_or(PrimType PT) const {
+ if (operator bool())
+ return static_cast<PrimType>(V);
+ return PT;
+ }
+
+ bool operator==(PrimType PT) const {
+ if (!operator bool())
+ return false;
+ return V == static_cast<unsigned>(PT);
+ }
+ bool operator==(OptPrimType OPT) const { return V == OPT.V; }
+ bool operator!=(PrimType PT) const { return !(*this == PT); }
+ bool operator!=(OptPrimType OPT) const { return V != OPT.V; }
+};
+static_assert(sizeof(OptPrimType) == sizeof(PrimType));
+
inline constexpr bool isPtrType(PrimType T) {
return T == PT_Ptr || T == PT_MemberPtr;
}
diff --git a/clang/lib/AST/ByteCode/Program.cpp b/clang/lib/AST/ByteCode/Program.cpp
index 5ac0f59f..7002724 100644
--- a/clang/lib/AST/ByteCode/Program.cpp
+++ b/clang/lib/AST/ByteCode/Program.cpp
@@ -74,27 +74,25 @@ unsigned Program::createGlobalString(const StringLiteral *S, const Expr *Base) {
const Pointer Ptr(G->block());
if (CharWidth == 1) {
- std::memcpy(&Ptr.atIndex(0).deref<char>(), S->getString().data(),
- StringLength);
+ std::memcpy(&Ptr.elem<char>(0), S->getString().data(), StringLength);
} else {
// Construct the string in storage.
for (unsigned I = 0; I <= StringLength; ++I) {
- Pointer Field = Ptr.atIndex(I);
const uint32_t CodePoint = I == StringLength ? 0 : S->getCodeUnit(I);
switch (CharType) {
case PT_Sint8: {
using T = PrimConv<PT_Sint8>::T;
- Field.deref<T>() = T::from(CodePoint, BitWidth);
+ Ptr.elem<T>(I) = T::from(CodePoint, BitWidth);
break;
}
case PT_Uint16: {
using T = PrimConv<PT_Uint16>::T;
- Field.deref<T>() = T::from(CodePoint, BitWidth);
+ Ptr.elem<T>(I) = T::from(CodePoint, BitWidth);
break;
}
case PT_Uint32: {
using T = PrimConv<PT_Uint32>::T;
- Field.deref<T>() = T::from(CodePoint, BitWidth);
+ Ptr.elem<T>(I) = T::from(CodePoint, BitWidth);
break;
}
default:
@@ -171,7 +169,7 @@ unsigned Program::getOrCreateDummy(const DeclTy &D) {
assert(!QT.isNull());
Descriptor *Desc;
- if (std::optional<PrimType> T = Ctx.classify(QT))
+ if (OptPrimType T = Ctx.classify(QT))
Desc = createDescriptor(D, *T, /*SourceTy=*/nullptr, std::nullopt,
/*IsConst=*/QT.isConstQualified());
else
@@ -250,7 +248,7 @@ std::optional<unsigned> Program::createGlobal(const DeclTy &D, QualType Ty,
const bool IsConst = Ty.isConstQualified();
const bool IsTemporary = D.dyn_cast<const Expr *>();
const bool IsVolatile = Ty.isVolatileQualified();
- if (std::optional<PrimType> T = Ctx.classify(Ty))
+ if (OptPrimType T = Ctx.classify(Ty))
Desc = createDescriptor(D, *T, nullptr, Descriptor::GlobalMD, IsConst,
IsTemporary, /*IsMutable=*/false, IsVolatile);
else
@@ -373,7 +371,7 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
const bool IsMutable = FD->isMutable();
const bool IsVolatile = FT.isVolatileQualified();
const Descriptor *Desc;
- if (std::optional<PrimType> T = Ctx.classify(FT)) {
+ if (OptPrimType T = Ctx.classify(FT)) {
Desc = createDescriptor(FD, *T, nullptr, std::nullopt, IsConst,
/*isTemporary=*/false, IsMutable, IsVolatile);
} else {
@@ -412,7 +410,7 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty,
// Array of well-known bounds.
if (const auto *CAT = dyn_cast<ConstantArrayType>(ArrayType)) {
size_t NumElems = CAT->getZExtSize();
- if (std::optional<PrimType> T = Ctx.classify(ElemTy)) {
+ if (OptPrimType T = Ctx.classify(ElemTy)) {
// Arrays of primitives.
unsigned ElemSize = primSize(*T);
if (std::numeric_limits<unsigned>::max() / ElemSize <= NumElems) {
@@ -439,7 +437,7 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty,
// is forbidden on pointers to such objects.
if (isa<IncompleteArrayType>(ArrayType) ||
isa<VariableArrayType>(ArrayType)) {
- if (std::optional<PrimType> T = Ctx.classify(ElemTy)) {
+ if (OptPrimType T = Ctx.classify(ElemTy)) {
return allocateDescriptor(D, *T, MDSize, IsConst, IsTemporary,
Descriptor::UnknownSize{});
} else {
@@ -462,7 +460,7 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty,
// Complex types - represented as arrays of elements.
if (const auto *CT = Ty->getAs<ComplexType>()) {
- std::optional<PrimType> ElemTy = Ctx.classify(CT->getElementType());
+ OptPrimType ElemTy = Ctx.classify(CT->getElementType());
if (!ElemTy)
return nullptr;
@@ -472,7 +470,7 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty,
// Same with vector types.
if (const auto *VT = Ty->getAs<VectorType>()) {
- std::optional<PrimType> ElemTy = Ctx.classify(VT->getElementType());
+ OptPrimType ElemTy = Ctx.classify(VT->getElementType());
if (!ElemTy)
return nullptr;
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index e575405..9808298 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -14636,7 +14636,9 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
if (!LHSDesignator.Invalid && !RHSDesignator.Invalid && IsRelational) {
bool WasArrayIndex;
unsigned Mismatch = FindDesignatorMismatch(
- getType(LHSValue.Base), LHSDesignator, RHSDesignator, WasArrayIndex);
+ LHSValue.Base.isNull() ? QualType()
+ : getType(LHSValue.Base).getNonReferenceType(),
+ LHSDesignator, RHSDesignator, WasArrayIndex);
// At the point where the designators diverge, the comparison has a
// specified value if:
// - we are comparing array indices
@@ -14680,7 +14682,7 @@ EvaluateComparisonBinaryOperator(EvalInfo &Info, const BinaryOperator *E,
// compare pointers within the object in question; otherwise, the result
// depends on where the object is located in memory.
if (!LHSValue.Base.isNull() && IsRelational) {
- QualType BaseTy = getType(LHSValue.Base);
+ QualType BaseTy = getType(LHSValue.Base).getNonReferenceType();
if (BaseTy->isIncompleteType())
return Error(E);
CharUnits Size = Info.Ctx.getTypeSizeInChars(BaseTy);
@@ -18184,6 +18186,10 @@ bool Expr::EvaluateCharRangeAsString(APValue &Result,
bool Expr::tryEvaluateStrLen(uint64_t &Result, ASTContext &Ctx) const {
Expr::EvalStatus Status;
EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold);
+
+ if (Info.EnableNewConstInterp)
+ return Info.Ctx.getInterpContext().evaluateStrlen(Info, this, Result);
+
return EvaluateBuiltinStrLen(this, Result, Info);
}
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index 3d9397f..6b524cf 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -843,7 +843,10 @@ void TextNodeDumper::Visit(const APValue &Value, QualType Ty) {
}
ColorScope Color(OS, ShowColors, DeclNameColor);
- OS << Value.getMemberPointerDecl()->getDeclName();
+ if (const ValueDecl *MemDecl = Value.getMemberPointerDecl())
+ OS << MemDecl->getDeclName();
+ else
+ OS << "null";
return;
}
case APValue::AddrLabelDiff:
diff --git a/clang/lib/Analysis/LifetimeSafety.cpp b/clang/lib/Analysis/LifetimeSafety.cpp
index e3a03cf..94b8197 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -23,9 +23,10 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/TimeProfiler.h"
#include <cstdint>
+#include <memory>
-namespace clang {
-namespace {
+namespace clang::lifetimes {
+namespace internal {
/// Represents the storage location being borrowed, e.g., a specific stack
/// variable.
@@ -36,32 +37,6 @@ struct AccessPath {
AccessPath(const clang::ValueDecl *D) : D(D) {}
};
-/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
-/// Used for giving ID to loans and origins.
-template <typename Tag> struct ID {
- uint32_t Value = 0;
-
- bool operator==(const ID<Tag> &Other) const { return Value == Other.Value; }
- bool operator!=(const ID<Tag> &Other) const { return !(*this == Other); }
- bool operator<(const ID<Tag> &Other) const { return Value < Other.Value; }
- ID<Tag> operator++(int) {
- ID<Tag> Tmp = *this;
- ++Value;
- return Tmp;
- }
- void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
- IDBuilder.AddInteger(Value);
- }
-};
-
-template <typename Tag>
-inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID<Tag> ID) {
- return OS << ID.Value;
-}
-
-using LoanID = ID<struct LoanTag>;
-using OriginID = ID<struct OriginTag>;
-
/// Information about a single borrow, or "Loan". A loan is created when a
/// reference or pointer is created.
struct Loan {
@@ -223,7 +198,9 @@ public:
/// An origin is propagated from a source to a destination (e.g., p = q).
AssignOrigin,
/// An origin escapes the function by flowing into the return value.
- ReturnOfOrigin
+ ReturnOfOrigin,
+ /// A marker for a specific point in the code, for testing.
+ TestPoint,
};
private:
@@ -310,6 +287,24 @@ public:
}
};
+/// A dummy-fact used to mark a specific point in the code for testing.
+/// It is generated by recognizing a `void("__lifetime_test_point_...")` cast.
+class TestPointFact : public Fact {
+ StringRef Annotation;
+
+public:
+ static bool classof(const Fact *F) { return F->getKind() == Kind::TestPoint; }
+
+ explicit TestPointFact(StringRef Annotation)
+ : Fact(Kind::TestPoint), Annotation(Annotation) {}
+
+ StringRef getAnnotation() const { return Annotation; }
+
+ void dump(llvm::raw_ostream &OS) const override {
+ OS << "TestPoint (Annotation: \"" << getAnnotation() << "\")\n";
+ }
+};
+
class FactManager {
public:
llvm::ArrayRef<const Fact *> getFacts(const CFGBlock *B) const {
@@ -363,6 +358,7 @@ private:
};
class FactGenerator : public ConstStmtVisitor<FactGenerator> {
+ using Base = ConstStmtVisitor<FactGenerator>;
public:
FactGenerator(FactManager &FactMgr, AnalysisDeclContext &AC)
@@ -458,6 +454,15 @@ public:
}
}
+ void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *FCE) {
+ // Check if this is a test point marker. If so, we are done with this
+ // expression.
+ if (VisitTestPoint(FCE))
+ return;
+ // Visit as normal otherwise.
+ Base::VisitCXXFunctionalCastExpr(FCE);
+ }
+
private:
// Check if a type has an origin.
bool hasOrigin(QualType QT) { return QT->isPointerOrReferenceType(); }
@@ -491,6 +496,27 @@ private:
}
}
+ /// Checks if the expression is a `void("__lifetime_test_point_...")` cast.
+ /// If so, creates a `TestPointFact` and returns true.
+ bool VisitTestPoint(const CXXFunctionalCastExpr *FCE) {
+ if (!FCE->getType()->isVoidType())
+ return false;
+
+ const auto *SubExpr = FCE->getSubExpr()->IgnoreParenImpCasts();
+ if (const auto *SL = dyn_cast<StringLiteral>(SubExpr)) {
+ llvm::StringRef LiteralValue = SL->getString();
+ const std::string Prefix = "__lifetime_test_point_";
+
+ if (LiteralValue.starts_with(Prefix)) {
+ StringRef Annotation = LiteralValue.drop_front(Prefix.length());
+ CurrentBlockFacts.push_back(
+ FactMgr.createFact<TestPointFact>(Annotation));
+ return true;
+ }
+ }
+ return false;
+ }
+
FactManager &FactMgr;
AnalysisDeclContext &AC;
llvm::SmallVector<Fact *> CurrentBlockFacts;
@@ -502,6 +528,13 @@ private:
enum class Direction { Forward, Backward };
+/// A `ProgramPoint` identifies a location in the CFG by pointing to a specific
+/// `Fact`. identified by a lifetime-related event (`Fact`).
+///
+/// A `ProgramPoint` has "after" semantics: it represents the location
+/// immediately after its corresponding `Fact`.
+using ProgramPoint = const Fact *;
+
/// A generic, policy-based driver for dataflow analyses. It combines
/// the dataflow runner and the transferer logic into a single class hierarchy.
///
@@ -524,14 +557,20 @@ template <typename Derived, typename LatticeType, Direction Dir>
class DataflowAnalysis {
public:
using Lattice = LatticeType;
- using Base = DataflowAnalysis<Derived, LatticeType, Dir>;
+ using Base = DataflowAnalysis<Derived, Lattice, Dir>;
private:
const CFG &Cfg;
AnalysisDeclContext &AC;
+ /// The dataflow state before a basic block is processed.
llvm::DenseMap<const CFGBlock *, Lattice> InStates;
+ /// The dataflow state after a basic block is processed.
llvm::DenseMap<const CFGBlock *, Lattice> OutStates;
+ /// The dataflow state at a Program Point.
+ /// In a forward analysis, this is the state after the Fact at that point has
+ /// been applied, while in a backward analysis, it is the state before.
+ llvm::DenseMap<ProgramPoint, Lattice> PerPointStates;
static constexpr bool isForward() { return Dir == Direction::Forward; }
@@ -577,6 +616,8 @@ public:
}
}
+ Lattice getState(ProgramPoint P) const { return PerPointStates.lookup(P); }
+
Lattice getInState(const CFGBlock *B) const { return InStates.lookup(B); }
Lattice getOutState(const CFGBlock *B) const { return OutStates.lookup(B); }
@@ -590,18 +631,23 @@ public:
getOutState(&B).dump(llvm::dbgs());
}
+private:
/// Computes the state at one end of a block by applying all its facts
/// sequentially to a given state from the other end.
- /// TODO: We might need to store intermediate states per-fact in the block for
- /// later analysis.
Lattice transferBlock(const CFGBlock *Block, Lattice State) {
auto Facts = AllFacts.getFacts(Block);
- if constexpr (isForward())
- for (const Fact *F : Facts)
+ if constexpr (isForward()) {
+ for (const Fact *F : Facts) {
State = transferFact(State, F);
- else
- for (const Fact *F : llvm::reverse(Facts))
+ PerPointStates[F] = State;
+ }
+ } else {
+ for (const Fact *F : llvm::reverse(Facts)) {
+ // In backward analysis, capture the state before applying the fact.
+ PerPointStates[F] = State;
State = transferFact(State, F);
+ }
+ }
return State;
}
@@ -617,6 +663,8 @@ public:
return D->transfer(In, *F->getAs<AssignOriginFact>());
case Fact::Kind::ReturnOfOrigin:
return D->transfer(In, *F->getAs<ReturnOfOriginFact>());
+ case Fact::Kind::TestPoint:
+ return D->transfer(In, *F->getAs<TestPointFact>());
}
llvm_unreachable("Unknown fact kind");
}
@@ -626,14 +674,16 @@ public:
Lattice transfer(Lattice In, const ExpireFact &) { return In; }
Lattice transfer(Lattice In, const AssignOriginFact &) { return In; }
Lattice transfer(Lattice In, const ReturnOfOriginFact &) { return In; }
+ Lattice transfer(Lattice In, const TestPointFact &) { return In; }
};
namespace utils {
/// Computes the union of two ImmutableSets.
template <typename T>
-llvm::ImmutableSet<T> join(llvm::ImmutableSet<T> A, llvm::ImmutableSet<T> B,
- typename llvm::ImmutableSet<T>::Factory &F) {
+static llvm::ImmutableSet<T> join(llvm::ImmutableSet<T> A,
+ llvm::ImmutableSet<T> B,
+ typename llvm::ImmutableSet<T>::Factory &F) {
if (A.getHeight() < B.getHeight())
std::swap(A, B);
for (const T &E : B)
@@ -646,7 +696,7 @@ llvm::ImmutableSet<T> join(llvm::ImmutableSet<T> A, llvm::ImmutableSet<T> B,
// efficient merge could be implemented using a Patricia Trie or HAMT
// instead of the current AVL-tree-based ImmutableMap.
template <typename K, typename V, typename Joiner>
-llvm::ImmutableMap<K, V>
+static llvm::ImmutableMap<K, V>
join(llvm::ImmutableMap<K, V> A, llvm::ImmutableMap<K, V> B,
typename llvm::ImmutableMap<K, V>::Factory &F, Joiner joinValues) {
if (A.getHeight() < B.getHeight())
@@ -670,10 +720,6 @@ join(llvm::ImmutableMap<K, V> A, llvm::ImmutableMap<K, V> B,
// Loan Propagation Analysis
// ========================================================================= //
-// Using LLVM's immutable collections is efficient for dataflow analysis
-// as it avoids deep copies during state transitions.
-// TODO(opt): Consider using a bitset to represent the set of loans.
-using LoanSet = llvm::ImmutableSet<LoanID>;
using OriginLoanMap = llvm::ImmutableMap<OriginID, LoanSet>;
/// An object to hold the factories for immutable collections, ensuring
@@ -769,6 +815,10 @@ public:
Factory.OriginMapFactory.add(In.Origins, DestOID, SrcLoans));
}
+ LoanSet getLoans(OriginID OID, ProgramPoint P) {
+ return getLoans(getState(P), OID);
+ }
+
private:
LoanSet getLoans(Lattice L, OriginID OID) {
if (auto *Loans = L.Origins.lookup(OID))
@@ -778,23 +828,118 @@ private:
};
// ========================================================================= //
+// Expired Loans Analysis
+// ========================================================================= //
+
+/// The dataflow lattice for tracking the set of expired loans.
+struct ExpiredLattice {
+ LoanSet Expired;
+
+ ExpiredLattice() : Expired(nullptr) {};
+ explicit ExpiredLattice(LoanSet S) : Expired(S) {}
+
+ bool operator==(const ExpiredLattice &Other) const {
+ return Expired == Other.Expired;
+ }
+ bool operator!=(const ExpiredLattice &Other) const {
+ return !(*this == Other);
+ }
+
+ void dump(llvm::raw_ostream &OS) const {
+ OS << "ExpiredLattice State:\n";
+ if (Expired.isEmpty())
+ OS << " <empty>\n";
+ for (const LoanID &LID : Expired)
+ OS << " Loan " << LID << " is expired\n";
+ }
+};
+
+/// The analysis that tracks which loans have expired.
+class ExpiredLoansAnalysis
+ : public DataflowAnalysis<ExpiredLoansAnalysis, ExpiredLattice,
+ Direction::Forward> {
+
+ LoanSet::Factory &Factory;
+
+public:
+ ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
+ LifetimeFactory &Factory)
+ : DataflowAnalysis(C, AC, F), Factory(Factory.LoanSetFactory) {}
+
+ using Base::transfer;
+
+ StringRef getAnalysisName() const { return "ExpiredLoans"; }
+
+ Lattice getInitialState() { return Lattice(Factory.getEmptySet()); }
+
+ /// Merges two lattices by taking the union of the expired loan sets.
+ Lattice join(Lattice L1, Lattice L2) const {
+ return Lattice(utils::join(L1.Expired, L2.Expired, Factory));
+ }
+
+ Lattice transfer(Lattice In, const ExpireFact &F) {
+ return Lattice(Factory.add(In.Expired, F.getLoanID()));
+ }
+
+ // Removes the loan from the set of expired loans.
+ //
+ // When a loan is re-issued (e.g., in a loop), it is no longer considered
+ // expired. A loan can be in the expired set at the point of issue due to
+ // the dataflow state from a previous loop iteration being propagated along
+ // a backedge in the CFG.
+ //
+ // Note: This has a subtle false-negative though where a loan from previous
+ // iteration is not overwritten by a reissue. This needs careful tracking
+ // of loans "across iterations" which can be considered for future
+ // enhancements.
+ //
+ // void foo(int safe) {
+ // int* p = &safe;
+ // int* q = &safe;
+ // while (condition()) {
+ // int x = 1;
+ // p = &x; // A loan to 'x' is issued to 'p' in every iteration.
+ // if (condition()) {
+ // q = p;
+ // }
+ // (void)*p; // OK — 'p' points to 'x' from new iteration.
+ // (void)*q; // UaF - 'q' still points to 'x' from previous iteration
+ // // which is now destroyed.
+ // }
+ // }
+ Lattice transfer(Lattice In, const IssueFact &F) {
+ return Lattice(Factory.remove(In.Expired, F.getLoanID()));
+ }
+};
+
+// ========================================================================= //
// TODO:
-// - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
// - Modify loan expiry analysis to answer `bool isExpired(Loan L, Point P)`
// - Modify origin liveness analysis to answer `bool isLive(Origin O, Point P)`
// - Using the above three to perform the final error reporting.
// ========================================================================= //
-} // anonymous namespace
-void runLifetimeSafetyAnalysis(const DeclContext &DC, const CFG &Cfg,
- AnalysisDeclContext &AC) {
+// ========================================================================= //
+// LifetimeSafetyAnalysis Class Implementation
+// ========================================================================= //
+
+// We need this here for unique_ptr with forward declared class.
+LifetimeSafetyAnalysis::~LifetimeSafetyAnalysis() = default;
+
+LifetimeSafetyAnalysis::LifetimeSafetyAnalysis(AnalysisDeclContext &AC)
+ : AC(AC), Factory(std::make_unique<LifetimeFactory>()),
+ FactMgr(std::make_unique<FactManager>()) {}
+
+void LifetimeSafetyAnalysis::run() {
llvm::TimeTraceScope TimeProfile("LifetimeSafetyAnalysis");
+
+ const CFG &Cfg = *AC.getCFG();
DEBUG_WITH_TYPE("PrintCFG", Cfg.dump(AC.getASTContext().getLangOpts(),
/*ShowColors=*/true));
- FactManager FactMgr;
- FactGenerator FactGen(FactMgr, AC);
+
+ FactGenerator FactGen(*FactMgr, AC);
FactGen.run();
- DEBUG_WITH_TYPE("LifetimeFacts", FactMgr.dump(Cfg, AC));
+ DEBUG_WITH_TYPE("LifetimeFacts", FactMgr->dump(Cfg, AC));
/// TODO(opt): Consider optimizing individual blocks before running the
/// dataflow analysis.
@@ -805,9 +950,65 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const CFG &Cfg,
/// blocks; only Decls are visible. Therefore, loans in a block that
/// never reach an Origin associated with a Decl can be safely dropped by
/// the analysis.
- LifetimeFactory Factory;
- LoanPropagationAnalysis LoanPropagation(Cfg, AC, FactMgr, Factory);
- LoanPropagation.run();
- DEBUG_WITH_TYPE("LifetimeLoanPropagation", LoanPropagation.dump());
+ LoanPropagation =
+ std::make_unique<LoanPropagationAnalysis>(Cfg, AC, *FactMgr, *Factory);
+ LoanPropagation->run();
+
+ ExpiredLoans =
+ std::make_unique<ExpiredLoansAnalysis>(Cfg, AC, *FactMgr, *Factory);
+ ExpiredLoans->run();
+}
+
+LoanSet LifetimeSafetyAnalysis::getLoansAtPoint(OriginID OID,
+ ProgramPoint PP) const {
+ assert(LoanPropagation && "Analysis has not been run.");
+ return LoanPropagation->getLoans(OID, PP);
+}
+
+LoanSet LifetimeSafetyAnalysis::getExpiredLoansAtPoint(ProgramPoint PP) const {
+ assert(ExpiredLoans && "ExpiredLoansAnalysis has not been run.");
+ return ExpiredLoans->getState(PP).Expired;
+}
+
+std::optional<OriginID>
+LifetimeSafetyAnalysis::getOriginIDForDecl(const ValueDecl *D) const {
+ assert(FactMgr && "FactManager not initialized");
+ // This assumes the OriginManager's `get` can find an existing origin.
+ // We might need a `find` method on OriginManager to avoid `getOrCreate` logic
+ // in a const-query context if that becomes an issue.
+ return FactMgr->getOriginMgr().get(*D);
+}
+
+std::vector<LoanID>
+LifetimeSafetyAnalysis::getLoanIDForVar(const VarDecl *VD) const {
+ assert(FactMgr && "FactManager not initialized");
+ std::vector<LoanID> Result;
+ for (const Loan &L : FactMgr->getLoanMgr().getLoans())
+ if (L.Path.D == VD)
+ Result.push_back(L.ID);
+ return Result;
+}
+
+llvm::StringMap<ProgramPoint> LifetimeSafetyAnalysis::getTestPoints() const {
+ assert(FactMgr && "FactManager not initialized");
+ llvm::StringMap<ProgramPoint> AnnotationToPointMap;
+ for (const CFGBlock *Block : *AC.getCFG()) {
+ for (const Fact *F : FactMgr->getFacts(Block)) {
+ if (const auto *TPF = F->getAs<TestPointFact>()) {
+ StringRef PointName = TPF->getAnnotation();
+ assert(AnnotationToPointMap.find(PointName) ==
+ AnnotationToPointMap.end() &&
+ "more than one test points with the same name");
+ AnnotationToPointMap[PointName] = F;
+ }
+ }
+ }
+ return AnnotationToPointMap;
+}
+} // namespace internal
+
+void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC) {
+ internal::LifetimeSafetyAnalysis Analysis(AC);
+ Analysis.run();
}
-} // namespace clang
+} // namespace clang::lifetimes
diff --git a/clang/lib/Analysis/plugins/CheckerDependencyHandling/CheckerDependencyHandling.cpp b/clang/lib/Analysis/plugins/CheckerDependencyHandling/CheckerDependencyHandling.cpp
index aacb886..518f9e7 100644
--- a/clang/lib/Analysis/plugins/CheckerDependencyHandling/CheckerDependencyHandling.cpp
+++ b/clang/lib/Analysis/plugins/CheckerDependencyHandling/CheckerDependencyHandling.cpp
@@ -2,6 +2,9 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
+// This barebones plugin is used by clang/test/Analysis/checker-plugins.c
+// to test dependency handling among checkers loaded from plugins.
+
using namespace clang;
using namespace ento;
@@ -15,12 +18,12 @@ struct DependendentChecker : public Checker<check::BeginFunction> {
} // end anonymous namespace
// Register plugin!
-extern "C" void clang_registerCheckers(CheckerRegistry &registry) {
- registry.addChecker<Dependency>("example.Dependency", "", "");
- registry.addChecker<DependendentChecker>("example.DependendentChecker", "",
- "");
+extern "C" void clang_registerCheckers(CheckerRegistry &Registry) {
+ Registry.addChecker<Dependency>("example.Dependency", "MockDescription");
+ Registry.addChecker<DependendentChecker>("example.DependendentChecker",
+ "MockDescription");
- registry.addDependency("example.DependendentChecker", "example.Dependency");
+ Registry.addDependency("example.DependendentChecker", "example.Dependency");
}
extern "C" const char clang_analyzerAPIVersionString[] =
diff --git a/clang/lib/Analysis/plugins/CheckerOptionHandling/CheckerOptionHandling.cpp b/clang/lib/Analysis/plugins/CheckerOptionHandling/CheckerOptionHandling.cpp
index 82c1058..2adb934 100644
--- a/clang/lib/Analysis/plugins/CheckerOptionHandling/CheckerOptionHandling.cpp
+++ b/clang/lib/Analysis/plugins/CheckerOptionHandling/CheckerOptionHandling.cpp
@@ -5,6 +5,9 @@
using namespace clang;
using namespace ento;
+// This barebones plugin is used by clang/test/Analysis/checker-plugins.c
+// to test option handling on checkers loaded from plugins.
+
namespace {
struct MyChecker : public Checker<check::BeginFunction> {
void checkBeginFunction(CheckerContext &Ctx) const {}
@@ -25,13 +28,11 @@ bool shouldRegisterMyChecker(const CheckerManager &mgr) { return true; }
} // end anonymous namespace
// Register plugin!
-extern "C" void clang_registerCheckers(CheckerRegistry &registry) {
- registry.addChecker(registerMyChecker, shouldRegisterMyChecker,
- "example.MyChecker", "Example Description",
- "example.mychecker.documentation.nonexistent.html",
- /*isHidden*/false);
+extern "C" void clang_registerCheckers(CheckerRegistry &Registry) {
+ Registry.addChecker(registerMyChecker, shouldRegisterMyChecker,
+ "example.MyChecker", "Example Description");
- registry.addCheckerOption(/*OptionType*/ "bool",
+ Registry.addCheckerOption(/*OptionType*/ "bool",
/*CheckerFullName*/ "example.MyChecker",
/*OptionName*/ "ExampleOption",
/*DefaultValStr*/ "false",
diff --git a/clang/lib/Analysis/plugins/SampleAnalyzer/MainCallChecker.cpp b/clang/lib/Analysis/plugins/SampleAnalyzer/MainCallChecker.cpp
index fd210d7..53a01d2 100644
--- a/clang/lib/Analysis/plugins/SampleAnalyzer/MainCallChecker.cpp
+++ b/clang/lib/Analysis/plugins/SampleAnalyzer/MainCallChecker.cpp
@@ -3,12 +3,16 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
+// This simple plugin is used by clang/test/Analysis/checker-plugins.c
+// to test the use of a checker that is defined in a plugin.
+
using namespace clang;
using namespace ento;
namespace {
class MainCallChecker : public Checker<check::PreStmt<CallExpr>> {
- mutable std::unique_ptr<BugType> BT;
+
+ const BugType BT{this, "call to main", "example analyzer plugin"};
public:
void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
@@ -33,21 +37,17 @@ void MainCallChecker::checkPreStmt(const CallExpr *CE,
if (!N)
return;
- if (!BT)
- BT.reset(new BugType(this, "call to main", "example analyzer plugin"));
-
auto report =
- std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);
+ std::make_unique<PathSensitiveBugReport>(BT, BT.getDescription(), N);
report->addRange(Callee->getSourceRange());
C.emitReport(std::move(report));
}
}
// Register plugin!
-extern "C" void clang_registerCheckers(CheckerRegistry &registry) {
- registry.addChecker<MainCallChecker>(
- "example.MainCallChecker", "Disallows calls to functions called main",
- "");
+extern "C" void clang_registerCheckers(CheckerRegistry &Registry) {
+ Registry.addChecker<MainCallChecker>("example.MainCallChecker",
+ "Example Description");
}
extern "C" const char clang_analyzerAPIVersionString[] =
diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp
index 09b6a1f..21fc084 100644
--- a/clang/lib/Basic/TargetInfo.cpp
+++ b/clang/lib/Basic/TargetInfo.cpp
@@ -172,7 +172,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) {
ComplexLongDoubleUsesFP2Ret = false;
// Set the C++ ABI based on the triple.
- TheCXXABI.set(Triple.isKnownWindowsMSVCEnvironment()
+ TheCXXABI.set(Triple.isKnownWindowsMSVCEnvironment() || Triple.isUEFI()
? TargetCXXABI::Microsoft
: TargetCXXABI::GenericItanium);
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index 5c2af9b..e3f9760 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -757,6 +757,9 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
case llvm::Triple::FreeBSD:
return std::make_unique<FreeBSDTargetInfo<LoongArch64TargetInfo>>(Triple,
Opts);
+ case llvm::Triple::OpenBSD:
+ return std::make_unique<OpenBSDTargetInfo<LoongArch64TargetInfo>>(Triple,
+ Opts);
default:
return std::make_unique<LoongArch64TargetInfo>(Triple, Opts);
}
diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp
index 72d2e5f..2b023e5 100644
--- a/clang/lib/Basic/Targets/AArch64.cpp
+++ b/clang/lib/Basic/Targets/AArch64.cpp
@@ -786,7 +786,8 @@ AArch64TargetInfo::getVScaleRange(const LangOptions &LangOpts,
return std::nullopt;
}
-uint64_t AArch64TargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const {
+llvm::APInt
+AArch64TargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const {
return llvm::AArch64::getFMVPriority(Features);
}
diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h
index f4277e9..dfd89be 100644
--- a/clang/lib/Basic/Targets/AArch64.h
+++ b/clang/lib/Basic/Targets/AArch64.h
@@ -152,7 +152,7 @@ public:
void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
bool setCPU(const std::string &Name) override;
- uint64_t getFMVPriority(ArrayRef<StringRef> Features) const override;
+ llvm::APInt getFMVPriority(ArrayRef<StringRef> Features) const override;
bool useFP16ConversionIntrinsics() const override {
return false;
diff --git a/clang/lib/Basic/Targets/ARM.cpp b/clang/lib/Basic/Targets/ARM.cpp
index 7ff8e51..29de34bb 100644
--- a/clang/lib/Basic/Targets/ARM.cpp
+++ b/clang/lib/Basic/Targets/ARM.cpp
@@ -623,13 +623,15 @@ bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
LDREX = LDREX_W;
break;
case 7:
+ case 8:
if (ArchProfile == llvm::ARM::ProfileKind::M)
LDREX = LDREX_W | LDREX_H | LDREX_B;
else
LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
break;
- case 8:
case 9:
+ assert(ArchProfile != llvm::ARM::ProfileKind::M &&
+ "No Armv9-M architectures defined");
LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
}
diff --git a/clang/lib/Basic/Targets/Mips.h b/clang/lib/Basic/Targets/Mips.h
index 35501ed..e199df3 100644
--- a/clang/lib/Basic/Targets/Mips.h
+++ b/clang/lib/Basic/Targets/Mips.h
@@ -129,7 +129,7 @@ public:
LongWidth = LongAlign = 32;
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
PointerWidth = PointerAlign = 32;
- PtrDiffType = SignedInt;
+ PtrDiffType = IntPtrType = SignedInt;
SizeType = UnsignedInt;
SuitableAlign = 64;
}
@@ -155,7 +155,7 @@ public:
IntMaxType = Int64Type;
LongWidth = LongAlign = 64;
PointerWidth = PointerAlign = 64;
- PtrDiffType = SignedLong;
+ PtrDiffType = IntPtrType = SignedLong;
SizeType = UnsignedLong;
}
@@ -165,7 +165,7 @@ public:
IntMaxType = Int64Type;
LongWidth = LongAlign = 32;
PointerWidth = PointerAlign = 32;
- PtrDiffType = SignedInt;
+ PtrDiffType = IntPtrType = SignedInt;
SizeType = UnsignedInt;
}
diff --git a/clang/lib/Basic/Targets/OSTargets.h b/clang/lib/Basic/Targets/OSTargets.h
index 42cff65..94b018a 100644
--- a/clang/lib/Basic/Targets/OSTargets.h
+++ b/clang/lib/Basic/Targets/OSTargets.h
@@ -496,6 +496,7 @@ public:
case llvm::Triple::sparcv9:
this->MCountName = "_mcount";
break;
+ case llvm::Triple::loongarch64:
case llvm::Triple::riscv64:
break;
}
diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp
index 8a28c07..a6a5ec4 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -568,7 +568,8 @@ ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const {
return Ret;
}
-uint64_t RISCVTargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const {
+llvm::APInt
+RISCVTargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const {
// Priority is explicitly specified on RISC-V unlike on other targets, where
// it is derived by all the features of a specific version. Therefore if a
// feature contains the priority string, then return it immediately.
@@ -580,12 +581,12 @@ uint64_t RISCVTargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const {
Feature = RHS;
else
continue;
- uint64_t Priority;
+ unsigned Priority;
if (!Feature.getAsInteger(0, Priority))
- return Priority;
+ return llvm::APInt(32, Priority);
}
// Default Priority is zero.
- return 0;
+ return llvm::APInt::getZero(32);
}
TargetInfo::CallingConvCheckResult
diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h
index 8d629ab..58bfad1 100644
--- a/clang/lib/Basic/Targets/RISCV.h
+++ b/clang/lib/Basic/Targets/RISCV.h
@@ -123,7 +123,7 @@ public:
void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override;
bool supportsTargetAttributeTune() const override { return true; }
ParsedTargetAttr parseTargetAttr(StringRef Str) const override;
- uint64_t getFMVPriority(ArrayRef<StringRef> Features) const override;
+ llvm::APInt getFMVPriority(ArrayRef<StringRef> Features) const override;
std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(32, 32);
diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp
index a1f5aa2..24ecec2 100644
--- a/clang/lib/Basic/Targets/X86.cpp
+++ b/clang/lib/Basic/Targets/X86.cpp
@@ -1390,8 +1390,8 @@ static llvm::X86::ProcessorFeatures getFeature(StringRef Name) {
// correct, so it asserts if the value is out of range.
}
-uint64_t X86TargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const {
- auto getPriority = [](StringRef Feature) -> uint64_t {
+llvm::APInt X86TargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const {
+ auto getPriority = [](StringRef Feature) -> unsigned {
// Valid CPUs have a 'key feature' that compares just better than its key
// feature.
using namespace llvm::X86;
@@ -1405,11 +1405,11 @@ uint64_t X86TargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const {
return getFeaturePriority(getFeature(Feature)) << 1;
};
- uint64_t Priority = 0;
+ unsigned Priority = 0;
for (StringRef Feature : Features)
if (!Feature.empty())
Priority = std::max(Priority, getPriority(Feature));
- return Priority;
+ return llvm::APInt(32, Priority);
}
bool X86TargetInfo::validateCPUSpecificCPUDispatch(StringRef Name) const {
diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h
index ebc59c9..eb15103 100644
--- a/clang/lib/Basic/Targets/X86.h
+++ b/clang/lib/Basic/Targets/X86.h
@@ -388,7 +388,7 @@ public:
return CPU != llvm::X86::CK_None;
}
- uint64_t getFMVPriority(ArrayRef<StringRef> Features) const override;
+ llvm::APInt getFMVPriority(ArrayRef<StringRef> Features) const override;
bool setFPMath(StringRef Name) override;
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 61d1c54..ef136f8 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -121,6 +121,13 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
return RValue::get(nullptr);
}
+ case Builtin::BI__builtin_assume_separate_storage: {
+ mlir::Value value0 = emitScalarExpr(e->getArg(0));
+ mlir::Value value1 = emitScalarExpr(e->getArg(1));
+ builder.create<cir::AssumeSepStorageOp>(loc, value0, value1);
+ return RValue::get(nullptr);
+ }
+
case Builtin::BI__builtin_complex: {
mlir::Value real = emitScalarExpr(e->getArg(0));
mlir::Value imag = emitScalarExpr(e->getArg(1));
diff --git a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
index eb079b8..5929568 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
+++ b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
@@ -75,6 +75,11 @@ public:
/// Emit dtor variants required by this ABI.
virtual void emitCXXDestructors(const clang::CXXDestructorDecl *d) = 0;
+ virtual void emitDestructorCall(CIRGenFunction &cgf,
+ const CXXDestructorDecl *dd, CXXDtorType type,
+ bool forVirtualBase, bool delegating,
+ Address thisAddr, QualType thisTy) = 0;
+
/// Returns true if the given destructor type should be emitted as a linkonce
/// delegating thunk, regardless of whether the dtor is defined in this TU or
/// not.
diff --git a/clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp
index 8da832d..67d8988 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp
@@ -246,6 +246,29 @@ static void emitNewInitializer(CIRGenFunction &cgf, const CXXNewExpr *e,
}
}
+RValue CIRGenFunction::emitCXXDestructorCall(
+ GlobalDecl dtor, const CIRGenCallee &callee, mlir::Value thisVal,
+ QualType thisTy, mlir::Value implicitParam, QualType implicitParamTy,
+ const CallExpr *ce) {
+ const CXXMethodDecl *dtorDecl = cast<CXXMethodDecl>(dtor.getDecl());
+
+ assert(!thisTy.isNull());
+ assert(thisTy->getAsCXXRecordDecl() == dtorDecl->getParent() &&
+ "Pointer/Object mixup");
+
+ assert(!cir::MissingFeatures::addressSpace());
+
+ CallArgList args;
+ commonBuildCXXMemberOrOperatorCall(*this, dtorDecl, thisVal, implicitParam,
+ implicitParamTy, ce, args, nullptr);
+ assert((ce || dtor.getDecl()) && "expected source location provider");
+ assert(!cir::MissingFeatures::opCallMustTail());
+ return emitCall(cgm.getTypes().arrangeCXXStructorDeclaration(dtor), callee,
+ ReturnValueSlot(), args, nullptr,
+ ce ? getLoc(ce->getExprLoc())
+ : getLoc(dtor.getDecl()->getSourceRange()));
+}
+
/// Emit a call to an operator new or operator delete function, as implicitly
/// created by new-expressions and delete-expressions.
static RValue emitNewDeleteCall(CIRGenFunction &cgf,
diff --git a/clang/lib/CIR/CodeGen/CIRGenClass.cpp b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
index 8667bb6..50cca0e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenClass.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
@@ -12,6 +12,7 @@
#include "CIRGenCXXABI.h"
#include "CIRGenFunction.h"
+#include "CIRGenValue.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecordLayout.h"
@@ -311,6 +312,116 @@ void CIRGenFunction::emitInitializerForField(FieldDecl *field, LValue lhs,
assert(!cir::MissingFeatures::requiresCleanups());
}
+/// Emit a loop to call a particular constructor for each of several members
+/// of an array.
+///
+/// \param ctor the constructor to call for each element
+/// \param arrayType the type of the array to initialize
+/// \param arrayBegin an arrayType*
+/// \param zeroInitialize true if each element should be
+/// zero-initialized before it is constructed
+void CIRGenFunction::emitCXXAggrConstructorCall(
+ const CXXConstructorDecl *ctor, const clang::ArrayType *arrayType,
+ Address arrayBegin, const CXXConstructExpr *e, bool newPointerIsChecked,
+ bool zeroInitialize) {
+ QualType elementType;
+ mlir::Value numElements = emitArrayLength(arrayType, elementType, arrayBegin);
+ emitCXXAggrConstructorCall(ctor, numElements, arrayBegin, e,
+ newPointerIsChecked, zeroInitialize);
+}
+
+/// Emit a loop to call a particular constructor for each of several members
+/// of an array.
+///
+/// \param ctor the constructor to call for each element
+/// \param numElements the number of elements in the array;
+/// may be zero
+/// \param arrayBase a T*, where T is the type constructed by ctor
+/// \param zeroInitialize true if each element should be
+/// zero-initialized before it is constructed
+void CIRGenFunction::emitCXXAggrConstructorCall(
+ const CXXConstructorDecl *ctor, mlir::Value numElements, Address arrayBase,
+ const CXXConstructExpr *e, bool newPointerIsChecked, bool zeroInitialize) {
+ // It's legal for numElements to be zero. This can happen both
+ // dynamically, because x can be zero in 'new A[x]', and statically,
+ // because of GCC extensions that permit zero-length arrays. There
+ // are probably legitimate places where we could assume that this
+ // doesn't happen, but it's not clear that it's worth it.
+
+ // Optimize for a constant count.
+ auto constantCount = dyn_cast<cir::ConstantOp>(numElements.getDefiningOp());
+ if (constantCount) {
+ auto constIntAttr = mlir::dyn_cast<cir::IntAttr>(constantCount.getValue());
+ // Just skip out if the constant count is zero.
+ if (constIntAttr && constIntAttr.getUInt() == 0)
+ return;
+ } else {
+ // Otherwise, emit the check.
+ cgm.errorNYI(e->getSourceRange(), "dynamic-length array expression");
+ }
+
+ auto arrayTy = mlir::cast<cir::ArrayType>(arrayBase.getElementType());
+ mlir::Type elementType = arrayTy.getElementType();
+ cir::PointerType ptrToElmType = builder.getPointerTo(elementType);
+
+ // Tradional LLVM codegen emits a loop here. CIR lowers to a loop as part of
+ // LoweringPrepare.
+
+ // The alignment of the base, adjusted by the size of a single element,
+ // provides a conservative estimate of the alignment of every element.
+ // (This assumes we never start tracking offsetted alignments.)
+ //
+ // Note that these are complete objects and so we don't need to
+ // use the non-virtual size or alignment.
+ QualType type = getContext().getTypeDeclType(ctor->getParent());
+ CharUnits eltAlignment = arrayBase.getAlignment().alignmentOfArrayElement(
+ getContext().getTypeSizeInChars(type));
+
+ // Zero initialize the storage, if requested.
+ if (zeroInitialize)
+ emitNullInitialization(*currSrcLoc, arrayBase, type);
+
+ // C++ [class.temporary]p4:
+ // There are two contexts in which temporaries are destroyed at a different
+ // point than the end of the full-expression. The first context is when a
+ // default constructor is called to initialize an element of an array.
+ // If the constructor has one or more default arguments, the destruction of
+ // every temporary created in a default argument expression is sequenced
+ // before the construction of the next array element, if any.
+ {
+ assert(!cir::MissingFeatures::runCleanupsScope());
+
+ // Evaluate the constructor and its arguments in a regular
+ // partial-destroy cleanup.
+ if (getLangOpts().Exceptions &&
+ !ctor->getParent()->hasTrivialDestructor()) {
+ cgm.errorNYI(e->getSourceRange(), "partial array cleanups");
+ }
+
+ // Emit the constructor call that will execute for every array element.
+ mlir::Value arrayOp =
+ builder.createPtrBitcast(arrayBase.getPointer(), arrayTy);
+ builder.create<cir::ArrayCtor>(
+ *currSrcLoc, arrayOp, [&](mlir::OpBuilder &b, mlir::Location loc) {
+ mlir::BlockArgument arg =
+ b.getInsertionBlock()->addArgument(ptrToElmType, loc);
+ Address curAddr = Address(arg, elementType, eltAlignment);
+ assert(!cir::MissingFeatures::sanitizers());
+ auto currAVS = AggValueSlot::forAddr(
+ curAddr, type.getQualifiers(), AggValueSlot::IsDestructed,
+ AggValueSlot::IsNotAliased, AggValueSlot::DoesNotOverlap,
+ AggValueSlot::IsNotZeroed);
+ emitCXXConstructorCall(ctor, Ctor_Complete,
+ /*ForVirtualBase=*/false,
+ /*Delegating=*/false, currAVS, e);
+ builder.create<cir::YieldOp>(loc);
+ });
+ }
+
+ if (constantCount.use_empty())
+ constantCount.erase();
+}
+
void CIRGenFunction::emitDelegateCXXConstructorCall(
const CXXConstructorDecl *ctor, CXXCtorType ctorType,
const FunctionArgList &args, SourceLocation loc) {
@@ -369,6 +480,19 @@ void CIRGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &args) {
s->getStmtClassName());
}
+void CIRGenFunction::destroyCXXObject(CIRGenFunction &cgf, Address addr,
+ QualType type) {
+ const RecordType *rtype = type->castAs<RecordType>();
+ const CXXRecordDecl *record = cast<CXXRecordDecl>(rtype->getDecl());
+ const CXXDestructorDecl *dtor = record->getDestructor();
+ // TODO(cir): Unlike traditional codegen, CIRGen should actually emit trivial
+ // dtors which shall be removed on later CIR passes. However, only remove this
+ // assertion after we have a test case to exercise this path.
+ assert(!dtor->isTrivial());
+ cgf.emitCXXDestructorCall(dtor, Dtor_Complete, /*forVirtualBase*/ false,
+ /*delegating=*/false, addr, type);
+}
+
void CIRGenFunction::emitDelegatingCXXConstructorCall(
const CXXConstructorDecl *ctor, const FunctionArgList &args) {
assert(ctor->isDelegatingConstructor());
@@ -392,6 +516,14 @@ void CIRGenFunction::emitDelegatingCXXConstructorCall(
}
}
+void CIRGenFunction::emitCXXDestructorCall(const CXXDestructorDecl *dd,
+ CXXDtorType type,
+ bool forVirtualBase, bool delegating,
+ Address thisAddr, QualType thisTy) {
+ cgm.getCXXABI().emitDestructorCall(*this, dd, type, forVirtualBase,
+ delegating, thisAddr, thisTy);
+}
+
Address CIRGenFunction::getAddressOfBaseClass(
Address value, const CXXRecordDecl *derived,
llvm::iterator_range<CastExpr::path_const_iterator> path,
diff --git a/clang/lib/CIR/CodeGen/CIRGenCleanup.cpp b/clang/lib/CIR/CodeGen/CIRGenCleanup.cpp
new file mode 100644
index 0000000..be21ce9
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenCleanup.cpp
@@ -0,0 +1,69 @@
+//===--- CIRGenCleanup.cpp - Bookkeeping and code emission for cleanups ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains code dealing with the IR generation for cleanups
+// and related information.
+//
+// A "cleanup" is a piece of code which needs to be executed whenever
+// control transfers out of a particular scope. This can be
+// conditionalized to occur only on exceptional control flow, only on
+// normal control flow, or both.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenFunction.h"
+
+#include "clang/CIR/MissingFeatures.h"
+
+using namespace clang;
+using namespace clang::CIRGen;
+
+//===----------------------------------------------------------------------===//
+// CIRGenFunction cleanup related
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// EHScopeStack
+//===----------------------------------------------------------------------===//
+
+void EHScopeStack::Cleanup::anchor() {}
+
+static mlir::Block *getCurCleanupBlock(CIRGenFunction &cgf) {
+ mlir::OpBuilder::InsertionGuard guard(cgf.getBuilder());
+ mlir::Block *cleanup =
+ cgf.curLexScope->getOrCreateCleanupBlock(cgf.getBuilder());
+ return cleanup;
+}
+
+/// Pops a cleanup block. If the block includes a normal cleanup, the
+/// current insertion point is threaded through the cleanup, as are
+/// any branch fixups on the cleanup.
+void CIRGenFunction::popCleanupBlock() {
+ assert(!ehStack.cleanupStack.empty() && "cleanup stack is empty!");
+ mlir::OpBuilder::InsertionGuard guard(builder);
+ std::unique_ptr<EHScopeStack::Cleanup> cleanup =
+ ehStack.cleanupStack.pop_back_val();
+
+ assert(!cir::MissingFeatures::ehCleanupFlags());
+ mlir::Block *cleanupEntry = getCurCleanupBlock(*this);
+ builder.setInsertionPointToEnd(cleanupEntry);
+ cleanup->emit(*this);
+}
+
+/// Pops cleanup blocks until the given savepoint is reached.
+void CIRGenFunction::popCleanupBlocks(size_t oldCleanupStackDepth) {
+ assert(!cir::MissingFeatures::ehstackBranches());
+
+ assert(ehStack.getStackDepth() >= oldCleanupStackDepth);
+
+ // Pop cleanup blocks until we reach the base stack depth for the
+ // current scope.
+ while (ehStack.getStackDepth() > oldCleanupStackDepth) {
+ popCleanupBlock();
+ }
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
index afbe92a..a28ac3c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
@@ -183,8 +183,8 @@ void CIRGenFunction::emitAutoVarCleanups(
const VarDecl &d = *emission.Variable;
// Check the type for a cleanup.
- if (d.needsDestruction(getContext()))
- cgm.errorNYI(d.getSourceRange(), "emitAutoVarCleanups: type cleanup");
+ if (QualType::DestructionKind dtorKind = d.needsDestruction(getContext()))
+ emitAutoVarTypeCleanup(emission, dtorKind);
assert(!cir::MissingFeatures::opAllocaPreciseLifetime());
@@ -648,3 +648,96 @@ void CIRGenFunction::emitNullabilityCheck(LValue lhs, mlir::Value rhs,
assert(!cir::MissingFeatures::sanitizers());
}
+
+/// Immediately perform the destruction of the given object.
+///
+/// \param addr - the address of the object; a type*
+/// \param type - the type of the object; if an array type, all
+/// objects are destroyed in reverse order
+/// \param destroyer - the function to call to destroy individual
+/// elements
+void CIRGenFunction::emitDestroy(Address addr, QualType type,
+ Destroyer *destroyer) {
+ if (getContext().getAsArrayType(type))
+ cgm.errorNYI("emitDestroy: array type");
+
+ return destroyer(*this, addr, type);
+}
+
+CIRGenFunction::Destroyer *
+CIRGenFunction::getDestroyer(QualType::DestructionKind kind) {
+ switch (kind) {
+ case QualType::DK_none:
+ llvm_unreachable("no destroyer for trivial dtor");
+ case QualType::DK_cxx_destructor:
+ return destroyCXXObject;
+ case QualType::DK_objc_strong_lifetime:
+ case QualType::DK_objc_weak_lifetime:
+ case QualType::DK_nontrivial_c_struct:
+ cgm.errorNYI("getDestroyer: other destruction kind");
+ return nullptr;
+ }
+ llvm_unreachable("Unknown DestructionKind");
+}
+
+namespace {
+struct DestroyObject final : EHScopeStack::Cleanup {
+ DestroyObject(Address addr, QualType type,
+ CIRGenFunction::Destroyer *destroyer)
+ : addr(addr), type(type), destroyer(destroyer) {}
+
+ Address addr;
+ QualType type;
+ CIRGenFunction::Destroyer *destroyer;
+
+ void emit(CIRGenFunction &cgf) override {
+ cgf.emitDestroy(addr, type, destroyer);
+ }
+};
+} // namespace
+
+/// Enter a destroy cleanup for the given local variable.
+void CIRGenFunction::emitAutoVarTypeCleanup(
+ const CIRGenFunction::AutoVarEmission &emission,
+ QualType::DestructionKind dtorKind) {
+ assert(dtorKind != QualType::DK_none);
+
+ // Note that for __block variables, we want to destroy the
+ // original stack object, not the possibly forwarded object.
+ Address addr = emission.getObjectAddress(*this);
+
+ const VarDecl *var = emission.Variable;
+ QualType type = var->getType();
+
+ CleanupKind cleanupKind = NormalAndEHCleanup;
+ CIRGenFunction::Destroyer *destroyer = nullptr;
+
+ switch (dtorKind) {
+ case QualType::DK_none:
+ llvm_unreachable("no cleanup for trivially-destructible variable");
+
+ case QualType::DK_cxx_destructor:
+ // If there's an NRVO flag on the emission, we need a different
+ // cleanup.
+ if (emission.NRVOFlag) {
+ cgm.errorNYI(var->getSourceRange(), "emitAutoVarTypeCleanup: NRVO");
+ return;
+ }
+ // Otherwise, this is handled below.
+ break;
+
+ case QualType::DK_objc_strong_lifetime:
+ case QualType::DK_objc_weak_lifetime:
+ case QualType::DK_nontrivial_c_struct:
+ cgm.errorNYI(var->getSourceRange(),
+ "emitAutoVarTypeCleanup: other dtor kind");
+ return;
+ }
+
+ // If we haven't chosen a more specific destroyer, use the default.
+ if (!destroyer)
+ destroyer = getDestroyer(dtorKind);
+
+ assert(!cir::MissingFeatures::ehCleanupFlags());
+ ehStack.pushCleanup<DestroyObject>(cleanupKind, addr, type, destroyer);
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 1f64801..7ff5f26 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -1657,37 +1657,38 @@ void CIRGenFunction::emitCXXConstructExpr(const CXXConstructExpr *e,
return;
}
- if (getContext().getAsArrayType(e->getType())) {
- cgm.errorNYI(e->getSourceRange(), "emitCXXConstructExpr: array type");
- return;
- }
+ if (const ArrayType *arrayType = getContext().getAsArrayType(e->getType())) {
+ assert(!cir::MissingFeatures::sanitizers());
+ emitCXXAggrConstructorCall(cd, arrayType, dest.getAddress(), e, false);
+ } else {
- clang::CXXCtorType type = Ctor_Complete;
- bool forVirtualBase = false;
- bool delegating = false;
-
- switch (e->getConstructionKind()) {
- case CXXConstructionKind::Complete:
- type = Ctor_Complete;
- break;
- case CXXConstructionKind::Delegating:
- // We should be emitting a constructor; GlobalDecl will assert this
- type = curGD.getCtorType();
- delegating = true;
- break;
- case CXXConstructionKind::VirtualBase:
- // This should just set 'forVirtualBase' to true and fall through, but
- // virtual base class support is otherwise missing, so this needs to wait
- // until it can be tested.
- cgm.errorNYI(e->getSourceRange(),
- "emitCXXConstructExpr: virtual base constructor");
- return;
- case CXXConstructionKind::NonVirtualBase:
- type = Ctor_Base;
- break;
- }
+ clang::CXXCtorType type = Ctor_Complete;
+ bool forVirtualBase = false;
+ bool delegating = false;
- emitCXXConstructorCall(cd, type, forVirtualBase, delegating, dest, e);
+ switch (e->getConstructionKind()) {
+ case CXXConstructionKind::Complete:
+ type = Ctor_Complete;
+ break;
+ case CXXConstructionKind::Delegating:
+ // We should be emitting a constructor; GlobalDecl will assert this
+ type = curGD.getCtorType();
+ delegating = true;
+ break;
+ case CXXConstructionKind::VirtualBase:
+ // This should just set 'forVirtualBase' to true and fall through, but
+ // virtual base class support is otherwise missing, so this needs to wait
+ // until it can be tested.
+ cgm.errorNYI(e->getSourceRange(),
+ "emitCXXConstructExpr: virtual base constructor");
+ return;
+ case CXXConstructionKind::NonVirtualBase:
+ type = Ctor_Base;
+ break;
+ }
+
+ emitCXXConstructorCall(cd, type, forVirtualBase, delegating, dest, e);
+ }
}
RValue CIRGenFunction::emitReferenceBindingToExpr(const Expr *e) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
index 6756a7c..7f2e2ce 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
@@ -34,11 +34,20 @@ public:
}
mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc);
+
/// Store the specified real/imag parts into the
/// specified value pointer.
void emitStoreOfComplex(mlir::Location loc, mlir::Value val, LValue lv,
bool isInit);
+ /// Emit a cast from complex value Val to DestType.
+ mlir::Value emitComplexToComplexCast(mlir::Value value, QualType srcType,
+ QualType destType, SourceLocation loc);
+
+ /// Emit a cast from scalar value Val to DestType.
+ mlir::Value emitScalarToComplexCast(mlir::Value value, QualType srcType,
+ QualType destType, SourceLocation loc);
+
mlir::Value
VisitAbstractConditionalOperator(const AbstractConditionalOperator *e);
mlir::Value VisitArraySubscriptExpr(Expr *e);
@@ -164,14 +173,110 @@ LValue ComplexExprEmitter::emitBinAssignLValue(const BinaryOperator *e,
mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op,
QualType destTy) {
switch (ck) {
+ case CK_Dependent:
+ llvm_unreachable("dependent type must be resolved before the CIR codegen");
+
case CK_NoOp:
case CK_LValueToRValue:
return Visit(op);
- default:
- break;
+
+ case CK_AtomicToNonAtomic:
+ case CK_NonAtomicToAtomic:
+ case CK_UserDefinedConversion: {
+ cgf.cgm.errorNYI(
+ "ComplexExprEmitter::emitCast Atmoic & UserDefinedConversion");
+ return {};
}
- cgf.cgm.errorNYI("ComplexType Cast");
- return {};
+
+ case CK_LValueBitCast: {
+ cgf.cgm.errorNYI("ComplexExprEmitter::emitCast CK_LValueBitCast");
+ return {};
+ }
+
+ case CK_LValueToRValueBitCast: {
+ LValue sourceLVal = cgf.emitLValue(op);
+ Address addr = sourceLVal.getAddress().withElementType(
+ builder, cgf.convertTypeForMem(destTy));
+ LValue destLV = cgf.makeAddrLValue(addr, destTy);
+ assert(!cir::MissingFeatures::opTBAA());
+ return emitLoadOfLValue(destLV, op->getExprLoc());
+ }
+
+ case CK_BitCast:
+ case CK_BaseToDerived:
+ case CK_DerivedToBase:
+ case CK_UncheckedDerivedToBase:
+ case CK_Dynamic:
+ case CK_ToUnion:
+ case CK_ArrayToPointerDecay:
+ case CK_FunctionToPointerDecay:
+ case CK_NullToPointer:
+ case CK_NullToMemberPointer:
+ case CK_BaseToDerivedMemberPointer:
+ case CK_DerivedToBaseMemberPointer:
+ case CK_MemberPointerToBoolean:
+ case CK_ReinterpretMemberPointer:
+ case CK_ConstructorConversion:
+ case CK_IntegralToPointer:
+ case CK_PointerToIntegral:
+ case CK_PointerToBoolean:
+ case CK_ToVoid:
+ case CK_VectorSplat:
+ case CK_IntegralCast:
+ case CK_BooleanToSignedIntegral:
+ case CK_IntegralToBoolean:
+ case CK_IntegralToFloating:
+ case CK_FloatingToIntegral:
+ case CK_FloatingToBoolean:
+ case CK_FloatingCast:
+ case CK_CPointerToObjCPointerCast:
+ case CK_BlockPointerToObjCPointerCast:
+ case CK_AnyPointerToBlockPointerCast:
+ case CK_ObjCObjectLValueCast:
+ case CK_FloatingComplexToReal:
+ case CK_FloatingComplexToBoolean:
+ case CK_IntegralComplexToReal:
+ case CK_IntegralComplexToBoolean:
+ case CK_ARCProduceObject:
+ case CK_ARCConsumeObject:
+ case CK_ARCReclaimReturnedObject:
+ case CK_ARCExtendBlockObject:
+ case CK_CopyAndAutoreleaseBlockObject:
+ case CK_BuiltinFnToFnPtr:
+ case CK_ZeroToOCLOpaqueType:
+ case CK_AddressSpaceConversion:
+ case CK_IntToOCLSampler:
+ case CK_FloatingToFixedPoint:
+ case CK_FixedPointToFloating:
+ case CK_FixedPointCast:
+ case CK_FixedPointToBoolean:
+ case CK_FixedPointToIntegral:
+ case CK_IntegralToFixedPoint:
+ case CK_MatrixCast:
+ case CK_HLSLVectorTruncation:
+ case CK_HLSLArrayRValue:
+ case CK_HLSLElementwiseCast:
+ case CK_HLSLAggregateSplatCast:
+ llvm_unreachable("invalid cast kind for complex value");
+
+ case CK_FloatingRealToComplex:
+ case CK_IntegralRealToComplex: {
+ assert(!cir::MissingFeatures::cgFPOptionsRAII());
+ return emitScalarToComplexCast(cgf.emitScalarExpr(op), op->getType(),
+ destTy, op->getExprLoc());
+ }
+
+ case CK_FloatingComplexCast:
+ case CK_FloatingComplexToIntegralComplex:
+ case CK_IntegralComplexCast:
+ case CK_IntegralComplexToFloatingComplex: {
+ assert(!cir::MissingFeatures::cgFPOptionsRAII());
+ return emitComplexToComplexCast(Visit(op), op->getType(), destTy,
+ op->getExprLoc());
+ }
+ }
+
+ llvm_unreachable("unknown cast resulting in complex value");
}
mlir::Value ComplexExprEmitter::emitConstant(
@@ -207,6 +312,49 @@ void ComplexExprEmitter::emitStoreOfComplex(mlir::Location loc, mlir::Value val,
builder.createStore(loc, val, destAddr);
}
+mlir::Value ComplexExprEmitter::emitComplexToComplexCast(mlir::Value val,
+ QualType srcType,
+ QualType destType,
+ SourceLocation loc) {
+ if (srcType == destType)
+ return val;
+
+ // Get the src/dest element type.
+ QualType srcElemTy = srcType->castAs<ComplexType>()->getElementType();
+ QualType destElemTy = destType->castAs<ComplexType>()->getElementType();
+
+ cir::CastKind castOpKind;
+ if (srcElemTy->isFloatingType() && destElemTy->isFloatingType())
+ castOpKind = cir::CastKind::float_complex;
+ else if (srcElemTy->isFloatingType() && destElemTy->isIntegerType())
+ castOpKind = cir::CastKind::float_complex_to_int_complex;
+ else if (srcElemTy->isIntegerType() && destElemTy->isFloatingType())
+ castOpKind = cir::CastKind::int_complex_to_float_complex;
+ else if (srcElemTy->isIntegerType() && destElemTy->isIntegerType())
+ castOpKind = cir::CastKind::int_complex;
+ else
+ llvm_unreachable("unexpected src type or dest type");
+
+ return builder.createCast(cgf.getLoc(loc), castOpKind, val,
+ cgf.convertType(destType));
+}
+
+mlir::Value ComplexExprEmitter::emitScalarToComplexCast(mlir::Value val,
+ QualType srcType,
+ QualType destType,
+ SourceLocation loc) {
+ cir::CastKind castOpKind;
+ if (srcType->isFloatingType())
+ castOpKind = cir::CastKind::float_to_complex;
+ else if (srcType->isIntegerType())
+ castOpKind = cir::CastKind::int_to_complex;
+ else
+ llvm_unreachable("unexpected src type");
+
+ return builder.createCast(cgf.getLoc(loc), castOpKind, val,
+ cgf.convertType(destType));
+}
+
mlir::Value ComplexExprEmitter::VisitAbstractConditionalOperator(
const AbstractConditionalOperator *e) {
mlir::Value condValue = Visit(e->getCond());
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index eba6bff..2523b0f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -88,6 +88,10 @@ public:
// Utilities
//===--------------------------------------------------------------------===//
+ mlir::Value emitComplexToScalarConversion(mlir::Location loc,
+ mlir::Value value, CastKind kind,
+ QualType destTy);
+
mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType) {
return builder.createFloatingCast(result, cgf.convertType(promotionType));
}
@@ -1125,7 +1129,7 @@ LValue ScalarExprEmitter::emitCompoundAssignLValue(
// 'An assignment expression has the value of the left operand after the
// assignment...'.
if (lhsLV.isBitField())
- cgf.cgm.errorNYI(e->getSourceRange(), "store through bitfield lvalue");
+ cgf.emitStoreThroughBitfieldLValue(RValue::get(result), lhsLV);
else
cgf.emitStoreThroughLValue(RValue::get(result), lhsLV);
@@ -1135,6 +1139,31 @@ LValue ScalarExprEmitter::emitCompoundAssignLValue(
return lhsLV;
}
+mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
+ mlir::Value value,
+ CastKind kind,
+ QualType destTy) {
+ cir::CastKind castOpKind;
+ switch (kind) {
+ case CK_FloatingComplexToReal:
+ castOpKind = cir::CastKind::float_complex_to_real;
+ break;
+ case CK_IntegralComplexToReal:
+ castOpKind = cir::CastKind::int_complex_to_real;
+ break;
+ case CK_FloatingComplexToBoolean:
+ castOpKind = cir::CastKind::float_complex_to_bool;
+ break;
+ case CK_IntegralComplexToBoolean:
+ castOpKind = cir::CastKind::int_complex_to_bool;
+ break;
+ default:
+ llvm_unreachable("invalid complex-to-scalar cast kind");
+ }
+
+ return builder.createCast(lov, castOpKind, value, cgf.convertType(destTy));
+}
+
mlir::Value ScalarExprEmitter::emitPromoted(const Expr *e,
QualType promotionType) {
e = e->IgnoreParens();
@@ -1758,6 +1787,15 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
ce->getExprLoc(), opts);
}
+ case CK_FloatingComplexToReal:
+ case CK_IntegralComplexToReal:
+ case CK_FloatingComplexToBoolean:
+ case CK_IntegralComplexToBoolean: {
+ mlir::Value value = cgf.emitComplexExpr(subExpr);
+ return emitComplexToScalarConversion(cgf.getLoc(ce->getExprLoc()), value,
+ kind, destTy);
+ }
+
case CK_FloatingRealToComplex:
case CK_FloatingComplexCast:
case CK_IntegralRealToComplex:
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index 7e1a44c..b4b95d6 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -26,7 +26,11 @@ namespace clang::CIRGen {
CIRGenFunction::CIRGenFunction(CIRGenModule &cgm, CIRGenBuilderTy &builder,
bool suppressNewContext)
- : CIRGenTypeCache(cgm), cgm{cgm}, builder(builder) {}
+ : CIRGenTypeCache(cgm), cgm{cgm}, builder(builder) {
+ ehStack.setCGF(this);
+ currentCleanupStackDepth = 0;
+ assert(ehStack.getStackDepth() == 0);
+}
CIRGenFunction::~CIRGenFunction() {}
@@ -227,6 +231,14 @@ void CIRGenFunction::LexicalScope::cleanup() {
CIRGenBuilderTy &builder = cgf.builder;
LexicalScope *localScope = cgf.curLexScope;
+ auto applyCleanup = [&]() {
+ if (performCleanup) {
+ // ApplyDebugLocation
+ assert(!cir::MissingFeatures::generateDebugInfo());
+ forceCleanup();
+ }
+ };
+
if (returnBlock != nullptr) {
// Write out the return block, which loads the value from `__retval` and
// issues the `cir.return`.
@@ -235,32 +247,42 @@ void CIRGenFunction::LexicalScope::cleanup() {
(void)emitReturn(*returnLoc);
}
- mlir::Block *curBlock = builder.getBlock();
- if (isGlobalInit() && !curBlock)
- return;
- if (curBlock->mightHaveTerminator() && curBlock->getTerminator())
- return;
-
- // Get rid of any empty block at the end of the scope.
- bool entryBlock = builder.getInsertionBlock()->isEntryBlock();
- if (!entryBlock && curBlock->empty()) {
- curBlock->erase();
- if (returnBlock != nullptr && returnBlock->getUses().empty())
- returnBlock->erase();
- return;
- }
-
- // Reached the end of the scope.
- {
+ auto insertCleanupAndLeave = [&](mlir::Block *insPt) {
mlir::OpBuilder::InsertionGuard guard(builder);
- builder.setInsertionPointToEnd(curBlock);
+ builder.setInsertionPointToEnd(insPt);
+
+ // If we still don't have a cleanup block, it means that `applyCleanup`
+ // below might be able to get us one.
+ mlir::Block *cleanupBlock = localScope->getCleanupBlock(builder);
+
+ // Leverage and defers to RunCleanupsScope's dtor and scope handling.
+ applyCleanup();
+
+ // If we now have one after `applyCleanup`, hook it up properly.
+ if (!cleanupBlock && localScope->getCleanupBlock(builder)) {
+ cleanupBlock = localScope->getCleanupBlock(builder);
+ builder.create<cir::BrOp>(insPt->back().getLoc(), cleanupBlock);
+ if (!cleanupBlock->mightHaveTerminator()) {
+ mlir::OpBuilder::InsertionGuard guard(builder);
+ builder.setInsertionPointToEnd(cleanupBlock);
+ builder.create<cir::YieldOp>(localScope->endLoc);
+ }
+ }
if (localScope->depth == 0) {
// Reached the end of the function.
if (returnBlock != nullptr) {
- if (returnBlock->getUses().empty())
+ if (returnBlock->getUses().empty()) {
returnBlock->erase();
- else {
+ } else {
+ // Thread return block via cleanup block.
+ if (cleanupBlock) {
+ for (mlir::BlockOperand &blockUse : returnBlock->getUses()) {
+ cir::BrOp brOp = mlir::cast<cir::BrOp>(blockUse.getOwner());
+ brOp.setSuccessor(cleanupBlock);
+ }
+ }
+
builder.create<cir::BrOp>(*returnLoc, returnBlock);
return;
}
@@ -268,13 +290,50 @@ void CIRGenFunction::LexicalScope::cleanup() {
emitImplicitReturn();
return;
}
- // Reached the end of a non-function scope. Some scopes, such as those
- // used with the ?: operator, can return a value.
- if (!localScope->isTernary() && !curBlock->mightHaveTerminator()) {
+
+ // End of any local scope != function
+ // Ternary ops have to deal with matching arms for yielding types
+ // and do return a value, it must do its own cir.yield insertion.
+ if (!localScope->isTernary() && !insPt->mightHaveTerminator()) {
!retVal ? builder.create<cir::YieldOp>(localScope->endLoc)
: builder.create<cir::YieldOp>(localScope->endLoc, retVal);
}
+ };
+
+ // If a cleanup block has been created at some point, branch to it
+ // and set the insertion point to continue at the cleanup block.
+ // Terminators are then inserted either in the cleanup block or
+ // inline in this current block.
+ mlir::Block *cleanupBlock = localScope->getCleanupBlock(builder);
+ if (cleanupBlock)
+ insertCleanupAndLeave(cleanupBlock);
+
+ // Now deal with any pending block wrap up like implicit end of
+ // scope.
+
+ mlir::Block *curBlock = builder.getBlock();
+ if (isGlobalInit() && !curBlock)
+ return;
+ if (curBlock->mightHaveTerminator() && curBlock->getTerminator())
+ return;
+
+ // Get rid of any empty block at the end of the scope.
+ bool entryBlock = builder.getInsertionBlock()->isEntryBlock();
+ if (!entryBlock && curBlock->empty()) {
+ curBlock->erase();
+ if (returnBlock != nullptr && returnBlock->getUses().empty())
+ returnBlock->erase();
+ return;
}
+
+ // If there's a cleanup block, branch to it, nothing else to do.
+ if (cleanupBlock) {
+ builder.create<cir::BrOp>(curBlock->back().getLoc(), cleanupBlock);
+ return;
+ }
+
+ // No pre-existent cleanup block, emit cleanup code and yield/return.
+ insertCleanupAndLeave(curBlock);
}
cir::ReturnOp CIRGenFunction::LexicalScope::emitReturn(mlir::Location loc) {
@@ -408,7 +467,19 @@ void CIRGenFunction::startFunction(GlobalDecl gd, QualType returnType,
}
}
-void CIRGenFunction::finishFunction(SourceLocation endLoc) {}
+void CIRGenFunction::finishFunction(SourceLocation endLoc) {
+ // Pop any cleanups that might have been associated with the
+ // parameters. Do this in whatever block we're currently in; it's
+ // important to do this before we enter the return block or return
+ // edges will be *really* confused.
+ // TODO(cir): Use prologueCleanupDepth here.
+ bool hasCleanups = ehStack.getStackDepth() != currentCleanupStackDepth;
+ if (hasCleanups) {
+ assert(!cir::MissingFeatures::generateDebugInfo());
+ // FIXME(cir): should we clearInsertionPoint? breaks many testcases
+ popCleanupBlocks(currentCleanupStackDepth);
+ }
+}
mlir::LogicalResult CIRGenFunction::emitFunctionBody(const clang::Stmt *body) {
auto result = mlir::LogicalResult::success();
@@ -593,11 +664,12 @@ void CIRGenFunction::emitDestructorBody(FunctionArgList &args) {
assert(!cir::MissingFeatures::dtorCleanups());
- // TODO(cir): A complete destructor is supposed to call the base destructor.
- // Since we have to emit both dtor kinds we just fall through for now and.
- // As long as we don't support virtual bases this should be functionally
- // equivalent.
- assert(!cir::MissingFeatures::completeDtors());
+ if (!isTryBody) {
+ QualType thisTy = dtor->getFunctionObjectParameterType();
+ emitCXXDestructorCall(dtor, Dtor_Base, /*forVirtualBase=*/false,
+ /*delegating=*/false, loadCXXThisAddress(), thisTy);
+ break;
+ }
// Fallthrough: act like we're in the base variant.
[[fallthrough]];
@@ -807,4 +879,48 @@ bool CIRGenFunction::shouldNullCheckClassCastValue(const CastExpr *ce) {
return true;
}
+/// Computes the length of an array in elements, as well as the base
+/// element type and a properly-typed first element pointer.
+mlir::Value
+CIRGenFunction::emitArrayLength(const clang::ArrayType *origArrayType,
+ QualType &baseType, Address &addr) {
+ const clang::ArrayType *arrayType = origArrayType;
+
+ // If it's a VLA, we have to load the stored size. Note that
+ // this is the size of the VLA in bytes, not its size in elements.
+ if (isa<VariableArrayType>(arrayType)) {
+ assert(cir::MissingFeatures::vlas());
+ cgm.errorNYI(*currSrcLoc, "VLAs");
+ return builder.getConstInt(*currSrcLoc, SizeTy, 0);
+ }
+
+ uint64_t countFromCLAs = 1;
+ QualType eltType;
+
+ auto cirArrayType = mlir::dyn_cast<cir::ArrayType>(addr.getElementType());
+
+ while (cirArrayType) {
+ assert(isa<ConstantArrayType>(arrayType));
+ countFromCLAs *= cirArrayType.getSize();
+ eltType = arrayType->getElementType();
+
+ cirArrayType =
+ mlir::dyn_cast<cir::ArrayType>(cirArrayType.getElementType());
+
+ arrayType = getContext().getAsArrayType(arrayType->getElementType());
+ assert((!cirArrayType || arrayType) &&
+ "CIR and Clang types are out-of-sync");
+ }
+
+ if (arrayType) {
+ // From this point onwards, the Clang array type has been emitted
+ // as some other type (probably a packed struct). Compute the array
+ // size, and just emit the 'begin' expression as a bitcast.
+ cgm.errorNYI(*currSrcLoc, "length for non-array underlying types");
+ }
+
+ baseType = eltType;
+ return builder.getConstInt(*currSrcLoc, SizeTy, countFromCLAs);
+}
+
} // namespace clang::CIRGen
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 12484196..4891c74 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -18,6 +18,7 @@
#include "CIRGenModule.h"
#include "CIRGenTypeCache.h"
#include "CIRGenValue.h"
+#include "EHScopeStack.h"
#include "Address.h"
@@ -61,6 +62,9 @@ public:
/// The compiler-generated variable that holds the return value.
std::optional<mlir::Value> fnRetAlloca;
+ /// Tracks function scope overall cleanup handling.
+ EHScopeStack ehStack;
+
/// CXXThisDecl - When generating code for a C++ member function,
/// this will hold the implicit 'this' declaration.
ImplicitParamDecl *cxxabiThisDecl = nullptr;
@@ -595,14 +599,65 @@ public:
FunctionArgList args, clang::SourceLocation loc,
clang::SourceLocation startLoc);
+ /// Takes the old cleanup stack size and emits the cleanup blocks
+ /// that have been added.
+ void popCleanupBlocks(size_t oldCleanupStackDepth);
+ void popCleanupBlock();
+
+ /// Enters a new scope for capturing cleanups, all of which
+ /// will be executed once the scope is exited.
+ class RunCleanupsScope {
+ size_t cleanupStackDepth, oldCleanupStackDepth;
+
+ protected:
+ bool performCleanup;
+
+ private:
+ RunCleanupsScope(const RunCleanupsScope &) = delete;
+ void operator=(const RunCleanupsScope &) = delete;
+
+ protected:
+ CIRGenFunction &cgf;
+
+ /// Enter a new cleanup scope.
+ explicit RunCleanupsScope(CIRGenFunction &cgf)
+ : performCleanup(true), cgf(cgf) {
+ cleanupStackDepth = cgf.ehStack.getStackDepth();
+ oldCleanupStackDepth = cgf.currentCleanupStackDepth;
+ cgf.currentCleanupStackDepth = cleanupStackDepth;
+ }
+
+ /// Exit this cleanup scope, emitting any accumulated cleanups.
+ ~RunCleanupsScope() {
+ if (performCleanup)
+ forceCleanup();
+ }
+
+ /// Force the emission of cleanups now, instead of waiting
+ /// until this object is destroyed.
+ void forceCleanup() {
+ assert(performCleanup && "Already forced cleanup");
+ {
+ mlir::OpBuilder::InsertionGuard guard(cgf.getBuilder());
+ cgf.popCleanupBlocks(cleanupStackDepth);
+ performCleanup = false;
+ cgf.currentCleanupStackDepth = oldCleanupStackDepth;
+ }
+ }
+ };
+
+ // Cleanup stack depth of the RunCleanupsScope that was pushed most recently.
+ size_t currentCleanupStackDepth;
+
+public:
/// Represents a scope, including function bodies, compound statements, and
/// the substatements of if/while/do/for/switch/try statements. This class
/// handles any automatic cleanup, along with the return value.
- struct LexicalScope {
+ struct LexicalScope : public RunCleanupsScope {
private:
- // TODO(CIR): This will live in the base class RunCleanupScope once that
- // class is upstreamed.
- CIRGenFunction &cgf;
+ // Block containing cleanup code for things initialized in this
+ // lexical context (scope).
+ mlir::Block *cleanupBlock = nullptr;
// Points to the scope entry block. This is useful, for instance, for
// helping to insert allocas before finalizing any recursive CodeGen from
@@ -632,8 +687,8 @@ public:
unsigned depth = 0;
LexicalScope(CIRGenFunction &cgf, mlir::Location loc, mlir::Block *eb)
- : cgf(cgf), entryBlock(eb), parentScope(cgf.curLexScope), beginLoc(loc),
- endLoc(loc) {
+ : RunCleanupsScope(cgf), entryBlock(eb), parentScope(cgf.curLexScope),
+ beginLoc(loc), endLoc(loc) {
assert(entryBlock && "LexicalScope requires an entry block");
cgf.curLexScope = this;
@@ -671,6 +726,27 @@ public:
void setAsSwitch() { scopeKind = Kind::Switch; }
void setAsTernary() { scopeKind = Kind::Ternary; }
+ // Lazy create cleanup block or return what's available.
+ mlir::Block *getOrCreateCleanupBlock(mlir::OpBuilder &builder) {
+ if (cleanupBlock)
+ return cleanupBlock;
+ cleanupBlock = createCleanupBlock(builder);
+ return cleanupBlock;
+ }
+
+ mlir::Block *getCleanupBlock(mlir::OpBuilder &builder) {
+ return cleanupBlock;
+ }
+
+ mlir::Block *createCleanupBlock(mlir::OpBuilder &builder) {
+ // Create the cleanup block but dont hook it up around just yet.
+ mlir::OpBuilder::InsertionGuard guard(builder);
+ mlir::Region *r = builder.getBlock() ? builder.getBlock()->getParent()
+ : &cgf.curFn->getRegion(0);
+ cleanupBlock = builder.createBlock(r);
+ return cleanupBlock;
+ }
+
// ---
// Return handling.
// ---
@@ -721,6 +797,12 @@ public:
LexicalScope *curLexScope = nullptr;
+ typedef void Destroyer(CIRGenFunction &cgf, Address addr, QualType ty);
+
+ static Destroyer destroyCXXObject;
+
+ Destroyer *getDestroyer(clang::QualType::DestructionKind kind);
+
/// ----------------------
/// CIR emit functions
/// ----------------------
@@ -766,6 +848,8 @@ public:
/// even if no aggregate location is provided.
RValue emitAnyExprToTemp(const clang::Expr *e);
+ mlir::Value emitArrayLength(const clang::ArrayType *arrayType,
+ QualType &baseType, Address &addr);
LValue emitArraySubscriptExpr(const clang::ArraySubscriptExpr *e);
Address emitArrayToPointerDecay(const Expr *array);
@@ -779,6 +863,8 @@ public:
void emitAutoVarCleanups(const AutoVarEmission &emission);
void emitAutoVarInit(const AutoVarEmission &emission);
+ void emitAutoVarTypeCleanup(const AutoVarEmission &emission,
+ clang::QualType::DestructionKind dtorKind);
void emitBaseInitializer(mlir::Location loc, const CXXRecordDecl *classDecl,
CXXCtorInitializer *baseInit);
@@ -836,6 +922,9 @@ public:
LValue emitCompoundLiteralLValue(const CompoundLiteralExpr *e);
void emitConstructorBody(FunctionArgList &args);
+
+ void emitDestroy(Address addr, QualType type, Destroyer *destroyer);
+
void emitDestructorBody(FunctionArgList &args);
mlir::LogicalResult emitContinueStmt(const clang::ContinueStmt &s);
@@ -843,6 +932,16 @@ public:
void emitCXXConstructExpr(const clang::CXXConstructExpr *e,
AggValueSlot dest);
+ void emitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
+ const clang::ArrayType *arrayType,
+ Address arrayBegin, const CXXConstructExpr *e,
+ bool newPointerIsChecked,
+ bool zeroInitialize = false);
+ void emitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
+ mlir::Value numElements, Address arrayBase,
+ const CXXConstructExpr *e,
+ bool newPointerIsChecked,
+ bool zeroInitialize);
void emitCXXConstructorCall(const clang::CXXConstructorDecl *d,
clang::CXXCtorType type, bool forVirtualBase,
bool delegating, AggValueSlot thisAVS,
@@ -853,6 +952,15 @@ public:
bool delegating, Address thisAddr,
CallArgList &args, clang::SourceLocation loc);
+ void emitCXXDestructorCall(const CXXDestructorDecl *dd, CXXDtorType type,
+ bool forVirtualBase, bool delegating,
+ Address thisAddr, QualType thisTy);
+
+ RValue emitCXXDestructorCall(GlobalDecl dtor, const CIRGenCallee &callee,
+ mlir::Value thisVal, QualType thisTy,
+ mlir::Value implicitParam,
+ QualType implicitParamTy, const CallExpr *e);
+
mlir::LogicalResult emitCXXForRangeStmt(const CXXForRangeStmt &s,
llvm::ArrayRef<const Attr *> attrs);
diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
index 1496d87..e5e4c68 100644
--- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
@@ -46,6 +46,11 @@ public:
void emitCXXDestructors(const clang::CXXDestructorDecl *d) override;
void emitCXXStructor(clang::GlobalDecl gd) override;
+ void emitDestructorCall(CIRGenFunction &cgf, const CXXDestructorDecl *dd,
+ CXXDtorType type, bool forVirtualBase,
+ bool delegating, Address thisAddr,
+ QualType thisTy) override;
+
bool useThunkForDtorVariant(const CXXDestructorDecl *dtor,
CXXDtorType dt) const override {
// Itanium does not emit any destructor variant as an inline thunk.
@@ -108,8 +113,6 @@ static StructorCIRGen getCIRGenToUse(CIRGenModule &cgm,
GlobalDecl aliasDecl;
if (const auto *dd = dyn_cast<CXXDestructorDecl>(md)) {
- // The assignment is correct here, but other support for this is NYI.
- cgm.errorNYI(md->getSourceRange(), "getCIRGenToUse: dtor");
aliasDecl = GlobalDecl(dd, Dtor_Complete);
} else {
const auto *cd = cast<CXXConstructorDecl>(md);
@@ -240,6 +243,25 @@ bool CIRGenItaniumCXXABI::needsVTTParameter(GlobalDecl gd) {
return false;
}
+void CIRGenItaniumCXXABI::emitDestructorCall(
+ CIRGenFunction &cgf, const CXXDestructorDecl *dd, CXXDtorType type,
+ bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy) {
+ GlobalDecl gd(dd, type);
+ if (needsVTTParameter(gd)) {
+ cgm.errorNYI(dd->getSourceRange(), "emitDestructorCall: VTT");
+ }
+
+ mlir::Value vtt = nullptr;
+ ASTContext &astContext = cgm.getASTContext();
+ QualType vttTy = astContext.getPointerType(astContext.VoidPtrTy);
+ assert(!cir::MissingFeatures::appleKext());
+ CIRGenCallee callee =
+ CIRGenCallee::forDirect(cgm.getAddrOfCXXStructor(gd), gd);
+
+ cgf.emitCXXDestructorCall(gd, callee, thisAddr.getPointer(), thisTy, vtt,
+ vttTy, nullptr);
+}
+
CIRGenCXXABI *clang::CIRGen::CreateCIRGenItaniumCXXABI(CIRGenModule &cgm) {
switch (cgm.getASTContext().getCXXABIKind()) {
case TargetCXXABI::GenericItanium:
diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
index 9193f6f..21bee33 100644
--- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
@@ -409,7 +409,10 @@ mlir::LogicalResult CIRGenFunction::emitReturnStmt(const ReturnStmt &s) {
}
auto *retBlock = curLexScope->getOrCreateRetBlock(*this, loc);
+ // This should emit a branch through the cleanup block if one exists.
builder.create<cir::BrOp>(loc, retBlock);
+ if (ehStack.getStackDepth() != currentCleanupStackDepth)
+ cgm.errorNYI(s.getSourceRange(), "return with cleanup stack");
builder.createBlock(builder.getBlock()->getParent());
return mlir::success();
diff --git a/clang/lib/CIR/CodeGen/CMakeLists.txt b/clang/lib/CIR/CodeGen/CMakeLists.txt
index 03ea60c..ca3a329 100644
--- a/clang/lib/CIR/CodeGen/CMakeLists.txt
+++ b/clang/lib/CIR/CodeGen/CMakeLists.txt
@@ -11,6 +11,7 @@ add_clang_library(clangCIR
CIRGenBuilder.cpp
CIRGenCall.cpp
CIRGenClass.cpp
+ CIRGenCleanup.cpp
CIRGenCXX.cpp
CIRGenCXXABI.cpp
CIRGenCXXExpr.cpp
diff --git a/clang/lib/CIR/CodeGen/EHScopeStack.h b/clang/lib/CIR/CodeGen/EHScopeStack.h
new file mode 100644
index 0000000..22750ac
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/EHScopeStack.h
@@ -0,0 +1,99 @@
+//===-- EHScopeStack.h - Stack for cleanup CIR generation -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// These classes should be the minimum interface required for other parts of
+// CIR CodeGen to emit cleanups. The implementation is in CIRGenCleanup.cpp and
+// other implemenentation details that are not widely needed are in
+// CIRGenCleanup.h.
+//
+// TODO(cir): this header should be shared between LLVM and CIR codegen.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_LIB_CIR_CODEGEN_EHSCOPESTACK_H
+#define CLANG_LIB_CIR_CODEGEN_EHSCOPESTACK_H
+
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang::CIRGen {
+
+class CIRGenFunction;
+
+enum CleanupKind : unsigned {
+ /// Denotes a cleanup that should run when a scope is exited using exceptional
+ /// control flow (a throw statement leading to stack unwinding, ).
+ EHCleanup = 0x1,
+
+ /// Denotes a cleanup that should run when a scope is exited using normal
+ /// control flow (falling off the end of the scope, return, goto, ...).
+ NormalCleanup = 0x2,
+
+ NormalAndEHCleanup = EHCleanup | NormalCleanup,
+
+ LifetimeMarker = 0x8,
+ NormalEHLifetimeMarker = LifetimeMarker | NormalAndEHCleanup,
+};
+
+/// A stack of scopes which respond to exceptions, including cleanups
+/// and catch blocks.
+class EHScopeStack {
+public:
+ /// Information for lazily generating a cleanup. Subclasses must be
+ /// POD-like: cleanups will not be destructed, and they will be
+ /// allocated on the cleanup stack and freely copied and moved
+ /// around.
+ ///
+ /// Cleanup implementations should generally be declared in an
+ /// anonymous namespace.
+ class Cleanup {
+ // Anchor the construction vtable.
+ virtual void anchor();
+
+ public:
+ Cleanup(const Cleanup &) = default;
+ Cleanup(Cleanup &&) {}
+ Cleanup() = default;
+
+ virtual ~Cleanup() = default;
+
+ /// Emit the cleanup. For normal cleanups, this is run in the
+ /// same EH context as when the cleanup was pushed, i.e. the
+ /// immediately-enclosing context of the cleanup scope. For
+ /// EH cleanups, this is run in a terminate context.
+ ///
+ // \param flags cleanup kind.
+ virtual void emit(CIRGenFunction &cgf) = 0;
+ };
+
+ // Classic codegen has a finely tuned custom allocator and a complex stack
+ // management scheme. We'll probably eventually want to find a way to share
+ // that implementation. For now, we will use a very simplified implementation
+ // to get cleanups working.
+ llvm::SmallVector<std::unique_ptr<Cleanup>, 8> cleanupStack;
+
+private:
+ /// The CGF this Stack belong to
+ CIRGenFunction *cgf = nullptr;
+
+public:
+ EHScopeStack() = default;
+ ~EHScopeStack() = default;
+
+ /// Push a lazily-created cleanup on the stack.
+ template <class T, class... As> void pushCleanup(CleanupKind kind, As... a) {
+ cleanupStack.push_back(std::make_unique<T>(a...));
+ }
+
+ void setCGF(CIRGenFunction *inCGF) { cgf = inCGF; }
+
+ size_t getStackDepth() const { return cleanupStack.size(); }
+};
+
+} // namespace clang::CIRGen
+
+#endif // CLANG_LIB_CIR_CODEGEN_EHSCOPESTACK_H
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index f0416b6..cd77166 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -489,6 +489,104 @@ LogicalResult cir::CastOp::verify() {
return emitOpError() << "requires two types differ in addrspace only";
return success();
}
+ case cir::CastKind::float_to_complex: {
+ if (!mlir::isa<cir::FPTypeInterface>(srcType))
+ return emitOpError() << "requires !cir.float type for source";
+ auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
+ if (!resComplexTy)
+ return emitOpError() << "requires !cir.complex type for result";
+ if (srcType != resComplexTy.getElementType())
+ return emitOpError() << "requires source type match result element type";
+ return success();
+ }
+ case cir::CastKind::int_to_complex: {
+ if (!mlir::isa<cir::IntType>(srcType))
+ return emitOpError() << "requires !cir.int type for source";
+ auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
+ if (!resComplexTy)
+ return emitOpError() << "requires !cir.complex type for result";
+ if (srcType != resComplexTy.getElementType())
+ return emitOpError() << "requires source type match result element type";
+ return success();
+ }
+ case cir::CastKind::float_complex_to_real: {
+ auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
+ if (!srcComplexTy)
+ return emitOpError() << "requires !cir.complex type for source";
+ if (!mlir::isa<cir::FPTypeInterface>(resType))
+ return emitOpError() << "requires !cir.float type for result";
+ if (srcComplexTy.getElementType() != resType)
+ return emitOpError() << "requires source element type match result type";
+ return success();
+ }
+ case cir::CastKind::int_complex_to_real: {
+ auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
+ if (!srcComplexTy)
+ return emitOpError() << "requires !cir.complex type for source";
+ if (!mlir::isa<cir::IntType>(resType))
+ return emitOpError() << "requires !cir.int type for result";
+ if (srcComplexTy.getElementType() != resType)
+ return emitOpError() << "requires source element type match result type";
+ return success();
+ }
+ case cir::CastKind::float_complex_to_bool: {
+ auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
+ if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
+ return emitOpError()
+ << "requires floating point !cir.complex type for source";
+ if (!mlir::isa<cir::BoolType>(resType))
+ return emitOpError() << "requires !cir.bool type for result";
+ return success();
+ }
+ case cir::CastKind::int_complex_to_bool: {
+ auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
+ if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
+ return emitOpError()
+ << "requires floating point !cir.complex type for source";
+ if (!mlir::isa<cir::BoolType>(resType))
+ return emitOpError() << "requires !cir.bool type for result";
+ return success();
+ }
+ case cir::CastKind::float_complex: {
+ auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
+ if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
+ return emitOpError()
+ << "requires floating point !cir.complex type for source";
+ auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
+ if (!resComplexTy || !resComplexTy.isFloatingPointComplex())
+ return emitOpError()
+ << "requires floating point !cir.complex type for result";
+ return success();
+ }
+ case cir::CastKind::float_complex_to_int_complex: {
+ auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
+ if (!srcComplexTy || !srcComplexTy.isFloatingPointComplex())
+ return emitOpError()
+ << "requires floating point !cir.complex type for source";
+ auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
+ if (!resComplexTy || !resComplexTy.isIntegerComplex())
+ return emitOpError() << "requires integer !cir.complex type for result";
+ return success();
+ }
+ case cir::CastKind::int_complex: {
+ auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
+ if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
+ return emitOpError() << "requires integer !cir.complex type for source";
+ auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
+ if (!resComplexTy || !resComplexTy.isIntegerComplex())
+ return emitOpError() << "requires integer !cir.complex type for result";
+ return success();
+ }
+ case cir::CastKind::int_complex_to_float_complex: {
+ auto srcComplexTy = mlir::dyn_cast<cir::ComplexType>(srcType);
+ if (!srcComplexTy || !srcComplexTy.isIntegerComplex())
+ return emitOpError() << "requires integer !cir.complex type for source";
+ auto resComplexTy = mlir::dyn_cast<cir::ComplexType>(resType);
+ if (!resComplexTy || !resComplexTy.isFloatingPointComplex())
+ return emitOpError()
+ << "requires floating point !cir.complex type for result";
+ return success();
+ }
default:
llvm_unreachable("Unknown CastOp kind?");
}
diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
index 8f848c7..cef83ea 100644
--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
@@ -8,11 +8,14 @@
#include "PassDetail.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/CharUnits.h"
#include "clang/CIR/Dialect/Builder/CIRBaseBuilder.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
#include "clang/CIR/Dialect/Passes.h"
+#include "clang/CIR/MissingFeatures.h"
+#include <iostream>
#include <memory>
using namespace mlir;
@@ -24,11 +27,106 @@ struct LoweringPreparePass : public LoweringPrepareBase<LoweringPreparePass> {
void runOnOperation() override;
void runOnOp(mlir::Operation *op);
+ void lowerCastOp(cir::CastOp op);
void lowerUnaryOp(cir::UnaryOp op);
+ void lowerArrayCtor(ArrayCtor op);
+
+ ///
+ /// AST related
+ /// -----------
+
+ clang::ASTContext *astCtx;
+
+ void setASTContext(clang::ASTContext *c) { astCtx = c; }
};
} // namespace
+static mlir::Value lowerScalarToComplexCast(mlir::MLIRContext &ctx,
+ cir::CastOp op) {
+ cir::CIRBaseBuilderTy builder(ctx);
+ builder.setInsertionPoint(op);
+
+ mlir::Value src = op.getSrc();
+ mlir::Value imag = builder.getNullValue(src.getType(), op.getLoc());
+ return builder.createComplexCreate(op.getLoc(), src, imag);
+}
+
+static mlir::Value lowerComplexToScalarCast(mlir::MLIRContext &ctx,
+ cir::CastOp op,
+ cir::CastKind elemToBoolKind) {
+ cir::CIRBaseBuilderTy builder(ctx);
+ builder.setInsertionPoint(op);
+
+ mlir::Value src = op.getSrc();
+ if (!mlir::isa<cir::BoolType>(op.getType()))
+ return builder.createComplexReal(op.getLoc(), src);
+
+ // Complex cast to bool: (bool)(a+bi) => (bool)a || (bool)b
+ mlir::Value srcReal = builder.createComplexReal(op.getLoc(), src);
+ mlir::Value srcImag = builder.createComplexImag(op.getLoc(), src);
+
+ cir::BoolType boolTy = builder.getBoolTy();
+ mlir::Value srcRealToBool =
+ builder.createCast(op.getLoc(), elemToBoolKind, srcReal, boolTy);
+ mlir::Value srcImagToBool =
+ builder.createCast(op.getLoc(), elemToBoolKind, srcImag, boolTy);
+ return builder.createLogicalOr(op.getLoc(), srcRealToBool, srcImagToBool);
+}
+
+static mlir::Value lowerComplexToComplexCast(mlir::MLIRContext &ctx,
+ cir::CastOp op,
+ cir::CastKind scalarCastKind) {
+ CIRBaseBuilderTy builder(ctx);
+ builder.setInsertionPoint(op);
+
+ mlir::Value src = op.getSrc();
+ auto dstComplexElemTy =
+ mlir::cast<cir::ComplexType>(op.getType()).getElementType();
+
+ mlir::Value srcReal = builder.createComplexReal(op.getLoc(), src);
+ mlir::Value srcImag = builder.createComplexImag(op.getLoc(), src);
+
+ mlir::Value dstReal = builder.createCast(op.getLoc(), scalarCastKind, srcReal,
+ dstComplexElemTy);
+ mlir::Value dstImag = builder.createCast(op.getLoc(), scalarCastKind, srcImag,
+ dstComplexElemTy);
+ return builder.createComplexCreate(op.getLoc(), dstReal, dstImag);
+}
+
+void LoweringPreparePass::lowerCastOp(cir::CastOp op) {
+ mlir::MLIRContext &ctx = getContext();
+ mlir::Value loweredValue = [&]() -> mlir::Value {
+ switch (op.getKind()) {
+ case cir::CastKind::float_to_complex:
+ case cir::CastKind::int_to_complex:
+ return lowerScalarToComplexCast(ctx, op);
+ case cir::CastKind::float_complex_to_real:
+ case cir::CastKind::int_complex_to_real:
+ return lowerComplexToScalarCast(ctx, op, op.getKind());
+ case cir::CastKind::float_complex_to_bool:
+ return lowerComplexToScalarCast(ctx, op, cir::CastKind::float_to_bool);
+ case cir::CastKind::int_complex_to_bool:
+ return lowerComplexToScalarCast(ctx, op, cir::CastKind::int_to_bool);
+ case cir::CastKind::float_complex:
+ return lowerComplexToComplexCast(ctx, op, cir::CastKind::floating);
+ case cir::CastKind::float_complex_to_int_complex:
+ return lowerComplexToComplexCast(ctx, op, cir::CastKind::float_to_int);
+ case cir::CastKind::int_complex:
+ return lowerComplexToComplexCast(ctx, op, cir::CastKind::integral);
+ case cir::CastKind::int_complex_to_float_complex:
+ return lowerComplexToComplexCast(ctx, op, cir::CastKind::int_to_float);
+ default:
+ return nullptr;
+ }
+ }();
+
+ if (loweredValue) {
+ op.replaceAllUsesWith(loweredValue);
+ op.erase();
+ }
+}
+
void LoweringPreparePass::lowerUnaryOp(cir::UnaryOp op) {
mlir::Type ty = op.getType();
if (!mlir::isa<cir::ComplexType>(ty))
@@ -71,8 +169,85 @@ void LoweringPreparePass::lowerUnaryOp(cir::UnaryOp op) {
op.erase();
}
+static void lowerArrayDtorCtorIntoLoop(cir::CIRBaseBuilderTy &builder,
+ clang::ASTContext *astCtx,
+ mlir::Operation *op, mlir::Type eltTy,
+ mlir::Value arrayAddr,
+ uint64_t arrayLen) {
+ // Generate loop to call into ctor/dtor for every element.
+ mlir::Location loc = op->getLoc();
+
+ // TODO: instead of fixed integer size, create alias for PtrDiffTy and unify
+ // with CIRGen stuff.
+ const unsigned sizeTypeSize =
+ astCtx->getTypeSize(astCtx->getSignedSizeType());
+ auto ptrDiffTy =
+ cir::IntType::get(builder.getContext(), sizeTypeSize, /*isSigned=*/false);
+ mlir::Value numArrayElementsConst = builder.getUnsignedInt(loc, arrayLen, 64);
+
+ auto begin = builder.create<cir::CastOp>(
+ loc, eltTy, cir::CastKind::array_to_ptrdecay, arrayAddr);
+ mlir::Value end = builder.create<cir::PtrStrideOp>(loc, eltTy, begin,
+ numArrayElementsConst);
+
+ mlir::Value tmpAddr = builder.createAlloca(
+ loc, /*addr type*/ builder.getPointerTo(eltTy),
+ /*var type*/ eltTy, "__array_idx", builder.getAlignmentAttr(1));
+ builder.createStore(loc, begin, tmpAddr);
+
+ cir::DoWhileOp loop = builder.createDoWhile(
+ loc,
+ /*condBuilder=*/
+ [&](mlir::OpBuilder &b, mlir::Location loc) {
+ auto currentElement = b.create<cir::LoadOp>(loc, eltTy, tmpAddr);
+ mlir::Type boolTy = cir::BoolType::get(b.getContext());
+ auto cmp = builder.create<cir::CmpOp>(loc, boolTy, cir::CmpOpKind::ne,
+ currentElement, end);
+ builder.createCondition(cmp);
+ },
+ /*bodyBuilder=*/
+ [&](mlir::OpBuilder &b, mlir::Location loc) {
+ auto currentElement = b.create<cir::LoadOp>(loc, eltTy, tmpAddr);
+
+ cir::CallOp ctorCall;
+ op->walk([&](cir::CallOp c) { ctorCall = c; });
+ assert(ctorCall && "expected ctor call");
+
+ auto one = builder.create<cir::ConstantOp>(
+ loc, ptrDiffTy, cir::IntAttr::get(ptrDiffTy, 1));
+
+ ctorCall->moveAfter(one);
+ ctorCall->setOperand(0, currentElement);
+
+ // Advance pointer and store them to temporary variable
+ auto nextElement =
+ builder.create<cir::PtrStrideOp>(loc, eltTy, currentElement, one);
+ builder.createStore(loc, nextElement, tmpAddr);
+ builder.createYield(loc);
+ });
+
+ op->replaceAllUsesWith(loop);
+ op->erase();
+}
+
+void LoweringPreparePass::lowerArrayCtor(cir::ArrayCtor op) {
+ cir::CIRBaseBuilderTy builder(getContext());
+ builder.setInsertionPointAfter(op.getOperation());
+
+ mlir::Type eltTy = op->getRegion(0).getArgument(0).getType();
+ assert(!cir::MissingFeatures::vlas());
+ auto arrayLen =
+ mlir::cast<cir::ArrayType>(op.getAddr().getType().getPointee()).getSize();
+ lowerArrayDtorCtorIntoLoop(builder, astCtx, op, eltTy, op.getAddr(),
+ arrayLen);
+}
+
void LoweringPreparePass::runOnOp(mlir::Operation *op) {
- if (auto unary = dyn_cast<cir::UnaryOp>(op))
+ if (auto arrayCtor = dyn_cast<ArrayCtor>(op))
+ lowerArrayCtor(arrayCtor);
+ else if (auto cast = mlir::dyn_cast<cir::CastOp>(op))
+ lowerCastOp(cast);
+ else if (auto unary = mlir::dyn_cast<cir::UnaryOp>(op))
lowerUnaryOp(unary);
}
@@ -82,7 +257,7 @@ void LoweringPreparePass::runOnOperation() {
llvm::SmallVector<mlir::Operation *> opsToTransform;
op->walk([&](mlir::Operation *op) {
- if (mlir::isa<cir::UnaryOp>(op))
+ if (mlir::isa<cir::ArrayCtor, cir::CastOp, cir::UnaryOp>(op))
opsToTransform.push_back(op);
});
@@ -93,3 +268,10 @@ void LoweringPreparePass::runOnOperation() {
std::unique_ptr<Pass> mlir::createLoweringPreparePass() {
return std::make_unique<LoweringPreparePass>();
}
+
+std::unique_ptr<Pass>
+mlir::createLoweringPreparePass(clang::ASTContext *astCtx) {
+ auto pass = std::make_unique<LoweringPreparePass>();
+ pass->setASTContext(astCtx);
+ return std::move(pass);
+}
diff --git a/clang/lib/CIR/Lowering/CIRPasses.cpp b/clang/lib/CIR/Lowering/CIRPasses.cpp
index 5607abc..bb9781b 100644
--- a/clang/lib/CIR/Lowering/CIRPasses.cpp
+++ b/clang/lib/CIR/Lowering/CIRPasses.cpp
@@ -31,7 +31,7 @@ mlir::LogicalResult runCIRToCIRPasses(mlir::ModuleOp theModule,
if (enableCIRSimplify)
pm.addPass(mlir::createCIRSimplifyPass());
- pm.addPass(mlir::createLoweringPreparePass());
+ pm.addPass(mlir::createLoweringPreparePass(&astContext));
pm.enableVerifier(enableVerifier);
(void)mlir::applyPassManagerCLOptions(pm);
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index f075be8..3cd7de0 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -460,6 +460,17 @@ mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite(
return mlir::success();
}
+mlir::LogicalResult CIRToLLVMAssumeSepStorageOpLowering::matchAndRewrite(
+ cir::AssumeSepStorageOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const {
+ auto cond = rewriter.create<mlir::LLVM::ConstantOp>(op.getLoc(),
+ rewriter.getI1Type(), 1);
+ rewriter.replaceOpWithNewOp<mlir::LLVM::AssumeOp>(
+ op, cond, mlir::LLVM::AssumeSeparateStorageTag{}, adaptor.getPtr1(),
+ adaptor.getPtr2());
+ return mlir::success();
+}
+
mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite(
cir::BitClrsbOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
@@ -2066,6 +2077,7 @@ void ConvertCIRToLLVMPass::runOnOperation() {
patterns.add<
// clang-format off
CIRToLLVMAssumeOpLowering,
+ CIRToLLVMAssumeSepStorageOpLowering,
CIRToLLVMBaseClassAddrOpLowering,
CIRToLLVMBinOpLowering,
CIRToLLVMBitClrsbOpLowering,
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
index 3faf1e9..2911ced 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
@@ -44,6 +44,16 @@ public:
mlir::ConversionPatternRewriter &) const override;
};
+class CIRToLLVMAssumeSepStorageOpLowering
+ : public mlir::OpConversionPattern<cir::AssumeSepStorageOp> {
+public:
+ using mlir::OpConversionPattern<cir::AssumeSepStorageOp>::OpConversionPattern;
+
+ mlir::LogicalResult
+ matchAndRewrite(cir::AssumeSepStorageOp op, OpAdaptor,
+ mlir::ConversionPatternRewriter &) const override;
+};
+
class CIRToLLVMBitClrsbOpLowering
: public mlir::OpConversionPattern<cir::BitClrsbOp> {
public:
diff --git a/clang/lib/CodeGen/ABIInfo.cpp b/clang/lib/CodeGen/ABIInfo.cpp
index d981d69..3ef430e1 100644
--- a/clang/lib/CodeGen/ABIInfo.cpp
+++ b/clang/lib/CodeGen/ABIInfo.cpp
@@ -218,8 +218,8 @@ void ABIInfo::appendAttributeMangling(StringRef AttrStr,
// only have "+" prefixes here.
assert(LHS.starts_with("+") && RHS.starts_with("+") &&
"Features should always have a prefix.");
- return TI.getFMVPriority({LHS.substr(1)}) >
- TI.getFMVPriority({RHS.substr(1)});
+ return TI.getFMVPriority({LHS.substr(1)})
+ .ugt(TI.getFMVPriority({RHS.substr(1)}));
});
bool IsFirst = true;
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 5f2eb76..3f784fc 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -4108,6 +4108,22 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
return RValue::get(Result);
}
+ case Builtin::BI__builtin_elementwise_maximumnum: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ Value *Op1 = EmitScalarExpr(E->getArg(1));
+ Value *Result = Builder.CreateBinaryIntrinsic(
+ Intrinsic::maximumnum, Op0, Op1, nullptr, "elt.maximumnum");
+ return RValue::get(Result);
+ }
+
+ case Builtin::BI__builtin_elementwise_minimumnum: {
+ Value *Op0 = EmitScalarExpr(E->getArg(0));
+ Value *Op1 = EmitScalarExpr(E->getArg(1));
+ Value *Result = Builder.CreateBinaryIntrinsic(
+ Intrinsic::minimumnum, Op0, Op1, nullptr, "elt.minimumnum");
+ return RValue::get(Result);
+ }
+
case Builtin::BI__builtin_reduce_max: {
auto GetIntrinsicID = [this](QualType QT) {
if (auto *VecTy = QT->getAs<VectorType>())
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 0bceece..d9bd443 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -2852,20 +2852,28 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
if (AI.getInReg())
Attrs.addAttribute(llvm::Attribute::InReg);
- // Depending on the ABI, this may be either a byval or a dead_on_return
- // argument.
- if (AI.getIndirectByVal()) {
- Attrs.addByValAttr(getTypes().ConvertTypeForMem(ParamType));
- } else {
- // Add dead_on_return when the object's lifetime ends in the callee.
- // This includes trivially-destructible objects, as well as objects
- // whose destruction / clean-up is carried out within the callee (e.g.,
- // Obj-C ARC-managed structs, MSVC callee-destroyed objects).
- if (!ParamType.isDestructedType() || !ParamType->isRecordType() ||
- ParamType->castAs<RecordType>()
- ->getDecl()
- ->isParamDestroyedInCallee())
- Attrs.addAttribute(llvm::Attribute::DeadOnReturn);
+ // HLSL out and inout parameters must not be marked with ByVal or
+ // DeadOnReturn attributes because stores to these parameters by the
+ // callee are visible to the caller.
+ if (auto ParamABI = FI.getExtParameterInfo(ArgNo).getABI();
+ ParamABI != ParameterABI::HLSLOut &&
+ ParamABI != ParameterABI::HLSLInOut) {
+
+ // Depending on the ABI, this may be either a byval or a dead_on_return
+ // argument.
+ if (AI.getIndirectByVal()) {
+ Attrs.addByValAttr(getTypes().ConvertTypeForMem(ParamType));
+ } else {
+ // Add dead_on_return when the object's lifetime ends in the callee.
+ // This includes trivially-destructible objects, as well as objects
+ // whose destruction / clean-up is carried out within the callee
+ // (e.g., Obj-C ARC-managed structs, MSVC callee-destroyed objects).
+ if (!ParamType.isDestructedType() || !ParamType->isRecordType() ||
+ ParamType->castAs<RecordType>()
+ ->getDecl()
+ ->isParamDestroyedInCallee())
+ Attrs.addAttribute(llvm::Attribute::DeadOnReturn);
+ }
}
auto *Decl = ParamType->getAsRecordDecl();
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index e24c68e..a371b67 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -6062,11 +6062,10 @@ void CGDebugInfo::EmitPseudoVariable(CGBuilderTy &Builder,
// ptr, in this case its debug info may not match the actual type of object
// being used as in the next instruction, so we will need to emit a pseudo
// variable for type-casted value.
- auto DeclareTypeMatches = [&](auto *DbgDeclare) {
+ auto DeclareTypeMatches = [&](llvm::DbgVariableRecord *DbgDeclare) {
return DbgDeclare->getVariable()->getType() == Type;
};
- if (any_of(llvm::findDbgDeclares(Var), DeclareTypeMatches) ||
- any_of(llvm::findDVRDeclares(Var), DeclareTypeMatches))
+ if (any_of(llvm::findDVRDeclares(Var), DeclareTypeMatches))
return;
}
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 359e30c..b8238a4 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -2146,30 +2146,9 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) {
return;
}
- // We might be deleting a pointer to array. If so, GEP down to the
- // first non-array element.
- // (this assumes that A(*)[3][7] is converted to [3 x [7 x %A]]*)
- if (DeleteTy->isConstantArrayType()) {
- llvm::Value *Zero = Builder.getInt32(0);
- SmallVector<llvm::Value*,8> GEP;
-
- GEP.push_back(Zero); // point at the outermost array
-
- // For each layer of array type we're pointing at:
- while (const ConstantArrayType *Arr
- = getContext().getAsConstantArrayType(DeleteTy)) {
- // 1. Unpeel the array type.
- DeleteTy = Arr->getElementType();
-
- // 2. GEP to the first element of the array.
- GEP.push_back(Zero);
- }
-
- Ptr = Builder.CreateInBoundsGEP(Ptr, GEP, ConvertTypeForMem(DeleteTy),
- Ptr.getAlignment(), "del.first");
- }
-
- assert(ConvertTypeForMem(DeleteTy) == Ptr.getElementType());
+ // We might be deleting a pointer to array.
+ DeleteTy = getContext().getBaseElementType(DeleteTy);
+ Ptr = Ptr.withElementType(ConvertTypeForMem(DeleteTy));
if (E->isArrayForm()) {
EmitArrayDelete(*this, E, Ptr, DeleteTy);
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index ce2dd4d..91237cf 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -7080,6 +7080,110 @@ private:
return ConstLength.getSExtValue() != 1;
}
+ /// A helper class to copy structures with overlapped elements, i.e. those
+ /// which have mappings of both "s" and "s.mem". Consecutive elements that
+ /// are not explicitly copied have mapping nodes synthesized for them,
+ /// taking care to avoid generating zero-sized copies.
+ class CopyOverlappedEntryGaps {
+ CodeGenFunction &CGF;
+ MapCombinedInfoTy &CombinedInfo;
+ OpenMPOffloadMappingFlags Flags = OpenMPOffloadMappingFlags::OMP_MAP_NONE;
+ const ValueDecl *MapDecl = nullptr;
+ const Expr *MapExpr = nullptr;
+ Address BP = Address::invalid();
+ bool IsNonContiguous = false;
+ uint64_t DimSize = 0;
+ // These elements track the position as the struct is iterated over
+ // (in order of increasing element address).
+ const RecordDecl *LastParent = nullptr;
+ uint64_t Cursor = 0;
+ unsigned LastIndex = -1u;
+ Address LB = Address::invalid();
+
+ public:
+ CopyOverlappedEntryGaps(CodeGenFunction &CGF,
+ MapCombinedInfoTy &CombinedInfo,
+ OpenMPOffloadMappingFlags Flags,
+ const ValueDecl *MapDecl, const Expr *MapExpr,
+ Address BP, Address LB, bool IsNonContiguous,
+ uint64_t DimSize)
+ : CGF(CGF), CombinedInfo(CombinedInfo), Flags(Flags), MapDecl(MapDecl),
+ MapExpr(MapExpr), BP(BP), IsNonContiguous(IsNonContiguous),
+ DimSize(DimSize), LB(LB) {}
+
+ void processField(
+ const OMPClauseMappableExprCommon::MappableComponent &MC,
+ const FieldDecl *FD,
+ llvm::function_ref<LValue(CodeGenFunction &, const MemberExpr *)>
+ EmitMemberExprBase) {
+ const RecordDecl *RD = FD->getParent();
+ const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout(RD);
+ uint64_t FieldOffset = RL.getFieldOffset(FD->getFieldIndex());
+ uint64_t FieldSize =
+ CGF.getContext().getTypeSize(FD->getType().getCanonicalType());
+ Address ComponentLB = Address::invalid();
+
+ if (FD->getType()->isLValueReferenceType()) {
+ const auto *ME = cast<MemberExpr>(MC.getAssociatedExpression());
+ LValue BaseLVal = EmitMemberExprBase(CGF, ME);
+ ComponentLB =
+ CGF.EmitLValueForFieldInitialization(BaseLVal, FD).getAddress();
+ } else {
+ ComponentLB =
+ CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()).getAddress();
+ }
+
+ if (!LastParent)
+ LastParent = RD;
+ if (FD->getParent() == LastParent) {
+ if (FD->getFieldIndex() != LastIndex + 1)
+ copyUntilField(FD, ComponentLB);
+ } else {
+ LastParent = FD->getParent();
+ if (((int64_t)FieldOffset - (int64_t)Cursor) > 0)
+ copyUntilField(FD, ComponentLB);
+ }
+ Cursor = FieldOffset + FieldSize;
+ LastIndex = FD->getFieldIndex();
+ LB = CGF.Builder.CreateConstGEP(ComponentLB, 1);
+ }
+
+ void copyUntilField(const FieldDecl *FD, Address ComponentLB) {
+ llvm::Value *ComponentLBPtr = ComponentLB.emitRawPointer(CGF);
+ llvm::Value *LBPtr = LB.emitRawPointer(CGF);
+ llvm::Value *Size =
+ CGF.Builder.CreatePtrDiff(CGF.Int8Ty, ComponentLBPtr, LBPtr);
+ copySizedChunk(LBPtr, Size);
+ }
+
+ void copyUntilEnd(Address HB) {
+ if (LastParent) {
+ const ASTRecordLayout &RL =
+ CGF.getContext().getASTRecordLayout(LastParent);
+ if ((uint64_t)CGF.getContext().toBits(RL.getSize()) <= Cursor)
+ return;
+ }
+ llvm::Value *LBPtr = LB.emitRawPointer(CGF);
+ llvm::Value *Size = CGF.Builder.CreatePtrDiff(
+ CGF.Int8Ty, CGF.Builder.CreateConstGEP(HB, 1).emitRawPointer(CGF),
+ LBPtr);
+ copySizedChunk(LBPtr, Size);
+ }
+
+ void copySizedChunk(llvm::Value *Base, llvm::Value *Size) {
+ CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
+ CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF));
+ CombinedInfo.DevicePtrDecls.push_back(nullptr);
+ CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
+ CombinedInfo.Pointers.push_back(Base);
+ CombinedInfo.Sizes.push_back(
+ CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
+ CombinedInfo.Types.push_back(Flags);
+ CombinedInfo.Mappers.push_back(nullptr);
+ CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1);
+ }
+ };
+
/// Generate the base pointers, section pointers, sizes, map type bits, and
/// user-defined mappers (all included in \a CombinedInfo) for the provided
/// map type, map or motion modifiers, and expression components.
@@ -7570,63 +7674,22 @@ private:
getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
/*AddPtrFlag=*/false,
/*AddIsTargetParamFlag=*/false, IsNonContiguous);
- llvm::Value *Size = nullptr;
+ CopyOverlappedEntryGaps CopyGaps(CGF, CombinedInfo, Flags, MapDecl,
+ MapExpr, BP, LB, IsNonContiguous,
+ DimSize);
// Do bitcopy of all non-overlapped structure elements.
for (OMPClauseMappableExprCommon::MappableExprComponentListRef
Component : OverlappedElements) {
- Address ComponentLB = Address::invalid();
for (const OMPClauseMappableExprCommon::MappableComponent &MC :
Component) {
if (const ValueDecl *VD = MC.getAssociatedDeclaration()) {
- const auto *FD = dyn_cast<FieldDecl>(VD);
- if (FD && FD->getType()->isLValueReferenceType()) {
- const auto *ME =
- cast<MemberExpr>(MC.getAssociatedExpression());
- LValue BaseLVal = EmitMemberExprBase(CGF, ME);
- ComponentLB =
- CGF.EmitLValueForFieldInitialization(BaseLVal, FD)
- .getAddress();
- } else {
- ComponentLB =
- CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
- .getAddress();
+ if (const auto *FD = dyn_cast<FieldDecl>(VD)) {
+ CopyGaps.processField(MC, FD, EmitMemberExprBase);
}
- llvm::Value *ComponentLBPtr = ComponentLB.emitRawPointer(CGF);
- llvm::Value *LBPtr = LB.emitRawPointer(CGF);
- Size = CGF.Builder.CreatePtrDiff(CGF.Int8Ty, ComponentLBPtr,
- LBPtr);
- break;
}
}
- assert(Size && "Failed to determine structure size");
- CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
- CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF));
- CombinedInfo.DevicePtrDecls.push_back(nullptr);
- CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
- CombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF));
- CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast(
- Size, CGF.Int64Ty, /*isSigned=*/true));
- CombinedInfo.Types.push_back(Flags);
- CombinedInfo.Mappers.push_back(nullptr);
- CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
- : 1);
- LB = CGF.Builder.CreateConstGEP(ComponentLB, 1);
}
- CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
- CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF));
- CombinedInfo.DevicePtrDecls.push_back(nullptr);
- CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
- CombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF));
- llvm::Value *LBPtr = LB.emitRawPointer(CGF);
- Size = CGF.Builder.CreatePtrDiff(
- CGF.Int8Ty, CGF.Builder.CreateConstGEP(HB, 1).emitRawPointer(CGF),
- LBPtr);
- CombinedInfo.Sizes.push_back(
- CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
- CombinedInfo.Types.push_back(Flags);
- CombinedInfo.Mappers.push_back(nullptr);
- CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
- : 1);
+ CopyGaps.copyUntilEnd(HB);
break;
}
llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index e065006..1a8c6f0 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -846,11 +846,13 @@ void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
if (HaveInsertPoint())
EmitStopPoint(&S);
+ ApplyAtomGroup Grp(getDebugInfo());
EmitBranchThroughCleanup(getJumpDestForLabel(S.getLabel()));
}
void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
+ ApplyAtomGroup Grp(getDebugInfo());
if (const LabelDecl *Target = S.getConstantTarget()) {
EmitBranchThroughCleanup(getJumpDestForLabel(Target));
return;
@@ -869,6 +871,8 @@ void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
cast<llvm::PHINode>(IndGotoBB->begin())->addIncoming(V, CurBB);
EmitBranch(IndGotoBB);
+ if (CurBB && CurBB->getTerminator())
+ addInstToCurrentSourceAtom(CurBB->getTerminator(), nullptr);
}
void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
@@ -2672,6 +2676,9 @@ static void UpdateAsmCallInst(llvm::CallBase &Result, bool HasSideEffect,
llvm::ConstantAsMetadata::get(Loc)));
}
+ // Make inline-asm calls Key for the debug info feature Key Instructions.
+ CGF.addInstToNewSourceAtom(&Result, nullptr);
+
if (!NoConvergent && CGF.getLangOpts().assumeFunctionsAreConvergent())
// Conservatively, mark all inline asm blocks in CUDA or OpenCL as
// convergent (meaning, they may call an intrinsically convergent op, such
@@ -2750,6 +2757,7 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S,
}
}
+ ApplyAtomGroup Grp(CGF.getDebugInfo());
LValue Dest = ResultRegDests[i];
// ResultTypeRequiresCast elements correspond to the first
// ResultTypeRequiresCast.size() elements of RegResults.
@@ -2757,7 +2765,8 @@ EmitAsmStores(CodeGenFunction &CGF, const AsmStmt &S,
unsigned Size = CGF.getContext().getTypeSize(ResultRegQualTys[i]);
Address A = Dest.getAddress().withElementType(ResultRegTypes[i]);
if (CGF.getTargetHooks().isScalarizableAsmOperand(CGF, TruncTy)) {
- Builder.CreateStore(Tmp, A);
+ llvm::StoreInst *S = Builder.CreateStore(Tmp, A);
+ CGF.addInstToCurrentSourceAtom(S, S->getValueOperand());
continue;
}
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 236cc3d..834b1c0 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -4418,8 +4418,9 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old,
llvm::Function *NewFn);
-static uint64_t getFMVPriority(const TargetInfo &TI,
- const CodeGenFunction::FMVResolverOption &RO) {
+static llvm::APInt
+getFMVPriority(const TargetInfo &TI,
+ const CodeGenFunction::FMVResolverOption &RO) {
llvm::SmallVector<StringRef, 8> Features{RO.Features};
if (RO.Architecture)
Features.push_back(*RO.Architecture);
@@ -4544,7 +4545,7 @@ void CodeGenModule::emitMultiVersionFunctions() {
llvm::stable_sort(
Options, [&TI](const CodeGenFunction::FMVResolverOption &LHS,
const CodeGenFunction::FMVResolverOption &RHS) {
- return getFMVPriority(TI, LHS) > getFMVPriority(TI, RHS);
+ return getFMVPriority(TI, LHS).ugt(getFMVPriority(TI, RHS));
});
CodeGenFunction CGF(*this);
CGF.EmitMultiVersionResolver(ResolverFunc, Options);
diff --git a/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp b/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp
index ee736a2..70f510a 100644
--- a/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp
@@ -274,7 +274,7 @@ llvm::Value *CodeGenFunction::EmitScalarOrConstFoldImmArg(unsigned ICEArguments,
void CodeGenFunction::AddAMDGPUFenceAddressSpaceMMRA(llvm::Instruction *Inst,
const CallExpr *E) {
- constexpr const char *Tag = "amdgpu-as";
+ constexpr const char *Tag = "amdgpu-synchronize-as";
LLVMContext &Ctx = Inst->getContext();
SmallVector<MMRAMetadata::TagT, 3> MMRAs;
@@ -633,6 +633,41 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
llvm::Function *F = CGM.getIntrinsic(IID, {LoadTy});
return Builder.CreateCall(F, {Addr});
}
+ case AMDGPU::BI__builtin_amdgcn_global_load_monitor_b32:
+ case AMDGPU::BI__builtin_amdgcn_global_load_monitor_b64:
+ case AMDGPU::BI__builtin_amdgcn_global_load_monitor_b128:
+ case AMDGPU::BI__builtin_amdgcn_flat_load_monitor_b32:
+ case AMDGPU::BI__builtin_amdgcn_flat_load_monitor_b64:
+ case AMDGPU::BI__builtin_amdgcn_flat_load_monitor_b128: {
+
+ Intrinsic::ID IID;
+ switch (BuiltinID) {
+ case AMDGPU::BI__builtin_amdgcn_global_load_monitor_b32:
+ IID = Intrinsic::amdgcn_global_load_monitor_b32;
+ break;
+ case AMDGPU::BI__builtin_amdgcn_global_load_monitor_b64:
+ IID = Intrinsic::amdgcn_global_load_monitor_b64;
+ break;
+ case AMDGPU::BI__builtin_amdgcn_global_load_monitor_b128:
+ IID = Intrinsic::amdgcn_global_load_monitor_b128;
+ break;
+ case AMDGPU::BI__builtin_amdgcn_flat_load_monitor_b32:
+ IID = Intrinsic::amdgcn_flat_load_monitor_b32;
+ break;
+ case AMDGPU::BI__builtin_amdgcn_flat_load_monitor_b64:
+ IID = Intrinsic::amdgcn_flat_load_monitor_b64;
+ break;
+ case AMDGPU::BI__builtin_amdgcn_flat_load_monitor_b128:
+ IID = Intrinsic::amdgcn_flat_load_monitor_b128;
+ break;
+ }
+
+ llvm::Type *LoadTy = ConvertType(E->getType());
+ llvm::Value *Addr = EmitScalarExpr(E->getArg(0));
+ llvm::Value *Val = EmitScalarExpr(E->getArg(1));
+ llvm::Function *F = CGM.getIntrinsic(IID, {LoadTy});
+ return Builder.CreateCall(F, {Addr, Val});
+ }
case AMDGPU::BI__builtin_amdgcn_load_to_lds: {
// Should this have asan instrumentation?
return emitBuiltinWithOneOverloadedType<5>(*this, E,
@@ -855,6 +890,7 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
case AMDGPU::BI__builtin_amdgcn_wmma_f32_16x16x128_bf8_fp8:
case AMDGPU::BI__builtin_amdgcn_wmma_f32_16x16x128_bf8_bf8:
case AMDGPU::BI__builtin_amdgcn_wmma_i32_16x16x64_iu8:
+ case AMDGPU::BI__builtin_amdgcn_wmma_f32_16x16x128_f8f6f4:
case AMDGPU::BI__builtin_amdgcn_wmma_f32_32x16x128_f4:
case AMDGPU::BI__builtin_amdgcn_swmmac_f32_16x16x64_f16:
case AMDGPU::BI__builtin_amdgcn_swmmac_f32_16x16x64_bf16:
@@ -1118,6 +1154,10 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
ArgsForMatchingMatrixTypes = {4, 1};
BuiltinWMMAOp = Intrinsic::amdgcn_wmma_i32_16x16x64_iu8;
break;
+ case AMDGPU::BI__builtin_amdgcn_wmma_f32_16x16x128_f8f6f4:
+ ArgsForMatchingMatrixTypes = {5, 1, 3};
+ BuiltinWMMAOp = Intrinsic::amdgcn_wmma_f32_16x16x128_f8f6f4;
+ break;
case AMDGPU::BI__builtin_amdgcn_wmma_f32_32x16x128_f4:
ArgsForMatchingMatrixTypes = {3, 0, 1};
BuiltinWMMAOp = Intrinsic::amdgcn_wmma_f32_32x16x128_f4;
diff --git a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
index 7e6a47f..2e6b4b3 100644
--- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
@@ -8112,7 +8112,7 @@ Value *CodeGenFunction::EmitAArch64CpuSupports(const CallExpr *E) {
llvm::Value *
CodeGenFunction::EmitAArch64CpuSupports(ArrayRef<StringRef> FeaturesStrs) {
- uint64_t FeaturesMask = llvm::AArch64::getCpuSupportsMask(FeaturesStrs);
+ llvm::APInt FeaturesMask = llvm::AArch64::getCpuSupportsMask(FeaturesStrs);
Value *Result = Builder.getTrue();
if (FeaturesMask != 0) {
// Get features from structure in runtime library
@@ -8128,7 +8128,7 @@ CodeGenFunction::EmitAArch64CpuSupports(ArrayRef<StringRef> FeaturesStrs) {
{ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, 0)});
Value *Features = Builder.CreateAlignedLoad(Int64Ty, CpuFeatures,
CharUnits::fromQuantity(8));
- Value *Mask = Builder.getInt64(FeaturesMask);
+ Value *Mask = Builder.getInt(FeaturesMask.trunc(64));
Value *Bitset = Builder.CreateAnd(Features, Mask);
Value *Cmp = Builder.CreateICmpEQ(Bitset, Mask);
Result = Builder.CreateAnd(Result, Cmp);
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index ec1135e..853f694 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -68,6 +68,7 @@
#include "clang/Driver/Types.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
@@ -83,6 +84,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ExitCodes.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/Path.h"
@@ -109,65 +111,6 @@ using namespace clang::driver;
using namespace clang;
using namespace llvm::opt;
-static std::optional<llvm::Triple> getOffloadTargetTriple(const Driver &D,
- const ArgList &Args) {
- auto OffloadTargets = Args.getAllArgValues(options::OPT_offload_EQ);
- // Offload compilation flow does not support multiple targets for now. We
- // need the HIPActionBuilder (and possibly the CudaActionBuilder{,Base}too)
- // to support multiple tool chains first.
- switch (OffloadTargets.size()) {
- default:
- D.Diag(diag::err_drv_only_one_offload_target_supported);
- return std::nullopt;
- case 0:
- D.Diag(diag::err_drv_invalid_or_unsupported_offload_target) << "";
- return std::nullopt;
- case 1:
- break;
- }
- return llvm::Triple(OffloadTargets[0]);
-}
-
-static std::optional<llvm::Triple>
-getNVIDIAOffloadTargetTriple(const Driver &D, const ArgList &Args,
- const llvm::Triple &HostTriple) {
- if (!Args.hasArg(options::OPT_offload_EQ)) {
- return llvm::Triple(HostTriple.isArch64Bit() ? "nvptx64-nvidia-cuda"
- : "nvptx-nvidia-cuda");
- }
- auto TT = getOffloadTargetTriple(D, Args);
- if (TT && (TT->getArch() == llvm::Triple::spirv32 ||
- TT->getArch() == llvm::Triple::spirv64)) {
- if (Args.hasArg(options::OPT_emit_llvm))
- return TT;
- D.Diag(diag::err_drv_cuda_offload_only_emit_bc);
- return std::nullopt;
- }
- D.Diag(diag::err_drv_invalid_or_unsupported_offload_target) << TT->str();
- return std::nullopt;
-}
-
-static std::optional<llvm::Triple>
-getHIPOffloadTargetTriple(const Driver &D, const ArgList &Args) {
- if (!Args.hasArg(options::OPT_offload_EQ)) {
- auto OffloadArchs = Args.getAllArgValues(options::OPT_offload_arch_EQ);
- if (llvm::is_contained(OffloadArchs, "amdgcnspirv") &&
- OffloadArchs.size() == 1)
- return llvm::Triple("spirv64-amd-amdhsa");
- return llvm::Triple("amdgcn-amd-amdhsa"); // Default HIP triple.
- }
- auto TT = getOffloadTargetTriple(D, Args);
- if (!TT)
- return std::nullopt;
- if (TT->isAMDGCN() && TT->getVendor() == llvm::Triple::AMD &&
- TT->getOS() == llvm::Triple::AMDHSA)
- return TT;
- if (TT->getArch() == llvm::Triple::spirv64)
- return TT;
- D.Diag(diag::err_drv_invalid_or_unsupported_offload_target) << TT->str();
- return std::nullopt;
-}
-
template <typename F> static bool usesInput(const ArgList &Args, F &&Fn) {
return llvm::any_of(Args, [&](Arg *A) {
return (A->getOption().matches(options::OPT_x) &&
@@ -266,8 +209,8 @@ Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,
CCLogDiagnostics(false), CCGenDiagnostics(false),
CCPrintProcessStats(false), CCPrintInternalStats(false),
TargetTriple(TargetTriple), Saver(Alloc), PrependArg(nullptr),
- CheckInputsExist(true), ProbePrecompiled(true),
- SuppressMissingInputWarning(false) {
+ PreferredLinker(CLANG_DEFAULT_LINKER), CheckInputsExist(true),
+ ProbePrecompiled(true), SuppressMissingInputWarning(false) {
// Provide a sane fallback if no VFS is specified.
if (!this->VFS)
this->VFS = llvm::vfs::getRealFileSystem();
@@ -458,6 +401,44 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
return FinalPhase;
}
+llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
+Driver::executeProgram(llvm::ArrayRef<llvm::StringRef> Args) const {
+ llvm::SmallString<64> OutputFile;
+ llvm::sys::fs::createTemporaryFile("driver-program", "txt", OutputFile,
+ llvm::sys::fs::OF_Text);
+ llvm::FileRemover OutputRemover(OutputFile.c_str());
+ std::optional<llvm::StringRef> Redirects[] = {
+ {""},
+ OutputFile.str(),
+ {""},
+ };
+
+ std::string ErrorMessage;
+ int SecondsToWait = 60;
+ if (std::optional<std::string> Str =
+ llvm::sys::Process::GetEnv("CLANG_TOOLCHAIN_PROGRAM_TIMEOUT")) {
+ if (!llvm::to_integer(*Str, SecondsToWait))
+ return llvm::createStringError(std::error_code(),
+ "CLANG_TOOLCHAIN_PROGRAM_TIMEOUT expected "
+ "an integer, got '" +
+ *Str + "'");
+ SecondsToWait = std::max(SecondsToWait, 0); // infinite
+ }
+ StringRef Executable = Args[0];
+ if (llvm::sys::ExecuteAndWait(Executable, Args, {}, Redirects, SecondsToWait,
+ /*MemoryLimit=*/0, &ErrorMessage))
+ return llvm::createStringError(std::error_code(),
+ Executable + ": " + ErrorMessage);
+
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> OutputBuf =
+ llvm::MemoryBuffer::getFile(OutputFile.c_str());
+ if (!OutputBuf)
+ return llvm::createStringError(OutputBuf.getError(),
+ "Failed to read stdout of " + Executable +
+ ": " + OutputBuf.getError().message());
+ return std::move(*OutputBuf);
+}
+
static Arg *MakeInputArg(DerivedArgList &Args, const OptTable &Opts,
StringRef Value, bool Claim = true) {
Arg *A = new Arg(Opts.getOption(options::OPT_INPUT), Value,
@@ -921,250 +902,266 @@ Driver::OpenMPRuntimeKind Driver::getOpenMPRuntime(const ArgList &Args) const {
return RT;
}
-static llvm::Triple getSYCLDeviceTriple(StringRef TargetArch) {
- SmallVector<StringRef, 5> SYCLAlias = {"spir", "spir64", "spirv", "spirv32",
- "spirv64"};
- if (llvm::is_contained(SYCLAlias, TargetArch)) {
- llvm::Triple TargetTriple;
- TargetTriple.setArchName(TargetArch);
- TargetTriple.setVendor(llvm::Triple::UnknownVendor);
- TargetTriple.setOS(llvm::Triple::UnknownOS);
- return TargetTriple;
- }
- return llvm::Triple(TargetArch);
+// Handles `native` offload architectures by using the 'offload-arch' utility.
+static llvm::SmallVector<std::string>
+getSystemOffloadArchs(Compilation &C, Action::OffloadKind Kind) {
+ StringRef Program = C.getArgs().getLastArgValue(
+ options::OPT_offload_arch_tool_EQ, "offload-arch");
+
+ SmallVector<std::string> GPUArchs;
+ if (llvm::ErrorOr<std::string> Executable =
+ llvm::sys::findProgramByName(Program)) {
+ llvm::SmallVector<StringRef> Args{*Executable};
+ if (Kind == Action::OFK_HIP)
+ Args.push_back("--only=amdgpu");
+ else if (Kind == Action::OFK_Cuda)
+ Args.push_back("--only=nvptx");
+ auto StdoutOrErr = C.getDriver().executeProgram(Args);
+
+ if (!StdoutOrErr) {
+ C.getDriver().Diag(diag::err_drv_undetermined_gpu_arch)
+ << Action::GetOffloadKindName(Kind) << StdoutOrErr.takeError()
+ << "--offload-arch";
+ return GPUArchs;
+ }
+ if ((*StdoutOrErr)->getBuffer().empty()) {
+ C.getDriver().Diag(diag::err_drv_undetermined_gpu_arch)
+ << Action::GetOffloadKindName(Kind) << "No GPU detected in the system"
+ << "--offload-arch";
+ return GPUArchs;
+ }
+
+ for (StringRef Arch : llvm::split((*StdoutOrErr)->getBuffer(), "\n"))
+ if (!Arch.empty())
+ GPUArchs.push_back(Arch.str());
+ } else {
+ C.getDriver().Diag(diag::err_drv_command_failure) << "offload-arch";
+ }
+ return GPUArchs;
}
-static bool addSYCLDefaultTriple(Compilation &C,
- SmallVectorImpl<llvm::Triple> &SYCLTriples) {
- // Check current set of triples to see if the default has already been set.
- for (const auto &SYCLTriple : SYCLTriples) {
- if (SYCLTriple.getSubArch() == llvm::Triple::NoSubArch &&
- SYCLTriple.isSPIROrSPIRV())
- return false;
+// Attempts to infer the correct offloading toolchain triple by looking at the
+// requested offloading kind and architectures.
+static llvm::DenseSet<llvm::StringRef>
+inferOffloadToolchains(Compilation &C, Action::OffloadKind Kind) {
+ std::set<std::string> Archs;
+ for (Arg *A : C.getInputArgs()) {
+ for (StringRef Arch : A->getValues()) {
+ if (A->getOption().matches(options::OPT_offload_arch_EQ)) {
+ if (Arch == "native") {
+ for (StringRef Str : getSystemOffloadArchs(C, Kind))
+ Archs.insert(Str.str());
+ } else {
+ Archs.insert(Arch.str());
+ }
+ } else if (A->getOption().matches(options::OPT_no_offload_arch_EQ)) {
+ if (Arch == "all")
+ Archs.clear();
+ else
+ Archs.erase(Arch.str());
+ }
+ }
}
- // Add the default triple as it was not found.
- llvm::Triple DefaultTriple = getSYCLDeviceTriple(
- C.getDefaultToolChain().getTriple().isArch32Bit() ? "spirv32"
- : "spirv64");
- SYCLTriples.insert(SYCLTriples.begin(), DefaultTriple);
- return true;
+
+ llvm::DenseSet<llvm::StringRef> Triples;
+ for (llvm::StringRef Arch : Archs) {
+ OffloadArch ID = StringToOffloadArch(Arch);
+ if (ID == OffloadArch::UNKNOWN)
+ ID = StringToOffloadArch(
+ getProcessorFromTargetID(llvm::Triple("amdgcn-amd-amdhsa"), Arch));
+
+ if (Kind == Action::OFK_HIP && !IsAMDOffloadArch(ID)) {
+ C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch)
+ << "HIP" << Arch;
+ return llvm::DenseSet<llvm::StringRef>();
+ }
+ if (Kind == Action::OFK_Cuda && !IsNVIDIAOffloadArch(ID)) {
+ C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch)
+ << "CUDA" << Arch;
+ return llvm::DenseSet<llvm::StringRef>();
+ }
+ if (Kind == Action::OFK_OpenMP &&
+ (ID == OffloadArch::UNKNOWN || ID == OffloadArch::UNUSED)) {
+ C.getDriver().Diag(clang::diag::err_drv_failed_to_deduce_target_from_arch)
+ << Arch;
+ return llvm::DenseSet<llvm::StringRef>();
+ }
+ if (ID == OffloadArch::UNKNOWN || ID == OffloadArch::UNUSED) {
+ C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch)
+ << "offload" << Arch;
+ return llvm::DenseSet<llvm::StringRef>();
+ }
+
+ StringRef Triple;
+ if (ID == OffloadArch::AMDGCNSPIRV)
+ Triple = "spirv64-amd-amdhsa";
+ else if (IsNVIDIAOffloadArch(ID))
+ Triple = C.getDefaultToolChain().getTriple().isArch64Bit()
+ ? "nvptx64-nvidia-cuda"
+ : "nvptx-nvidia-cuda";
+ else if (IsAMDOffloadArch(ID))
+ Triple = "amdgcn-amd-amdhsa";
+ else
+ continue;
+
+ // Make a new argument that dispatches this argument to the appropriate
+ // toolchain. This is required when we infer it and create potentially
+ // incompatible toolchains from the global option.
+ Option Opt = C.getDriver().getOpts().getOption(options::OPT_Xarch__);
+ unsigned Index = C.getArgs().getBaseArgs().MakeIndex("-Xarch_");
+ Arg *A = new Arg(Opt, C.getArgs().getArgString(Index), Index,
+ C.getArgs().MakeArgString(Triple.split("-").first),
+ C.getArgs().MakeArgString("--offload-arch=" + Arch));
+ C.getArgs().append(A);
+ C.getArgs().AddSynthesizedArg(A);
+ Triples.insert(Triple);
+ }
+
+ // Infer the default target triple if no specific architectures are given.
+ if (Archs.empty() && Kind == Action::OFK_HIP)
+ Triples.insert("amdgcn-amd-amdhsa");
+ else if (Archs.empty() && Kind == Action::OFK_Cuda)
+ Triples.insert(C.getDefaultToolChain().getTriple().isArch64Bit()
+ ? "nvptx64-nvidia-cuda"
+ : "nvptx-nvidia-cuda");
+ else if (Archs.empty() && Kind == Action::OFK_SYCL)
+ Triples.insert(C.getDefaultToolChain().getTriple().isArch64Bit()
+ ? "spirv64-unknown-unknown"
+ : "spirv32-unknown-unknown");
+
+ // We need to dispatch these to the appropriate toolchain now.
+ C.getArgs().eraseArg(options::OPT_offload_arch_EQ);
+ C.getArgs().eraseArg(options::OPT_no_offload_arch_EQ);
+
+ return Triples;
}
void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
InputList &Inputs) {
-
- //
- // CUDA/HIP
- //
- // We need to generate a CUDA/HIP toolchain if any of the inputs has a CUDA
- // or HIP type. However, mixed CUDA/HIP compilation is not supported.
+ bool UseLLVMOffload = C.getInputArgs().hasArg(
+ options::OPT_foffload_via_llvm, options::OPT_fno_offload_via_llvm, false);
bool IsCuda =
- llvm::any_of(Inputs, [](std::pair<types::ID, const llvm::opt::Arg *> &I) {
- return types::isCuda(I.first);
- });
- bool IsHIP =
llvm::any_of(Inputs,
[](std::pair<types::ID, const llvm::opt::Arg *> &I) {
- return types::isHIP(I.first);
- }) ||
- C.getInputArgs().hasArg(options::OPT_hip_link) ||
- C.getInputArgs().hasArg(options::OPT_hipstdpar);
- bool UseLLVMOffload = C.getInputArgs().hasArg(
- options::OPT_foffload_via_llvm, options::OPT_fno_offload_via_llvm, false);
- if (IsCuda && IsHIP) {
- Diag(clang::diag::err_drv_mix_cuda_hip);
+ return types::isCuda(I.first);
+ }) &&
+ !UseLLVMOffload;
+ bool IsHIP =
+ (llvm::any_of(Inputs,
+ [](std::pair<types::ID, const llvm::opt::Arg *> &I) {
+ return types::isHIP(I.first);
+ }) ||
+ C.getInputArgs().hasArg(options::OPT_hip_link) ||
+ C.getInputArgs().hasArg(options::OPT_hipstdpar)) &&
+ !UseLLVMOffload;
+ bool IsSYCL = C.getInputArgs().hasFlag(options::OPT_fsycl,
+ options::OPT_fno_sycl, false);
+ bool IsOpenMPOffloading =
+ UseLLVMOffload ||
+ (C.getInputArgs().hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
+ options::OPT_fno_openmp, false) &&
+ (C.getInputArgs().hasArg(options::OPT_offload_targets_EQ) ||
+ (C.getInputArgs().hasArg(options::OPT_offload_arch_EQ) &&
+ !(IsCuda || IsHIP))));
+
+ llvm::SmallSet<Action::OffloadKind, 4> Kinds;
+ const std::pair<bool, Action::OffloadKind> ActiveKinds[] = {
+ {IsCuda, Action::OFK_Cuda},
+ {IsHIP, Action::OFK_HIP},
+ {IsOpenMPOffloading, Action::OFK_OpenMP},
+ {IsSYCL, Action::OFK_SYCL}};
+ for (const auto &[Active, Kind] : ActiveKinds)
+ if (Active)
+ Kinds.insert(Kind);
+
+ // We currently don't support any kind of mixed offloading.
+ if (Kinds.size() > 1) {
+ Diag(clang::diag::err_drv_mix_offload)
+ << Action::GetOffloadKindName(*Kinds.begin()).upper()
+ << Action::GetOffloadKindName(*(++Kinds.begin())).upper();
return;
}
- if (IsCuda && !UseLLVMOffload) {
- auto CudaTriple = getNVIDIAOffloadTargetTriple(
- *this, C.getInputArgs(), C.getDefaultToolChain().getTriple());
- if (!CudaTriple)
- return;
-
- auto &TC =
- getOffloadToolChain(C.getInputArgs(), Action::OFK_Cuda, *CudaTriple,
- C.getDefaultToolChain().getTriple());
-
- // Emit a warning if the detected CUDA version is too new.
- const CudaInstallationDetector &CudaInstallation =
- static_cast<const toolchains::CudaToolChain &>(TC).CudaInstallation;
- if (CudaInstallation.isValid())
- CudaInstallation.WarnIfUnsupportedVersion();
- C.addOffloadDeviceToolChain(&TC, Action::OFK_Cuda);
- OffloadArchs[&TC] = getOffloadArchs(C, C.getArgs(), Action::OFK_Cuda, &TC,
- /*SpecificToolchain=*/true);
- } else if (IsHIP && !UseLLVMOffload) {
- if (auto *OMPTargetArg =
- C.getInputArgs().getLastArg(options::OPT_offload_targets_EQ)) {
- Diag(clang::diag::err_drv_unsupported_opt_for_language_mode)
- << OMPTargetArg->getSpelling() << "HIP";
- return;
- }
-
- auto HIPTriple = getHIPOffloadTargetTriple(*this, C.getInputArgs());
- if (!HIPTriple)
- return;
-
- auto &TC =
- getOffloadToolChain(C.getInputArgs(), Action::OFK_HIP, *HIPTriple,
- C.getDefaultToolChain().getTriple());
- C.addOffloadDeviceToolChain(&TC, Action::OFK_HIP);
-
- // TODO: Fix 'amdgcnspirv' handling with the new driver.
- if (C.getInputArgs().hasFlag(options::OPT_offload_new_driver,
- options::OPT_no_offload_new_driver, false))
- OffloadArchs[&TC] = getOffloadArchs(C, C.getArgs(), Action::OFK_HIP, &TC,
- /*SpecificToolchain=*/true);
- }
+ // Initialize the compilation identifier used for unique CUDA / HIP names.
if (IsCuda || IsHIP)
CUIDOpts = CUIDOptions(C.getArgs(), *this);
- //
- // OpenMP
- //
- // We need to generate an OpenMP toolchain if the user specified targets with
- // the -fopenmp-targets option or used --offload-arch with OpenMP enabled.
- bool IsOpenMPOffloading =
- ((IsCuda || IsHIP) && UseLLVMOffload) ||
- (C.getInputArgs().hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
- options::OPT_fno_openmp, false) &&
- (C.getInputArgs().hasArg(options::OPT_offload_targets_EQ) ||
- C.getInputArgs().hasArg(options::OPT_offload_arch_EQ)));
- if (IsOpenMPOffloading) {
- // 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.
- OpenMPRuntimeKind RuntimeKind = getOpenMPRuntime(C.getInputArgs());
- if (RuntimeKind != OMPRT_OMP && RuntimeKind != OMPRT_IOMP5) {
- Diag(clang::diag::err_drv_expecting_fopenmp_with_fopenmp_targets);
- return;
- }
-
- // If the user specified -fopenmp-targets= we create a toolchain for each
- // valid triple. Otherwise, if only --offload-arch= was specified we instead
- // attempt to derive the appropriate toolchains from the arguments.
- if (Arg *OpenMPTargets =
- C.getInputArgs().getLastArg(options::OPT_offload_targets_EQ)) {
- if (OpenMPTargets && !OpenMPTargets->getNumValues()) {
- Diag(clang::diag::warn_drv_empty_joined_argument)
- << OpenMPTargets->getAsString(C.getInputArgs());
+ // Get the list of requested offloading toolchains. If they were not
+ // explicitly specified we will infer them based on the offloading language
+ // and requested architectures.
+ std::multiset<llvm::StringRef> Triples;
+ if (C.getInputArgs().hasArg(options::OPT_offload_targets_EQ)) {
+ std::vector<std::string> ArgValues =
+ C.getInputArgs().getAllArgValues(options::OPT_offload_targets_EQ);
+ for (llvm::StringRef Target : ArgValues)
+ Triples.insert(C.getInputArgs().MakeArgString(Target));
+
+ if (ArgValues.empty())
+ Diag(clang::diag::warn_drv_empty_joined_argument)
+ << C.getInputArgs()
+ .getLastArg(options::OPT_offload_targets_EQ)
+ ->getAsString(C.getInputArgs());
+ } else if (Kinds.size() > 0) {
+ for (Action::OffloadKind Kind : Kinds) {
+ llvm::DenseSet<llvm::StringRef> Derived = inferOffloadToolchains(C, Kind);
+ Triples.insert(Derived.begin(), Derived.end());
+ }
+ }
+
+ // Build an offloading toolchain for every requested target and kind.
+ llvm::StringMap<StringRef> FoundNormalizedTriples;
+ for (StringRef Target : Triples) {
+ // OpenMP offloading requires a compatible libomp.
+ if (Kinds.contains(Action::OFK_OpenMP)) {
+ OpenMPRuntimeKind RuntimeKind = getOpenMPRuntime(C.getInputArgs());
+ if (RuntimeKind != OMPRT_OMP && RuntimeKind != OMPRT_IOMP5) {
+ Diag(clang::diag::err_drv_expecting_fopenmp_with_fopenmp_targets);
return;
}
+ }
- // Make sure these show up in a deterministic order.
- std::multiset<StringRef> OpenMPTriples;
- for (StringRef T : OpenMPTargets->getValues())
- OpenMPTriples.insert(T);
-
- llvm::StringMap<StringRef> FoundNormalizedTriples;
- for (StringRef T : OpenMPTriples) {
- llvm::Triple TT(ToolChain::getOpenMPTriple(T));
- std::string NormalizedName = TT.normalize();
-
- // Make sure we don't have a duplicate triple.
- auto [TripleIt, Inserted] =
- FoundNormalizedTriples.try_emplace(NormalizedName, T);
- if (!Inserted) {
- Diag(clang::diag::warn_drv_omp_offload_target_duplicate)
- << T << TripleIt->second;
- continue;
- }
-
- // If the specified target is invalid, emit a diagnostic.
- if (TT.getArch() == llvm::Triple::UnknownArch) {
- Diag(clang::diag::err_drv_invalid_omp_target) << T;
- continue;
- }
+ // Certain options are not allowed when combined with SYCL compilation.
+ if (Kinds.contains(Action::OFK_SYCL)) {
+ for (auto ID :
+ {options::OPT_static_libstdcxx, options::OPT_ffreestanding})
+ if (Arg *IncompatArg = C.getInputArgs().getLastArg(ID))
+ Diag(clang::diag::err_drv_argument_not_allowed_with)
+ << IncompatArg->getSpelling() << "-fsycl";
+ }
- auto &TC = getOffloadToolChain(C.getInputArgs(), Action::OFK_OpenMP, TT,
- C.getDefaultToolChain().getTriple());
- C.addOffloadDeviceToolChain(&TC, Action::OFK_OpenMP);
- OffloadArchs[&TC] =
- getOffloadArchs(C, C.getArgs(), Action::OFK_OpenMP, &TC,
- /*SpecificToolchain=*/true);
- }
- } else if (C.getInputArgs().hasArg(options::OPT_offload_arch_EQ) &&
- ((!IsHIP && !IsCuda) || UseLLVMOffload)) {
- llvm::Triple AMDTriple("amdgcn-amd-amdhsa");
- llvm::Triple NVPTXTriple("nvptx64-nvidia-cuda");
-
- for (StringRef Arch :
- C.getInputArgs().getAllArgValues(options::OPT_offload_arch_EQ)) {
- bool IsNVPTX = IsNVIDIAOffloadArch(
- StringToOffloadArch(getProcessorFromTargetID(NVPTXTriple, Arch)));
- bool IsAMDGPU = IsAMDOffloadArch(
- StringToOffloadArch(getProcessorFromTargetID(AMDTriple, Arch)));
- if (!IsNVPTX && !IsAMDGPU && !Arch.empty() &&
- !Arch.equals_insensitive("native")) {
- Diag(clang::diag::err_drv_failed_to_deduce_target_from_arch) << Arch;
- return;
- }
+ // Create a device toolchain for every specified kind and triple.
+ for (Action::OffloadKind Kind : Kinds) {
+ llvm::Triple TT = Kind == Action::OFK_OpenMP
+ ? ToolChain::getOpenMPTriple(Target)
+ : llvm::Triple(Target);
+ if (TT.getArch() == llvm::Triple::ArchType::UnknownArch) {
+ Diag(diag::err_drv_invalid_or_unsupported_offload_target) << TT.str();
+ continue;
}
- // Attempt to deduce the offloading triple from the set of architectures.
- // We can only correctly deduce NVPTX / AMDGPU triples currently.
- for (const llvm::Triple &TT : {AMDTriple, NVPTXTriple}) {
- auto &TC = getOffloadToolChain(C.getInputArgs(), Action::OFK_OpenMP, TT,
- C.getDefaultToolChain().getTriple());
-
- llvm::SmallVector<StringRef> Archs =
- getOffloadArchs(C, C.getArgs(), Action::OFK_OpenMP, &TC,
- /*SpecificToolchain=*/false);
- if (!Archs.empty()) {
- C.addOffloadDeviceToolChain(&TC, Action::OFK_OpenMP);
- OffloadArchs[&TC] = Archs;
- }
+ std::string NormalizedName = TT.normalize();
+ auto [TripleIt, Inserted] =
+ FoundNormalizedTriples.try_emplace(NormalizedName, Target);
+ if (!Inserted) {
+ Diag(clang::diag::warn_drv_omp_offload_target_duplicate)
+ << Target << TripleIt->second;
+ continue;
}
- // If the set is empty then we failed to find a native architecture.
- auto TCRange = C.getOffloadToolChains(Action::OFK_OpenMP);
- if (TCRange.first == TCRange.second)
- Diag(clang::diag::err_drv_failed_to_deduce_target_from_arch)
- << "native";
- }
- } else if (C.getInputArgs().hasArg(options::OPT_offload_targets_EQ)) {
- Diag(clang::diag::err_drv_expecting_fopenmp_with_fopenmp_targets);
- return;
- }
+ auto &TC = getOffloadToolChain(C.getInputArgs(), Kind, TT,
+ C.getDefaultToolChain().getTriple());
- // We need to generate a SYCL toolchain if the user specified -fsycl.
- bool IsSYCL = C.getInputArgs().hasFlag(options::OPT_fsycl,
- options::OPT_fno_sycl, false);
-
- auto argSYCLIncompatible = [&](OptSpecifier OptId) {
- if (!IsSYCL)
- return;
- if (Arg *IncompatArg = C.getInputArgs().getLastArg(OptId))
- Diag(clang::diag::err_drv_argument_not_allowed_with)
- << IncompatArg->getSpelling() << "-fsycl";
- };
- // -static-libstdc++ is not compatible with -fsycl.
- argSYCLIncompatible(options::OPT_static_libstdcxx);
- // -ffreestanding cannot be used with -fsycl
- argSYCLIncompatible(options::OPT_ffreestanding);
-
- llvm::SmallVector<llvm::Triple, 4> UniqueSYCLTriplesVec;
-
- if (IsSYCL) {
- addSYCLDefaultTriple(C, UniqueSYCLTriplesVec);
+ // Emit a warning if the detected CUDA version is too new.
+ if (Kind == Action::OFK_Cuda) {
+ auto &CudaInstallation =
+ static_cast<const toolchains::CudaToolChain &>(TC).CudaInstallation;
+ if (CudaInstallation.isValid())
+ CudaInstallation.WarnIfUnsupportedVersion();
+ }
- // We'll need to use the SYCL and host triples as the key into
- // getOffloadingDeviceToolChain, because the device toolchains we're
- // going to create will depend on both.
- const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
- for (const auto &TT : UniqueSYCLTriplesVec) {
- auto &TC = getOffloadToolChain(C.getInputArgs(), Action::OFK_SYCL, TT,
- HostTC->getTriple());
- C.addOffloadDeviceToolChain(&TC, Action::OFK_SYCL);
- OffloadArchs[&TC] = getOffloadArchs(C, C.getArgs(), Action::OFK_SYCL, &TC,
- /*SpecificToolchain=*/true);
+ C.addOffloadDeviceToolChain(&TC, Kind);
}
}
-
- //
- // TODO: Add support for other offloading programming models here.
- //
}
bool Driver::loadZOSCustomizationFile(llvm::cl::ExpansionContext &ExpCtx) {
@@ -3306,9 +3303,6 @@ class OffloadingActionBuilder final {
// 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 or HIP, we don't need to bother about
// this input.
if (!(IA->getType() == types::TY_CUDA ||
@@ -3408,10 +3402,6 @@ class OffloadingActionBuilder final {
CudaDeviceActions.clear();
}
- /// Get canonicalized offload arch option. \returns empty StringRef if the
- /// option is invalid.
- virtual StringRef getCanonicalOffloadArch(StringRef Arch) = 0;
-
virtual std::optional<std::pair<llvm::StringRef, llvm::StringRef>>
getConflictOffloadArchCombination(const std::set<StringRef> &GpuArchs) = 0;
@@ -3440,91 +3430,25 @@ class OffloadingActionBuilder final {
return true;
}
- ToolChains.push_back(
- AssociatedOffloadKind == Action::OFK_Cuda
- ? C.getSingleOffloadToolChain<Action::OFK_Cuda>()
- : C.getSingleOffloadToolChain<Action::OFK_HIP>());
-
- CompileHostOnly = C.getDriver().offloadHostOnly();
- EmitLLVM = Args.getLastArg(options::OPT_emit_llvm);
- EmitAsm = Args.getLastArg(options::OPT_S);
-
- // --offload and --offload-arch options are mutually exclusive.
- if (Args.hasArgNoClaim(options::OPT_offload_EQ) &&
- Args.hasArgNoClaim(options::OPT_offload_arch_EQ,
- options::OPT_no_offload_arch_EQ)) {
- C.getDriver().Diag(diag::err_opt_not_valid_with_opt) << "--offload-arch"
- << "--offload";
- }
-
- // Collect all offload arch parameters, removing duplicates.
std::set<StringRef> GpuArchs;
- bool Error = false;
- const ToolChain &TC = *ToolChains.front();
- for (Arg *A : C.getArgsForToolChain(&TC, /*BoundArch=*/"",
- AssociatedOffloadKind)) {
- if (!(A->getOption().matches(options::OPT_offload_arch_EQ) ||
- A->getOption().matches(options::OPT_no_offload_arch_EQ)))
- continue;
- A->claim();
-
- for (StringRef ArchStr : llvm::split(A->getValue(), ",")) {
- if (A->getOption().matches(options::OPT_no_offload_arch_EQ) &&
- ArchStr == "all") {
- GpuArchs.clear();
- } else if (ArchStr == "native") {
- auto GPUsOrErr = ToolChains.front()->getSystemGPUArchs(Args);
- if (!GPUsOrErr) {
- TC.getDriver().Diag(diag::err_drv_undetermined_gpu_arch)
- << llvm::Triple::getArchTypeName(TC.getArch())
- << llvm::toString(GPUsOrErr.takeError()) << "--offload-arch";
- continue;
- }
+ for (Action::OffloadKind Kind : {Action::OFK_Cuda, Action::OFK_HIP}) {
+ for (auto &I : llvm::make_range(C.getOffloadToolChains(Kind))) {
+ ToolChains.push_back(I.second);
- for (auto GPU : *GPUsOrErr) {
- GpuArchs.insert(Args.MakeArgString(GPU));
- }
- } else {
- ArchStr = getCanonicalOffloadArch(ArchStr);
- if (ArchStr.empty()) {
- Error = true;
- } else if (A->getOption().matches(options::OPT_offload_arch_EQ))
- GpuArchs.insert(ArchStr);
- else if (A->getOption().matches(options::OPT_no_offload_arch_EQ))
- GpuArchs.erase(ArchStr);
- else
- llvm_unreachable("Unexpected option.");
- }
+ for (auto Arch :
+ C.getDriver().getOffloadArchs(C, C.getArgs(), Kind, *I.second))
+ GpuArchs.insert(Arch);
}
}
- auto &&ConflictingArchs = getConflictOffloadArchCombination(GpuArchs);
- if (ConflictingArchs) {
- C.getDriver().Diag(clang::diag::err_drv_bad_offload_arch_combo)
- << ConflictingArchs->first << ConflictingArchs->second;
- C.setContainsError();
- return true;
- }
-
- // Collect list of GPUs remaining in the set.
for (auto Arch : GpuArchs)
GpuArchList.push_back(Arch.data());
- // 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()) {
- if (ToolChains.front()->getTriple().isSPIRV()) {
- if (ToolChains.front()->getTriple().getVendor() == llvm::Triple::AMD)
- GpuArchList.push_back(OffloadArch::AMDGCNSPIRV);
- else
- GpuArchList.push_back(OffloadArch::Generic);
- } else {
- GpuArchList.push_back(DefaultOffloadArch);
- }
- }
+ CompileHostOnly = C.getDriver().offloadHostOnly();
+ EmitLLVM = Args.getLastArg(options::OPT_emit_llvm);
+ EmitAsm = Args.getLastArg(options::OPT_S);
- return Error;
+ return false;
}
};
@@ -3538,15 +3462,6 @@ class OffloadingActionBuilder final {
DefaultOffloadArch = OffloadArch::CudaDefault;
}
- StringRef getCanonicalOffloadArch(StringRef ArchStr) override {
- OffloadArch Arch = StringToOffloadArch(ArchStr);
- if (Arch == OffloadArch::UNKNOWN || !IsNVIDIAOffloadArch(Arch)) {
- C.getDriver().Diag(clang::diag::err_drv_cuda_bad_gpu_arch) << ArchStr;
- return StringRef();
- }
- return OffloadArchToString(Arch);
- }
-
std::optional<std::pair<llvm::StringRef, llvm::StringRef>>
getConflictOffloadArchCombination(
const std::set<StringRef> &GpuArchs) override {
@@ -3705,24 +3620,6 @@ class OffloadingActionBuilder final {
bool canUseBundlerUnbundler() const override { return true; }
- StringRef getCanonicalOffloadArch(StringRef IdStr) override {
- llvm::StringMap<bool> Features;
- // getHIPOffloadTargetTriple() is known to return valid value as it has
- // been called successfully in the CreateOffloadingDeviceToolChains().
- auto T =
- (IdStr == "amdgcnspirv")
- ? llvm::Triple("spirv64-amd-amdhsa")
- : *getHIPOffloadTargetTriple(C.getDriver(), C.getInputArgs());
- auto ArchStr = parseTargetID(T, IdStr, &Features);
- if (!ArchStr) {
- C.getDriver().Diag(clang::diag::err_drv_bad_target_id) << IdStr;
- C.setContainsError();
- return StringRef();
- }
- auto CanId = getCanonicalTargetID(*ArchStr, Features);
- return Args.MakeArgStringRef(CanId);
- };
-
std::optional<std::pair<llvm::StringRef, llvm::StringRef>>
getConflictOffloadArchCombination(
const std::set<StringRef> &GpuArchs) override {
@@ -4715,23 +4612,20 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
static StringRef getCanonicalArchString(Compilation &C,
const llvm::opt::DerivedArgList &Args,
StringRef ArchStr,
- const llvm::Triple &Triple,
- bool SpecificToolchain) {
+ const llvm::Triple &Triple) {
// Lookup the CUDA / HIP architecture string. Only report an error if we were
// expecting the triple to be only NVPTX / AMDGPU.
OffloadArch Arch =
StringToOffloadArch(getProcessorFromTargetID(Triple, ArchStr));
if (Triple.isNVPTX() &&
(Arch == OffloadArch::UNKNOWN || !IsNVIDIAOffloadArch(Arch))) {
- if (SpecificToolchain)
- C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch)
- << "CUDA" << ArchStr;
+ C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch)
+ << "CUDA" << ArchStr;
return StringRef();
} else if (Triple.isAMDGPU() &&
(Arch == OffloadArch::UNKNOWN || !IsAMDOffloadArch(Arch))) {
- if (SpecificToolchain)
- C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch)
- << "HIP" << ArchStr;
+ C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch)
+ << "HIP" << ArchStr;
return StringRef();
}
@@ -4767,11 +4661,7 @@ getConflictOffloadArchCombination(const llvm::DenseSet<StringRef> &Archs,
llvm::SmallVector<StringRef>
Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,
- Action::OffloadKind Kind, const ToolChain *TC,
- bool SpecificToolchain) const {
- if (!TC)
- TC = &C.getDefaultToolChain();
-
+ Action::OffloadKind Kind, const ToolChain &TC) const {
// --offload and --offload-arch options are mutually exclusive.
if (Args.hasArgNoClaim(options::OPT_offload_EQ) &&
Args.hasArgNoClaim(options::OPT_offload_arch_EQ,
@@ -4784,48 +4674,44 @@ Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,
}
llvm::DenseSet<StringRef> Archs;
- for (auto *Arg : C.getArgsForToolChain(TC, /*BoundArch=*/"", Kind)) {
+ for (auto *Arg : C.getArgsForToolChain(&TC, /*BoundArch=*/"", Kind)) {
// Add or remove the seen architectures in order of appearance. If an
// invalid architecture is given we simply exit.
if (Arg->getOption().matches(options::OPT_offload_arch_EQ)) {
for (StringRef Arch : Arg->getValues()) {
if (Arch == "native" || Arch.empty()) {
- auto GPUsOrErr = TC->getSystemGPUArchs(Args);
+ auto GPUsOrErr = TC.getSystemGPUArchs(Args);
if (!GPUsOrErr) {
- if (!SpecificToolchain)
- llvm::consumeError(GPUsOrErr.takeError());
- else
- TC->getDriver().Diag(diag::err_drv_undetermined_gpu_arch)
- << llvm::Triple::getArchTypeName(TC->getArch())
- << llvm::toString(GPUsOrErr.takeError()) << "--offload-arch";
+ TC.getDriver().Diag(diag::err_drv_undetermined_gpu_arch)
+ << llvm::Triple::getArchTypeName(TC.getArch())
+ << llvm::toString(GPUsOrErr.takeError()) << "--offload-arch";
continue;
}
for (auto ArchStr : *GPUsOrErr) {
- StringRef CanonicalStr =
- getCanonicalArchString(C, Args, Args.MakeArgString(ArchStr),
- TC->getTriple(), SpecificToolchain);
+ StringRef CanonicalStr = getCanonicalArchString(
+ C, Args, Args.MakeArgString(ArchStr), TC.getTriple());
if (!CanonicalStr.empty())
Archs.insert(CanonicalStr);
- else if (SpecificToolchain)
+ else
return llvm::SmallVector<StringRef>();
}
} else {
- StringRef CanonicalStr = getCanonicalArchString(
- C, Args, Arch, TC->getTriple(), SpecificToolchain);
+ StringRef CanonicalStr =
+ getCanonicalArchString(C, Args, Arch, TC.getTriple());
if (!CanonicalStr.empty())
Archs.insert(CanonicalStr);
- else if (SpecificToolchain)
+ else
return llvm::SmallVector<StringRef>();
}
}
} else if (Arg->getOption().matches(options::OPT_no_offload_arch_EQ)) {
- for (StringRef Arch : llvm::split(Arg->getValue(), ",")) {
+ for (StringRef Arch : Arg->getValues()) {
if (Arch == "all") {
Archs.clear();
} else {
- StringRef ArchStr = getCanonicalArchString(
- C, Args, Arch, TC->getTriple(), SpecificToolchain);
+ StringRef ArchStr =
+ getCanonicalArchString(C, Args, Arch, TC.getTriple());
Archs.erase(ArchStr);
}
}
@@ -4833,28 +4719,30 @@ Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,
}
if (auto ConflictingArchs =
- getConflictOffloadArchCombination(Archs, TC->getTriple()))
+ getConflictOffloadArchCombination(Archs, TC.getTriple()))
C.getDriver().Diag(clang::diag::err_drv_bad_offload_arch_combo)
<< ConflictingArchs->first << ConflictingArchs->second;
- // Skip filling defaults if we're just querying what is availible.
- if (SpecificToolchain && Archs.empty()) {
+ // Fill in the default architectures if not provided explicitly.
+ if (Archs.empty()) {
if (Kind == Action::OFK_Cuda) {
Archs.insert(OffloadArchToString(OffloadArch::CudaDefault));
} else if (Kind == Action::OFK_HIP) {
- Archs.insert(OffloadArchToString(OffloadArch::HIPDefault));
+ Archs.insert(OffloadArchToString(TC.getTriple().isSPIRV()
+ ? OffloadArch::Generic
+ : OffloadArch::HIPDefault));
} else if (Kind == Action::OFK_SYCL) {
Archs.insert(StringRef());
} else if (Kind == Action::OFK_OpenMP) {
// Accept legacy `-march` device arguments for OpenMP.
- if (auto *Arg = C.getArgsForToolChain(TC, /*BoundArch=*/"", Kind)
+ if (auto *Arg = C.getArgsForToolChain(&TC, /*BoundArch=*/"", Kind)
.getLastArg(options::OPT_march_EQ)) {
Archs.insert(Arg->getValue());
} else {
- auto ArchsOrErr = TC->getSystemGPUArchs(Args);
+ auto ArchsOrErr = TC.getSystemGPUArchs(Args);
if (!ArchsOrErr) {
- TC->getDriver().Diag(diag::err_drv_undetermined_gpu_arch)
- << llvm::Triple::getArchTypeName(TC->getArch())
+ TC.getDriver().Diag(diag::err_drv_undetermined_gpu_arch)
+ << llvm::Triple::getArchTypeName(TC.getArch())
<< llvm::toString(ArchsOrErr.takeError()) << "--offload-arch";
} else if (!ArchsOrErr->empty()) {
for (auto Arch : *ArchsOrErr)
@@ -4934,7 +4822,7 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
// Get the product of all bound architectures and toolchains.
SmallVector<std::pair<const ToolChain *, StringRef>> TCAndArchs;
for (const ToolChain *TC : ToolChains) {
- for (StringRef Arch : OffloadArchs.lookup(TC)) {
+ for (StringRef Arch : getOffloadArchs(C, C.getArgs(), Kind, *TC)) {
TCAndArchs.push_back(std::make_pair(TC, Arch));
DeviceActions.push_back(
C.MakeAction<InputAction>(*InputArg, InputType, CUID));
@@ -4966,7 +4854,7 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
if (Kind == Action::OFK_SYCL && Phase == phases::Assemble)
continue;
- auto TCAndArch = TCAndArchs.begin();
+ auto *TCAndArch = TCAndArchs.begin();
for (Action *&A : DeviceActions) {
if (A->getType() == types::TY_Nothing)
continue;
@@ -4998,7 +4886,13 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
// Compiling HIP in device-only non-RDC mode requires linking each action
// individually.
for (Action *&A : DeviceActions) {
- if ((A->getType() != types::TY_Object &&
+ // Special handling for the HIP SPIR-V toolchain because it doesn't use
+ // the SPIR-V backend yet doesn't report the output as an object.
+ bool IsAMDGCNSPIRV = A->getOffloadingToolChain() &&
+ A->getOffloadingToolChain()->getTriple().getOS() ==
+ llvm::Triple::OSType::AMDHSA &&
+ A->getOffloadingToolChain()->getTriple().isSPIRV();
+ if ((A->getType() != types::TY_Object && !IsAMDGCNSPIRV &&
A->getType() != types::TY_LTO_BC) ||
!HIPNoRDC || !offloadDeviceOnly())
continue;
@@ -5006,7 +4900,7 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
A = C.MakeAction<LinkJobAction>(LinkerInput, types::TY_Image);
}
- auto TCAndArch = TCAndArchs.begin();
+ auto *TCAndArch = TCAndArchs.begin();
for (Action *A : DeviceActions) {
DDeps.add(*A, *TCAndArch->first, TCAndArch->second.data(), Kind);
OffloadAction::DeviceDependences DDep;
@@ -5054,8 +4948,9 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
// fatbinary for each translation unit, linking each input individually.
Action *FatbinAction =
C.MakeAction<LinkJobAction>(OffloadActions, types::TY_HIP_FATBIN);
- DDep.add(*FatbinAction, *C.getSingleOffloadToolChain<Action::OFK_HIP>(),
- nullptr, Action::OFK_HIP);
+ DDep.add(*FatbinAction,
+ *C.getOffloadToolChains<Action::OFK_HIP>().first->second, nullptr,
+ Action::OFK_HIP);
} else {
// Package all the offloading actions into a single output that can be
// embedded in the host and linked.
@@ -5131,11 +5026,13 @@ Action *Driver::ConstructPhaseAction(
if (Args.hasArg(options::OPT_extract_api))
return C.MakeAction<ExtractAPIJobAction>(Input, types::TY_API_INFO);
- // With 'fexperimental-modules-reduced-bmi', we don't want to run the
+ // With 'fmodules-reduced-bmi', we don't want to run the
// precompile phase unless the user specified '--precompile'. In the case
// the '--precompile' flag is enabled, we will try to emit the reduced BMI
// as a by product in GenerateModuleInterfaceAction.
- if (Args.hasArg(options::OPT_modules_reduced_bmi) &&
+ if (!Args.hasArg(options::OPT_fno_modules_reduced_bmi) &&
+ (Input->getType() == driver::types::TY_CXXModule ||
+ Input->getType() == driver::types::TY_PP_CXXModule) &&
!Args.getLastArg(options::OPT__precompile))
return Input;
@@ -5208,7 +5105,10 @@ Action *Driver::ConstructPhaseAction(
false) ||
(Args.hasFlag(options::OPT_offload_new_driver,
options::OPT_no_offload_new_driver, false) &&
- !offloadDeviceOnly())) ||
+ (!offloadDeviceOnly() ||
+ (Input->getOffloadingToolChain() &&
+ TargetDeviceOffloadKind == Action::OFK_HIP &&
+ Input->getOffloadingToolChain()->getTriple().isSPIRV())))) ||
TargetDeviceOffloadKind == Action::OFK_OpenMP))) {
types::ID Output =
Args.hasArg(options::OPT_S) &&
@@ -6323,7 +6223,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
// `-fmodule-output`.
if (!AtTopLevel && isa<PrecompileJobAction>(JA) &&
JA.getType() == types::TY_ModuleFile && SpecifiedModuleOutput) {
- assert(!C.getArgs().hasArg(options::OPT_modules_reduced_bmi));
+ assert(C.getArgs().hasArg(options::OPT_fno_modules_reduced_bmi));
return GetModuleOutputPath(C, JA, BaseInput);
}
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 481f575..1d7dad0 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -104,44 +104,6 @@ ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
addIfExists(getFilePaths(), Path);
}
-llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
-ToolChain::executeToolChainProgram(StringRef Executable) const {
- llvm::SmallString<64> OutputFile;
- llvm::sys::fs::createTemporaryFile("toolchain-program", "txt", OutputFile,
- llvm::sys::fs::OF_Text);
- llvm::FileRemover OutputRemover(OutputFile.c_str());
- std::optional<llvm::StringRef> Redirects[] = {
- {""},
- OutputFile.str(),
- {""},
- };
-
- std::string ErrorMessage;
- int SecondsToWait = 60;
- if (std::optional<std::string> Str =
- llvm::sys::Process::GetEnv("CLANG_TOOLCHAIN_PROGRAM_TIMEOUT")) {
- if (!llvm::to_integer(*Str, SecondsToWait))
- return llvm::createStringError(std::error_code(),
- "CLANG_TOOLCHAIN_PROGRAM_TIMEOUT expected "
- "an integer, got '" +
- *Str + "'");
- SecondsToWait = std::max(SecondsToWait, 0); // infinite
- }
- if (llvm::sys::ExecuteAndWait(Executable, {Executable}, {}, Redirects,
- SecondsToWait,
- /*MemoryLimit=*/0, &ErrorMessage))
- return llvm::createStringError(std::error_code(),
- Executable + ": " + ErrorMessage);
-
- llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> OutputBuf =
- llvm::MemoryBuffer::getFile(OutputFile.c_str());
- if (!OutputBuf)
- return llvm::createStringError(OutputBuf.getError(),
- "Failed to read stdout of " + Executable +
- ": " + OutputBuf.getError().message());
- return std::move(*OutputBuf);
-}
-
void ToolChain::setTripleEnvironment(llvm::Triple::EnvironmentType Env) {
Triple.setEnvironment(Env);
if (EffectiveTriple != llvm::Triple())
@@ -255,6 +217,18 @@ static void getAArch64MultilibFlags(const Driver &D,
Result.push_back(ABIArg->getAsString(Args));
}
+ if (const Arg *A = Args.getLastArg(options::OPT_O_Group);
+ A && A->getOption().matches(options::OPT_O)) {
+ switch (A->getValue()[0]) {
+ case 's':
+ Result.push_back("-Os");
+ break;
+ case 'z':
+ Result.push_back("-Oz");
+ break;
+ }
+ }
+
processMultilibCustomFlags(Result, Args);
}
@@ -332,6 +306,19 @@ static void getARMMultilibFlags(const Driver &D, const llvm::Triple &Triple,
if (Endian->getOption().matches(options::OPT_mbig_endian))
Result.push_back(Endian->getAsString(Args));
}
+
+ if (const Arg *A = Args.getLastArg(options::OPT_O_Group);
+ A && A->getOption().matches(options::OPT_O)) {
+ switch (A->getValue()[0]) {
+ case 's':
+ Result.push_back("-Os");
+ break;
+ case 'z':
+ Result.push_back("-Oz");
+ break;
+ }
+ }
+
processMultilibCustomFlags(Result, Args);
}
@@ -1100,7 +1087,7 @@ std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD) const {
// Get -fuse-ld= first to prevent -Wunused-command-line-argument. -fuse-ld= is
// considered as the linker flavor, e.g. "bfd", "gold", or "lld".
const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ);
- StringRef UseLinker = A ? A->getValue() : CLANG_DEFAULT_LINKER;
+ StringRef UseLinker = A ? A->getValue() : getDriver().getPreferredLinker();
// --ld-path= takes precedence over -fuse-ld= and specifies the executable
// name. -B, COMPILER_PATH and PATH and consulted if the value does not
@@ -1644,7 +1631,8 @@ void ToolChain::addSYCLIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {}
llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
-ToolChain::getDeviceLibs(const ArgList &DriverArgs) const {
+ToolChain::getDeviceLibs(const ArgList &DriverArgs,
+ const Action::OffloadKind DeviceOffloadingKind) const {
return {};
}
diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp
index 7fc34f4..0781683 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -31,6 +31,68 @@ using namespace clang::driver::toolchains;
using namespace clang;
using namespace llvm::opt;
+RocmInstallationDetector::CommonBitcodeLibsPreferences::
+ CommonBitcodeLibsPreferences(const Driver &D,
+ const llvm::opt::ArgList &DriverArgs,
+ StringRef GPUArch,
+ const Action::OffloadKind DeviceOffloadingKind,
+ const bool NeedsASanRT)
+ : ABIVer(DeviceLibABIVersion::fromCodeObjectVersion(
+ tools::getAMDGPUCodeObjectVersion(D, DriverArgs))) {
+ const auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch);
+ const unsigned ArchAttr = llvm::AMDGPU::getArchAttrAMDGCN(Kind);
+
+ IsOpenMP = DeviceOffloadingKind == Action::OFK_OpenMP;
+
+ const bool HasWave32 = (ArchAttr & llvm::AMDGPU::FEATURE_WAVE32);
+ Wave64 =
+ !HasWave32 || DriverArgs.hasFlag(options::OPT_mwavefrontsize64,
+ options::OPT_mno_wavefrontsize64, false);
+
+ const bool IsKnownOffloading = DeviceOffloadingKind == Action::OFK_OpenMP ||
+ DeviceOffloadingKind == Action::OFK_HIP;
+
+ // Default to enabling f32 denormals on subtargets where fma is fast with
+ // denormals
+ const bool DefaultDAZ =
+ (Kind == llvm::AMDGPU::GK_NONE)
+ ? false
+ : !((ArchAttr & llvm::AMDGPU::FEATURE_FAST_FMA_F32) &&
+ (ArchAttr & llvm::AMDGPU::FEATURE_FAST_DENORMAL_F32));
+ // TODO: There are way too many flags that change this. Do we need to
+ // check them all?
+ DAZ = IsKnownOffloading
+ ? DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
+ options::OPT_fno_gpu_flush_denormals_to_zero,
+ DefaultDAZ)
+ : DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) || DefaultDAZ;
+
+ FiniteOnly = DriverArgs.hasArg(options::OPT_cl_finite_math_only) ||
+ DriverArgs.hasFlag(options::OPT_ffinite_math_only,
+ options::OPT_fno_finite_math_only, false);
+
+ UnsafeMathOpt =
+ DriverArgs.hasArg(options::OPT_cl_unsafe_math_optimizations) ||
+ DriverArgs.hasFlag(options::OPT_funsafe_math_optimizations,
+ options::OPT_fno_unsafe_math_optimizations, false);
+
+ FastRelaxedMath = DriverArgs.hasArg(options::OPT_cl_fast_relaxed_math) ||
+ DriverArgs.hasFlag(options::OPT_ffast_math,
+ options::OPT_fno_fast_math, false);
+
+ const bool DefaultSqrt = IsKnownOffloading ? true : false;
+ CorrectSqrt =
+ DriverArgs.hasArg(options::OPT_cl_fp32_correctly_rounded_divide_sqrt) ||
+ DriverArgs.hasFlag(
+ options::OPT_fhip_fp32_correctly_rounded_divide_sqrt,
+ options::OPT_fno_hip_fp32_correctly_rounded_divide_sqrt, DefaultSqrt);
+ // GPU Sanitizer currently only supports ASan and is enabled through host
+ // ASan.
+ GPUSan = (DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
+ options::OPT_fno_gpu_sanitize, true) &&
+ NeedsASanRT);
+}
+
void RocmInstallationDetector::scanLibDevicePath(llvm::StringRef Path) {
assert(!Path.empty());
@@ -841,7 +903,7 @@ AMDGPUToolChain::getSystemGPUArchs(const ArgList &Args) const {
else
Program = GetProgramPath("amdgpu-arch");
- auto StdoutOrErr = executeToolChainProgram(Program);
+ auto StdoutOrErr = getDriver().executeProgram({Program});
if (!StdoutOrErr)
return StdoutOrErr.takeError();
@@ -884,33 +946,14 @@ void ROCMToolChain::addClangTargetOptions(
ABIVer))
return;
- bool Wave64 = isWave64(DriverArgs, Kind);
- // TODO: There are way too many flags that change this. Do we need to check
- // them all?
- bool DAZ = DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) ||
- getDefaultDenormsAreZeroForTarget(Kind);
- bool FiniteOnly = DriverArgs.hasArg(options::OPT_cl_finite_math_only);
-
- bool UnsafeMathOpt =
- DriverArgs.hasArg(options::OPT_cl_unsafe_math_optimizations);
- bool FastRelaxedMath = DriverArgs.hasArg(options::OPT_cl_fast_relaxed_math);
- bool CorrectSqrt =
- DriverArgs.hasArg(options::OPT_cl_fp32_correctly_rounded_divide_sqrt);
-
- // GPU Sanitizer currently only supports ASan and is enabled through host
- // ASan.
- bool GPUSan = DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
- options::OPT_fno_gpu_sanitize, true) &&
- getSanitizerArgs(DriverArgs).needsAsanRt();
-
// Add the OpenCL specific bitcode library.
llvm::SmallVector<BitCodeLibraryInfo, 12> BCLibs;
BCLibs.emplace_back(RocmInstallation->getOpenCLPath().str());
// Add the generic set of libraries.
BCLibs.append(RocmInstallation->getCommonBitcodeLibs(
- DriverArgs, LibDeviceFile, Wave64, DAZ, FiniteOnly, UnsafeMathOpt,
- FastRelaxedMath, CorrectSqrt, ABIVer, GPUSan, false));
+ DriverArgs, LibDeviceFile, GpuArch, DeviceOffloadingKind,
+ getSanitizerArgs(DriverArgs).needsAsanRt()));
for (auto [BCFile, Internalize] : BCLibs) {
if (Internalize)
@@ -947,35 +990,37 @@ bool RocmInstallationDetector::checkCommonBitcodeLibs(
llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
RocmInstallationDetector::getCommonBitcodeLibs(
- const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile, bool Wave64,
- bool DAZ, bool FiniteOnly, bool UnsafeMathOpt, bool FastRelaxedMath,
- bool CorrectSqrt, DeviceLibABIVersion ABIVer, bool GPUSan,
- bool isOpenMP) const {
+ const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile,
+ StringRef GPUArch, const Action::OffloadKind DeviceOffloadingKind,
+ const bool NeedsASanRT) const {
llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12> BCLibs;
+ CommonBitcodeLibsPreferences Pref{D, DriverArgs, GPUArch,
+ DeviceOffloadingKind, NeedsASanRT};
+
auto AddBCLib = [&](ToolChain::BitCodeLibraryInfo BCLib,
bool Internalize = true) {
BCLib.ShouldInternalize = Internalize;
BCLibs.emplace_back(BCLib);
};
auto AddSanBCLibs = [&]() {
- if (GPUSan)
+ if (Pref.GPUSan)
AddBCLib(getAsanRTLPath(), false);
};
AddSanBCLibs();
AddBCLib(getOCMLPath());
- if (!isOpenMP)
+ if (!Pref.IsOpenMP)
AddBCLib(getOCKLPath());
- else if (GPUSan && isOpenMP)
+ else if (Pref.GPUSan && Pref.IsOpenMP)
AddBCLib(getOCKLPath(), false);
- AddBCLib(getDenormalsAreZeroPath(DAZ));
- AddBCLib(getUnsafeMathPath(UnsafeMathOpt || FastRelaxedMath));
- AddBCLib(getFiniteOnlyPath(FiniteOnly || FastRelaxedMath));
- AddBCLib(getCorrectlyRoundedSqrtPath(CorrectSqrt));
- AddBCLib(getWavefrontSize64Path(Wave64));
+ AddBCLib(getDenormalsAreZeroPath(Pref.DAZ));
+ AddBCLib(getUnsafeMathPath(Pref.UnsafeMathOpt || Pref.FastRelaxedMath));
+ AddBCLib(getFiniteOnlyPath(Pref.FiniteOnly || Pref.FastRelaxedMath));
+ AddBCLib(getCorrectlyRoundedSqrtPath(Pref.CorrectSqrt));
+ AddBCLib(getWavefrontSize64Path(Pref.Wave64));
AddBCLib(LibDeviceFile);
- auto ABIVerPath = getABIVersionPath(ABIVer);
+ auto ABIVerPath = getABIVersionPath(Pref.ABIVer);
if (!ABIVerPath.empty())
AddBCLib(ABIVerPath);
@@ -983,9 +1028,9 @@ RocmInstallationDetector::getCommonBitcodeLibs(
}
llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
-ROCMToolChain::getCommonDeviceLibNames(const llvm::opt::ArgList &DriverArgs,
- const std::string &GPUArch,
- bool isOpenMP) const {
+ROCMToolChain::getCommonDeviceLibNames(
+ const llvm::opt::ArgList &DriverArgs, const std::string &GPUArch,
+ Action::OffloadKind DeviceOffloadingKind) const {
auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch);
const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind);
@@ -996,33 +1041,9 @@ ROCMToolChain::getCommonDeviceLibNames(const llvm::opt::ArgList &DriverArgs,
ABIVer))
return {};
- // If --hip-device-lib is not set, add the default bitcode libraries.
- // TODO: There are way too many flags that change this. Do we need to check
- // them all?
- bool DAZ = DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
- options::OPT_fno_gpu_flush_denormals_to_zero,
- getDefaultDenormsAreZeroForTarget(Kind));
- bool FiniteOnly = DriverArgs.hasFlag(
- options::OPT_ffinite_math_only, options::OPT_fno_finite_math_only, false);
- bool UnsafeMathOpt =
- DriverArgs.hasFlag(options::OPT_funsafe_math_optimizations,
- options::OPT_fno_unsafe_math_optimizations, false);
- bool FastRelaxedMath = DriverArgs.hasFlag(options::OPT_ffast_math,
- options::OPT_fno_fast_math, false);
- bool CorrectSqrt = DriverArgs.hasFlag(
- options::OPT_fhip_fp32_correctly_rounded_divide_sqrt,
- options::OPT_fno_hip_fp32_correctly_rounded_divide_sqrt, true);
- bool Wave64 = isWave64(DriverArgs, Kind);
-
- // GPU Sanitizer currently only supports ASan and is enabled through host
- // ASan.
- bool GPUSan = DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
- options::OPT_fno_gpu_sanitize, true) &&
- getSanitizerArgs(DriverArgs).needsAsanRt();
-
return RocmInstallation->getCommonBitcodeLibs(
- DriverArgs, LibDeviceFile, Wave64, DAZ, FiniteOnly, UnsafeMathOpt,
- FastRelaxedMath, CorrectSqrt, ABIVer, GPUSan, isOpenMP);
+ DriverArgs, LibDeviceFile, GPUArch, DeviceOffloadingKind,
+ getSanitizerArgs(DriverArgs).needsAsanRt());
}
bool AMDGPUToolChain::shouldSkipSanitizeOption(
diff --git a/clang/lib/Driver/ToolChains/AMDGPU.h b/clang/lib/Driver/ToolChains/AMDGPU.h
index 08bd4fa..513c77d 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.h
+++ b/clang/lib/Driver/ToolChains/AMDGPU.h
@@ -147,7 +147,7 @@ public:
llvm::SmallVector<BitCodeLibraryInfo, 12>
getCommonDeviceLibNames(const llvm::opt::ArgList &DriverArgs,
const std::string &GPUArch,
- bool isOpenMP = false) const;
+ Action::OffloadKind DeviceOffloadingKind) const;
SanitizerMask getSupportedSanitizers() const override {
return SanitizerKind::Address;
diff --git a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
index 7ffa3f0..2b41d54 100644
--- a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
@@ -44,7 +44,7 @@ void AMDGPUOpenMPToolChain::addClangTargetOptions(
true))
return;
- for (auto BCFile : getDeviceLibs(DriverArgs)) {
+ for (auto BCFile : getDeviceLibs(DriverArgs, DeviceOffloadingKind)) {
CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode"
: "-mlink-bitcode-file");
CC1Args.push_back(DriverArgs.MakeArgString(BCFile.Path));
@@ -132,7 +132,9 @@ AMDGPUOpenMPToolChain::computeMSVCVersion(const Driver *D,
}
llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
-AMDGPUOpenMPToolChain::getDeviceLibs(const llvm::opt::ArgList &Args) const {
+AMDGPUOpenMPToolChain::getDeviceLibs(
+ const llvm::opt::ArgList &Args,
+ const Action::OffloadKind DeviceOffloadingKind) const {
if (!Args.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib, true))
return {};
@@ -140,8 +142,8 @@ AMDGPUOpenMPToolChain::getDeviceLibs(const llvm::opt::ArgList &Args) const {
getTriple(), Args.getLastArgValue(options::OPT_march_EQ));
SmallVector<BitCodeLibraryInfo, 12> BCLibs;
- for (auto BCLib : getCommonDeviceLibNames(Args, GpuArch.str(),
- /*IsOpenMP=*/true))
+ for (auto BCLib :
+ getCommonDeviceLibNames(Args, GpuArch.str(), DeviceOffloadingKind))
BCLibs.emplace_back(BCLib);
return BCLibs;
diff --git a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h
index 0536c9f..cbafdf5 100644
--- a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h
+++ b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h
@@ -58,7 +58,8 @@ public:
const llvm::opt::ArgList &Args) const override;
llvm::SmallVector<BitCodeLibraryInfo, 12>
- getDeviceLibs(const llvm::opt::ArgList &Args) const override;
+ getDeviceLibs(const llvm::opt::ArgList &Args,
+ const Action::OffloadKind DeviceOffloadKind) const override;
const ToolChain &HostTC;
};
diff --git a/clang/lib/Driver/ToolChains/Arch/Sparc.cpp b/clang/lib/Driver/ToolChains/Arch/Sparc.cpp
index 9595ee8..94a94f1 100644
--- a/clang/lib/Driver/ToolChains/Arch/Sparc.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/Sparc.cpp
@@ -23,7 +23,9 @@ const char *sparc::getSparcAsmModeForCPU(StringRef Name,
if (Triple.getArch() == llvm::Triple::sparcv9) {
const char *DefV9CPU;
- if (Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD())
+ if (Triple.isOSSolaris())
+ DefV9CPU = "-Av9b";
+ else if (Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD())
DefV9CPU = "-Av9a";
else
DefV9CPU = "-Av9";
@@ -35,6 +37,13 @@ const char *sparc::getSparcAsmModeForCPU(StringRef Name,
.Case("niagara4", "-Av9d")
.Default(DefV9CPU);
} else {
+ const char *DefV8CPU;
+
+ if (Triple.isOSSolaris())
+ DefV8CPU = "-Av8plus";
+ else
+ DefV8CPU = "-Av8";
+
return llvm::StringSwitch<const char *>(Name)
.Case("v8", "-Av8")
.Case("supersparc", "-Av8")
@@ -70,7 +79,7 @@ const char *sparc::getSparcAsmModeForCPU(StringRef Name,
.Case("gr712rc", "-Aleon")
.Case("leon4", "-Aleon")
.Case("gr740", "-Aleon")
- .Default("-Av8");
+ .Default(DefV8CPU);
}
}
@@ -130,7 +139,8 @@ std::string sparc::getSparcTargetCPU(const Driver &D, const ArgList &Args,
return "";
}
-void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args,
+void sparc::getSparcTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args,
std::vector<StringRef> &Features) {
sparc::FloatABI FloatABI = sparc::getSparcFloatABI(D, Args);
if (FloatABI == sparc::FloatABI::Soft)
@@ -150,11 +160,22 @@ void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args,
Features.push_back("-popc");
}
+ // Those OSes default to enabling VIS on 64-bit SPARC.
+ // See also the corresponding code for external assemblers in
+ // sparc::getSparcAsmModeForCPU().
+ bool IsSparcV9ATarget =
+ (Triple.getArch() == llvm::Triple::sparcv9) &&
+ (Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD());
+ bool IsSparcV9BTarget = Triple.isOSSolaris();
+ bool IsSparcV8PlusTarget =
+ Triple.getArch() == llvm::Triple::sparc && Triple.isOSSolaris();
if (Arg *A = Args.getLastArg(options::OPT_mvis, options::OPT_mno_vis)) {
if (A->getOption().matches(options::OPT_mvis))
Features.push_back("+vis");
else
Features.push_back("-vis");
+ } else if (IsSparcV9ATarget) {
+ Features.push_back("+vis");
}
if (Arg *A = Args.getLastArg(options::OPT_mvis2, options::OPT_mno_vis2)) {
@@ -162,6 +183,8 @@ void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args,
Features.push_back("+vis2");
else
Features.push_back("-vis2");
+ } else if (IsSparcV9BTarget) {
+ Features.push_back("+vis2");
}
if (Arg *A = Args.getLastArg(options::OPT_mvis3, options::OPT_mno_vis3)) {
@@ -182,6 +205,8 @@ void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args,
if (Arg *A = Args.getLastArg(options::OPT_mv8plus, options::OPT_mno_v8plus)) {
if (A->getOption().matches(options::OPT_mv8plus))
Features.push_back("+v8plus");
+ } else if (IsSparcV8PlusTarget) {
+ Features.push_back("+v8plus");
}
if (Args.hasArg(options::OPT_ffixed_g1))
diff --git a/clang/lib/Driver/ToolChains/Arch/Sparc.h b/clang/lib/Driver/ToolChains/Arch/Sparc.h
index 2b178d9..fa25b49 100644
--- a/clang/lib/Driver/ToolChains/Arch/Sparc.h
+++ b/clang/lib/Driver/ToolChains/Arch/Sparc.h
@@ -31,7 +31,8 @@ FloatABI getSparcFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
std::string getSparcTargetCPU(const Driver &D, const llvm::opt::ArgList &Args,
const llvm::Triple &Triple);
-void getSparcTargetFeatures(const Driver &D, const llvm::opt::ArgList &Args,
+void getSparcTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args,
std::vector<llvm::StringRef> &Features);
const char *getSparcAsmModeForCPU(llvm::StringRef Name,
const llvm::Triple &Triple);
diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp
index e670696..497f333 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -694,9 +694,6 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
NeedCRTs)
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath(CRTEnd)));
- if (TC.getTriple().isRISCV())
- CmdArgs.push_back("-X");
-
// The R_ARM_TARGET2 relocation must be treated as R_ARM_REL32 on arm*-*-elf
// and arm*-*-eabi (the default is R_ARM_GOT_PREL, used on arm*-*-linux and
// arm*-*-*bsd).
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 8880c93..7d0c142 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -97,32 +97,15 @@ forAllAssociatedToolChains(Compilation &C, const JobAction &JA,
// Apply Work on all the offloading tool chains associated with the current
// action.
- if (JA.isHostOffloading(Action::OFK_Cuda))
- Work(*C.getSingleOffloadToolChain<Action::OFK_Cuda>());
- else if (JA.isDeviceOffloading(Action::OFK_Cuda))
- Work(*C.getSingleOffloadToolChain<Action::OFK_Host>());
- else if (JA.isHostOffloading(Action::OFK_HIP))
- Work(*C.getSingleOffloadToolChain<Action::OFK_HIP>());
- else if (JA.isDeviceOffloading(Action::OFK_HIP))
- Work(*C.getSingleOffloadToolChain<Action::OFK_Host>());
-
- if (JA.isHostOffloading(Action::OFK_OpenMP)) {
- auto TCs = C.getOffloadToolChains<Action::OFK_OpenMP>();
- for (auto II = TCs.first, IE = TCs.second; II != IE; ++II)
- Work(*II->second);
- } else if (JA.isDeviceOffloading(Action::OFK_OpenMP))
- Work(*C.getSingleOffloadToolChain<Action::OFK_Host>());
-
- if (JA.isHostOffloading(Action::OFK_SYCL)) {
- auto TCs = C.getOffloadToolChains<Action::OFK_SYCL>();
- for (auto II = TCs.first, IE = TCs.second; II != IE; ++II)
- Work(*II->second);
- } else if (JA.isDeviceOffloading(Action::OFK_SYCL))
- Work(*C.getSingleOffloadToolChain<Action::OFK_Host>());
-
- //
- // TODO: Add support for other offloading programming models here.
- //
+ for (Action::OffloadKind Kind : {Action::OFK_Cuda, Action::OFK_OpenMP,
+ Action::OFK_HIP, Action::OFK_SYCL}) {
+ if (JA.isHostOffloading(Kind)) {
+ auto TCs = C.getOffloadToolChains(Kind);
+ for (auto II = TCs.first, IE = TCs.second; II != IE; ++II)
+ Work(*II->second);
+ } else if (JA.isDeviceOffloading(Kind))
+ Work(*C.getSingleOffloadToolChain<Action::OFK_Host>());
+ }
}
static bool
@@ -2731,16 +2714,6 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
CmdArgs.push_back(MipsTargetFeature);
}
- // Those OSes default to enabling VIS on 64-bit SPARC.
- // See also the corresponding code for external assemblers in
- // sparc::getSparcAsmModeForCPU().
- bool IsSparcV9ATarget =
- (C.getDefaultToolChain().getArch() == llvm::Triple::sparcv9) &&
- (Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD());
- if (IsSparcV9ATarget && SparcTargetFeatures.empty()) {
- CmdArgs.push_back("-target-feature");
- CmdArgs.push_back("+vis");
- }
for (const char *Feature : SparcTargetFeatures) {
CmdArgs.push_back("-target-feature");
CmdArgs.push_back(Feature);
@@ -4095,31 +4068,34 @@ static bool RenderModulesOptions(Compilation &C, const Driver &D,
// module fragment.
CmdArgs.push_back("-fskip-odr-check-in-gmf");
- if (Args.hasArg(options::OPT_modules_reduced_bmi) &&
+ if (!Args.hasArg(options::OPT_fno_modules_reduced_bmi) &&
(Input.getType() == driver::types::TY_CXXModule ||
- Input.getType() == driver::types::TY_PP_CXXModule)) {
+ Input.getType() == driver::types::TY_PP_CXXModule) &&
+ !Args.hasArg(options::OPT__precompile)) {
CmdArgs.push_back("-fmodules-reduced-bmi");
if (Args.hasArg(options::OPT_fmodule_output_EQ))
Args.AddLastArg(CmdArgs, options::OPT_fmodule_output_EQ);
- else {
- if (Args.hasArg(options::OPT__precompile) &&
- (!Args.hasArg(options::OPT_o) ||
- Args.getLastArg(options::OPT_o)->getValue() ==
- getCXX20NamedModuleOutputPath(Args, Input.getBaseInput()))) {
- D.Diag(diag::err_drv_reduced_module_output_overrided);
- }
-
+ else
CmdArgs.push_back(Args.MakeArgString(
"-fmodule-output=" +
getCXX20NamedModuleOutputPath(Args, Input.getBaseInput())));
- }
}
- // Noop if we see '-fmodules-reduced-bmi' with other translation
- // units than module units. This is more user friendly to allow end uers to
- // enable this feature without asking for help from build systems.
- Args.ClaimAllArgs(options::OPT_modules_reduced_bmi);
+ if (Args.hasArg(options::OPT_fmodules_reduced_bmi) &&
+ Args.hasArg(options::OPT__precompile) &&
+ (!Args.hasArg(options::OPT_o) ||
+ Args.getLastArg(options::OPT_o)->getValue() ==
+ getCXX20NamedModuleOutputPath(Args, Input.getBaseInput()))) {
+ D.Diag(diag::err_drv_reduced_module_output_overrided);
+ }
+
+ // Noop if we see '-fmodules-reduced-bmi' or `-fno-modules-reduced-bmi` with
+ // other translation units than module units. This is more user friendly to
+ // allow end uers to enable this feature without asking for help from build
+ // systems.
+ Args.ClaimAllArgs(options::OPT_fmodules_reduced_bmi);
+ Args.ClaimAllArgs(options::OPT_fno_modules_reduced_bmi);
// We need to include the case the input file is a module file here.
// Since the default compilation model for C++ module interface unit will
@@ -4992,8 +4968,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
else {
// Host-side compilation.
NormalizedTriple =
- (IsCuda ? C.getSingleOffloadToolChain<Action::OFK_Cuda>()
- : C.getSingleOffloadToolChain<Action::OFK_HIP>())
+ (IsCuda ? C.getOffloadToolChains(Action::OFK_Cuda).first->second
+ : C.getOffloadToolChains(Action::OFK_HIP).first->second)
->getTriple()
.normalize();
if (IsCuda) {
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 651a39c..826e2ea 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -856,7 +856,7 @@ void tools::getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
case llvm::Triple::sparcv9:
- sparc::getSparcTargetFeatures(D, Args, Features);
+ sparc::getSparcTargetFeatures(D, Triple, Args, Features);
break;
case llvm::Triple::r600:
case llvm::Triple::amdgcn:
diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp
index 2373d94..7d803be 100644
--- a/clang/lib/Driver/ToolChains/Cuda.cpp
+++ b/clang/lib/Driver/ToolChains/Cuda.cpp
@@ -815,7 +815,7 @@ NVPTXToolChain::getSystemGPUArchs(const ArgList &Args) const {
else
Program = GetProgramPath("nvptx-arch");
- auto StdoutOrErr = executeToolChainProgram(Program);
+ auto StdoutOrErr = getDriver().executeProgram({Program});
if (!StdoutOrErr)
return StdoutOrErr.takeError();
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 1edb83f..7ab41e9 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -447,6 +447,7 @@ void Flang::addTargetOptions(const ArgList &Args,
// Add the target features.
switch (TC.getArch()) {
default:
+ getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);
break;
case llvm::Triple::aarch64:
getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false);
diff --git a/clang/lib/Driver/ToolChains/HIPAMD.cpp b/clang/lib/Driver/ToolChains/HIPAMD.cpp
index 5fe0f85..b4c6da0 100644
--- a/clang/lib/Driver/ToolChains/HIPAMD.cpp
+++ b/clang/lib/Driver/ToolChains/HIPAMD.cpp
@@ -264,7 +264,7 @@ void HIPAMDToolChain::addClangTargetOptions(
return; // No DeviceLibs for SPIR-V.
}
- for (auto BCFile : getDeviceLibs(DriverArgs)) {
+ for (auto BCFile : getDeviceLibs(DriverArgs, DeviceOffloadingKind)) {
CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode"
: "-mlink-bitcode-file");
CC1Args.push_back(DriverArgs.MakeArgString(BCFile.Path));
@@ -355,7 +355,8 @@ VersionTuple HIPAMDToolChain::computeMSVCVersion(const Driver *D,
}
llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
-HIPAMDToolChain::getDeviceLibs(const llvm::opt::ArgList &DriverArgs) const {
+HIPAMDToolChain::getDeviceLibs(const llvm::opt::ArgList &DriverArgs,
+ Action::OffloadKind DeviceOffloadingKind) const {
llvm::SmallVector<BitCodeLibraryInfo, 12> BCLibs;
if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
true) ||
@@ -397,7 +398,8 @@ HIPAMDToolChain::getDeviceLibs(const llvm::opt::ArgList &DriverArgs) const {
assert(!GpuArch.empty() && "Must have an explicit GPU arch.");
// Add common device libraries like ocml etc.
- for (auto N : getCommonDeviceLibNames(DriverArgs, GpuArch.str()))
+ for (auto N : getCommonDeviceLibNames(DriverArgs, GpuArch.str(),
+ DeviceOffloadingKind))
BCLibs.emplace_back(N);
// Add instrument lib.
diff --git a/clang/lib/Driver/ToolChains/HIPAMD.h b/clang/lib/Driver/ToolChains/HIPAMD.h
index 3630b11..bcc3ebb 100644
--- a/clang/lib/Driver/ToolChains/HIPAMD.h
+++ b/clang/lib/Driver/ToolChains/HIPAMD.h
@@ -80,7 +80,8 @@ public:
void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
llvm::SmallVector<BitCodeLibraryInfo, 12>
- getDeviceLibs(const llvm::opt::ArgList &Args) const override;
+ getDeviceLibs(const llvm::opt::ArgList &Args,
+ Action::OffloadKind DeviceOffloadKind) const override;
SanitizerMask getSupportedSanitizers() const override;
diff --git a/clang/lib/Driver/ToolChains/HIPSPV.cpp b/clang/lib/Driver/ToolChains/HIPSPV.cpp
index 53649ca..643a67f 100644
--- a/clang/lib/Driver/ToolChains/HIPSPV.cpp
+++ b/clang/lib/Driver/ToolChains/HIPSPV.cpp
@@ -149,7 +149,8 @@ void HIPSPVToolChain::addClangTargetOptions(
CC1Args.append(
{"-fvisibility=hidden", "-fapply-global-visibility-to-externs"});
- for (const BitCodeLibraryInfo &BCFile : getDeviceLibs(DriverArgs))
+ for (const BitCodeLibraryInfo &BCFile :
+ getDeviceLibs(DriverArgs, DeviceOffloadingKind))
CC1Args.append(
{"-mlink-builtin-bitcode", DriverArgs.MakeArgString(BCFile.Path)});
}
@@ -200,7 +201,9 @@ void HIPSPVToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
}
llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
-HIPSPVToolChain::getDeviceLibs(const llvm::opt::ArgList &DriverArgs) const {
+HIPSPVToolChain::getDeviceLibs(
+ const llvm::opt::ArgList &DriverArgs,
+ const Action::OffloadKind DeviceOffloadingKind) const {
llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12> BCLibs;
if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib,
true))
diff --git a/clang/lib/Driver/ToolChains/HIPSPV.h b/clang/lib/Driver/ToolChains/HIPSPV.h
index ecd82e7..caf6924 100644
--- a/clang/lib/Driver/ToolChains/HIPSPV.h
+++ b/clang/lib/Driver/ToolChains/HIPSPV.h
@@ -69,7 +69,8 @@ public:
void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
llvm::SmallVector<BitCodeLibraryInfo, 12>
- getDeviceLibs(const llvm::opt::ArgList &Args) const override;
+ getDeviceLibs(const llvm::opt::ArgList &Args,
+ const Action::OffloadKind DeviceOffloadKind) const override;
SanitizerMask getSupportedSanitizers() const override;
diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp
index 7d31eea..bb469ff 100644
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -279,8 +279,8 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
AddRunTimeLibs(TC, TC.getDriver(), CmdArgs, Args);
}
- StringRef Linker =
- Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER);
+ StringRef Linker = Args.getLastArgValue(options::OPT_fuse_ld_EQ,
+ TC.getDriver().getPreferredLinker());
if (Linker.empty())
Linker = "link";
// We need to translate 'lld' into 'lld-link'.
diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp
index b2e36ae..6abd0c0 100644
--- a/clang/lib/Driver/ToolChains/MinGW.cpp
+++ b/clang/lib/Driver/ToolChains/MinGW.cpp
@@ -548,7 +548,7 @@ toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple,
getFilePaths().push_back(Base + "lib");
NativeLLVMSupport =
- Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER)
+ Args.getLastArgValue(options::OPT_fuse_ld_EQ, D.getPreferredLinker())
.equals_insensitive("lld");
}
diff --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp b/clang/lib/Driver/ToolChains/OpenBSD.cpp
index 79b1b69..8f58918 100644
--- a/clang/lib/Driver/ToolChains/OpenBSD.cpp
+++ b/clang/lib/Driver/ToolChains/OpenBSD.cpp
@@ -161,7 +161,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Nopie || Profiling)
CmdArgs.push_back("-nopie");
- if (Triple.isRISCV64()) {
+ if (Triple.isLoongArch64() || Triple.isRISCV64()) {
CmdArgs.push_back("-X");
if (Args.hasArg(options::OPT_mno_relax))
CmdArgs.push_back("--no-relax");
diff --git a/clang/lib/Driver/ToolChains/ROCm.h b/clang/lib/Driver/ToolChains/ROCm.h
index 2a09da01..ebd5443 100644
--- a/clang/lib/Driver/ToolChains/ROCm.h
+++ b/clang/lib/Driver/ToolChains/ROCm.h
@@ -11,6 +11,7 @@
#include "clang/Basic/Cuda.h"
#include "clang/Basic/LLVM.h"
+#include "clang/Driver/CommonArgs.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
@@ -18,6 +19,7 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/VersionTuple.h"
+#include "llvm/TargetParser/TargetParser.h"
#include "llvm/TargetParser/Triple.h"
namespace clang {
@@ -77,6 +79,24 @@ private:
SPACKReleaseStr(SPACKReleaseStr.str()) {}
};
+ struct CommonBitcodeLibsPreferences {
+ CommonBitcodeLibsPreferences(const Driver &D,
+ const llvm::opt::ArgList &DriverArgs,
+ StringRef GPUArch,
+ const Action::OffloadKind DeviceOffloadingKind,
+ const bool NeedsASanRT);
+
+ DeviceLibABIVersion ABIVer;
+ bool IsOpenMP;
+ bool Wave64;
+ bool DAZ;
+ bool FiniteOnly;
+ bool UnsafeMathOpt;
+ bool FastRelaxedMath;
+ bool CorrectSqrt;
+ bool GPUSan;
+ };
+
const Driver &D;
bool HasHIPRuntime = false;
bool HasDeviceLibrary = false;
@@ -175,11 +195,11 @@ public:
/// Get file paths of default bitcode libraries common to AMDGPU based
/// toolchains.
- llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12> getCommonBitcodeLibs(
- const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile,
- bool Wave64, bool DAZ, bool FiniteOnly, bool UnsafeMathOpt,
- bool FastRelaxedMath, bool CorrectSqrt, DeviceLibABIVersion ABIVer,
- bool GPUSan, bool isOpenMP) const;
+ llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
+ getCommonBitcodeLibs(const llvm::opt::ArgList &DriverArgs,
+ StringRef LibDeviceFile, StringRef GPUArch,
+ const Action::OffloadKind DeviceOffloadingKind,
+ const bool NeedsASanRT) const;
/// Check file paths of default bitcode libraries common to AMDGPU based
/// toolchains. \returns false if there are invalid or missing files.
bool checkCommonBitcodeLibs(StringRef GPUArch, StringRef LibDeviceFile,
diff --git a/clang/lib/Driver/ToolChains/Solaris.cpp b/clang/lib/Driver/ToolChains/Solaris.cpp
index a3574e1..02aa598 100644
--- a/clang/lib/Driver/ToolChains/Solaris.cpp
+++ b/clang/lib/Driver/ToolChains/Solaris.cpp
@@ -39,7 +39,7 @@ void solaris::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
bool solaris::isLinkerGnuLd(const ToolChain &TC, const ArgList &Args) {
// Only used if targetting Solaris.
const Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ);
- StringRef UseLinker = A ? A->getValue() : CLANG_DEFAULT_LINKER;
+ StringRef UseLinker = A ? A->getValue() : TC.getDriver().getPreferredLinker();
return UseLinker == "bfd" || UseLinker == "gld";
}
@@ -52,7 +52,7 @@ static bool getPIE(const ArgList &Args, const ToolChain &TC) {
TC.isPIEDefault(Args));
}
-// FIXME: Need to handle CLANG_DEFAULT_LINKER here?
+// FIXME: Need to handle PreferredLinker here?
std::string solaris::Linker::getLinkerPath(const ArgList &Args) const {
const ToolChain &ToolChain = getToolChain();
if (const Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
@@ -345,7 +345,7 @@ SanitizerMask Solaris::getSupportedSanitizers() const {
const char *Solaris::getDefaultLinker() const {
// FIXME: Only handle Solaris ld and GNU ld here.
- return llvm::StringSwitch<const char *>(CLANG_DEFAULT_LINKER)
+ return llvm::StringSwitch<const char *>(getDriver().getPreferredLinker())
.Cases("bfd", "gld", "/usr/gnu/bin/ld")
.Default("/usr/bin/ld");
}
diff --git a/clang/lib/Driver/ToolChains/UEFI.cpp b/clang/lib/Driver/ToolChains/UEFI.cpp
index ac6668e..2b41173 100644
--- a/clang/lib/Driver/ToolChains/UEFI.cpp
+++ b/clang/lib/Driver/ToolChains/UEFI.cpp
@@ -83,8 +83,8 @@ void tools::uefi::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// This should ideally be handled by ToolChain::GetLinkerPath but we need
// to special case some linker paths. In the case of lld, we need to
// translate 'lld' into 'lld-link'.
- StringRef Linker =
- Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER);
+ StringRef Linker = Args.getLastArgValue(options::OPT_fuse_ld_EQ,
+ TC.getDriver().getPreferredLinker());
if (Linker.empty() || Linker == "lld")
Linker = "lld-link";
diff --git a/clang/lib/Format/BreakableToken.cpp b/clang/lib/Format/BreakableToken.cpp
index c36cb74..29db200 100644
--- a/clang/lib/Format/BreakableToken.cpp
+++ b/clang/lib/Format/BreakableToken.cpp
@@ -25,7 +25,7 @@
namespace clang {
namespace format {
-static constexpr StringRef Blanks = " \t\v\f\r";
+static constexpr StringRef Blanks(" \t\v\f\r");
static StringRef getLineCommentIndentPrefix(StringRef Comment,
const FormatStyle &Style) {
@@ -513,7 +513,7 @@ BreakableBlockComment::BreakableBlockComment(
Decoration = "";
}
for (size_t i = 1, e = Content.size(); i < e && !Decoration.empty(); ++i) {
- const StringRef &Text = Content[i];
+ const StringRef Text(Content[i]);
if (i + 1 == e) {
// If the last line is empty, the closing "*/" will have a star.
if (Text.empty())
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp
index 4010f7f..9a10403 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -560,6 +560,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
return true;
}
} else if (Current.is(TT_BinaryOperator) && Current.CanBreakBefore &&
+ Current.getPrecedence() != prec::Assignment &&
CurrentState.BreakBeforeParameter) {
return true;
}
@@ -1724,7 +1725,8 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
}
if (Previous && (Previous->isOneOf(TT_BinaryOperator, TT_ConditionalExpr) ||
(Previous->isOneOf(tok::l_paren, tok::comma, tok::colon) &&
- !Previous->isOneOf(TT_DictLiteral, TT_ObjCMethodExpr)))) {
+ !Previous->isOneOf(TT_DictLiteral, TT_ObjCMethodExpr,
+ TT_CtorInitializerColon)))) {
CurrentState.NestedBlockInlined =
!Newline && hasNestedBlockInlined(Previous, Current, Style);
}
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 62feb3d..1cfa3d1 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -731,6 +731,7 @@ template <> struct MappingTraits<FormatStyle::SpaceBeforeParensCustom> {
IO.mapOptional("AfterFunctionDeclarationName",
Spacing.AfterFunctionDeclarationName);
IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros);
+ IO.mapOptional("AfterNot", Spacing.AfterNot);
IO.mapOptional("AfterOverloadedOperator", Spacing.AfterOverloadedOperator);
IO.mapOptional("AfterPlacementOperator", Spacing.AfterPlacementOperator);
IO.mapOptional("AfterRequiresInClause", Spacing.AfterRequiresInClause);
@@ -2643,13 +2644,14 @@ private:
for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) {
if (Tok->isNot(TT_PointerOrReference))
continue;
- // Don't treat space in `void foo() &&` as evidence.
+ // Don't treat space in `void foo() &&` or `void() &&` as evidence.
if (const auto *Prev = Tok->getPreviousNonComment()) {
if (Prev->is(tok::r_paren) && Prev->MatchingParen) {
if (const auto *Func =
Prev->MatchingParen->getPreviousNonComment()) {
if (Func->isOneOf(TT_FunctionDeclarationName, TT_StartOfName,
- TT_OverloadedOperator)) {
+ TT_OverloadedOperator) ||
+ Func->isTypeName(LangOpts)) {
continue;
}
}
diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp
index 49da316..3f4aa52 100644
--- a/clang/lib/Format/FormatTokenLexer.cpp
+++ b/clang/lib/Format/FormatTokenLexer.cpp
@@ -1198,7 +1198,7 @@ void FormatTokenLexer::truncateToken(size_t NewLen) {
/// Count the length of leading whitespace in a token.
static size_t countLeadingWhitespace(StringRef Text) {
// Basically counting the length matched by this regex.
- // "^([\n\r\f\v \t]|(\\\\|\\?\\?/)[\n\r])+"
+ // "^([\n\r\f\v \t]|\\\\[\n\r])+"
// Directly using the regex turned out to be slow. With the regex
// version formatting all files in this directory took about 1.25
// seconds. This version took about 0.5 seconds.
@@ -1222,13 +1222,6 @@ static size_t countLeadingWhitespace(StringRef Text) {
break;
// Splice found, consume it.
Cur = Lookahead + 1;
- } else if (Cur[0] == '?' && Cur[1] == '?' && Cur[2] == '/' &&
- (Cur[3] == '\n' || Cur[3] == '\r')) {
- // Newlines can also be escaped by a '?' '?' '/' trigraph. By the way, the
- // characters are quoted individually in this comment because if we write
- // them together some compilers warn that we have a trigraph in the code.
- assert(End - Cur >= 4);
- Cur += 4;
} else {
break;
}
@@ -1300,22 +1293,16 @@ FormatToken *FormatTokenLexer::getNextToken() {
Style.TabWidth - (Style.TabWidth ? Column % Style.TabWidth : 0);
break;
case '\\':
- case '?':
- case '/':
- // The text was entirely whitespace when this loop was entered. Thus
- // this has to be an escape sequence.
- assert(Text.substr(i, 4) == "\?\?/\r" ||
- Text.substr(i, 4) == "\?\?/\n" ||
- (i >= 1 && (Text.substr(i - 1, 4) == "\?\?/\r" ||
- Text.substr(i - 1, 4) == "\?\?/\n")) ||
- (i >= 2 && (Text.substr(i - 2, 4) == "\?\?/\r" ||
- Text.substr(i - 2, 4) == "\?\?/\n")) ||
- (Text[i] == '\\' && [&]() -> bool {
- size_t j = i + 1;
- while (j < Text.size() && isHorizontalWhitespace(Text[j]))
- ++j;
- return j < Text.size() && (Text[j] == '\n' || Text[j] == '\r');
- }()));
+ // The code preceding the loop and in the countLeadingWhitespace
+ // function guarantees that Text is entirely whitespace, not including
+ // comments but including escaped newlines. So the character shows up,
+ // then it has to be in an escape sequence.
+ assert([&]() -> bool {
+ size_t j = i + 1;
+ while (j < Text.size() && isHorizontalWhitespace(Text[j]))
+ ++j;
+ return j < Text.size() && (Text[j] == '\n' || Text[j] == '\r');
+ }());
InEscape = true;
break;
default:
diff --git a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp
index 87823ae..80487fa 100644
--- a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp
+++ b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp
@@ -19,7 +19,7 @@ namespace format {
enum class Base { Binary, Decimal, Hex, Other };
-static Base getBase(const StringRef IntegerLiteral) {
+static Base getBase(StringRef IntegerLiteral) {
assert(IntegerLiteral.size() > 1);
if (IntegerLiteral[0] > '0') {
@@ -164,8 +164,8 @@ IntegerLiteralSeparatorFixer::process(const Environment &Env,
return {Result, 0};
}
-bool IntegerLiteralSeparatorFixer::checkSeparator(
- const StringRef IntegerLiteral, int DigitsPerGroup) const {
+bool IntegerLiteralSeparatorFixer::checkSeparator(StringRef IntegerLiteral,
+ int DigitsPerGroup) const {
assert(DigitsPerGroup > 0);
int I = 0;
@@ -184,7 +184,7 @@ bool IntegerLiteralSeparatorFixer::checkSeparator(
return true;
}
-std::string IntegerLiteralSeparatorFixer::format(const StringRef IntegerLiteral,
+std::string IntegerLiteralSeparatorFixer::format(StringRef IntegerLiteral,
int DigitsPerGroup,
int DigitCount,
bool RemoveSeparator) const {
diff --git a/clang/lib/Format/IntegerLiteralSeparatorFixer.h b/clang/lib/Format/IntegerLiteralSeparatorFixer.h
index 2c158e4..e24af18 100644
--- a/clang/lib/Format/IntegerLiteralSeparatorFixer.h
+++ b/clang/lib/Format/IntegerLiteralSeparatorFixer.h
@@ -26,8 +26,8 @@ public:
const FormatStyle &Style);
private:
- bool checkSeparator(const StringRef IntegerLiteral, int DigitsPerGroup) const;
- std::string format(const StringRef IntegerLiteral, int DigitsPerGroup,
+ bool checkSeparator(StringRef IntegerLiteral, int DigitsPerGroup) const;
+ std::string format(StringRef IntegerLiteral, int DigitsPerGroup,
int DigitCount, bool RemoveSeparator) const;
char Separator;
diff --git a/clang/lib/Format/ObjCPropertyAttributeOrderFixer.cpp b/clang/lib/Format/ObjCPropertyAttributeOrderFixer.cpp
index 37a1807..b885942 100644
--- a/clang/lib/Format/ObjCPropertyAttributeOrderFixer.cpp
+++ b/clang/lib/Format/ObjCPropertyAttributeOrderFixer.cpp
@@ -66,7 +66,7 @@ void ObjCPropertyAttributeOrderFixer::sortPropertyAttributes(
return;
}
- const StringRef Attribute{Tok->TokenText};
+ const StringRef Attribute(Tok->TokenText);
StringRef Value;
// Also handle `getter=getFoo` attributes.
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 581bfba..d28d2fd 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -5478,7 +5478,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
if (Left.TokenText == "!")
return Style.SpaceAfterLogicalNot;
assert(Left.TokenText == "not");
- return Right.isOneOf(tok::coloncolon, TT_UnaryOperator);
+ return Right.isOneOf(tok::coloncolon, TT_UnaryOperator) ||
+ (Right.is(tok::l_paren) && Style.SpaceBeforeParensOptions.AfterNot);
}
// If the next token is a binary operator or a selector name, we have
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 3a36250..ab4384a 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -2013,8 +2013,8 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
: llvm::codegenoptions::DebugTemplateNamesKind::Mangled);
}
- if (const Arg *A = Args.getLastArg(OPT_ftime_report, OPT_ftime_report_EQ,
- OPT_ftime_report_json)) {
+ if (Args.hasArg(OPT_ftime_report, OPT_ftime_report_EQ, OPT_ftime_report_json,
+ OPT_stats_file_timers)) {
Opts.TimePasses = true;
// -ftime-report= is only for new pass manager.
@@ -2026,7 +2026,7 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
Opts.TimePassesPerRun = true;
else
Diags.Report(diag::err_drv_invalid_value)
- << A->getAsString(Args) << A->getValue();
+ << EQ->getAsString(Args) << EQ->getValue();
}
if (Args.getLastArg(OPT_ftime_report_json))
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index db6a2bb..9b71486 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -761,10 +761,18 @@ Interpreter::getSymbolAddressFromLinkerName(llvm::StringRef Name) const {
llvm::Error Interpreter::Undo(unsigned N) {
- if (N > getEffectivePTUSize())
+ if (getEffectivePTUSize() == 0) {
return llvm::make_error<llvm::StringError>("Operation failed. "
- "Too many undos",
+ "No input left to undo",
std::error_code());
+ } else if (N > getEffectivePTUSize()) {
+ return llvm::make_error<llvm::StringError>(
+ llvm::formatv(
+ "Operation failed. Wanted to undo {0} inputs, only have {1}.", N,
+ getEffectivePTUSize()),
+ std::error_code());
+ }
+
for (unsigned I = 0; I < N; I++) {
if (IncrExecutor) {
if (llvm::Error Err = IncrExecutor->removeModule(PTUs.back()))
diff --git a/clang/lib/Interpreter/InterpreterValuePrinter.cpp b/clang/lib/Interpreter/InterpreterValuePrinter.cpp
index 34ffd62..0ea6274 100644
--- a/clang/lib/Interpreter/InterpreterValuePrinter.cpp
+++ b/clang/lib/Interpreter/InterpreterValuePrinter.cpp
@@ -106,7 +106,7 @@ static std::string EnumToString(const Value &V) {
assert(EnumTy && "Fail to cast to enum type");
EnumDecl *ED = EnumTy->getDecl();
- uint64_t Data = V.getULongLong();
+ uint64_t Data = V.convertTo<uint64_t>();
bool IsFirst = true;
llvm::APSInt AP = Ctx.MakeIntValue(Data, DesugaredTy);
diff --git a/clang/lib/Lex/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp
index a62508e..5b08d7f 100644
--- a/clang/lib/Lex/LiteralSupport.cpp
+++ b/clang/lib/Lex/LiteralSupport.cpp
@@ -1467,7 +1467,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
if (s != PossibleNewDigitStart)
DigitsBegin = PossibleNewDigitStart;
else
- IsSingleZero = (s == ThisTokEnd); // Is the only thing we've seen a 0?
+ IsSingleZero = (s == ThisTokBegin + 1);
if (s == ThisTokEnd)
return; // Done, simple octal number like 01234
diff --git a/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp
index 01c85e6..bba3c89 100644
--- a/clang/lib/Lex/Pragma.cpp
+++ b/clang/lib/Lex/Pragma.cpp
@@ -591,7 +591,8 @@ IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) {
}
// Remember the macro string.
- std::string StrVal = getSpelling(Tok);
+ Token StrTok = Tok;
+ std::string StrVal = getSpelling(StrTok);
// Read the ')'.
Lex(Tok);
@@ -604,6 +605,15 @@ IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) {
assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' &&
"Invalid string token!");
+ if (StrVal.size() <= 2) {
+ Diag(StrTok.getLocation(), diag::warn_pargma_push_pop_macro_empty_string)
+ << SourceRange(
+ StrTok.getLocation(),
+ StrTok.getLocation().getLocWithOffset(StrTok.getLength()))
+ << PragmaTok.getIdentifierInfo()->isStr("pop_macro");
+ return nullptr;
+ }
+
// Create a Token from the string.
Token MacroTok;
MacroTok.startToken();
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 893ef02..e47caeb 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -5695,11 +5695,10 @@ Parser::DeclGroupPtrTy Parser::ParseTopLevelStmtDecl() {
Scope::CompoundStmtScope);
TopLevelStmtDecl *TLSD = Actions.ActOnStartTopLevelStmtDecl(getCurScope());
StmtResult R = ParseStatementOrDeclaration(Stmts, SubStmtCtx);
+ Actions.ActOnFinishTopLevelStmtDecl(TLSD, R.get());
if (!R.isUsable())
R = Actions.ActOnNullStmt(Tok.getLocation());
- Actions.ActOnFinishTopLevelStmtDecl(TLSD, R.get());
-
if (Tok.is(tok::annot_repl_input_end) &&
Tok.getAnnotationValue() != nullptr) {
ConsumeAnnotationToken();
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 31392d1d..bc8841c 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -4940,9 +4940,8 @@ void Parser::ParseHLSLRootSignatureAttributeArgs(ParsedAttributes &Attrs) {
// signature string and construct the in-memory elements
if (!Found) {
// Invoke the root signature parser to construct the in-memory constructs
- SmallVector<hlsl::RootSignatureElement> RootElements;
- hlsl::RootSignatureParser Parser(getLangOpts().HLSLRootSigVer, RootElements,
- Signature, PP);
+ hlsl::RootSignatureParser Parser(getLangOpts().HLSLRootSigVer, Signature,
+ PP);
if (Parser.parse()) {
T.consumeClose();
return;
@@ -4950,7 +4949,7 @@ void Parser::ParseHLSLRootSignatureAttributeArgs(ParsedAttributes &Attrs) {
// Construct the declaration.
Actions.HLSL().ActOnFinishRootSignatureDecl(RootSignatureLoc, DeclIdent,
- RootElements);
+ Parser.getElements());
}
// Create the arg for the ParsedAttr
diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp
index db9ed83..98dc458 100644
--- a/clang/lib/Parse/ParseHLSLRootSignature.cpp
+++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp
@@ -27,11 +27,10 @@ static const TokenKind RootElementKeywords[] = {
};
RootSignatureParser::RootSignatureParser(
- llvm::dxbc::RootSignatureVersion Version,
- SmallVector<RootSignatureElement> &Elements, StringLiteral *Signature,
+ llvm::dxbc::RootSignatureVersion Version, StringLiteral *Signature,
Preprocessor &PP)
- : Version(Version), Elements(Elements), Signature(Signature),
- Lexer(Signature->getString()), PP(PP), CurToken(0) {}
+ : Version(Version), Signature(Signature), Lexer(Signature->getString()),
+ PP(PP), CurToken(0) {}
bool RootSignatureParser::parse() {
// Iterate as many RootSignatureElements as possible, until we hit the
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index d1400cb..829c81b 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -2901,8 +2901,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
.setAlwaysAdd(Stmt::UnaryOperatorClass);
}
- bool EnableLifetimeSafetyAnalysis = !Diags.isIgnored(
- diag::warn_experimental_lifetime_safety_dummy_warning, D->getBeginLoc());
+ bool EnableLifetimeSafetyAnalysis = S.getLangOpts().EnableLifetimeSafety;
// Install the logical handler.
std::optional<LogicalErrorHandler> LEH;
if (LogicalErrorHandler::hasActiveDiagnostics(Diags, D->getBeginLoc())) {
@@ -3029,8 +3028,8 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
// TODO: Enable lifetime safety analysis for other languages once it is
// stable.
if (EnableLifetimeSafetyAnalysis && S.getLangOpts().CPlusPlus) {
- if (CFG *cfg = AC.getCFG())
- runLifetimeSafetyAnalysis(*cast<DeclContext>(D), *cfg, AC);
+ if (AC.getCFG())
+ lifetimes::runLifetimeSafetyAnalysis(AC);
}
// Check for violations of "called once" parameter properties.
if (S.getLangOpts().ObjC && !S.getLangOpts().CPlusPlus &&
diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp
index bd603a9..8e27fab 100644
--- a/clang/lib/Sema/SemaARM.cpp
+++ b/clang/lib/Sema/SemaARM.cpp
@@ -1535,4 +1535,95 @@ bool SemaARM::areLaxCompatibleSveTypes(QualType FirstType,
IsLaxCompatible(SecondType, FirstType);
}
+bool SemaARM::checkTargetVersionAttr(const StringRef Param,
+ const SourceLocation Loc) {
+ using namespace DiagAttrParams;
+
+ llvm::SmallVector<StringRef, 8> Features;
+ Param.split(Features, '+');
+ for (StringRef Feat : Features) {
+ Feat = Feat.trim();
+ if (Feat == "default")
+ continue;
+ if (!getASTContext().getTargetInfo().validateCpuSupports(Feat))
+ return Diag(Loc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << Feat << TargetVersion;
+ }
+ return false;
+}
+
+bool SemaARM::checkTargetClonesAttr(
+ SmallVectorImpl<StringRef> &Params, SmallVectorImpl<SourceLocation> &Locs,
+ SmallVectorImpl<SmallString<64>> &NewParams) {
+ using namespace DiagAttrParams;
+
+ if (!getASTContext().getTargetInfo().hasFeature("fmv"))
+ return true;
+
+ assert(Params.size() == Locs.size() &&
+ "Mismatch between number of string parameters and locations");
+
+ bool HasDefault = false;
+ bool HasNonDefault = false;
+ for (unsigned I = 0, E = Params.size(); I < E; ++I) {
+ const StringRef Param = Params[I].trim();
+ const SourceLocation &Loc = Locs[I];
+
+ if (Param.empty())
+ return Diag(Loc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << "" << TargetClones;
+
+ if (Param == "default") {
+ if (HasDefault)
+ Diag(Loc, diag::warn_target_clone_duplicate_options);
+ else {
+ NewParams.push_back(Param);
+ HasDefault = true;
+ }
+ continue;
+ }
+
+ bool HasCodeGenImpact = false;
+ llvm::SmallVector<StringRef, 8> Features;
+ llvm::SmallVector<StringRef, 8> ValidFeatures;
+ Param.split(Features, '+');
+ for (StringRef Feat : Features) {
+ Feat = Feat.trim();
+ if (!getASTContext().getTargetInfo().validateCpuSupports(Feat)) {
+ Diag(Loc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << Feat << TargetClones;
+ continue;
+ }
+ if (getASTContext().getTargetInfo().doesFeatureAffectCodeGen(Feat))
+ HasCodeGenImpact = true;
+ ValidFeatures.push_back(Feat);
+ }
+
+ // Ignore features that don't impact code generation.
+ if (!HasCodeGenImpact) {
+ Diag(Loc, diag::warn_target_clone_no_impact_options);
+ continue;
+ }
+
+ if (ValidFeatures.empty())
+ continue;
+
+ // Canonicalize attribute parameter.
+ llvm::sort(ValidFeatures);
+ SmallString<64> NewParam(llvm::join(ValidFeatures, "+"));
+ if (llvm::is_contained(NewParams, NewParam)) {
+ Diag(Loc, diag::warn_target_clone_duplicate_options);
+ continue;
+ }
+
+ // Valid non-default argument.
+ NewParams.push_back(NewParam);
+ HasNonDefault = true;
+ }
+ if (!HasNonDefault)
+ return true;
+
+ return false;
+}
+
} // namespace clang
diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp
index 8c6a173..68a698f 100644
--- a/clang/lib/Sema/SemaAvailability.cpp
+++ b/clang/lib/Sema/SemaAvailability.cpp
@@ -547,6 +547,12 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
return;
}
case AR_Deprecated:
+ // Suppress -Wdeprecated-declarations in implicit
+ // functions.
+ if (const auto *FD = dyn_cast_or_null<FunctionDecl>(S.getCurFunctionDecl());
+ FD && FD->isImplicit())
+ return;
+
if (ObjCPropertyAccess)
diag = diag::warn_property_method_deprecated;
else if (S.currentEvaluationContext().IsCaseExpr)
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 5e523fe..c74b671 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3013,6 +3013,8 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
case Builtin::BI__builtin_elementwise_maxnum:
case Builtin::BI__builtin_elementwise_minimum:
case Builtin::BI__builtin_elementwise_maximum:
+ case Builtin::BI__builtin_elementwise_minimumnum:
+ case Builtin::BI__builtin_elementwise_maximumnum:
case Builtin::BI__builtin_elementwise_atan2:
case Builtin::BI__builtin_elementwise_fmod:
case Builtin::BI__builtin_elementwise_pow:
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 5205ca0b..044cf5c 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -588,6 +588,9 @@ static bool CheckConstraintSatisfaction(
return true;
for (const AssociatedConstraint &AC : AssociatedConstraints) {
+ if (AC.isNull())
+ return true;
+
Sema::ArgPackSubstIndexRAII _(S, AC.ArgPackSubstIndex);
ExprResult Res = calculateConstraintSatisfaction(
S, Template, TemplateIDRange.getBegin(), TemplateArgsLists,
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 14403e6..d7420bd 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -3267,6 +3267,14 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
if (isa<UsedAttr>(I) || isa<RetainAttr>(I))
continue;
+ if (isa<InferredNoReturnAttr>(I)) {
+ if (auto *FD = dyn_cast<FunctionDecl>(New)) {
+ if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+ continue; // Don't propagate inferred noreturn attributes to explicit
+ // specializations.
+ }
+ }
+
if (mergeDeclAttribute(*this, New, I, LocalAMK))
foundAny = true;
}
@@ -18476,6 +18484,10 @@ CreateNewDecl:
// record.
AddPushedVisibilityAttribute(New);
+ // If this is not a definition, process API notes for it now.
+ if (TUK != TagUseKind::Definition)
+ ProcessAPINotes(New);
+
if (isMemberSpecialization && !New->isInvalidDecl())
CompleteMemberSpecialization(New, Previous);
@@ -20569,7 +20581,8 @@ TopLevelStmtDecl *Sema::ActOnStartTopLevelStmtDecl(Scope *S) {
}
void Sema::ActOnFinishTopLevelStmtDecl(TopLevelStmtDecl *D, Stmt *Statement) {
- D->setStmt(Statement);
+ if (Statement)
+ D->setStmt(Statement);
PopCompoundScope();
PopFunctionScopeInfo();
PopDeclContext();
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 78f4804..a4e8de4 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -1970,6 +1970,13 @@ void clang::inferNoReturnAttr(Sema &S, const Decl *D) {
if (!FD)
return;
+ // Skip explicit specializations here as they may have
+ // a user-provided definition that may deliberately differ from the primary
+ // template. If an explicit specialization truly never returns, the user
+ // should explicitly mark it with [[noreturn]].
+ if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+ return;
+
auto *NonConstFD = const_cast<FunctionDecl *>(FD);
DiagnosticsEngine &Diags = S.getDiagnostics();
if (Diags.isIgnored(diag::warn_falloff_nonvoid, FD->getLocation()) &&
@@ -2034,7 +2041,8 @@ bool Sema::CheckAttrTarget(const ParsedAttr &AL) {
// Check whether the attribute is valid on the current target.
if (!AL.existsInTarget(Context.getTargetInfo())) {
if (AL.isRegularKeywordAttribute())
- Diag(AL.getLoc(), diag::err_keyword_not_supported_on_target);
+ Diag(AL.getLoc(), diag::err_keyword_not_supported_on_target)
+ << AL << AL.getRange();
else
DiagnoseUnknownAttribute(AL);
AL.setInvalid();
@@ -3254,9 +3262,8 @@ static void handleCodeSegAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}
bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
- enum FirstParam { Unsupported, Duplicate, Unknown };
- enum SecondParam { None, CPU, Tune };
- enum ThirdParam { Target, TargetClones };
+ using namespace DiagAttrParams;
+
if (AttrStr.contains("fpmath="))
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << "fpmath=" << Target;
@@ -3331,80 +3338,22 @@ bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) {
return false;
}
-bool Sema::checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D,
- StringRef AttrStr) {
- enum FirstParam { Unsupported };
- enum SecondParam { None };
- enum ThirdParam { Target, TargetClones, TargetVersion };
- llvm::SmallVector<StringRef, 8> Features;
- if (Context.getTargetInfo().getTriple().isRISCV()) {
- llvm::SmallVector<StringRef, 8> AttrStrs;
- AttrStr.split(AttrStrs, ';');
-
- bool HasArch = false;
- bool HasPriority = false;
- bool HasDefault = false;
- bool DuplicateAttr = false;
- for (auto &AttrStr : AttrStrs) {
- // Only support arch=+ext,... syntax.
- if (AttrStr.starts_with("arch=+")) {
- if (HasArch)
- DuplicateAttr = true;
- HasArch = true;
- ParsedTargetAttr TargetAttr =
- Context.getTargetInfo().parseTargetAttr(AttrStr);
-
- if (TargetAttr.Features.empty() ||
- llvm::any_of(TargetAttr.Features, [&](const StringRef Ext) {
- return !RISCV().isValidFMVExtension(Ext);
- }))
- return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << AttrStr << TargetVersion;
- } else if (AttrStr.starts_with("default")) {
- if (HasDefault)
- DuplicateAttr = true;
- HasDefault = true;
- } else if (AttrStr.consume_front("priority=")) {
- if (HasPriority)
- DuplicateAttr = true;
- HasPriority = true;
- unsigned Digit;
- if (AttrStr.getAsInteger(0, Digit))
- return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << AttrStr << TargetVersion;
- } else {
- return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << AttrStr << TargetVersion;
- }
- }
-
- if (((HasPriority || HasArch) && HasDefault) || DuplicateAttr ||
- (HasPriority && !HasArch))
- return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << AttrStr << TargetVersion;
+static void handleTargetVersionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ StringRef Param;
+ SourceLocation Loc;
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, Param, &Loc))
+ return;
- return false;
- }
- AttrStr.split(Features, "+");
- for (auto &CurFeature : Features) {
- CurFeature = CurFeature.trim();
- if (CurFeature == "default")
- continue;
- if (!Context.getTargetInfo().validateCpuSupports(CurFeature))
- return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << CurFeature << TargetVersion;
+ if (S.Context.getTargetInfo().getTriple().isAArch64()) {
+ if (S.ARM().checkTargetVersionAttr(Param, Loc))
+ return;
+ } else if (S.Context.getTargetInfo().getTriple().isRISCV()) {
+ if (S.RISCV().checkTargetVersionAttr(Param, Loc))
+ return;
}
- return false;
-}
-static void handleTargetVersionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- StringRef Str;
- SourceLocation LiteralLoc;
- if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc) ||
- S.checkTargetVersionAttr(LiteralLoc, D, Str))
- return;
TargetVersionAttr *NewAttr =
- ::new (S.Context) TargetVersionAttr(S.Context, AL, Str);
+ ::new (S.Context) TargetVersionAttr(S.Context, AL, Param);
D->addAttr(NewAttr);
}
@@ -3419,158 +3368,7 @@ static void handleTargetAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
D->addAttr(NewAttr);
}
-bool Sema::checkTargetClonesAttrString(
- SourceLocation LiteralLoc, StringRef Str, const StringLiteral *Literal,
- Decl *D, bool &HasDefault, bool &HasCommas, bool &HasNotDefault,
- SmallVectorImpl<SmallString<64>> &StringsBuffer) {
- enum FirstParam { Unsupported, Duplicate, Unknown };
- enum SecondParam { None, CPU, Tune };
- enum ThirdParam { Target, TargetClones };
- HasCommas = HasCommas || Str.contains(',');
- const TargetInfo &TInfo = Context.getTargetInfo();
- // Warn on empty at the beginning of a string.
- if (Str.size() == 0)
- return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << "" << TargetClones;
-
- std::pair<StringRef, StringRef> Parts = {{}, Str};
- while (!Parts.second.empty()) {
- Parts = Parts.second.split(',');
- StringRef Cur = Parts.first.trim();
- SourceLocation CurLoc =
- Literal->getLocationOfByte(Cur.data() - Literal->getString().data(),
- getSourceManager(), getLangOpts(), TInfo);
-
- bool DefaultIsDupe = false;
- bool HasCodeGenImpact = false;
- if (Cur.empty())
- return Diag(CurLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << "" << TargetClones;
-
- if (TInfo.getTriple().isAArch64()) {
- // AArch64 target clones specific
- if (Cur == "default") {
- DefaultIsDupe = HasDefault;
- HasDefault = true;
- if (llvm::is_contained(StringsBuffer, Cur) || DefaultIsDupe)
- Diag(CurLoc, diag::warn_target_clone_duplicate_options);
- else
- StringsBuffer.push_back(Cur);
- } else {
- std::pair<StringRef, StringRef> CurParts = {{}, Cur};
- llvm::SmallVector<StringRef, 8> CurFeatures;
- while (!CurParts.second.empty()) {
- CurParts = CurParts.second.split('+');
- StringRef CurFeature = CurParts.first.trim();
- if (!TInfo.validateCpuSupports(CurFeature)) {
- Diag(CurLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << CurFeature << TargetClones;
- continue;
- }
- if (TInfo.doesFeatureAffectCodeGen(CurFeature))
- HasCodeGenImpact = true;
- CurFeatures.push_back(CurFeature);
- }
- // Canonize TargetClones Attributes
- llvm::sort(CurFeatures);
- SmallString<64> Res;
- for (auto &CurFeat : CurFeatures) {
- if (!Res.empty())
- Res.append("+");
- Res.append(CurFeat);
- }
- if (llvm::is_contained(StringsBuffer, Res) || DefaultIsDupe)
- Diag(CurLoc, diag::warn_target_clone_duplicate_options);
- else if (!HasCodeGenImpact)
- // Ignore features in target_clone attribute that don't impact
- // code generation
- Diag(CurLoc, diag::warn_target_clone_no_impact_options);
- else if (!Res.empty()) {
- StringsBuffer.push_back(Res);
- HasNotDefault = true;
- }
- }
- } else if (TInfo.getTriple().isRISCV()) {
- // Suppress warn_target_clone_mixed_values
- HasCommas = false;
-
- // Cur is split's parts of Str. RISC-V uses Str directly,
- // so skip when encountered more than once.
- if (!Str.starts_with(Cur))
- continue;
-
- llvm::SmallVector<StringRef, 8> AttrStrs;
- Str.split(AttrStrs, ";");
-
- bool IsPriority = false;
- bool IsDefault = false;
- for (auto &AttrStr : AttrStrs) {
- // Only support arch=+ext,... syntax.
- if (AttrStr.starts_with("arch=+")) {
- ParsedTargetAttr TargetAttr =
- Context.getTargetInfo().parseTargetAttr(AttrStr);
-
- if (TargetAttr.Features.empty() ||
- llvm::any_of(TargetAttr.Features, [&](const StringRef Ext) {
- return !RISCV().isValidFMVExtension(Ext);
- }))
- return Diag(CurLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << Str << TargetClones;
- } else if (AttrStr.starts_with("default")) {
- IsDefault = true;
- DefaultIsDupe = HasDefault;
- HasDefault = true;
- } else if (AttrStr.consume_front("priority=")) {
- IsPriority = true;
- unsigned Digit;
- if (AttrStr.getAsInteger(0, Digit))
- return Diag(CurLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << Str << TargetClones;
- } else {
- return Diag(CurLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << Str << TargetClones;
- }
- }
-
- if (IsPriority && IsDefault)
- return Diag(CurLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << Str << TargetClones;
-
- if (llvm::is_contained(StringsBuffer, Str) || DefaultIsDupe)
- Diag(CurLoc, diag::warn_target_clone_duplicate_options);
- StringsBuffer.push_back(Str);
- } else {
- // Other targets ( currently X86 )
- if (Cur.starts_with("arch=")) {
- if (!Context.getTargetInfo().isValidCPUName(
- Cur.drop_front(sizeof("arch=") - 1)))
- return Diag(CurLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << CPU << Cur.drop_front(sizeof("arch=") - 1)
- << TargetClones;
- } else if (Cur == "default") {
- DefaultIsDupe = HasDefault;
- HasDefault = true;
- } else if (!Context.getTargetInfo().isValidFeatureName(Cur) ||
- Context.getTargetInfo().getFMVPriority(Cur) == 0)
- return Diag(CurLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << Cur << TargetClones;
- if (llvm::is_contained(StringsBuffer, Cur) || DefaultIsDupe)
- Diag(CurLoc, diag::warn_target_clone_duplicate_options);
- // Note: Add even if there are duplicates, since it changes name mangling.
- StringsBuffer.push_back(Cur);
- }
- }
- if (Str.rtrim().ends_with(","))
- return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
- << Unsupported << None << "" << TargetClones;
- return false;
-}
-
static void handleTargetClonesAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (S.Context.getTargetInfo().getTriple().isAArch64() &&
- !S.Context.getTargetInfo().hasFeature("fmv"))
- return;
-
// Ensure we don't combine these with themselves, since that causes some
// confusing behavior.
if (const auto *Other = D->getAttr<TargetClonesAttr>()) {
@@ -3581,31 +3379,6 @@ static void handleTargetClonesAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (checkAttrMutualExclusion<TargetClonesAttr>(S, D, AL))
return;
- SmallVector<StringRef, 2> Strings;
- SmallVector<SmallString<64>, 2> StringsBuffer;
- bool HasCommas = false, HasDefault = false, HasNotDefault = false;
-
- for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
- StringRef CurStr;
- SourceLocation LiteralLoc;
- if (!S.checkStringLiteralArgumentAttr(AL, I, CurStr, &LiteralLoc) ||
- S.checkTargetClonesAttrString(
- LiteralLoc, CurStr,
- cast<StringLiteral>(AL.getArgAsExpr(I)->IgnoreParenCasts()), D,
- HasDefault, HasCommas, HasNotDefault, StringsBuffer))
- return;
- }
- for (auto &SmallStr : StringsBuffer)
- Strings.push_back(SmallStr.str());
-
- if (HasCommas && AL.getNumArgs() > 1)
- S.Diag(AL.getLoc(), diag::warn_target_clone_mixed_values);
-
- if (!HasDefault && !S.Context.getTargetInfo().getTriple().isAArch64()) {
- S.Diag(AL.getLoc(), diag::err_target_clone_must_have_default);
- return;
- }
-
// FIXME: We could probably figure out how to get this to work for lambdas
// someday.
if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
@@ -3617,13 +3390,34 @@ static void handleTargetClonesAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}
}
- // No multiversion if we have default version only.
- if (S.Context.getTargetInfo().getTriple().isAArch64() && !HasNotDefault)
- return;
+ SmallVector<StringRef, 2> Params;
+ SmallVector<SourceLocation, 2> Locations;
+ for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) {
+ StringRef Param;
+ SourceLocation Loc;
+ if (!S.checkStringLiteralArgumentAttr(AL, I, Param, &Loc))
+ return;
+ Params.push_back(Param);
+ Locations.push_back(Loc);
+ }
+
+ SmallVector<SmallString<64>, 2> NewParams;
+ if (S.Context.getTargetInfo().getTriple().isAArch64()) {
+ if (S.ARM().checkTargetClonesAttr(Params, Locations, NewParams))
+ return;
+ } else if (S.Context.getTargetInfo().getTriple().isRISCV()) {
+ if (S.RISCV().checkTargetClonesAttr(Params, Locations, NewParams))
+ return;
+ } else if (S.Context.getTargetInfo().getTriple().isX86()) {
+ if (S.X86().checkTargetClonesAttr(Params, Locations, NewParams))
+ return;
+ }
+ Params.clear();
+ for (auto &SmallStr : NewParams)
+ Params.push_back(SmallStr.str());
- cast<FunctionDecl>(D)->setIsMultiVersion();
TargetClonesAttr *NewAttr = ::new (S.Context)
- TargetClonesAttr(S.Context, AL, Strings.data(), Strings.size());
+ TargetClonesAttr(S.Context, AL, Params.data(), Params.size());
D->addAttr(NewAttr);
}
diff --git a/clang/lib/Sema/SemaOpenACCAtomic.cpp b/clang/lib/Sema/SemaOpenACCAtomic.cpp
index 9c8c8d1..a9319dc 100644
--- a/clang/lib/Sema/SemaOpenACCAtomic.cpp
+++ b/clang/lib/Sema/SemaOpenACCAtomic.cpp
@@ -576,6 +576,11 @@ class AtomicOperandChecker {
return AssocStmt;
}
+ const Expr *IgnoreBeforeCompare(const Expr *E) {
+ return E->IgnoreParenImpCasts()->IgnoreParenNoopCasts(
+ SemaRef.getASTContext());
+ }
+
bool CheckVarRefsSame(IDACInfo::ExprKindTy FirstKind, const Expr *FirstX,
IDACInfo::ExprKindTy SecondKind, const Expr *SecondX) {
llvm::FoldingSetNodeID First_ID, Second_ID;
@@ -648,8 +653,10 @@ class AtomicOperandChecker {
if (CheckOperandVariable(AssignRes->RHS, PD))
return getRecoveryExpr();
- if (CheckVarRefsSame(FirstExprResults.ExprKind, FirstExprResults.X_Var,
- IDACInfo::SimpleAssign, AssignRes->RHS))
+ if (CheckVarRefsSame(FirstExprResults.ExprKind,
+ IgnoreBeforeCompare(FirstExprResults.X_Var),
+ IDACInfo::SimpleAssign,
+ IgnoreBeforeCompare(AssignRes->RHS)))
return getRecoveryExpr();
break;
}
@@ -660,9 +667,10 @@ class AtomicOperandChecker {
if (SecondExprResults.Failed)
return getRecoveryExpr();
- if (CheckVarRefsSame(FirstExprResults.ExprKind, FirstExprResults.X_Var,
+ if (CheckVarRefsSame(FirstExprResults.ExprKind,
+ IgnoreBeforeCompare(FirstExprResults.X_Var),
SecondExprResults.ExprKind,
- SecondExprResults.X_Var))
+ IgnoreBeforeCompare(SecondExprResults.X_Var)))
return getRecoveryExpr();
break;
}
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 4ecc9b0..2c5d97c 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -2829,7 +2829,7 @@ static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
continue;
}
for (Expr *Ref : RC->varlist()) {
- assert(Ref && "NULL expr in OpenMP nontemporal clause.");
+ assert(Ref && "NULL expr in OpenMP reduction clause.");
SourceLocation ELoc;
SourceRange ERange;
Expr *SimpleRefExpr = Ref;
@@ -7612,6 +7612,23 @@ void SemaOpenMP::ActOnOpenMPDeclareVariantDirective(
return;
}
+ // OpenMP 6.0 [9.6.2 (page 332, line 31-33, adjust_args clause, Restrictions]
+ // If the `need_device_addr` adjust-op modifier is present, each list item
+ // that appears in the clause must refer to an argument in the declaration of
+ // the function variant that has a reference type
+ if (getLangOpts().OpenMP >= 60) {
+ for (Expr *E : AdjustArgsNeedDeviceAddr) {
+ E = E->IgnoreParenImpCasts();
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
+ if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
+ if (!VD->getType()->isReferenceType())
+ Diag(E->getExprLoc(),
+ diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
+ }
+ }
+ }
+ }
+
auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
getASTContext(), VariantRef, &TI,
const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
@@ -18344,7 +18361,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
for (Expr *RefExpr : VarList) {
- assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
+ assert(RefExpr && "NULL expr in OpenMP shared clause.");
SourceLocation ELoc;
SourceRange ERange;
Expr *SimpleRefExpr = RefExpr;
@@ -19991,7 +20008,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPAlignedClause(
SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
for (Expr *RefExpr : VarList) {
- assert(RefExpr && "NULL expr in OpenMP linear clause.");
+ assert(RefExpr && "NULL expr in OpenMP aligned clause.");
SourceLocation ELoc;
SourceRange ERange;
Expr *SimpleRefExpr = RefExpr;
@@ -20167,7 +20184,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
SmallVector<Expr *, 8> DstExprs;
SmallVector<Expr *, 8> AssignmentOps;
for (Expr *RefExpr : VarList) {
- assert(RefExpr && "NULL expr in OpenMP linear clause.");
+ assert(RefExpr && "NULL expr in OpenMP copyprivate clause.");
SourceLocation ELoc;
SourceRange ERange;
Expr *SimpleRefExpr = RefExpr;
@@ -20526,7 +20543,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPDependClause(
TotalDepCount = VarOffset.TotalDepCount;
} else {
for (Expr *RefExpr : VarList) {
- assert(RefExpr && "NULL expr in OpenMP shared clause.");
+ assert(RefExpr && "NULL expr in OpenMP depend clause.");
if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
Vars.push_back(RefExpr);
@@ -23737,7 +23754,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPAllocateClause(
// Analyze and build list of variables.
SmallVector<Expr *, 8> Vars;
for (Expr *RefExpr : VarList) {
- assert(RefExpr && "NULL expr in OpenMP private clause.");
+ assert(RefExpr && "NULL expr in OpenMP allocate clause.");
SourceLocation ELoc;
SourceRange ERange;
Expr *SimpleRefExpr = RefExpr;
@@ -23829,7 +23846,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
for (Expr *RefExpr : VarList) {
- assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
+ assert(RefExpr && "NULL expr in OpenMP inclusive clause.");
SourceLocation ELoc;
SourceRange ERange;
Expr *SimpleRefExpr = RefExpr;
@@ -23870,7 +23887,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
for (Expr *RefExpr : VarList) {
- assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
+ assert(RefExpr && "NULL expr in OpenMP exclusive clause.");
SourceLocation ELoc;
SourceRange ERange;
Expr *SimpleRefExpr = RefExpr;
@@ -24063,7 +24080,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPAffinityClause(
SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
SmallVector<Expr *, 8> Vars;
for (Expr *RefExpr : Locators) {
- assert(RefExpr && "NULL expr in OpenMP shared clause.");
+ assert(RefExpr && "NULL expr in OpenMP affinity clause.");
if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
// It will be analyzed later.
Vars.push_back(RefExpr);
@@ -24375,7 +24392,7 @@ ExprResult SemaOpenMP::ActOnOMPArraySectionExpr(
return ExprError();
}
}
- } else if (ColonLocFirst.isValid() &&
+ } else if (SemaRef.getLangOpts().OpenMP < 60 && ColonLocFirst.isValid() &&
(OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
!OriginalTy->isVariableArrayType()))) {
// OpenMP 5.0, [2.1.5 Array Sections]
diff --git a/clang/lib/Sema/SemaRISCV.cpp b/clang/lib/Sema/SemaRISCV.cpp
index 43f7992..994cd07 100644
--- a/clang/lib/Sema/SemaRISCV.cpp
+++ b/clang/lib/Sema/SemaRISCV.cpp
@@ -1635,6 +1635,116 @@ bool SemaRISCV::isValidFMVExtension(StringRef Ext) {
return -1 != RISCVISAInfo::getRISCVFeaturesBitsInfo(Ext).second;
}
+bool SemaRISCV::checkTargetVersionAttr(const StringRef Param,
+ const SourceLocation Loc) {
+ using namespace DiagAttrParams;
+
+ llvm::SmallVector<StringRef, 8> AttrStrs;
+ Param.split(AttrStrs, ';');
+
+ bool HasArch = false;
+ bool HasPriority = false;
+ bool HasDefault = false;
+ bool DuplicateAttr = false;
+ for (StringRef AttrStr : AttrStrs) {
+ AttrStr = AttrStr.trim();
+ // Only support arch=+ext,... syntax.
+ if (AttrStr.starts_with("arch=+")) {
+ DuplicateAttr = HasArch;
+ HasArch = true;
+ ParsedTargetAttr TargetAttr =
+ getASTContext().getTargetInfo().parseTargetAttr(AttrStr);
+
+ if (TargetAttr.Features.empty() ||
+ llvm::any_of(TargetAttr.Features, [&](const StringRef Ext) {
+ return !isValidFMVExtension(Ext);
+ }))
+ return Diag(Loc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << AttrStr << TargetVersion;
+ } else if (AttrStr == "default") {
+ DuplicateAttr = HasDefault;
+ HasDefault = true;
+ } else if (AttrStr.consume_front("priority=")) {
+ DuplicateAttr = HasPriority;
+ HasPriority = true;
+ unsigned Digit;
+ if (AttrStr.getAsInteger(0, Digit))
+ return Diag(Loc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << AttrStr << TargetVersion;
+ } else {
+ return Diag(Loc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << AttrStr << TargetVersion;
+ }
+ }
+
+ if (((HasPriority || HasArch) && HasDefault) || DuplicateAttr ||
+ (HasPriority && !HasArch))
+ return Diag(Loc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << Param << TargetVersion;
+
+ return false;
+}
+
+bool SemaRISCV::checkTargetClonesAttr(
+ SmallVectorImpl<StringRef> &Params, SmallVectorImpl<SourceLocation> &Locs,
+ SmallVectorImpl<SmallString<64>> &NewParams) {
+ using namespace DiagAttrParams;
+
+ assert(Params.size() == Locs.size() &&
+ "Mismatch between number of string parameters and locations");
+
+ bool HasDefault = false;
+ for (unsigned I = 0, E = Params.size(); I < E; ++I) {
+ const StringRef Param = Params[I].trim();
+ const SourceLocation &Loc = Locs[I];
+
+ llvm::SmallVector<StringRef, 8> AttrStrs;
+ Param.split(AttrStrs, ';');
+
+ bool IsPriority = false;
+ bool IsDefault = false;
+ for (StringRef AttrStr : AttrStrs) {
+ AttrStr = AttrStr.trim();
+ // Only support arch=+ext,... syntax.
+ if (AttrStr.starts_with("arch=+")) {
+ ParsedTargetAttr TargetAttr =
+ getASTContext().getTargetInfo().parseTargetAttr(AttrStr);
+
+ if (TargetAttr.Features.empty() ||
+ llvm::any_of(TargetAttr.Features, [&](const StringRef Ext) {
+ return !isValidFMVExtension(Ext);
+ }))
+ return Diag(Loc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << Param << TargetClones;
+ } else if (AttrStr == "default") {
+ IsDefault = true;
+ HasDefault = true;
+ } else if (AttrStr.consume_front("priority=")) {
+ IsPriority = true;
+ unsigned Digit;
+ if (AttrStr.getAsInteger(0, Digit))
+ return Diag(Loc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << Param << TargetClones;
+ } else {
+ return Diag(Loc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << Param << TargetClones;
+ }
+ }
+
+ if (IsPriority && IsDefault)
+ return Diag(Loc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << Param << TargetClones;
+
+ if (llvm::is_contained(NewParams, Param))
+ Diag(Loc, diag::warn_target_clone_duplicate_options);
+ NewParams.push_back(Param);
+ }
+ if (!HasDefault)
+ return Diag(Locs[0], diag::err_target_clone_must_have_default);
+
+ return false;
+}
+
SemaRISCV::SemaRISCV(Sema &S) : SemaBase(S) {}
} // namespace clang
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index e1a975b..9e56e697 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -5523,6 +5523,15 @@ static TemplateDeductionResult CheckDeductionConsistency(
// FIXME: A substitution can be incomplete on a non-structural part of the
// type. Use the canonical type for now, until the TemplateInstantiator can
// deal with that.
+
+ // Workaround: Implicit deduction guides use InjectedClassNameTypes, whereas
+ // the explicit guides don't. The substitution doesn't transform these types,
+ // so let it transform their specializations instead.
+ bool IsDeductionGuide = isa<CXXDeductionGuideDecl>(FTD->getTemplatedDecl());
+ if (IsDeductionGuide) {
+ if (auto *Injected = P->getAs<InjectedClassNameType>())
+ P = Injected->getInjectedSpecializationType();
+ }
QualType InstP = S.SubstType(P.getCanonicalType(), MLTAL, FTD->getLocation(),
FTD->getDeclName(), &IsIncompleteSubstitution);
if (InstP.isNull() && !IsIncompleteSubstitution)
@@ -5537,9 +5546,15 @@ static TemplateDeductionResult CheckDeductionConsistency(
if (auto *PA = dyn_cast<PackExpansionType>(A);
PA && !isa<PackExpansionType>(InstP))
A = PA->getPattern();
- if (!S.Context.hasSameType(
- S.Context.getUnqualifiedArrayType(InstP.getNonReferenceType()),
- S.Context.getUnqualifiedArrayType(A.getNonReferenceType())))
+ auto T1 = S.Context.getUnqualifiedArrayType(InstP.getNonReferenceType());
+ auto T2 = S.Context.getUnqualifiedArrayType(A.getNonReferenceType());
+ if (IsDeductionGuide) {
+ if (auto *Injected = T1->getAs<InjectedClassNameType>())
+ T1 = Injected->getInjectedSpecializationType();
+ if (auto *Injected = T2->getAs<InjectedClassNameType>())
+ T2 = Injected->getInjectedSpecializationType();
+ }
+ if (!S.Context.hasSameType(T1, T2))
return TemplateDeductionResult::NonDeducedMismatch;
return TemplateDeductionResult::Success;
}
diff --git a/clang/lib/Sema/SemaX86.cpp b/clang/lib/Sema/SemaX86.cpp
index 5c149bd..850bcb1 100644
--- a/clang/lib/Sema/SemaX86.cpp
+++ b/clang/lib/Sema/SemaX86.cpp
@@ -954,6 +954,11 @@ bool SemaX86::CheckBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
l = 0;
u = 15;
break;
+ case X86::BI__builtin_ia32_prefetchi:
+ i = 1;
+ l = 2; // _MM_HINT_T1
+ u = 3; // _MM_HINT_T0
+ break;
}
// Note that we don't force a hard error on the range check here, allowing
@@ -1056,4 +1061,61 @@ void SemaX86::handleForceAlignArgPointerAttr(Decl *D, const ParsedAttr &AL) {
X86ForceAlignArgPointerAttr(getASTContext(), AL));
}
+bool SemaX86::checkTargetClonesAttr(
+ SmallVectorImpl<StringRef> &Params, SmallVectorImpl<SourceLocation> &Locs,
+ SmallVectorImpl<SmallString<64>> &NewParams) {
+ using namespace DiagAttrParams;
+
+ assert(Params.size() == Locs.size() &&
+ "Mismatch between number of string parameters and locations");
+
+ bool HasDefault = false;
+ bool HasComma = false;
+ for (unsigned I = 0, E = Params.size(); I < E; ++I) {
+ const StringRef Param = Params[I].trim();
+ const SourceLocation &Loc = Locs[I];
+
+ if (Param.empty() || Param.ends_with(','))
+ return Diag(Loc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << "" << TargetClones;
+
+ if (Param.contains(','))
+ HasComma = true;
+
+ StringRef LHS;
+ StringRef RHS = Param;
+ do {
+ std::tie(LHS, RHS) = RHS.split(',');
+ LHS = LHS.trim();
+ const SourceLocation &CurLoc =
+ Loc.getLocWithOffset(LHS.data() - Param.data());
+
+ if (LHS.starts_with("arch=")) {
+ if (!getASTContext().getTargetInfo().isValidCPUName(
+ LHS.drop_front(sizeof("arch=") - 1)))
+ return Diag(CurLoc, diag::warn_unsupported_target_attribute)
+ << Unsupported << CPU << LHS.drop_front(sizeof("arch=") - 1)
+ << TargetClones;
+ } else if (LHS == "default")
+ HasDefault = true;
+ else if (!getASTContext().getTargetInfo().isValidFeatureName(LHS) ||
+ getASTContext().getTargetInfo().getFMVPriority(LHS) == 0)
+ return Diag(CurLoc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << LHS << TargetClones;
+
+ if (llvm::is_contained(NewParams, LHS))
+ Diag(CurLoc, diag::warn_target_clone_duplicate_options);
+ // Note: Add even if there are duplicates, since it changes name mangling.
+ NewParams.push_back(LHS);
+ } while (!RHS.empty());
+ }
+ if (HasComma && Params.size() > 1)
+ Diag(Locs[0], diag::warn_target_clone_mixed_values);
+
+ if (!HasDefault)
+ return Diag(Locs[0], diag::err_target_clone_must_have_default);
+
+ return false;
+}
+
} // namespace clang
diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 68efdba..a7704da 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -3730,13 +3730,15 @@ PathDiagnosticPieceRef MallocBugVisitor::VisitNode(const ExplodedNode *N,
return nullptr;
}
- // Save the first destructor/function as release point.
- assert(!ReleaseFunctionLC && "There should be only one release point");
+ // Record the stack frame that is _responsible_ for this memory release
+ // event. This will be used by the false positive suppression heuristics
+ // that recognize the release points of reference-counted objects.
+ //
+ // Usually (e.g. in C) we say that the _responsible_ stack frame is the
+ // current innermost stack frame:
ReleaseFunctionLC = CurrentLC->getStackFrame();
-
- // See if we're releasing memory while inlining a destructor that
- // decrement reference counters (or one of its callees).
- // This turns on various common false positive suppressions.
+ // ...but if the stack contains a destructor call, then we say that the
+ // outermost destructor stack frame is the _responsible_ one:
for (const LocationContext *LC = CurrentLC; LC; LC = LC->getParent()) {
if (const auto *DD = dyn_cast<CXXDestructorDecl>(LC->getDecl())) {
if (isReferenceCountingPointerDestructor(DD)) {
diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
index 9bd8547..8ce2706 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
@@ -24,7 +24,6 @@
#include "clang/Tooling/DependencyScanning/DependencyScanningService.h"
#include "clang/Tooling/DependencyScanning/InProcessModuleCache.h"
#include "clang/Tooling/DependencyScanning/ModuleDepCollector.h"
-#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Error.h"
@@ -376,25 +375,23 @@ public:
/// A clang tool that runs the preprocessor in a mode that's optimized for
/// dependency scanning for the given compiler invocation.
-class DependencyScanningAction : public tooling::ToolAction {
+class DependencyScanningAction {
public:
DependencyScanningAction(
DependencyScanningService &Service, StringRef WorkingDirectory,
DependencyConsumer &Consumer, DependencyActionController &Controller,
llvm::IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS,
- bool DisableFree, std::optional<StringRef> ModuleName = std::nullopt)
+ std::optional<StringRef> ModuleName = std::nullopt)
: Service(Service), WorkingDirectory(WorkingDirectory),
Consumer(Consumer), Controller(Controller), DepFS(std::move(DepFS)),
- DisableFree(DisableFree), ModuleName(ModuleName) {}
+ ModuleName(ModuleName) {}
bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
- FileManager *DriverFileMgr,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
- DiagnosticConsumer *DiagConsumer) override {
+ DiagnosticConsumer *DiagConsumer) {
// Make a deep copy of the original Clang invocation.
CompilerInvocation OriginalInvocation(*Invocation);
- // Restore the value of DisableFree, which may be modified by Tooling.
- OriginalInvocation.getFrontendOpts().DisableFree = DisableFree;
if (any(Service.getOptimizeArgs() & ScanningOptimizations::Macros))
canonicalizeDefines(OriginalInvocation.getPreprocessorOpts());
@@ -419,8 +416,8 @@ public:
// Create the compiler's actual diagnostics engine.
sanitizeDiagOpts(ScanInstance.getDiagnosticOpts());
assert(!DiagConsumerFinished && "attempt to reuse finished consumer");
- ScanInstance.createDiagnostics(DriverFileMgr->getVirtualFileSystem(),
- DiagConsumer, /*ShouldOwnClient=*/false);
+ ScanInstance.createDiagnostics(*FS, DiagConsumer,
+ /*ShouldOwnClient=*/false);
if (!ScanInstance.hasDiagnostics())
return false;
@@ -431,6 +428,7 @@ public:
ScanInstance.getHeaderSearchOpts().BuildSessionTimestamp =
Service.getBuildSessionTimestamp();
+ ScanInstance.getFrontendOpts().DisableFree = false;
ScanInstance.getFrontendOpts().GenerateGlobalModuleIndex = false;
ScanInstance.getFrontendOpts().UseGlobalModuleIndex = false;
// This will prevent us compiling individual modules asynchronously since
@@ -441,9 +439,9 @@ public:
any(Service.getOptimizeArgs() & ScanningOptimizations::VFS);
// Support for virtual file system overlays.
- auto FS = createVFSFromCompilerInvocation(
- ScanInstance.getInvocation(), ScanInstance.getDiagnostics(),
- DriverFileMgr->getVirtualFileSystemPtr());
+ FS = createVFSFromCompilerInvocation(ScanInstance.getInvocation(),
+ ScanInstance.getDiagnostics(),
+ std::move(FS));
// Create a new FileManager to match the invocation's FileSystemOptions.
auto *FileMgr = ScanInstance.createFileManager(FS);
@@ -554,9 +552,6 @@ public:
if (Result)
setLastCC1Arguments(std::move(OriginalInvocation));
- // Propagate the statistics to the parent FileManager.
- DriverFileMgr->AddStats(ScanInstance.getFileManager());
-
return Result;
}
@@ -584,7 +579,6 @@ private:
DependencyConsumer &Consumer;
DependencyActionController &Controller;
llvm::IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS;
- bool DisableFree;
std::optional<StringRef> ModuleName;
std::optional<CompilerInstance> ScanInstanceStorage;
std::shared_ptr<ModuleDepCollector> MDC;
@@ -669,15 +663,14 @@ llvm::Error DependencyScanningWorker::computeDependencies(
}
static bool forEachDriverJob(
- ArrayRef<std::string> ArgStrs, DiagnosticsEngine &Diags, FileManager &FM,
+ ArrayRef<std::string> ArgStrs, DiagnosticsEngine &Diags,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
llvm::function_ref<bool(const driver::Command &Cmd)> Callback) {
SmallVector<const char *, 256> Argv;
Argv.reserve(ArgStrs.size());
for (const std::string &Arg : ArgStrs)
Argv.push_back(Arg.c_str());
- llvm::vfs::FileSystem *FS = &FM.getVirtualFileSystem();
-
std::unique_ptr<driver::Driver> Driver = std::make_unique<driver::Driver>(
Argv[0], llvm::sys::getDefaultTargetTriple(), Diags,
"clang LLVM compiler", FS);
@@ -687,7 +680,8 @@ static bool forEachDriverJob(
bool CLMode = driver::IsClangCL(
driver::getDriverMode(Argv[0], ArrayRef(Argv).slice(1)));
- if (llvm::Error E = driver::expandResponseFiles(Argv, CLMode, Alloc, FS)) {
+ if (llvm::Error E =
+ driver::expandResponseFiles(Argv, CLMode, Alloc, FS.get())) {
Diags.Report(diag::err_drv_expand_response_file)
<< llvm::toString(std::move(E));
return false;
@@ -710,17 +704,25 @@ static bool forEachDriverJob(
static bool createAndRunToolInvocation(
std::vector<std::string> CommandLine, DependencyScanningAction &Action,
- FileManager &FM,
+ IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
std::shared_ptr<clang::PCHContainerOperations> &PCHContainerOps,
DiagnosticsEngine &Diags, DependencyConsumer &Consumer) {
// Save executable path before providing CommandLine to ToolInvocation
std::string Executable = CommandLine[0];
- ToolInvocation Invocation(std::move(CommandLine), &Action, &FM,
- PCHContainerOps);
- Invocation.setDiagnosticConsumer(Diags.getClient());
- Invocation.setDiagnosticOptions(&Diags.getDiagnosticOptions());
- if (!Invocation.run())
+
+ llvm::opt::ArgStringList Argv;
+ for (const std::string &Str : ArrayRef(CommandLine).drop_front())
+ Argv.push_back(Str.c_str());
+
+ auto Invocation = std::make_shared<CompilerInvocation>();
+ if (!CompilerInvocation::CreateFromArgs(*Invocation, Argv, Diags)) {
+ // FIXME: Should we just go on like cc1_main does?
+ return false;
+ }
+
+ if (!Action.runInvocation(std::move(Invocation), std::move(FS),
+ PCHContainerOps, Diags.getClient()))
return false;
std::vector<std::string> Args = Action.takeLastCC1Arguments();
@@ -733,37 +735,24 @@ bool DependencyScanningWorker::scanDependencies(
DependencyConsumer &Consumer, DependencyActionController &Controller,
DiagnosticConsumer &DC, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
std::optional<StringRef> ModuleName) {
- auto FileMgr =
- llvm::makeIntrusiveRefCnt<FileManager>(FileSystemOptions{}, FS);
-
std::vector<const char *> CCommandLine(CommandLine.size(), nullptr);
llvm::transform(CommandLine, CCommandLine.begin(),
[](const std::string &Str) { return Str.c_str(); });
auto DiagOpts = CreateAndPopulateDiagOpts(CCommandLine);
sanitizeDiagOpts(*DiagOpts);
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
- CompilerInstance::createDiagnostics(FileMgr->getVirtualFileSystem(),
- *DiagOpts, &DC,
- /*ShouldOwnClient=*/false);
-
- // Although `Diagnostics` are used only for command-line parsing, the
- // custom `DiagConsumer` might expect a `SourceManager` to be present.
- SourceManager SrcMgr(*Diags, *FileMgr);
- Diags->setSourceManager(&SrcMgr);
- // DisableFree is modified by Tooling for running
- // in-process; preserve the original value, which is
- // always true for a driver invocation.
- bool DisableFree = true;
+ auto Diags = CompilerInstance::createDiagnostics(*FS, *DiagOpts, &DC,
+ /*ShouldOwnClient=*/false);
+
DependencyScanningAction Action(Service, WorkingDirectory, Consumer,
- Controller, DepFS, DisableFree, ModuleName);
+ Controller, DepFS, ModuleName);
bool Success = false;
if (CommandLine[1] == "-cc1") {
- Success = createAndRunToolInvocation(CommandLine, Action, *FileMgr,
+ Success = createAndRunToolInvocation(CommandLine, Action, FS,
PCHContainerOps, *Diags, Consumer);
} else {
Success = forEachDriverJob(
- CommandLine, *Diags, *FileMgr, [&](const driver::Command &Cmd) {
+ CommandLine, *Diags, FS, [&](const driver::Command &Cmd) {
if (StringRef(Cmd.getCreator().getName()) != "clang") {
// Non-clang command. Just pass through to the dependency
// consumer.
@@ -782,7 +771,7 @@ bool DependencyScanningWorker::scanDependencies(
// system to ensure that any file system requests that
// are made by the driver do not go through the
// dependency scanning filesystem.
- return createAndRunToolInvocation(std::move(Argv), Action, *FileMgr,
+ return createAndRunToolInvocation(std::move(Argv), Action, FS,
PCHContainerOps, *Diags, Consumer);
});
}
diff --git a/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp b/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
index 9f10ee1..2b5a293 100644
--- a/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ b/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -285,8 +285,7 @@ HeaderIncludes::HeaderIncludes(StringRef FileName, StringRef Code,
MaxInsertOffset(MinInsertOffset +
getMaxHeaderInsertionOffset(
FileName, Code.drop_front(MinInsertOffset), Style)),
- MainIncludeFound(false),
- Categories(Style, FileName) {
+ MainIncludeFound(false), Categories(Style, FileName) {
// Add 0 for main header and INT_MAX for headers that are not in any
// category.
Priorities = {0, INT_MAX};
diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
index b88e6db..807a8d8 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
+++ b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
@@ -131,7 +131,7 @@ static int initialize(Lang Language) {
Mapping->SymbolNames[SymIndex] = {
QName.data(), NSLen, static_cast<unsigned int>(QName.size() - NSLen)};
if (!HeaderName.empty())
- Mapping->SymbolHeaderIDs[SymIndex].push_back(AddHeader(HeaderName));
+ Mapping->SymbolHeaderIDs[SymIndex].push_back(AddHeader(HeaderName));
NSSymbolMap &NSSymbols = AddNS(QName.take_front(NSLen));
NSSymbols.try_emplace(QName.drop_front(NSLen), SymIndex);
@@ -236,7 +236,7 @@ std::optional<Symbol> Symbol::named(llvm::StringRef Scope, llvm::StringRef Name,
return std::nullopt;
}
std::optional<Header> Symbol::header() const {
- const auto& Headers = getMappingPerLang(Language)->SymbolHeaderIDs[ID];
+ const auto &Headers = getMappingPerLang(Language)->SymbolHeaderIDs[ID];
if (Headers.empty())
return std::nullopt;
return Header(Headers.front(), Language);
diff --git a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes
index 66fc46e..c096822 100644
--- a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes
+++ b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes
@@ -19,6 +19,10 @@ Tags:
SwiftReleaseOp: release
SwiftRetainOp: retain
SwiftDefaultOwnership: unretained
+- Name: OpaqueRefCountedType
+ SwiftImportAs: reference
+ SwiftReleaseOp: ORCRelease
+ SwiftRetainOp: ORCRetain
- Name: NonCopyableType
SwiftCopyable: false
SwiftConformsTo: MySwiftModule.MySwiftNonCopyableProtocol
diff --git a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h
index 20b8f04..5f817ac 100644
--- a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h
+++ b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h
@@ -23,3 +23,9 @@ struct EscapableType { int value; };
struct RefCountedTypeWithDefaultConvention {};
inline void retain(RefCountedType *x) {}
inline void release(RefCountedType *x) {}
+
+struct OpaqueRefCountedType;
+struct OpaqueRefCountedType; // redeclaration
+
+inline void ORCRetain(struct OpaqueRefCountedType *x);
+inline void ORCRelease(struct OpaqueRefCountedType *x);
diff --git a/clang/test/APINotes/swift-import-as.cpp b/clang/test/APINotes/swift-import-as.cpp
index 929f924..179170f 100644
--- a/clang/test/APINotes/swift-import-as.cpp
+++ b/clang/test/APINotes/swift-import-as.cpp
@@ -3,6 +3,7 @@
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter ImmortalRefType | FileCheck -check-prefix=CHECK-IMMORTAL %s
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter RefCountedType | FileCheck -check-prefix=CHECK-REF-COUNTED %s
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter RefCountedTypeWithDefaultConvention | FileCheck -check-prefix=CHECK-REF-COUNTED-DEFAULT %s
+// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter OpaqueRefCountedType | FileCheck -check-prefix=CHECK-OPAQUE-REF-COUNTED %s
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter NonCopyableType | FileCheck -check-prefix=CHECK-NON-COPYABLE %s
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter CopyableType | FileCheck -check-prefix=CHECK-COPYABLE %s
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter NonEscapableType | FileCheck -check-prefix=CHECK-NON-ESCAPABLE %s
@@ -34,6 +35,20 @@
// CHECK-REF-COUNTED-DEFAULT: SwiftAttrAttr {{.+}} <<invalid sloc>> "release:release"
// CHECK-REF-COUNTED-DEFAULT: SwiftAttrAttr {{.+}} <<invalid sloc>> "returned_as_unretained_by_default"
+// CHECK-OPAQUE-REF-COUNTED: Dumping OpaqueRefCountedType:
+// CHECK-OPAQUE-REF-COUNTED-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs{{.*}}struct OpaqueRefCountedType
+// CHECK-OPAQUE-REF-COUNTED: SwiftAttrAttr {{.+}} <<invalid sloc>> "import_reference"
+// CHECK-OPAQUE-REF-COUNTED: SwiftAttrAttr {{.+}} <<invalid sloc>> "retain:ORCRetain"
+// CHECK-OPAQUE-REF-COUNTED: SwiftAttrAttr {{.+}} <<invalid sloc>> "release:ORCRelease"
+// CHECK-OPAQUE-REF-COUNTED-NOT: SwiftAttrAttr {{.+}} <<invalid sloc>> "release:ORCRelease"
+
+// CHECK-OPAQUE-REF-COUNTED: Dumping OpaqueRefCountedType:
+// CHECK-OPAQUE-REF-COUNTED-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs{{.*}}struct OpaqueRefCountedType
+// CHECK-OPAQUE-REF-COUNTED: SwiftAttrAttr {{.+}} <<invalid sloc>> "import_reference"
+// CHECK-OPAQUE-REF-COUNTED: SwiftAttrAttr {{.+}} <<invalid sloc>> "retain:ORCRetain"
+// CHECK-OPAQUE-REF-COUNTED: SwiftAttrAttr {{.+}} <<invalid sloc>> "release:ORCRelease"
+
+// CHECK-OPAQUE-REF-COUNTED-NOT: SwiftAttrAttr {{.+}} <<invalid sloc>> "release:
// CHECK-NON-COPYABLE: Dumping NonCopyableType:
// CHECK-NON-COPYABLE-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs {{.+}} struct NonCopyableType
// CHECK-NON-COPYABLE: SwiftAttrAttr {{.+}} <<invalid sloc>> "conforms_to:MySwiftModule.MySwiftNonCopyableProtocol"
diff --git a/clang/test/AST/ByteCode/builtin-bit-cast.cpp b/clang/test/AST/ByteCode/builtin-bit-cast.cpp
index 3c5e89d7..bc356b0 100644
--- a/clang/test/AST/ByteCode/builtin-bit-cast.cpp
+++ b/clang/test/AST/ByteCode/builtin-bit-cast.cpp
@@ -22,6 +22,10 @@ typedef __INTPTR_TYPE__ intptr_t;
static_assert(sizeof(int) == 4);
static_assert(sizeof(long long) == 8);
+
+constexpr bool test_bad_bool = __builtin_bit_cast(bool, (char)0xff); // both-error {{must be initialized by a constant expression}} \
+ // both-note {{value 255 cannot be represented in type 'bool'}}
+
template <class To, class From>
constexpr To bit_cast(const From &from) {
static_assert(sizeof(To) == sizeof(From));
diff --git a/clang/test/AST/ByteCode/unions.cpp b/clang/test/AST/ByteCode/unions.cpp
index 7cfd0d6..139e318 100644
--- a/clang/test/AST/ByteCode/unions.cpp
+++ b/clang/test/AST/ByteCode/unions.cpp
@@ -79,10 +79,9 @@ namespace DefaultInit {
constexpr U1 u1; /// OK.
- constexpr int foo() { // expected-error {{never produces a constant expression}}
+ constexpr int foo() {
U1 u;
- return u.a; // both-note {{read of member 'a' of union with active member 'b'}} \
- // expected-note {{read of member 'a' of union with active member 'b'}}
+ return u.a; // both-note {{read of member 'a' of union with active member 'b'}}
}
static_assert(foo() == 42); // both-error {{not an integral constant expression}} \
// both-note {{in call to}}
@@ -861,6 +860,73 @@ namespace CopyCtorMutable {
// both-note {{in call}}
}
+
+namespace NonTrivialCtor {
+ struct A { int x = 1; constexpr int f() { return 1; } };
+ struct B : A { int y = 1; constexpr int g() { return 2; } };
+ struct C {
+ int x;
+ constexpr virtual int f() = 0;
+ };
+ struct D : C {
+ int y;
+ constexpr virtual int f() override { return 3; }
+ };
+
+ union U {
+ int n;
+ B b;
+ D d;
+ };
+
+ consteval int test(int which) {
+ if (which == 0) {}
+
+ U u{.n = 5};
+ assert_active(u);
+ assert_active(u.n);
+ assert_inactive(u.b);
+
+ switch (which) {
+ case 0:
+ u.b.x = 10; // both-note {{assignment to member 'b' of union with active member 'n'}}
+ return u.b.f();
+ case 1:
+ u.b.y = 10; // both-note {{assignment to member 'b' of union with active member 'n'}}
+ return u.b.g();
+ case 2:
+ u.d.x = 10; // both-note {{assignment to member 'd' of union with active member 'n'}}
+ return u.d.f();
+ case 3:
+ u.d.y = 10; // both-note {{assignment to member 'd' of union with active member 'n'}}
+ return u.d.f();
+ }
+
+ return 1;
+ }
+ static_assert(test(0)); // both-error {{not an integral constant expression}} \
+ // both-note {{in call}}
+ static_assert(test(1)); // both-error {{not an integral constant expression}} \
+ // both-note {{in call}}
+ static_assert(test(2)); // both-error {{not an integral constant expression}} \
+ // both-note {{in call}}
+ static_assert(test(3)); // both-error {{not an integral constant expression}} \
+ // both-note {{in call}}
+
+}
+
+namespace PrimitiveFieldInitActivates {
+ /// The initializer of a needs the field to be active _before_ it's visited.
+ template<int> struct X {};
+ union V {
+ int a, b;
+ constexpr V(X<0>) : a(a = 1) {} // ok
+ constexpr V(X<2>) : a() { b = 1; } // ok
+ };
+ constinit V v0 = X<0>();
+ constinit V v2 = X<2>();
+}
+
#endif
namespace AddressComparison {
diff --git a/clang/test/AST/ast-dump-APValue-lvalue.cpp b/clang/test/AST/ast-dump-APValue-lvalue.cpp
index 51d22a5..f4cf2f5 100644
--- a/clang/test/AST/ast-dump-APValue-lvalue.cpp
+++ b/clang/test/AST/ast-dump-APValue-lvalue.cpp
@@ -67,6 +67,10 @@ void Test(int (&arr)[10]) {
// CHECK-NEXT: | |-value: LValue Base=TypeInfoLValue typeid(int), Null=0, Offset=0, HasPath=1, PathLength=0, Path=()
constexpr int(MP::*pmi) = (int MP::*)&P::x;
- // CHECK: `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} pmi 'int (MP::*const)' constexpr cinit
- // CHECK-NEXT: |-value: MemberPointer MP::x
+ // CHECK: | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} pmi 'int (MP::*const)' constexpr cinit
+ // CHECK-NEXT: | |-value: MemberPointer MP::x
+
+ constexpr int(MP::*pmn) = (int MP::*)nullptr;
+ // CHECK: `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} pmn 'int (MP::*const)' constexpr cinit
+ // CHECK-NEXT: |-value: MemberPointer null
}
diff --git a/clang/test/Analysis/malloc.c b/clang/test/Analysis/malloc.c
index 27a04ff..a9828cf 100644
--- a/clang/test/Analysis/malloc.c
+++ b/clang/test/Analysis/malloc.c
@@ -1954,9 +1954,23 @@ int conjure(void);
void testExtent(void) {
int x = conjure();
clang_analyzer_dump(x);
- // expected-warning-re@-1 {{{{^conj_\$[[:digit:]]+{int, LC1, S[[:digit:]]+, #1}}}}}}
+ // expected-warning-re@-1 {{{{^conj_\$[[:digit:]]+{int, LC[[:digit:]]+, S[[:digit:]]+, #1}}}}}}
int *p = (int *)malloc(x);
clang_analyzer_dumpExtent(p);
- // expected-warning-re@-1 {{{{^conj_\$[[:digit:]]+{int, LC1, S[[:digit:]]+, #1}}}}}}
+ // expected-warning-re@-1 {{{{^conj_\$[[:digit:]]+{int, LC[[:digit:]]+, S[[:digit:]]+, #1}}}}}}
free(p);
}
+
+void gh149754(void *p) {
+ // This testcase demonstrates an unusual situation where a certain symbol
+ // (the value of `p`) is released (more precisely, transitions from
+ // untracked state to Released state) twice within the same bug path because
+ // the `EvalAssume` callback resets it to untracked state after the first
+ // time when it is released. This caused the failure of an assertion, which
+ // was since then removed for the codebase.
+ if (!realloc(p, 8)) {
+ realloc(p, 8);
+ free(p); // expected-warning {{Attempt to free released memory}}
+ }
+ // expected-warning@+1 {{Potential memory leak}}
+}
diff --git a/clang/test/C/C2y/n3353.c b/clang/test/C/C2y/n3353.c
index cd61cbf..a2e08cf 100644
--- a/clang/test/C/C2y/n3353.c
+++ b/clang/test/C/C2y/n3353.c
@@ -44,7 +44,12 @@ static const void *ptr = 0o0; /* ext-warning {{octal integer literals are a C2y
#endif
// 0 by itself is not deprecated, of course.
-int k = 0;
+int k1 = 0;
+unsigned int k2 = 0u;
+long k3 = 0l;
+unsigned long k4 = 0ul;
+long long k5 = 0ll;
+unsigned long long k6 = 0ull;
// Test a preprocessor use of 0 by itself, which is also not deprecated.
#if 0
@@ -65,7 +70,6 @@ static_assert(__extension__ _Generic(typeof(l), const int : 1, default : 0)); //
// Note that 0o by itself is an invalid literal.
int m = 0o; /* expected-error {{invalid suffix 'o' on integer constant}}
- c2y-warning {{octal literals without a '0o' prefix are deprecated}}
*/
// Ensure negation works as expected.
@@ -83,13 +87,11 @@ int n = 0o18; /* expected-error {{invalid digit '8' in octal constant}}
cpp-warning {{octal integer literals are a Clang extension}}
*/
int o1 = 0o8; /* expected-error {{invalid suffix 'o8' on integer constant}}
- c2y-warning {{octal literals without a '0o' prefix are deprecated}}
*/
// FIXME: however, it matches the behavior for hex literals in terms of the
// error reported. Unfortunately, we then go on to think 0 is an octal literal
// without a prefix, which is again a bit confusing.
int o2 = 0xG; /* expected-error {{invalid suffix 'xG' on integer constant}}
- c2y-warning {{octal literals without a '0o' prefix are deprecated}}
*/
// Show that floating-point suffixes on octal literals are rejected.
@@ -130,7 +132,6 @@ constexpr int p = 0o0'1'2'3'4'5'6'7; /* compat-warning {{octal integer literals
*/
static_assert(p == 01234567); // c2y-warning {{octal literals without a '0o' prefix are deprecated}}
int q = 0o'0'1; /* expected-error {{invalid suffix 'o'0'1' on integer constant}}
- c2y-warning {{octal literals without a '0o' prefix are deprecated}}
*/
#define M 0o123
diff --git a/clang/test/CIR/CodeGen/array-ctor.cpp b/clang/test/CIR/CodeGen/array-ctor.cpp
new file mode 100644
index 0000000..b3d81a8
--- /dev/null
+++ b/clang/test/CIR/CodeGen/array-ctor.cpp
@@ -0,0 +1,106 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-lowering-prepare %s -o - 2>&1 | FileCheck --check-prefixes=CIR-BEFORE-LPP %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+struct S {
+ S();
+};
+
+void foo() {
+ S s[42];
+}
+
+// CIR-BEFORE-LPP: cir.func dso_local @_Z3foov()
+// CIR-BEFORE-LPP: %[[ARRAY:.*]] = cir.alloca !cir.array<!rec_S x 42>, !cir.ptr<!cir.array<!rec_S x 42>>, ["s", init]
+// CIR-BEFORE-LPP: cir.array.ctor %[[ARRAY]] : !cir.ptr<!cir.array<!rec_S x 42>> {
+// CIR-BEFORE-LPP: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_S>):
+// CIR-BEFORE-LPP: cir.call @_ZN1SC1Ev(%[[ARG]]) : (!cir.ptr<!rec_S>) -> ()
+// CIR-BEFORE-LPP: cir.yield
+// CIR-BEFORE-LPP: }
+// CIR-BEFORE-LPP: cir.return
+// CIR-BEFORE-LPP: }
+
+// CIR: cir.func dso_local @_Z3foov()
+// CIR: %[[ARRAY:.*]] = cir.alloca !cir.array<!rec_S x 42>, !cir.ptr<!cir.array<!rec_S x 42>>, ["s", init]
+// CIR: %[[CONST42:.*]] = cir.const #cir.int<42> : !u64i
+// CIR: %[[DECAY:.*]] = cir.cast(array_to_ptrdecay, %[[ARRAY]] : !cir.ptr<!cir.array<!rec_S x 42>>), !cir.ptr<!rec_S>
+// CIR: %[[END_PTR:.*]] = cir.ptr_stride(%[[DECAY]] : !cir.ptr<!rec_S>, %[[CONST42]] : !u64i), !cir.ptr<!rec_S>
+// CIR: %[[ITER:.*]] = cir.alloca !cir.ptr<!rec_S>, !cir.ptr<!cir.ptr<!rec_S>>, ["__array_idx"]
+// CIR: cir.store %[[DECAY]], %[[ITER]] : !cir.ptr<!rec_S>, !cir.ptr<!cir.ptr<!rec_S>>
+// CIR: cir.do {
+// CIR: %[[CURRENT:.*]] = cir.load %[[ITER]] : !cir.ptr<!cir.ptr<!rec_S>>, !cir.ptr<!rec_S>
+// CIR: %[[CONST1:.*]] = cir.const #cir.int<1> : !u64i
+// CIR: cir.call @_ZN1SC1Ev(%[[CURRENT]]) : (!cir.ptr<!rec_S>) -> ()
+// CIR: %[[NEXT:.*]] = cir.ptr_stride(%[[CURRENT]] : !cir.ptr<!rec_S>, %[[CONST1]] : !u64i), !cir.ptr<!rec_S>
+// CIR: cir.store %[[NEXT]], %[[ITER]] : !cir.ptr<!rec_S>, !cir.ptr<!cir.ptr<!rec_S>>
+// CIR: cir.yield
+// CIR: } while {
+// CIR: %[[CURRENT2:.*]] = cir.load %[[ITER]] : !cir.ptr<!cir.ptr<!rec_S>>, !cir.ptr<!rec_S>
+// CIR: %[[CMP:.*]] = cir.cmp(ne, %[[CURRENT2]], %[[END_PTR]]) : !cir.ptr<!rec_S>, !cir.bool
+// CIR: cir.condition(%[[CMP]])
+// CIR: }
+// CIR: cir.return
+// CIR: }
+
+// LLVM: define dso_local void @_Z3foov()
+// LLVM: %[[ARRAY:.*]] = alloca [42 x %struct.S]
+// LLVM: %[[START:.*]] = getelementptr %struct.S, ptr %[[ARRAY]], i32 0
+// LLVM: %[[END:.*]] = getelementptr %struct.S, ptr %[[START]], i64 42
+// LLVM: %[[ITER:.*]] = alloca ptr
+// LLVM: store ptr %[[START]], ptr %[[ITER]]
+// LLVM: br label %[[LOOP:.*]]
+// LLVM: [[COND:.*]]:
+// LLVM: %[[CURRENT_CHECK:.*]] = load ptr, ptr %[[ITER]]
+// LLVM: %[[DONE:.*]] = icmp ne ptr %[[CURRENT_CHECK]], %[[END]]
+// LLVM: br i1 %[[DONE]], label %[[LOOP]], label %[[EXIT:.*]]
+// LLVM: [[LOOP]]:
+// LLVM: %[[CURRENT:.*]] = load ptr, ptr %[[ITER]]
+// LLVM: call void @_ZN1SC1Ev(ptr %[[CURRENT]])
+// LLVM: %[[NEXT:.*]] = getelementptr %struct.S, ptr %[[CURRENT]], i64 1
+// LLVM: store ptr %[[NEXT]], ptr %[[ITER]]
+// LLVM: br label %[[COND]]
+// LLVM: [[EXIT]]:
+// LLVM: ret void
+
+// OGCG: define dso_local void @_Z3foov()
+// OGCG: %[[ARRAY:.*]] = alloca [42 x %struct.S]
+// OGCG: %[[START:.*]] = getelementptr{{.*}} %struct.S{{.*}}
+// OGCG: %[[END:.*]] = getelementptr{{.*}} %struct.S{{.*}} i64 42
+// OGCG: br label %[[LOOP:.*]]
+// OGCG: [[LOOP]]:
+// OGCG: %[[CURRENT:.*]] = phi ptr [ %[[START]], %{{.*}} ], [ %[[NEXT:.*]], %[[LOOP]] ]
+// OGCG: call void @_ZN1SC1Ev(ptr{{.*}})
+// OGCG: %[[NEXT]] = getelementptr{{.*}} %struct.S{{.*}} i64 1
+// OGCG: %[[DONE:.*]] = icmp eq ptr %[[NEXT]], %[[END]]
+// OGCG: br i1 %[[DONE]], label %[[EXIT:.*]], label %[[LOOP]]
+// OGCG: [[EXIT]]:
+// OGCG: ret void
+
+void zero_sized() {
+ S s[0];
+}
+
+// CIR-BEFORE-LPP: cir.func dso_local @_Z10zero_sizedv()
+// CIR-BEFORE-LPP: cir.alloca !cir.array<!rec_S x 0>, !cir.ptr<!cir.array<!rec_S x 0>>, ["s"]
+// CIR-BEFORE-LPP-NOT: cir.array.ctor
+// CIR-BEFORE-LPP: cir.return
+
+// CIR: cir.func dso_local @_Z10zero_sizedv()
+// CIR: cir.alloca !cir.array<!rec_S x 0>, !cir.ptr<!cir.array<!rec_S x 0>>, ["s"]
+// CIR-NOT: cir.do
+// CIR-NOT: cir.call @_ZN1SC1Ev
+// CIR: cir.return
+
+// LLVM: define dso_local void @_Z10zero_sizedv()
+// LLVM: alloca [0 x %struct.S]
+// LLVM-NOT: call void @_ZN1SC1Ev
+// LLVM: ret void
+
+// OGCG: define dso_local void @_Z10zero_sizedv()
+// OGCG: alloca [0 x %struct.S]
+// OGCG-NOT: call void @_ZN1SC1Ev
+// OGCG: ret void
diff --git a/clang/test/CIR/CodeGen/bitfields.c b/clang/test/CIR/CodeGen/bitfields.c
index a73c076..869a7c9 100644
--- a/clang/test/CIR/CodeGen/bitfields.c
+++ b/clang/test/CIR/CodeGen/bitfields.c
@@ -315,3 +315,51 @@ void unOp(S* s) {
// OGCG: [[TMP12:%.*]] = shl i64 [[TMP8]], 62
// OGCG: [[TMP13:%.*]] = ashr i64 [[TMP12]], 62
// OGCG: [[TMP14:%.*]] = trunc i64 [[TMP13]] to i32
+
+void binOp(S* s) {
+ s->d |= 42;
+}
+
+// CIR: cir.func {{.*@binOp}}
+// CIR: [[TMP0:%.*]] = cir.const #cir.int<42> : !s32i
+// CIR: [[TMP1:%.*]] = cir.get_member {{.*}}[0] {name = "d"} : !cir.ptr<!rec_S> -> !cir.ptr<!u64i>
+// CIR: [[TMP2:%.*]] = cir.get_bitfield align(4) (#bfi_d, [[TMP1]] : !cir.ptr<!u64i>) -> !s32i
+// CIR: [[TMP3:%.*]] = cir.binop(or, [[TMP2]], [[TMP0]]) : !s32i
+// CIR: cir.set_bitfield align(4) (#bfi_d, [[TMP1]] : !cir.ptr<!u64i>, [[TMP3]] : !s32i)
+
+// LLVM: define {{.*@binOp}}
+// LLVM: [[TMP0:%.*]] = load ptr, ptr {{.*}}, align 8
+// LLVM: [[TMP1:%.*]] = getelementptr %struct.S, ptr [[TMP0]], i32 0, i32 0
+// LLVM: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
+// LLVM: [[TMP3:%.*]] = shl i64 [[TMP2]], 13
+// LLVM: [[TMP4:%.*]] = ashr i64 [[TMP3]], 62
+// LLVM: [[TMP5:%.*]] = trunc i64 [[TMP4]] to i32
+// LLVM: [[TMP6:%.*]] = or i32 [[TMP5]], 42
+// LLVM: [[TMP7:%.*]] = zext i32 [[TMP6]] to i64
+// LLVM: [[TMP8:%.*]] = load i64, ptr [[TMP1]], align 4
+// LLVM: [[TMP9:%.*]] = and i64 [[TMP7]], 3
+// LLVM: [[TMP10:%.*]] = shl i64 [[TMP9]], 49
+// LLVM: [[TMP11:%.*]] = and i64 [[TMP8]], -1688849860263937
+// LLVM: [[TMP12:%.*]] = or i64 [[TMP11]], [[TMP10]]
+// LLVM: store i64 [[TMP12]], ptr [[TMP1]], align 4
+// LLVM: [[TMP13:%.*]] = shl i64 [[TMP9]], 62
+// LLVM: [[TMP14:%.*]] = ashr i64 [[TMP13]], 62
+// LLVM: [[TMP15:%.*]] = trunc i64 [[TMP14]] to i32
+
+// OGCG: define {{.*@binOp}}
+// OGCG: [[TMP0:%.*]] = load ptr, ptr %s.addr, align 8
+// OGCG: [[TMP1:%.*]] = load i64, ptr [[TMP0]], align 4
+// OGCG: [[TMP2:%.*]] = shl i64 [[TMP1]], 13
+// OGCG: [[TMP3:%.*]] = ashr i64 [[TMP2]], 62
+// OGCG: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32
+// OGCG: [[TMP5:%.*]] = or i32 [[TMP4]], 42
+// OGCG: [[TMP6:%.*]] = zext i32 [[TMP5]] to i64
+// OGCG: [[TMP7:%.*]] = load i64, ptr [[TMP0]], align 4
+// OGCG: [[TMP8:%.*]] = and i64 [[TMP6]], 3
+// OGCG: [[TMP9:%.*]] = shl i64 [[TMP8]], 49
+// OGCG: [[TMP10:%.*]] = and i64 [[TMP7]], -1688849860263937
+// OGCG: [[TMP11:%.*]] = or i64 [[TMP10]], [[TMP9]]
+// OGCG: store i64 [[TMP11]], ptr [[TMP0]], align 4
+// OGCG: [[TMP12:%.*]] = shl i64 [[TMP8]], 62
+// OGCG: [[TMP13:%.*]] = ashr i64 [[TMP12]], 62
+// OGCG: [[TMP14:%.*]] = trunc i64 [[TMP13]] to i32
diff --git a/clang/test/CIR/CodeGen/builtin_call.cpp b/clang/test/CIR/CodeGen/builtin_call.cpp
index ad0e478..d9a7068 100644
--- a/clang/test/CIR/CodeGen/builtin_call.cpp
+++ b/clang/test/CIR/CodeGen/builtin_call.cpp
@@ -111,6 +111,22 @@ void assume(bool arg) {
// OGCG: call void @llvm.assume(i1 %{{.+}})
// OGCG: }
+void assume_separate_storage(void *p1, void *p2) {
+ __builtin_assume_separate_storage(p1, p2);
+}
+
+// CIR: cir.func{{.*}} @_Z23assume_separate_storagePvS_
+// CIR: cir.assume_separate_storage %{{.+}}, %{{.+}} : !cir.ptr<!void>
+// CIR: }
+
+// LLVM: define {{.*}}void @_Z23assume_separate_storagePvS_
+// LLVM: call void @llvm.assume(i1 true) [ "separate_storage"(ptr %{{.+}}, ptr %{{.+}}) ]
+// LLVM: }
+
+// OGCG: define {{.*}}void @_Z23assume_separate_storagePvS_
+// OGCG: call void @llvm.assume(i1 true) [ "separate_storage"(ptr %{{.+}}, ptr %{{.+}}) ]
+// OGCG: }
+
void expect(int x, int y) {
__builtin_expect(x, y);
}
diff --git a/clang/test/CIR/CodeGen/cleanup.cpp b/clang/test/CIR/CodeGen/cleanup.cpp
new file mode 100644
index 0000000..41961513
--- /dev/null
+++ b/clang/test/CIR/CodeGen/cleanup.cpp
@@ -0,0 +1,83 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s
+
+struct Struk {
+ ~Struk();
+};
+
+// CHECK: !rec_Struk = !cir.record<struct "Struk" padded {!u8i}>
+
+// CHECK: cir.func{{.*}} @_ZN5StrukD1Ev(!cir.ptr<!rec_Struk>)
+
+void test_cleanup() {
+ Struk s;
+}
+
+// CHECK: cir.func{{.*}} @_Z12test_cleanupv()
+// CHECK: %[[S_ADDR:.*]] = cir.alloca !rec_Struk, !cir.ptr<!rec_Struk>, ["s"]
+// CHECK: cir.call @_ZN5StrukD1Ev(%[[S_ADDR]]) nothrow : (!cir.ptr<!rec_Struk>) -> ()
+// CHECK: cir.return
+
+void test_cleanup_ifelse(bool b) {
+ if (b) {
+ Struk s;
+ } else {
+ Struk s;
+ }
+}
+
+// CHECK: cir.func{{.*}} @_Z19test_cleanup_ifelseb(%arg0: !cir.bool
+// CHECK: cir.scope {
+// CHECK: %[[B:.*]] = cir.load{{.*}} %0 : !cir.ptr<!cir.bool>
+// CHECK: cir.if %[[B]] {
+// CHECK: %[[S:.*]] = cir.alloca !rec_Struk, !cir.ptr<!rec_Struk>, ["s"]
+// CHECK: cir.call @_ZN5StrukD1Ev(%[[S]]) nothrow : (!cir.ptr<!rec_Struk>) -> ()
+// CHECK: } else {
+// CHECK: %[[S_TOO:.*]] = cir.alloca !rec_Struk, !cir.ptr<!rec_Struk>, ["s"]
+// CHECK: cir.call @_ZN5StrukD1Ev(%[[S_TOO]]) nothrow : (!cir.ptr<!rec_Struk>) -> ()
+// CHECK: }
+// CHECK: }
+// CHECK: cir.return
+
+void test_cleanup_for() {
+ for (int i = 0; i < 10; i++) {
+ Struk s;
+ }
+}
+
+// CHECK: cir.func{{.*}} @_Z16test_cleanup_forv()
+// CHECK: cir.scope {
+// CHECK: cir.for : cond {
+// CHECK: } body {
+// CHECK: cir.scope {
+// CHECK: %[[S:.*]] = cir.alloca !rec_Struk, !cir.ptr<!rec_Struk>, ["s"]
+// CHECK: cir.call @_ZN5StrukD1Ev(%[[S]]) nothrow : (!cir.ptr<!rec_Struk>) -> ()
+// CHECK: }
+// CHECK: cir.yield
+// CHECK: } step {
+// CHECK: }
+// CHECK: }
+// CHECK: cir.return
+
+void test_cleanup_nested() {
+ Struk outer;
+ {
+ Struk middle;
+ {
+ Struk inner;
+ }
+ }
+}
+
+// CHECK: cir.func{{.*}} @_Z19test_cleanup_nestedv()
+// CHECK: %[[OUTER:.*]] = cir.alloca !rec_Struk, !cir.ptr<!rec_Struk>, ["outer"]
+// CHECK: cir.scope {
+// CHECK: %[[MIDDLE:.*]] = cir.alloca !rec_Struk, !cir.ptr<!rec_Struk>, ["middle"]
+// CHECK: cir.scope {
+// CHECK: %[[INNER:.*]] = cir.alloca !rec_Struk, !cir.ptr<!rec_Struk>, ["inner"]
+// CHECK: cir.call @_ZN5StrukD1Ev(%[[INNER]]) nothrow : (!cir.ptr<!rec_Struk>) -> ()
+// CHECK: }
+// CHECK: cir.call @_ZN5StrukD1Ev(%[[MIDDLE]]) nothrow : (!cir.ptr<!rec_Struk>) -> ()
+// CHECK: }
+// CHECK: cir.call @_ZN5StrukD1Ev(%[[OUTER]]) nothrow : (!cir.ptr<!rec_Struk>) -> ()
+// CHECK: cir.return
diff --git a/clang/test/CIR/CodeGen/complex-cast.cpp b/clang/test/CIR/CodeGen/complex-cast.cpp
new file mode 100644
index 0000000..0881057
--- /dev/null
+++ b/clang/test/CIR/CodeGen/complex-cast.cpp
@@ -0,0 +1,358 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-canonicalize -o %t.cir %s 2>&1 | FileCheck --check-prefix=CIR-BEFORE %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-after=cir-lowering-prepare -o %t.cir %s 2>&1 | FileCheck --check-prefixes=CIR-AFTER %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+double _Complex cd;
+float _Complex cf;
+int _Complex ci;
+short _Complex cs;
+double sd;
+int si;
+bool b;
+
+void scalar_to_complex() {
+ cd = sd;
+ ci = si;
+ cd = si;
+ ci = sd;
+}
+
+// CIR-BEFORE: %[[FP_TO_COMPLEX:.*]] = cir.cast(float_to_complex, %{{.*}} : !cir.double), !cir.complex<!cir.double>
+
+// CIR-AFTER: %[[REAL:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.double>, !cir.double
+// CIR-AFTER-NEXT: %[[IMAG:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.double
+// CIR-AFTER-NEXT: %{{.*}} = cir.complex.create %[[REAL]], %[[IMAG]] : !cir.double -> !cir.complex<!cir.double>
+
+// LLVM: %[[REAL:.*]] = load double, ptr {{.*}}, align 8
+// LLVM-NEXT: %[[TMP:.*]] = insertvalue { double, double } undef, double %[[REAL]], 0
+// LLVM-NEXT: %[[COMPLEX:.*]] = insertvalue { double, double } %[[TMP]], double 0.000000e+00, 1
+// LLVM-NEXT: store { double, double } %[[COMPLEX]], ptr {{.*}}, align 8
+
+// OGCG: %[[REAL:.*]] = load double, ptr {{.*}}, align 8
+// OGCG: store double %[[REAL]], ptr {{.*}}, align 8
+// OGCG: store double 0.000000e+00, ptr getelementptr inbounds nuw ({ double, double }, ptr @cd, i32 0, i32 1), align 8
+
+// CIR-BEFORE: %[[INT_TO_COMPLEX:.*]] = cir.cast(int_to_complex, %{{.*}} : !s32i), !cir.complex<!s32i>
+
+// CIR-AFTER: %[[REAL:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s32i>, !s32i
+// CIR-AFTER-NEXT: %[[IMAG:.*]] = cir.const #cir.int<0> : !s32i
+// CIR-AFTER-NEXT: %{{.*}} = cir.complex.create %[[REAL]], %[[IMAG]] : !s32i -> !cir.complex<!s32i>
+
+// LLVM: %[[REAL:.*]] = load i32, ptr {{.*}}, align 4
+// LLVM-NEXT: %[[TMP:.*]] = insertvalue { i32, i32 } undef, i32 %[[REAL]], 0
+// LLVM-NEXT: %[[COMPLEX:.*]] = insertvalue { i32, i32 } %[[TMP]], i32 0, 1
+// LLVM-NEXT: store { i32, i32 } %[[COMPLEX]], ptr {{.*}}, align 4
+
+// OGCG: %[[REAL:.*]] = load i32, ptr {{.*}}, align 4
+// OGCG: store i32 %[[REAL]], ptr {{.*}}, align 4
+// OGCG: store i32 0, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci, i32 0, i32 1), align 4
+
+// CIR-BEFORE: %[[INT_TO_FP:.*]] = cir.cast(int_to_float, %{{.*}} : !s32i), !cir.double
+// CIR-BEFORE: %[[FP_TO_COMPLEX:.*]] = cir.cast(float_to_complex, %[[INT_TO_FP]] : !cir.double), !cir.complex<!cir.double>
+
+// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s32i>, !s32i
+// CIR-AFTER-NEXT: %[[REAL:.*]] = cir.cast(int_to_float, %[[TMP]] : !s32i), !cir.double
+// CIR-AFTER-NEXT: %[[IMAG:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.double
+// CIR-AFTER-NEXT: %{{.*}} = cir.complex.create %[[REAL]], %[[IMAG]] : !cir.double -> !cir.complex<!cir.double>
+
+// LLVM: %[[TMP:.*]] = load i32, ptr {{.*}}, align 4
+// LLVM-NEXT: %[[REAL:.*]] = sitofp i32 %[[TMP]] to double
+// LLVM-NEXT: %[[TMP_2:.*]] = insertvalue { double, double } undef, double %[[REAL]], 0
+// LLVM-NEXT: %[[COMPLEX:.*]] = insertvalue { double, double } %[[TMP_2]], double 0.000000e+00, 1
+// LLVM-NEXT: store { double, double } %[[COMPLEX]], ptr {{.*}}, align 8
+
+// OGCG: %[[TMP:.*]] = load i32, ptr {{.*}}, align 4
+// OGCG: %[[REAL:.*]] = sitofp i32 %[[TMP]] to double
+// OGCG: store double %[[REAL]], ptr {{.*}}, align 8
+// OGCG: store double 0.000000e+00, ptr getelementptr inbounds nuw ({ double, double }, ptr {{.*}}, i32 0, i32 1), align 8
+
+// CIR-BEFORE: %[[FP_TO_INT:.*]] = cir.cast(float_to_int, %{{.*}} : !cir.double), !s32i
+// CIR-BEFORE: %[[INT_TO_COMPLEX:.*]] = cir.cast(int_to_complex, %[[FP_TO_INT]] : !s32i), !cir.complex<!s32i>
+
+// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.double>, !cir.double
+// CIR-AFTER-NEXT: %[[REAL:.*]] = cir.cast(float_to_int, %[[TMP]] : !cir.double), !s32i
+// CIR-AFTER-NEXT: %[[IMAG:.*]] = cir.const #cir.int<0> : !s32i
+// CIR-AFTER-NEXT: %{{.*}} = cir.complex.create %[[REAL]], %[[IMAG]] : !s32i -> !cir.complex<!s32i>
+
+// LLVM: %[[TMP:.*]] = load double, ptr {{.*}}, align 8
+// LLVM-NEXT: %[[REAL:.*]] = fptosi double %[[TMP]] to i32
+// LLVM-NEXT: %[[TMP_2:.*]] = insertvalue { i32, i32 } undef, i32 %[[REAL]], 0
+// LLVM-NEXT: %[[COMPLEX:.*]] = insertvalue { i32, i32 } %[[TMP_2]], i32 0, 1
+// LLVM-NEXT: store { i32, i32 } %[[COMPLEX]], ptr {{.*}}, align 4
+
+// OGCG: %[[TMP:.*]] = load double, ptr {{.*}}, align 8
+// OGCG: %[[REAL:.*]] = fptosi double %[[TMP]] to i32
+// OGCG: store i32 %[[REAL]], ptr {{.*}}, align 4
+// OGCG: store i32 0, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr {{.*}}, i32 0, i32 1), align 4
+
+void scalar_to_complex_explicit() {
+ cd = (double _Complex)sd;
+ ci = (int _Complex)si;
+ cd = (double _Complex)si;
+ ci = (int _Complex)sd;
+}
+
+// CIR-BEFORE: %[[FP_TO_COMPLEX:.*]] = cir.cast(float_to_complex, %{{.*}} : !cir.double), !cir.complex<!cir.double>
+
+// CIR-AFTER: %[[REAL:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.double>, !cir.double
+// CIR-AFTER-NEXT: %[[IMAG:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.double
+// CIR-AFTER-NEXT: %{{.*}} = cir.complex.create %[[REAL]], %[[IMAG]] : !cir.double -> !cir.complex<!cir.double>
+
+// LLVM: %[[REAL:.*]] = load double, ptr {{.*}}, align 8
+// LLVM-NEXT: %[[TMP:.*]] = insertvalue { double, double } undef, double %[[REAL]], 0
+// LLVM-NEXT: %[[COMPLEX:.*]] = insertvalue { double, double } %[[TMP]], double 0.000000e+00, 1
+// LLVM-NEXT: store { double, double } %[[COMPLEX]], ptr {{.*}}, align 8
+
+// OGCG: %[[REAL:.*]] = load double, ptr {{.*}}, align 8
+// OGCG: store double %[[REAL]], ptr {{.*}}, align 8
+// OGCG: store double 0.000000e+00, ptr getelementptr inbounds nuw ({ double, double }, ptr @cd, i32 0, i32 1), align 8
+
+// CIR-BEFORE: %[[INT_TO_COMPLEX:.*]] = cir.cast(int_to_complex, %{{.*}} : !s32i), !cir.complex<!s32i>
+
+// CIR-AFTER: %[[REAL:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s32i>, !s32i
+// CIR-AFTER-NEXT: %[[IMAG:.*]] = cir.const #cir.int<0> : !s32i
+// CIR-AFTER-NEXT: %{{.*}} = cir.complex.create %[[REAL]], %[[IMAG]] : !s32i -> !cir.complex<!s32i>
+
+// LLVM: %[[REAL:.*]] = load i32, ptr {{.*}}, align 4
+// LLVM-NEXT: %[[TMP:.*]] = insertvalue { i32, i32 } undef, i32 %[[REAL]], 0
+// LLVM-NEXT: %[[COMPLEX:.*]] = insertvalue { i32, i32 } %[[TMP]], i32 0, 1
+// LLVM-NEXT: store { i32, i32 } %[[COMPLEX]], ptr {{.*}}, align 4
+
+// OGCG: %[[REAL:.*]] = load i32, ptr {{.*}}, align 4
+// OGCG: store i32 %[[REAL]], ptr {{.*}}, align 4
+// OGCG: store i32 0, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr @ci, i32 0, i32 1), align 4
+
+// CIR-BEFORE: %[[INT_TO_FP:.*]] = cir.cast(int_to_float, %{{.*}} : !s32i), !cir.double
+// CIR-BEFORE: %[[FP_TO_COMPLEX:.*]] = cir.cast(float_to_complex, %[[INT_TO_FP]] : !cir.double), !cir.complex<!cir.double>
+
+// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s32i>, !s32i
+// CIR-AFTER-NEXT: %[[REAL:.*]] = cir.cast(int_to_float, %[[TMP]] : !s32i), !cir.double
+// CIR-AFTER-NEXT: %[[IMAG:.*]] = cir.const #cir.fp<0.000000e+00> : !cir.double
+// CIR-AFTER-NEXT: %{{.*}} = cir.complex.create %[[REAL]], %[[IMAG]] : !cir.double -> !cir.complex<!cir.double>
+
+// LLVM: %[[TMP:.*]] = load i32, ptr {{.*}}, align 4
+// LLVM-NEXT: %[[REAL:.*]] = sitofp i32 %[[TMP]] to double
+// LLVM-NEXT: %[[TMP_2:.*]] = insertvalue { double, double } undef, double %[[REAL]], 0
+// LLVM-NEXT: %[[COMPLEX:.*]] = insertvalue { double, double } %[[TMP_2]], double 0.000000e+00, 1
+// LLVM-NEXT: store { double, double } %[[COMPLEX]], ptr {{.*}}, align 8
+
+// OGCG: %[[TMP:.*]] = load i32, ptr {{.*}}, align 4
+// OGCG: %[[REAL:.*]] = sitofp i32 %[[TMP]] to double
+// OGCG: store double %[[REAL]], ptr {{.*}}, align 8
+// OGCG: store double 0.000000e+00, ptr getelementptr inbounds nuw ({ double, double }, ptr {{.*}}, i32 0, i32 1), align 8
+
+// CIR-BEFORE: %[[FP_TO_INT:.*]] = cir.cast(float_to_int, %{{.*}} : !cir.double), !s32i
+// CIR-BEFORE: %[[INT_TO_COMPLEX:.*]] = cir.cast(int_to_complex, %[[FP_TO_INT]] : !s32i), !cir.complex<!s32i>
+
+// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.double>, !cir.double
+// CIR-AFTER-NEXT: %[[REAL:.*]] = cir.cast(float_to_int, %[[TMP]] : !cir.double), !s32i
+// CIR-AFTER-NEXT: %[[IMAG:.*]] = cir.const #cir.int<0> : !s32i
+// CIR-AFTER-NEXT: %{{.*}} = cir.complex.create %[[REAL]], %[[IMAG]] : !s32i -> !cir.complex<!s32i>
+
+// LLVM: %[[TMP:.*]] = load double, ptr {{.*}}, align 8
+// LLVM-NEXT: %[[REAL:.*]] = fptosi double %[[TMP]] to i32
+// LLVM-NEXT: %[[TMP_2:.*]] = insertvalue { i32, i32 } undef, i32 %[[REAL]], 0
+// LLVM-NEXT: %[[COMPLEX:.*]] = insertvalue { i32, i32 } %[[TMP_2]], i32 0, 1
+// LLVM-NEXT: store { i32, i32 } %[[COMPLEX]], ptr {{.*}}, align 4
+
+// OGCG: %[[TMP:.*]] = load double, ptr {{.*}}, align 8
+// OGCG: %[[REAL:.*]] = fptosi double %[[TMP]] to i32
+// OGCG: store i32 %[[REAL]], ptr {{.*}}, align 4
+// OGCG: store i32 0, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr {{.*}}, i32 0, i32 1), align 4
+
+void complex_to_scalar() {
+ sd = (double)cd;
+ si = (int)ci;
+ sd = (double)ci;
+ si = (int)cd;
+}
+
+// CIR-BEFORE: %[[FP_TO_COMPLEX_REAL:.*]] = cir.cast(float_complex_to_real, %{{.*}} : !cir.complex<!cir.double>), !cir.double
+
+// CIR-AFTER: %{{.*}} = cir.complex.real %{{.*}} : !cir.complex<!cir.double> -> !cir.double
+
+// LLVM: %[[REAL:.*]] = extractvalue { double, double } %{{.*}}, 0
+// LLVM: store double %[[REAL]], ptr {{.*}}, align 8
+
+// OGCG: %[[REAL:.*]] = load double, ptr {{.*}}, align 8
+// OGCG: store double %[[REAL]], ptr {{.*}}, align 8
+
+// CIR-BEFORE: %[[INT_COMPLEX_TO_REAL:.*]] = cir.cast(int_complex_to_real, %{{.*}} : !cir.complex<!s32i>), !s32i
+
+// CIR-AFTER: %{{.*}} = cir.complex.real %{{.*}} : !cir.complex<!s32i> -> !s32i
+
+// LLVM: %[[REAL:.*]] = extractvalue { i32, i32 } %{{.*}}, 0
+// LLVM: store i32 %[[REAL]], ptr {{.*}}, align 4
+
+// OGCG: %[[REAL:.*]] = load i32, ptr {{.*}}, align 4
+// OGCG: store i32 %[[REAL]], ptr {{.*}}, align 4
+
+// CIR-BEFORE: %[[INT_COMPLEX_TO_REAL:.*]] = cir.cast(int_complex_to_real, %{{.*}} : !cir.complex<!s32i>), !s32i
+// CIR-BEFORE: %[[INT_TO_FP:.*]] = cir.cast(int_to_float, %[[INT_COMPLEX_TO_REAL]] : !s32i), !cir.double
+
+// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %{{.*}} : !cir.complex<!s32i> -> !s32i
+// CIR-AFTER-NEXT: %{{.*}} = cir.cast(int_to_float, %[[REAL]] : !s32i), !cir.double
+
+// LLVM: %[[REAL:.*]] = extractvalue { i32, i32 } %{{.+}}, 0
+// LLVM-NEXT: %[[REAL_TO_DOUBLE:.*]] = sitofp i32 %[[REAL]] to double
+// LLVM-NEXT: store double %[[REAL_TO_DOUBLE]], ptr {{.*}}, align 8
+
+// OGCG: %[[REAL:.*]] = load i32, ptr {{.*}}, align 4
+// OGCG: %[[INT_TO_FP:.*]] = sitofp i32 %[[REAL]] to double
+// OGCG: store double %[[INT_TO_FP]], ptr {{.*}}, align 8
+
+// CIR-BEFORE: %[[FP_TO_COMPLEX_REAL:.*]] = cir.cast(float_complex_to_real, %{{.*}} : !cir.complex<!cir.double>), !cir.double
+// CIR-BEFORE: %[[FP_TO_INT:.*]] = cir.cast(float_to_int, %[[FP_TO_COMPLEX_REAL]] : !cir.double), !s32i
+
+// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %{{.*}} : !cir.complex<!cir.double> -> !cir.double
+// CIR-AFTER-NEXT: %{{.*}} = cir.cast(float_to_int, %[[REAL]] : !cir.double), !s32i
+
+// LLVM: %[[REAL:.*]] = extractvalue { double, double } %{{.+}}, 0
+// LLVM-NEXT: %[[REAL_TO_INT:.*]] = fptosi double %[[REAL]] to i32
+// LLVM-NEXT: store i32 %[[REAL_TO_INT]], ptr {{.*}}, align 4
+
+// OGCG: %[[REAL:.*]] = load double, ptr {{.*}}, align 8
+// OGCG: %[[FP_TO_INT:.*]] = fptosi double %[[REAL]] to i32
+// OGCG: store i32 %[[FP_TO_INT]], ptr {{.*}}, align 4
+
+void complex_to_bool() {
+ b = (bool)cd;
+ b = (bool)ci;
+}
+
+// CIR-BEFORE: %[[FP_COMPLEX_TO_BOOL:.*]] = cir.cast(float_complex_to_bool, %{{.*}} : !cir.complex<!cir.double>), !cir.bool
+
+// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %{{.*}} : !cir.complex<!cir.double> -> !cir.double
+// CIR-AFTER-NEXT: %[[IMAG:.*]] = cir.complex.imag %{{.*}} : !cir.complex<!cir.double> -> !cir.double
+// CIR-AFTER-NEXT: %[[REAL_TO_BOOL:.*]] = cir.cast(float_to_bool, %[[REAL]] : !cir.double), !cir.bool
+// CIR-AFTER-NEXT: %[[IMAG_TO_BOOL:.*]] = cir.cast(float_to_bool, %[[IMAG]] : !cir.double), !cir.bool
+// CIR-AFTER-NEXT: %[[CONST_TRUE:.*]] = cir.const #true
+// CIR-AFTER-NEXT: %{{.*}} = cir.select if %[[REAL_TO_BOOL]] then %[[CONST_TRUE]] else %[[IMAG_TO_BOOL]] : (!cir.bool, !cir.bool, !cir.bool) -> !cir.bool
+
+// LLVM: %[[REAL:.*]] = extractvalue { double, double } %{{.*}}, 0
+// LLVM-NEXT: %[[IMAG:.*]] = extractvalue { double, double } %{{.*}}, 1
+// LLVM-NEXT: %[[REAL_TO_BOOL:.*]] = fcmp une double %[[REAL]], 0.000000e+00
+// LLVM-NEXT: %[[IMAG_TO_BOOL:.*]] = fcmp une double %[[IMAG]], 0.000000e+00
+// LLVM-NEXT: %[[OR:.*]] = or i1 %[[REAL_TO_BOOL]], %[[IMAG_TO_BOOL]]
+// LLVM-NEXT: %[[RESULT:.*]] = zext i1 %[[OR]] to i8
+// LLVM-NEXT: store i8 %[[RESULT]], ptr {{.*}}, align 1
+
+// OGCG: %[[REAL:.*]] = load double, ptr {{.*}}, align 8
+// OGCG: %[[IMAG:.*]] = load double, ptr getelementptr inbounds nuw ({ double, double }, ptr {{.*}}, i32 0, i32 1), align 8
+// OGCG: %[[REAL_TO_BOOL:.*]] = fcmp une double %[[REAL]], 0.000000e+00
+// OGCG: %[[IMAG_TO_BOOL:.*]] = fcmp une double %[[IMAG]], 0.000000e+00
+// OGCG: %[[COMPLEX_TO_BOOL:.*]] = or i1 %[[REAL_TO_BOOL]], %[[IMAG_TO_BOOL]]
+// OGCG: %[[BOOL_TO_INT:.*]] = zext i1 %[[COMPLEX_TO_BOOL]] to i8
+// OGCG: store i8 %[[BOOL_TO_INT]], ptr {{.*}}, align 1
+
+// CIR-BEFORE: %[[INT_COMPLEX_TO_BOOL:.*]] = cir.cast(int_complex_to_bool, %{{.*}} : !cir.complex<!s32i>), !cir.bool
+
+// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %{{.*}} : !cir.complex<!s32i> -> !s32i
+// CIR-AFTER-NEXT: %[[IMAG:.*]] = cir.complex.imag %{{.*}} : !cir.complex<!s32i> -> !s32i
+// CIR-AFTER-NEXT: %[[REAL_TO_BOOL:.*]] = cir.cast(int_to_bool, %[[REAL]] : !s32i), !cir.bool
+// CIR-AFTER-NEXT: %[[IMAG_TO_BOOL:.*]] = cir.cast(int_to_bool, %[[IMAG]] : !s32i), !cir.bool
+// CIR-AFTER-NEXT: %[[CONST_TRUE:.*]] = cir.const #true
+// CIR-AFTER-NEXT: %{{.+}} = cir.select if %[[REAL_TO_BOOL]] then %[[CONST_TRUE]] else %[[IMAG_TO_BOOL]] : (!cir.bool, !cir.bool, !cir.bool) -> !cir.bool
+
+// LLVM: %[[REAL:.*]] = extractvalue { i32, i32 } %{{.*}}, 0
+// LLVM-NEXT: %[[IMAG:.*]] = extractvalue { i32, i32 } %{{.*}}, 1
+// LLVM-NEXT: %[[REAL_TO_BOOL:.*]] = icmp ne i32 %[[REAL]], 0
+// LLVM-NEXT: %[[IMAG_TO_BOOL:.*]] = icmp ne i32 %[[IMAG]], 0
+// LLVM-NEXT: %[[OR:.*]] = or i1 %[[REAL_TO_BOOL]], %[[IMAG_TO_BOOL]]
+// LLVM-NEXT: %[[RESULT:.*]] = zext i1 %[[OR]] to i8
+// LLVM-NEXT: store i8 %[[RESULT]], ptr {{.*}}, align 1
+
+// OGCG: %[[REAL:.*]] = load i32, ptr {{.*}}, align 4
+// OGCG: %[[IMAG:.*]] = load i32, ptr getelementptr inbounds nuw ({ i32, i32 }, ptr {{.*}}, i32 0, i32 1), align 4
+// OGCG: %[[REAL_TO_BOOL:.*]] = icmp ne i32 %[[REAL]], 0
+// OGCG: %[[IMAG_TO_BOOL:.*]] = icmp ne i32 %[[IMAG]], 0
+// OGCG: %[[COMPLEX_TO_BOOL:.*]] = or i1 %[[REAL_TO_BOOL]], %[[IMAG_TO_BOOL]]
+// OGCG: %[[BOOL_TO_INT:.*]] = zext i1 %[[COMPLEX_TO_BOOL]] to i8
+// OGCG: store i8 %[[BOOL_TO_INT]], ptr {{.*}}, align 1
+
+void complex_to_complex_cast() {
+ cd = cf;
+ ci = cs;
+}
+
+// CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
+// CIR-BEFORE: %[[FP_COMPLEX:.*]] = cir.cast(float_complex, %[[TMP]] : !cir.complex<!cir.float>), !cir.complex<!cir.double>
+
+// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %{{.*}} : !cir.complex<!cir.float> -> !cir.float
+// CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %{{.*}} : !cir.complex<!cir.float> -> !cir.float
+// CIR-AFTER: %[[REAL_FP_CAST:.*]] = cir.cast(floating, %[[REAL]] : !cir.float), !cir.double
+// CIR-AFTER: %[[IMAG_FP_CAST:.*]] = cir.cast(floating, %[[IMAG]] : !cir.float), !cir.double
+// CIR-AFTER: %{{.*}} = cir.complex.create %[[REAL_FP_CAST]], %[[IMAG_FP_CAST]] : !cir.double -> !cir.complex<!cir.double>
+
+// LLVM: %[[REAL:.*]] = extractvalue { float, float } %{{.*}}, 0
+// LLVM: %[[IMAG:.*]] = extractvalue { float, float } %{{.*}}, 1
+// LLVM: %[[REAL_FP_CAST:.*]] = fpext float %[[REAL]] to double
+// LLVM: %[[IMAG_FP_CAST:.*]] = fpext float %[[IMAG]] to double
+// LLVM: %[[TMP:.*]] = insertvalue { double, double } undef, double %[[REAL_FP_CAST]], 0
+// LLVM: %[[COMPLEX:.*]] = insertvalue { double, double } %[[TMP]], double %[[IMAG_FP_CAST]], 1
+// LLVM: store { double, double } %[[COMPLEX]], ptr {{.*}}, align 8
+
+// OGCG: %[[REAL:.*]] = load float, ptr {{.*}}, align 4
+// OGCG: %[[IMAG:.*]] = load float, ptr getelementptr inbounds nuw ({ float, float }, ptr {{.*}}, i32 0, i32 1), align 4
+// OGCG: %[[REAL_FP_CAST:.*]] = fpext float %[[REAL]] to double
+// OGCG: %[[IMAG_FP_CAST:.*]] = fpext float %[[IMAG]] to double
+// OGCG: store double %[[REAL_FP_CAST]], ptr {{.*}}, align 8
+// OGCG: store double %[[IMAG_FP_CAST]], ptr getelementptr inbounds nuw ({ double, double }, ptr {{.*}}, i32 0, i32 1), align 8
+
+// CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!cir.complex<!s16i>>, !cir.complex<!s16i>
+// CIR-BEFORE: %[[INT_COMPLEX:.*]] = cir.cast(int_complex, %[[TMP]] : !cir.complex<!s16i>), !cir.complex<!s32i>
+
+// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %{{.*}} : !cir.complex<!s16i> -> !s16i
+// CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %{{.*}} : !cir.complex<!s16i> -> !s16i
+// CIR-AFTER: %[[REAL_INT_CAST:.*]] = cir.cast(integral, %[[REAL]] : !s16i), !s32i
+// CIR-AFTER: %[[IMAG_INT_CAST:.*]] = cir.cast(integral, %[[IMAG]] : !s16i), !s32i
+// CIR-AFTER: %{{.*}} = cir.complex.create %[[REAL_INT_CAST]], %[[IMAG_INT_CAST]] : !s32i -> !cir.complex<!s32i>
+
+// LLVM: %[[REAL:.*]] = extractvalue { i16, i16 } %{{.*}}, 0
+// LLVM: %[[IMAG:.*]] = extractvalue { i16, i16 } %{{.*}}, 1
+// LLVM: %[[REAL_INT_CAST:.*]] = sext i16 %[[REAL]] to i32
+// LLVM: %[[IMAG_INT_CAST:.*]] = sext i16 %[[IMAG]] to i32
+// LLVM: %[[TMP:.*]] = insertvalue { i32, i32 } undef, i32 %[[REAL_INT_CAST]], 0
+// LLVM: %[[COMPLEX:.*]] = insertvalue { i32, i32 } %[[TMP]], i32 %[[IMAG_INT_CAST]], 1
+// LLVM: store { i32, i32 } %[[COMPLEX]], ptr {{.*}}, align 4
+
+// OGCG: %[[REAL:.*]] = load i16, ptr {{.*}}, align 2
+// OGCG: %[[IMAG:.*]] = load i16, ptr getelementptr inbounds nuw ({ i16, i16 }, ptr {{.*}}, i32 0, i32 1), align 2
+// OGCG: %[[REAL_INT_CAST:.*]] = sext i16 %[[REAL]] to i32
+// OGCG: %[[IMAG_INT_CAST:.*]] = sext i16 %[[IMAG]] to i32
+// OGCG: store i32 %[[REAL_INT_CAST]], ptr {{.*}}, align 4
+// OGCG: store i32 %[[IMAG_INT_CAST]], ptr getelementptr inbounds nuw ({ i32, i32 }, ptr {{.*}}, i32 0, i32 1), align 4
+
+struct CX {
+ double real;
+ double imag;
+};
+
+void lvalue_to_rvalue_bitcast() {
+ CX a;
+ double _Complex b = __builtin_bit_cast(double _Complex, a);
+}
+
+
+// CIR-BEFORE: %{{.*}} = cir.cast(bitcast, %{{.*}} : !cir.ptr<!rec_CX>), !cir.ptr<!cir.complex<!cir.double>>
+
+// CIR-AFTER: %{{.*}} = cir.cast(bitcast, %{{.*}} : !cir.ptr<!rec_CX>), !cir.ptr<!cir.complex<!cir.double>>
+
+// LLVM: %[[PTR_ADDR:.*]] = alloca %struct.CX, i64 1, align 8
+// LLVM: %[[COMPLEX_ADDR:.*]] = alloca { double, double }, i64 1, align 8
+// LLVM: %[[PTR_TO_COMPLEX:.*]] = load { double, double }, ptr %[[PTR_ADDR]], align 8
+// LLVM: store { double, double } %[[PTR_TO_COMPLEX]], ptr %[[COMPLEX_ADDR]], align 8
+
+// OGCG: %[[A_ADDR:.*]] = alloca %struct.CX, align 8
+// OGCG: %[[B_ADDR:.*]] = alloca { double, double }, align 8
+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 0
+// OGCG: %[[A_REAL:.*]] = load double, ptr %[[A_REAL_PTR]], align 8
+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 1
+// OGCG: %[[A_IMAG:.*]] = load double, ptr %[[A_IMAG_PTR]], align 8
+// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 0
+// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 1
+// OGCG: store double %[[A_REAL]], ptr %[[B_REAL_PTR]], align 8
+// OGCG: store double %[[A_IMAG]], ptr %[[B_IMAG_PTR]], align 8
diff --git a/clang/test/CIR/CodeGen/destructors.cpp b/clang/test/CIR/CodeGen/destructors.cpp
index d8f9f23..de7718f 100644
--- a/clang/test/CIR/CodeGen/destructors.cpp
+++ b/clang/test/CIR/CodeGen/destructors.cpp
@@ -31,11 +31,11 @@ out_of_line_destructor::~out_of_line_destructor() {
// OGCG: ret void
// CIR: cir.func dso_local @_ZN22out_of_line_destructorD1Ev(%{{.+}}: !cir.ptr<!rec_out_of_line_destructor>
-// CIR: cir.call @_Z13some_functionv() nothrow : () -> ()
+// CIR: cir.call @_ZN22out_of_line_destructorD2Ev(%{{.*}}) nothrow : (!cir.ptr<!rec_out_of_line_destructor>)
// CIR: cir.return
// LLVM: define dso_local void @_ZN22out_of_line_destructorD1Ev(ptr %{{.+}})
-// LLVM: call void @_Z13some_functionv()
+// LLVM: call void @_ZN22out_of_line_destructorD2Ev
// LLVM: ret void
// OGCG: define dso_local void @_ZN22out_of_line_destructorD1Ev(ptr {{.*}}%{{.+}})
diff --git a/clang/test/CIR/CodeGen/dtor-alias.cpp b/clang/test/CIR/CodeGen/dtor-alias.cpp
new file mode 100644
index 0000000..e37ddab
--- /dev/null
+++ b/clang/test/CIR/CodeGen/dtor-alias.cpp
@@ -0,0 +1,75 @@
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -mconstructor-aliases -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -mconstructor-aliases -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -mconstructor-aliases -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
+
+struct B {
+ ~B();
+};
+B::~B() {
+}
+
+// OGCG: @_ZN1BD1Ev = unnamed_addr alias void (ptr), ptr @_ZN1BD2Ev
+
+// CHECK: cir.func{{.*}} @_ZN1BD2Ev(%arg0: !cir.ptr<!rec_B>
+// CHECK: %[[THIS_ADDR:.*]] = cir.alloca !cir.ptr<!rec_B>, !cir.ptr<!cir.ptr<!rec_B>>, ["this", init]
+// CHECK: cir.store %arg0, %[[THIS_ADDR]]
+// CHECK: %[[THIS:.*]] = cir.load %[[THIS_ADDR]] : !cir.ptr<!cir.ptr<!rec_B>>, !cir.ptr<!rec_B>
+
+// CHECK: cir.func{{.*}} private dso_local @_ZN1BD1Ev(!cir.ptr<!rec_B>) alias(@_ZN1BD2Ev)
+
+// LLVM: define{{.*}} @_ZN1BD2Ev(ptr %[[THIS_ARG:.*]])
+// LLVM: %[[THIS_ADDR:.*]] = alloca ptr
+// LLVM: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
+// LLVM: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
+
+// This should be an alias, like the similar OGCG alias above, but that's not
+// implemented yet.
+// LLVM: declare dso_local void @_ZN1BD1Ev(ptr)
+
+// OGCG: define{{.*}} @_ZN1BD2Ev(ptr{{.*}} %[[THIS_ARG:.*]])
+// OGCG: %[[THIS_ADDR:.*]] = alloca ptr
+// OGCG: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
+// OGCG: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
+
+// The destructor in this case is handled by RAUW rather than aliasing.
+struct Struk {
+ ~Struk() {}
+};
+
+void baz() {
+ Struk s;
+}
+
+// CHECK: cir.func{{.*}} @_ZN5StrukD2Ev(%arg0: !cir.ptr<!rec_Struk>
+// CHECK: %[[THIS_ADDR:.*]] = cir.alloca !cir.ptr<!rec_Struk>, !cir.ptr<!cir.ptr<!rec_Struk>>, ["this", init]
+// CHECK: cir.store %arg0, %[[THIS_ADDR]] : !cir.ptr<!rec_Struk>, !cir.ptr<!cir.ptr<!rec_Struk>>
+// CHECK: %[[THIS:.*]] = cir.load %[[THIS_ADDR]] : !cir.ptr<!cir.ptr<!rec_Struk>>, !cir.ptr<!rec_Struk>
+// CHECK: cir.return
+
+// CHECK-NOT: cir.func{{.*}} @_ZN5StrukD1Ev
+
+// CHECK: cir.func{{.*}} @_Z3bazv()
+// CHECK: %[[S_ADDR:.*]] = cir.alloca !rec_Struk, !cir.ptr<!rec_Struk>, ["s"]
+// CHECK: cir.call @_ZN5StrukD2Ev(%[[S_ADDR]]) nothrow : (!cir.ptr<!rec_Struk>) -> ()
+
+// LLVM: define linkonce_odr void @_ZN5StrukD2Ev(ptr %[[THIS_ARG]])
+// LLVM: %[[THIS_ADDR:.*]] = alloca ptr
+// LLVM: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
+// LLVM: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
+
+// LLVM: define{{.*}} void @_Z3bazv()
+// LLVM: %[[S_ADDR:.*]] = alloca %struct.Struk
+// LLVM: call void @_ZN5StrukD2Ev(ptr{{.*}} %[[S_ADDR]])
+
+// This function gets emitted before the destructor in OGCG.
+// OGCG: define{{.*}} void @_Z3bazv()
+// OGCG: %[[S_ADDR:.*]] = alloca %struct.Struk
+// OGCG: call void @_ZN5StrukD2Ev(ptr{{.*}} %[[S_ADDR]])
+
+// OGCG: define linkonce_odr void @_ZN5StrukD2Ev(ptr{{.*}} %[[THIS_ARG]])
+// OGCG: %[[THIS_ADDR:.*]] = alloca ptr
+// OGCG: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
+// OGCG: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
diff --git a/clang/test/CIR/IR/array-ctor.cir b/clang/test/CIR/IR/array-ctor.cir
new file mode 100644
index 0000000..2378992
--- /dev/null
+++ b/clang/test/CIR/IR/array-ctor.cir
@@ -0,0 +1,29 @@
+
+// RUN: cir-opt %s | FileCheck %s
+
+!u8i = !cir.int<u, 8>
+!rec_S = !cir.record<struct "S" padded {!u8i}>
+
+module {
+ cir.func private @_ZN1SC1Ev(!cir.ptr<!rec_S>)
+ cir.func dso_local @_Z3foov() {
+ %0 = cir.alloca !cir.array<!rec_S x 42>, !cir.ptr<!cir.array<!rec_S x 42>>, ["s", init] {alignment = 16 : i64}
+ cir.array.ctor %0 : !cir.ptr<!cir.array<!rec_S x 42>> {
+ ^bb0(%arg0: !cir.ptr<!rec_S>):
+ cir.call @_ZN1SC1Ev(%arg0) : (!cir.ptr<!rec_S>) -> ()
+ cir.yield
+ }
+ cir.return
+ }
+
+ // CHECK: cir.func private @_ZN1SC1Ev(!cir.ptr<!rec_S>)
+ // CHECK: cir.func dso_local @_Z3foov() {
+ // CHECK: %0 = cir.alloca !cir.array<!rec_S x 42>, !cir.ptr<!cir.array<!rec_S x 42>>, ["s", init] {alignment = 16 : i64}
+ // CHECK: cir.array.ctor %0 : !cir.ptr<!cir.array<!rec_S x 42>> {
+ // CHECK: ^bb0(%arg0: !cir.ptr<!rec_S>):
+ // CHECK: cir.call @_ZN1SC1Ev(%arg0) : (!cir.ptr<!rec_S>) -> ()
+ // CHECK: cir.yield
+ // CHECK: }
+ // CHECK: cir.return
+ // CHECK: }
+}
diff --git a/clang/test/ClangScanDeps/modules-full-named-modules.cppm b/clang/test/ClangScanDeps/modules-full-named-modules.cppm
index 5967a87..c69a215 100644
--- a/clang/test/ClangScanDeps/modules-full-named-modules.cppm
+++ b/clang/test/ClangScanDeps/modules-full-named-modules.cppm
@@ -92,14 +92,7 @@ export void Hello();
// CHECK-NEXT: ]
// CHECK: "command-line": [
// CHECK: "-o",
-// CHECK-NEXT: "{{.*}}/M-{{.*}}.pcm"
-// CHECK: ]
-// CHECK: "input-file": "[[PREFIX]]/M.cppm"
-// CHECK: },
-// CHECK-NEXT: {
-// CHECK: "command-line": [
-// CHECK: "-o",
-// CHECK-NEXT: "[[PREFIX]]/M.o"
+// CHECK-NEXT: "{{.*}}/M.o"
// CHECK: ]
// CHECK: "input-file": "[[PREFIX]]/M.cppm"
// CHECK: }
@@ -160,18 +153,7 @@ void World() {
// CHECK-NEXT: ]
// CHECK: "command-line": [
// CHECK: "-o",
-// CHECK-NEXT: "{{.*}}/impl_part-{{.*}}.pcm",
-// CHECK: ]
-// CHECK: "input-file": "[[PREFIX]]/impl_part.cppm"
-// CHECK: },
-// CHECK-NEXT: {
-// CHECK: "named-module": "M:impl_part"
-// CHECK-NEXT: "named-module-deps": [
-// CHECK-NEXT: "M:interface_part"
-// CHECK-NEXT: ]
-// CHECK: "command-line": [
-// CHECK: "-o",
-// CHECK-NEXT: "[[PREFIX]]/impl_part.o",
+// CHECK-NEXT: "{{.*}}/impl_part.o",
// CHECK: ]
// CHECK: "input-file": "[[PREFIX]]/impl_part.cppm"
// CHECK: }
@@ -194,16 +176,7 @@ export void World();
// CHECK-NOT: "named-module-deps": []
// CHECK: "command-line": [
// CHECK: "-o",
-// CHECK-NEXT: "{{.*}}/interface_part-{{.*}}.pcm",
-// CHECK: ]
-// CHECK: "input-file": "[[PREFIX]]/interface_part.cppm"
-// CHECK: },
-// CHECK-NEXT: {
-// CHECK: "named-module": "M:interface_part"
-// CHECK-NOT: "named-module-deps": []
-// CHECK: "command-line": [
-// CHECK: "-o",
-// CHECK-NEXT: "[[PREFIX]]/interface_part.o",
+// CHECK-NEXT: "{{.*}}/interface_part.o",
// CHECK: ]
// CHECK: "input-file": "[[PREFIX]]/interface_part.cppm"
// CHECK: }
@@ -259,14 +232,7 @@ int main() {
// CHECK-NEXT: ]
// CHECK: "command-line": [
// CHECK: "-o",
-// CHECK-NEXT: "{{.*}}/M-{{.*}}.pcm"
-// CHECK: ]
-// CHECK: "input-file": "[[PREFIX]]/M.cppm"
-// CHECK: },
-// CHECK-NEXT: {
-// CHECK: "command-line": [
-// CHECK: "-o",
-// CHECK-NEXT: "[[PREFIX]]/M.o"
+// CHECK-NEXT: "{{.*}}/M.o"
// CHECK: ]
// CHECK: "input-file": "[[PREFIX]]/M.cppm"
// CHECK: },
@@ -292,18 +258,7 @@ int main() {
// CHECK-NEXT: ]
// CHECK: "command-line": [
// CHECK: "-o",
-// CHECK-NEXT: "{{.*}}/impl_part-{{.*}}.pcm",
-// CHECK: ]
-// CHECK: "input-file": "[[PREFIX]]/impl_part.cppm"
-// CHECK: },
-// CHECK-NEXT: {
-// CHECK: "named-module": "M:impl_part"
-// CHECK-NEXT: "named-module-deps": [
-// CHECK-NEXT: "M:interface_part"
-// CHECK-NEXT: ]
-// CHECK: "command-line": [
-// CHECK: "-o",
-// CHECK-NEXT: "[[PREFIX]]/impl_part.o",
+// CHECK-NEXT: "{{.*}}/impl_part.o",
// CHECK: ]
// CHECK: "input-file": "[[PREFIX]]/impl_part.cppm"
// CHECK: }
@@ -316,16 +271,7 @@ int main() {
// CHECK-NOT: "named-module-deps": []
// CHECK: "command-line": [
// CHECK: "-o",
-// CHECK-NEXT: "{{.*}}/interface_part-{{.*}}.pcm",
-// CHECK: ]
-// CHECK: "input-file": "[[PREFIX]]/interface_part.cppm"
-// CHECK: },
-// CHECK-NEXT: {
-// CHECK: "named-module": "M:interface_part"
-// CHECK-NOT: "named-module-deps": []
-// CHECK: "command-line": [
-// CHECK: "-o",
-// CHECK-NEXT: "[[PREFIX]]/interface_part.o",
+// CHECK-NEXT: "{{.*}}/interface_part.o",
// CHECK: ]
// CHECK: "input-file": "[[PREFIX]]/interface_part.cppm"
// CHECK: }
diff --git a/clang/test/CodeGen/AArch64/neon-intrinsics.c b/clang/test/CodeGen/AArch64/neon-intrinsics.c
index 6304245..035e1ca 100644
--- a/clang/test/CodeGen/AArch64/neon-intrinsics.c
+++ b/clang/test/CodeGen/AArch64/neon-intrinsics.c
@@ -8585,7 +8585,7 @@ uint32x2_t test_vqshrun_n_s64(int64x2_t a) {
// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> [[A]], <8 x i8> [[VQSHRUN_N3]], <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-NEXT: ret <16 x i8> [[SHUFFLE_I]]
//
-int8x16_t test_vqshrun_high_n_s16(int8x8_t a, int16x8_t b) {
+uint8x16_t test_vqshrun_high_n_s16(uint8x8_t a, int16x8_t b) {
return vqshrun_high_n_s16(a, b, 3);
}
@@ -8598,7 +8598,7 @@ int8x16_t test_vqshrun_high_n_s16(int8x8_t a, int16x8_t b) {
// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> [[A]], <4 x i16> [[VQSHRUN_N3]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
// CHECK-NEXT: ret <8 x i16> [[SHUFFLE_I]]
//
-int16x8_t test_vqshrun_high_n_s32(int16x4_t a, int32x4_t b) {
+uint16x8_t test_vqshrun_high_n_s32(uint16x4_t a, int32x4_t b) {
return vqshrun_high_n_s32(a, b, 9);
}
@@ -8611,7 +8611,7 @@ int16x8_t test_vqshrun_high_n_s32(int16x4_t a, int32x4_t b) {
// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <2 x i32> [[A]], <2 x i32> [[VQSHRUN_N3]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK-NEXT: ret <4 x i32> [[SHUFFLE_I]]
//
-int32x4_t test_vqshrun_high_n_s64(int32x2_t a, int64x2_t b) {
+uint32x4_t test_vqshrun_high_n_s64(uint32x2_t a, int64x2_t b) {
return vqshrun_high_n_s64(a, b, 19);
}
@@ -8810,7 +8810,7 @@ uint32x2_t test_vqrshrun_n_s64(int64x2_t a) {
// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> [[A]], <8 x i8> [[VQRSHRUN_N3]], <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-NEXT: ret <16 x i8> [[SHUFFLE_I]]
//
-int8x16_t test_vqrshrun_high_n_s16(int8x8_t a, int16x8_t b) {
+uint8x16_t test_vqrshrun_high_n_s16(uint8x8_t a, int16x8_t b) {
return vqrshrun_high_n_s16(a, b, 3);
}
@@ -8823,7 +8823,7 @@ int8x16_t test_vqrshrun_high_n_s16(int8x8_t a, int16x8_t b) {
// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <4 x i16> [[A]], <4 x i16> [[VQRSHRUN_N3]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
// CHECK-NEXT: ret <8 x i16> [[SHUFFLE_I]]
//
-int16x8_t test_vqrshrun_high_n_s32(int16x4_t a, int32x4_t b) {
+uint16x8_t test_vqrshrun_high_n_s32(uint16x4_t a, int32x4_t b) {
return vqrshrun_high_n_s32(a, b, 9);
}
@@ -8836,7 +8836,7 @@ int16x8_t test_vqrshrun_high_n_s32(int16x4_t a, int32x4_t b) {
// CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <2 x i32> [[A]], <2 x i32> [[VQRSHRUN_N3]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
// CHECK-NEXT: ret <4 x i32> [[SHUFFLE_I]]
//
-int32x4_t test_vqrshrun_high_n_s64(int32x2_t a, int64x2_t b) {
+uint32x4_t test_vqrshrun_high_n_s64(uint32x2_t a, int64x2_t b) {
return vqrshrun_high_n_s64(a, b, 19);
}
diff --git a/clang/test/CodeGen/PowerPC/ppc-dmf-future-builtin-err.c b/clang/test/CodeGen/PowerPC/ppc-dmf-future-builtin-err.c
deleted file mode 100644
index 9def39f..0000000
--- a/clang/test/CodeGen/PowerPC/ppc-dmf-future-builtin-err.c
+++ /dev/null
@@ -1,15 +0,0 @@
-// RUN: not %clang_cc1 -triple powerpc64le-unknown-linux-gnu -target-cpu pwr10 \
-// RUN: %s -emit-llvm-only 2>&1 | FileCheck %s
-
-__attribute__((target("no-mma")))
-void test_mma(unsigned char *vdmrp, unsigned char *vpp, vector unsigned char vc) {
- __dmr1024 vdmr = *((__dmr1024 *)vdmrp);
- __vector_pair vp = *((__vector_pair *)vpp);
- __builtin_mma_dmsetdmrz(&vdmr);
- __builtin_mma_dmmr(&vdmr, (__dmr1024*)vpp);
- __builtin_mma_dmxor(&vdmr, (__dmr1024*)vpp);
-
-// CHECK: error: '__builtin_mma_dmsetdmrz' needs target feature mma,isa-future-instructions
-// CHECK: error: '__builtin_mma_dmmr' needs target feature mma,isa-future-instructions
-// CHECK: error: '__builtin_mma_dmxor' needs target feature mma,isa-future-instructions
-}
diff --git a/clang/test/CodeGen/PowerPC/ppc-dmf-mma-builtin-err.c b/clang/test/CodeGen/PowerPC/ppc-dmf-mma-builtin-err.c
index c022746..5a92d6e 100644
--- a/clang/test/CodeGen/PowerPC/ppc-dmf-mma-builtin-err.c
+++ b/clang/test/CodeGen/PowerPC/ppc-dmf-mma-builtin-err.c
@@ -1,3 +1,5 @@
+// RUN: not %clang_cc1 -triple powerpc64le-unknown-linux-gnu -target-cpu pwr10 \
+// RUN: %s -emit-llvm-only 2>&1 | FileCheck %s
// RUN: not %clang_cc1 -triple powerpc64le-unknown-linux-gnu -target-cpu future \
// RUN: %s -emit-llvm-only 2>&1 | FileCheck %s
diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/non-overloaded/vcompress.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/non-overloaded/vcompress.c
new file mode 100644
index 0000000..6cff3df
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/non-overloaded/vcompress.c
@@ -0,0 +1,74 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
+// REQUIRES: riscv-registered-target
+// RUN: %clang_cc1 -triple riscv64 -target-feature +zve64x \
+// RUN: -target-feature +zvfbfmin -disable-O0-optnone \
+// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \
+// RUN: FileCheck --check-prefix=CHECK-RV64 %s
+
+#include <riscv_vector.h>
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vcompress_vm_bf16mf4(
+// CHECK-RV64-SAME: <vscale x 1 x bfloat> [[VS2:%.*]], <vscale x 1 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vcompress.nxv1bf16.i64(<vscale x 1 x bfloat> poison, <vscale x 1 x bfloat> [[VS2]], <vscale x 1 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vcompress_vm_bf16mf4(vbfloat16mf4_t vs2, vbool64_t vs1,
+ size_t vl) {
+ return __riscv_vcompress_vm_bf16mf4(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vcompress_vm_bf16mf2(
+// CHECK-RV64-SAME: <vscale x 2 x bfloat> [[VS2:%.*]], <vscale x 2 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vcompress.nxv2bf16.i64(<vscale x 2 x bfloat> poison, <vscale x 2 x bfloat> [[VS2]], <vscale x 2 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vcompress_vm_bf16mf2(vbfloat16mf2_t vs2, vbool32_t vs1,
+ size_t vl) {
+ return __riscv_vcompress_vm_bf16mf2(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vcompress_vm_bf16m1(
+// CHECK-RV64-SAME: <vscale x 4 x bfloat> [[VS2:%.*]], <vscale x 4 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vcompress.nxv4bf16.i64(<vscale x 4 x bfloat> poison, <vscale x 4 x bfloat> [[VS2]], <vscale x 4 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vcompress_vm_bf16m1(vbfloat16m1_t vs2, vbool16_t vs1,
+ size_t vl) {
+ return __riscv_vcompress_vm_bf16m1(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vcompress_vm_bf16m2(
+// CHECK-RV64-SAME: <vscale x 8 x bfloat> [[VS2:%.*]], <vscale x 8 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vcompress.nxv8bf16.i64(<vscale x 8 x bfloat> poison, <vscale x 8 x bfloat> [[VS2]], <vscale x 8 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vcompress_vm_bf16m2(vbfloat16m2_t vs2, vbool8_t vs1,
+ size_t vl) {
+ return __riscv_vcompress_vm_bf16m2(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vcompress_vm_bf16m4(
+// CHECK-RV64-SAME: <vscale x 16 x bfloat> [[VS2:%.*]], <vscale x 16 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vcompress.nxv16bf16.i64(<vscale x 16 x bfloat> poison, <vscale x 16 x bfloat> [[VS2]], <vscale x 16 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vcompress_vm_bf16m4(vbfloat16m4_t vs2, vbool4_t vs1,
+ size_t vl) {
+ return __riscv_vcompress_vm_bf16m4(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vcompress_vm_bf16m8(
+// CHECK-RV64-SAME: <vscale x 32 x bfloat> [[VS2:%.*]], <vscale x 32 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vcompress.nxv32bf16.i64(<vscale x 32 x bfloat> poison, <vscale x 32 x bfloat> [[VS2]], <vscale x 32 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vcompress_vm_bf16m8(vbfloat16m8_t vs2, vbool2_t vs1,
+ size_t vl) {
+ return __riscv_vcompress_vm_bf16m8(vs2, vs1, vl);
+}
diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/non-overloaded/vrgather.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/non-overloaded/vrgather.c
new file mode 100644
index 0000000..cb0004f
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/non-overloaded/vrgather.c
@@ -0,0 +1,272 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
+// REQUIRES: riscv-registered-target
+// RUN: %clang_cc1 -triple riscv64 -target-feature +zve64x \
+// RUN: -target-feature +zvfbfmin -disable-O0-optnone \
+// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \
+// RUN: FileCheck --check-prefix=CHECK-RV64 %s
+
+#include <riscv_vector.h>
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vv_bf16mf4(
+// CHECK-RV64-SAME: <vscale x 1 x bfloat> [[VS2:%.*]], <vscale x 1 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vv.nxv1bf16.i64(<vscale x 1 x bfloat> poison, <vscale x 1 x bfloat> [[VS2]], <vscale x 1 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vv_bf16mf4(vbfloat16mf4_t vs2, vuint16mf4_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_vv_bf16mf4(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vx_bf16mf4(
+// CHECK-RV64-SAME: <vscale x 1 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vx.nxv1bf16.i64(<vscale x 1 x bfloat> poison, <vscale x 1 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vx_bf16mf4(vbfloat16mf4_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_vx_bf16mf4(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vv_bf16mf2(
+// CHECK-RV64-SAME: <vscale x 2 x bfloat> [[VS2:%.*]], <vscale x 2 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vv.nxv2bf16.i64(<vscale x 2 x bfloat> poison, <vscale x 2 x bfloat> [[VS2]], <vscale x 2 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vv_bf16mf2(vbfloat16mf2_t vs2, vuint16mf2_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_vv_bf16mf2(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vx_bf16mf2(
+// CHECK-RV64-SAME: <vscale x 2 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vx.nxv2bf16.i64(<vscale x 2 x bfloat> poison, <vscale x 2 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vx_bf16mf2(vbfloat16mf2_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_vx_bf16mf2(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vv_bf16m1(
+// CHECK-RV64-SAME: <vscale x 4 x bfloat> [[VS2:%.*]], <vscale x 4 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vv.nxv4bf16.i64(<vscale x 4 x bfloat> poison, <vscale x 4 x bfloat> [[VS2]], <vscale x 4 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vv_bf16m1(vbfloat16m1_t vs2, vuint16m1_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_vv_bf16m1(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vx_bf16m1(
+// CHECK-RV64-SAME: <vscale x 4 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vx.nxv4bf16.i64(<vscale x 4 x bfloat> poison, <vscale x 4 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vx_bf16m1(vbfloat16m1_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_vx_bf16m1(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vv_bf16m2(
+// CHECK-RV64-SAME: <vscale x 8 x bfloat> [[VS2:%.*]], <vscale x 8 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vv.nxv8bf16.i64(<vscale x 8 x bfloat> poison, <vscale x 8 x bfloat> [[VS2]], <vscale x 8 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vv_bf16m2(vbfloat16m2_t vs2, vuint16m2_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_vv_bf16m2(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vx_bf16m2(
+// CHECK-RV64-SAME: <vscale x 8 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vx.nxv8bf16.i64(<vscale x 8 x bfloat> poison, <vscale x 8 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vx_bf16m2(vbfloat16m2_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_vx_bf16m2(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vv_bf16m4(
+// CHECK-RV64-SAME: <vscale x 16 x bfloat> [[VS2:%.*]], <vscale x 16 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vv.nxv16bf16.i64(<vscale x 16 x bfloat> poison, <vscale x 16 x bfloat> [[VS2]], <vscale x 16 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vv_bf16m4(vbfloat16m4_t vs2, vuint16m4_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_vv_bf16m4(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vx_bf16m4(
+// CHECK-RV64-SAME: <vscale x 16 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vx.nxv16bf16.i64(<vscale x 16 x bfloat> poison, <vscale x 16 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vx_bf16m4(vbfloat16m4_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_vx_bf16m4(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vv_bf16m8(
+// CHECK-RV64-SAME: <vscale x 32 x bfloat> [[VS2:%.*]], <vscale x 32 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vv.nxv32bf16.i64(<vscale x 32 x bfloat> poison, <vscale x 32 x bfloat> [[VS2]], <vscale x 32 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vv_bf16m8(vbfloat16m8_t vs2, vuint16m8_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_vv_bf16m8(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vx_bf16m8(
+// CHECK-RV64-SAME: <vscale x 32 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vx.nxv32bf16.i64(<vscale x 32 x bfloat> poison, <vscale x 32 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vx_bf16m8(vbfloat16m8_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_vx_bf16m8(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vv_bf16mf4_m(
+// CHECK-RV64-SAME: <vscale x 1 x i1> [[VM:%.*]], <vscale x 1 x bfloat> [[VS2:%.*]], <vscale x 1 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv1bf16.i64(<vscale x 1 x bfloat> poison, <vscale x 1 x bfloat> [[VS2]], <vscale x 1 x i16> [[VS1]], <vscale x 1 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vv_bf16mf4_m(vbool64_t vm, vbfloat16mf4_t vs2,
+ vuint16mf4_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16mf4_m(vm, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vx_bf16mf4_m(
+// CHECK-RV64-SAME: <vscale x 1 x i1> [[VM:%.*]], <vscale x 1 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv1bf16.i64(<vscale x 1 x bfloat> poison, <vscale x 1 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 1 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vx_bf16mf4_m(vbool64_t vm, vbfloat16mf4_t vs2,
+ size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16mf4_m(vm, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vv_bf16mf2_m(
+// CHECK-RV64-SAME: <vscale x 2 x i1> [[VM:%.*]], <vscale x 2 x bfloat> [[VS2:%.*]], <vscale x 2 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv2bf16.i64(<vscale x 2 x bfloat> poison, <vscale x 2 x bfloat> [[VS2]], <vscale x 2 x i16> [[VS1]], <vscale x 2 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vv_bf16mf2_m(vbool32_t vm, vbfloat16mf2_t vs2,
+ vuint16mf2_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16mf2_m(vm, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vx_bf16mf2_m(
+// CHECK-RV64-SAME: <vscale x 2 x i1> [[VM:%.*]], <vscale x 2 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv2bf16.i64(<vscale x 2 x bfloat> poison, <vscale x 2 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 2 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vx_bf16mf2_m(vbool32_t vm, vbfloat16mf2_t vs2,
+ size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16mf2_m(vm, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vv_bf16m1_m(
+// CHECK-RV64-SAME: <vscale x 4 x i1> [[VM:%.*]], <vscale x 4 x bfloat> [[VS2:%.*]], <vscale x 4 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv4bf16.i64(<vscale x 4 x bfloat> poison, <vscale x 4 x bfloat> [[VS2]], <vscale x 4 x i16> [[VS1]], <vscale x 4 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vv_bf16m1_m(vbool16_t vm, vbfloat16m1_t vs2,
+ vuint16m1_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16m1_m(vm, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vx_bf16m1_m(
+// CHECK-RV64-SAME: <vscale x 4 x i1> [[VM:%.*]], <vscale x 4 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv4bf16.i64(<vscale x 4 x bfloat> poison, <vscale x 4 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 4 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vx_bf16m1_m(vbool16_t vm, vbfloat16m1_t vs2,
+ size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16m1_m(vm, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vv_bf16m2_m(
+// CHECK-RV64-SAME: <vscale x 8 x i1> [[VM:%.*]], <vscale x 8 x bfloat> [[VS2:%.*]], <vscale x 8 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv8bf16.i64(<vscale x 8 x bfloat> poison, <vscale x 8 x bfloat> [[VS2]], <vscale x 8 x i16> [[VS1]], <vscale x 8 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vv_bf16m2_m(vbool8_t vm, vbfloat16m2_t vs2,
+ vuint16m2_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16m2_m(vm, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vx_bf16m2_m(
+// CHECK-RV64-SAME: <vscale x 8 x i1> [[VM:%.*]], <vscale x 8 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv8bf16.i64(<vscale x 8 x bfloat> poison, <vscale x 8 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 8 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vx_bf16m2_m(vbool8_t vm, vbfloat16m2_t vs2,
+ size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16m2_m(vm, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vv_bf16m4_m(
+// CHECK-RV64-SAME: <vscale x 16 x i1> [[VM:%.*]], <vscale x 16 x bfloat> [[VS2:%.*]], <vscale x 16 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv16bf16.i64(<vscale x 16 x bfloat> poison, <vscale x 16 x bfloat> [[VS2]], <vscale x 16 x i16> [[VS1]], <vscale x 16 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vv_bf16m4_m(vbool4_t vm, vbfloat16m4_t vs2,
+ vuint16m4_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16m4_m(vm, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vx_bf16m4_m(
+// CHECK-RV64-SAME: <vscale x 16 x i1> [[VM:%.*]], <vscale x 16 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv16bf16.i64(<vscale x 16 x bfloat> poison, <vscale x 16 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 16 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vx_bf16m4_m(vbool4_t vm, vbfloat16m4_t vs2,
+ size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16m4_m(vm, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vv_bf16m8_m(
+// CHECK-RV64-SAME: <vscale x 32 x i1> [[VM:%.*]], <vscale x 32 x bfloat> [[VS2:%.*]], <vscale x 32 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv32bf16.i64(<vscale x 32 x bfloat> poison, <vscale x 32 x bfloat> [[VS2]], <vscale x 32 x i16> [[VS1]], <vscale x 32 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vv_bf16m8_m(vbool2_t vm, vbfloat16m8_t vs2,
+ vuint16m8_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16m8_m(vm, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vx_bf16m8_m(
+// CHECK-RV64-SAME: <vscale x 32 x i1> [[VM:%.*]], <vscale x 32 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv32bf16.i64(<vscale x 32 x bfloat> poison, <vscale x 32 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 32 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vx_bf16m8_m(vbool2_t vm, vbfloat16m8_t vs2,
+ size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16m8_m(vm, vs2, vs1, vl);
+}
diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/overloaded/vcompress.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/overloaded/vcompress.c
new file mode 100644
index 0000000..40de6fd
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/overloaded/vcompress.c
@@ -0,0 +1,74 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
+// REQUIRES: riscv-registered-target
+// RUN: %clang_cc1 -triple riscv64 -target-feature +zve64x \
+// RUN: -target-feature +zvfbfmin -disable-O0-optnone \
+// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \
+// RUN: FileCheck --check-prefix=CHECK-RV64 %s
+
+#include <riscv_vector.h>
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vcompress_vm_bf16mf4(
+// CHECK-RV64-SAME: <vscale x 1 x bfloat> [[VS2:%.*]], <vscale x 1 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vcompress.nxv1bf16.i64(<vscale x 1 x bfloat> poison, <vscale x 1 x bfloat> [[VS2]], <vscale x 1 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vcompress_vm_bf16mf4(vbfloat16mf4_t vs2, vbool64_t vs1,
+ size_t vl) {
+ return __riscv_vcompress(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vcompress_vm_bf16mf2(
+// CHECK-RV64-SAME: <vscale x 2 x bfloat> [[VS2:%.*]], <vscale x 2 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vcompress.nxv2bf16.i64(<vscale x 2 x bfloat> poison, <vscale x 2 x bfloat> [[VS2]], <vscale x 2 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vcompress_vm_bf16mf2(vbfloat16mf2_t vs2, vbool32_t vs1,
+ size_t vl) {
+ return __riscv_vcompress(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vcompress_vm_bf16m1(
+// CHECK-RV64-SAME: <vscale x 4 x bfloat> [[VS2:%.*]], <vscale x 4 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vcompress.nxv4bf16.i64(<vscale x 4 x bfloat> poison, <vscale x 4 x bfloat> [[VS2]], <vscale x 4 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vcompress_vm_bf16m1(vbfloat16m1_t vs2, vbool16_t vs1,
+ size_t vl) {
+ return __riscv_vcompress(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vcompress_vm_bf16m2(
+// CHECK-RV64-SAME: <vscale x 8 x bfloat> [[VS2:%.*]], <vscale x 8 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vcompress.nxv8bf16.i64(<vscale x 8 x bfloat> poison, <vscale x 8 x bfloat> [[VS2]], <vscale x 8 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vcompress_vm_bf16m2(vbfloat16m2_t vs2, vbool8_t vs1,
+ size_t vl) {
+ return __riscv_vcompress(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vcompress_vm_bf16m4(
+// CHECK-RV64-SAME: <vscale x 16 x bfloat> [[VS2:%.*]], <vscale x 16 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vcompress.nxv16bf16.i64(<vscale x 16 x bfloat> poison, <vscale x 16 x bfloat> [[VS2]], <vscale x 16 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vcompress_vm_bf16m4(vbfloat16m4_t vs2, vbool4_t vs1,
+ size_t vl) {
+ return __riscv_vcompress(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vcompress_vm_bf16m8(
+// CHECK-RV64-SAME: <vscale x 32 x bfloat> [[VS2:%.*]], <vscale x 32 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vcompress.nxv32bf16.i64(<vscale x 32 x bfloat> poison, <vscale x 32 x bfloat> [[VS2]], <vscale x 32 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vcompress_vm_bf16m8(vbfloat16m8_t vs2, vbool2_t vs1,
+ size_t vl) {
+ return __riscv_vcompress(vs2, vs1, vl);
+}
diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/overloaded/vrgather.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/overloaded/vrgather.c
new file mode 100644
index 0000000..068d849
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/non-policy/overloaded/vrgather.c
@@ -0,0 +1,272 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
+// REQUIRES: riscv-registered-target
+// RUN: %clang_cc1 -triple riscv64 -target-feature +zve64x \
+// RUN: -target-feature +zvfbfmin -disable-O0-optnone \
+// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \
+// RUN: FileCheck --check-prefix=CHECK-RV64 %s
+
+#include <riscv_vector.h>
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vv_bf16mf4(
+// CHECK-RV64-SAME: <vscale x 1 x bfloat> [[VS2:%.*]], <vscale x 1 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vv.nxv1bf16.i64(<vscale x 1 x bfloat> poison, <vscale x 1 x bfloat> [[VS2]], <vscale x 1 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vv_bf16mf4(vbfloat16mf4_t vs2, vuint16mf4_t vs1,
+ size_t vl) {
+ return __riscv_vrgather(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vx_bf16mf4(
+// CHECK-RV64-SAME: <vscale x 1 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vx.nxv1bf16.i64(<vscale x 1 x bfloat> poison, <vscale x 1 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vx_bf16mf4(vbfloat16mf4_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vv_bf16mf2(
+// CHECK-RV64-SAME: <vscale x 2 x bfloat> [[VS2:%.*]], <vscale x 2 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vv.nxv2bf16.i64(<vscale x 2 x bfloat> poison, <vscale x 2 x bfloat> [[VS2]], <vscale x 2 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vv_bf16mf2(vbfloat16mf2_t vs2, vuint16mf2_t vs1,
+ size_t vl) {
+ return __riscv_vrgather(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vx_bf16mf2(
+// CHECK-RV64-SAME: <vscale x 2 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vx.nxv2bf16.i64(<vscale x 2 x bfloat> poison, <vscale x 2 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vx_bf16mf2(vbfloat16mf2_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vv_bf16m1(
+// CHECK-RV64-SAME: <vscale x 4 x bfloat> [[VS2:%.*]], <vscale x 4 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vv.nxv4bf16.i64(<vscale x 4 x bfloat> poison, <vscale x 4 x bfloat> [[VS2]], <vscale x 4 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vv_bf16m1(vbfloat16m1_t vs2, vuint16m1_t vs1,
+ size_t vl) {
+ return __riscv_vrgather(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vx_bf16m1(
+// CHECK-RV64-SAME: <vscale x 4 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vx.nxv4bf16.i64(<vscale x 4 x bfloat> poison, <vscale x 4 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vx_bf16m1(vbfloat16m1_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vv_bf16m2(
+// CHECK-RV64-SAME: <vscale x 8 x bfloat> [[VS2:%.*]], <vscale x 8 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vv.nxv8bf16.i64(<vscale x 8 x bfloat> poison, <vscale x 8 x bfloat> [[VS2]], <vscale x 8 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vv_bf16m2(vbfloat16m2_t vs2, vuint16m2_t vs1,
+ size_t vl) {
+ return __riscv_vrgather(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vx_bf16m2(
+// CHECK-RV64-SAME: <vscale x 8 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vx.nxv8bf16.i64(<vscale x 8 x bfloat> poison, <vscale x 8 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vx_bf16m2(vbfloat16m2_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vv_bf16m4(
+// CHECK-RV64-SAME: <vscale x 16 x bfloat> [[VS2:%.*]], <vscale x 16 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vv.nxv16bf16.i64(<vscale x 16 x bfloat> poison, <vscale x 16 x bfloat> [[VS2]], <vscale x 16 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vv_bf16m4(vbfloat16m4_t vs2, vuint16m4_t vs1,
+ size_t vl) {
+ return __riscv_vrgather(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vx_bf16m4(
+// CHECK-RV64-SAME: <vscale x 16 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vx.nxv16bf16.i64(<vscale x 16 x bfloat> poison, <vscale x 16 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vx_bf16m4(vbfloat16m4_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vv_bf16m8(
+// CHECK-RV64-SAME: <vscale x 32 x bfloat> [[VS2:%.*]], <vscale x 32 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vv.nxv32bf16.i64(<vscale x 32 x bfloat> poison, <vscale x 32 x bfloat> [[VS2]], <vscale x 32 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vv_bf16m8(vbfloat16m8_t vs2, vuint16m8_t vs1,
+ size_t vl) {
+ return __riscv_vrgather(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vx_bf16m8(
+// CHECK-RV64-SAME: <vscale x 32 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vx.nxv32bf16.i64(<vscale x 32 x bfloat> poison, <vscale x 32 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vx_bf16m8(vbfloat16m8_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather(vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vv_bf16mf4_m(
+// CHECK-RV64-SAME: <vscale x 1 x i1> [[VM:%.*]], <vscale x 1 x bfloat> [[VS2:%.*]], <vscale x 1 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv1bf16.i64(<vscale x 1 x bfloat> poison, <vscale x 1 x bfloat> [[VS2]], <vscale x 1 x i16> [[VS1]], <vscale x 1 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vv_bf16mf4_m(vbool64_t vm, vbfloat16mf4_t vs2,
+ vuint16mf4_t vs1, size_t vl) {
+ return __riscv_vrgather(vm, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vx_bf16mf4_m(
+// CHECK-RV64-SAME: <vscale x 1 x i1> [[VM:%.*]], <vscale x 1 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv1bf16.i64(<vscale x 1 x bfloat> poison, <vscale x 1 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 1 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vx_bf16mf4_m(vbool64_t vm, vbfloat16mf4_t vs2,
+ size_t vs1, size_t vl) {
+ return __riscv_vrgather(vm, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vv_bf16mf2_m(
+// CHECK-RV64-SAME: <vscale x 2 x i1> [[VM:%.*]], <vscale x 2 x bfloat> [[VS2:%.*]], <vscale x 2 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv2bf16.i64(<vscale x 2 x bfloat> poison, <vscale x 2 x bfloat> [[VS2]], <vscale x 2 x i16> [[VS1]], <vscale x 2 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vv_bf16mf2_m(vbool32_t vm, vbfloat16mf2_t vs2,
+ vuint16mf2_t vs1, size_t vl) {
+ return __riscv_vrgather(vm, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vx_bf16mf2_m(
+// CHECK-RV64-SAME: <vscale x 2 x i1> [[VM:%.*]], <vscale x 2 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv2bf16.i64(<vscale x 2 x bfloat> poison, <vscale x 2 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 2 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vx_bf16mf2_m(vbool32_t vm, vbfloat16mf2_t vs2,
+ size_t vs1, size_t vl) {
+ return __riscv_vrgather(vm, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vv_bf16m1_m(
+// CHECK-RV64-SAME: <vscale x 4 x i1> [[VM:%.*]], <vscale x 4 x bfloat> [[VS2:%.*]], <vscale x 4 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv4bf16.i64(<vscale x 4 x bfloat> poison, <vscale x 4 x bfloat> [[VS2]], <vscale x 4 x i16> [[VS1]], <vscale x 4 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vv_bf16m1_m(vbool16_t vm, vbfloat16m1_t vs2,
+ vuint16m1_t vs1, size_t vl) {
+ return __riscv_vrgather(vm, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vx_bf16m1_m(
+// CHECK-RV64-SAME: <vscale x 4 x i1> [[VM:%.*]], <vscale x 4 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv4bf16.i64(<vscale x 4 x bfloat> poison, <vscale x 4 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 4 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vx_bf16m1_m(vbool16_t vm, vbfloat16m1_t vs2,
+ size_t vs1, size_t vl) {
+ return __riscv_vrgather(vm, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vv_bf16m2_m(
+// CHECK-RV64-SAME: <vscale x 8 x i1> [[VM:%.*]], <vscale x 8 x bfloat> [[VS2:%.*]], <vscale x 8 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv8bf16.i64(<vscale x 8 x bfloat> poison, <vscale x 8 x bfloat> [[VS2]], <vscale x 8 x i16> [[VS1]], <vscale x 8 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vv_bf16m2_m(vbool8_t vm, vbfloat16m2_t vs2,
+ vuint16m2_t vs1, size_t vl) {
+ return __riscv_vrgather(vm, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vx_bf16m2_m(
+// CHECK-RV64-SAME: <vscale x 8 x i1> [[VM:%.*]], <vscale x 8 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv8bf16.i64(<vscale x 8 x bfloat> poison, <vscale x 8 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 8 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vx_bf16m2_m(vbool8_t vm, vbfloat16m2_t vs2,
+ size_t vs1, size_t vl) {
+ return __riscv_vrgather(vm, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vv_bf16m4_m(
+// CHECK-RV64-SAME: <vscale x 16 x i1> [[VM:%.*]], <vscale x 16 x bfloat> [[VS2:%.*]], <vscale x 16 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv16bf16.i64(<vscale x 16 x bfloat> poison, <vscale x 16 x bfloat> [[VS2]], <vscale x 16 x i16> [[VS1]], <vscale x 16 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vv_bf16m4_m(vbool4_t vm, vbfloat16m4_t vs2,
+ vuint16m4_t vs1, size_t vl) {
+ return __riscv_vrgather(vm, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vx_bf16m4_m(
+// CHECK-RV64-SAME: <vscale x 16 x i1> [[VM:%.*]], <vscale x 16 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv16bf16.i64(<vscale x 16 x bfloat> poison, <vscale x 16 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 16 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vx_bf16m4_m(vbool4_t vm, vbfloat16m4_t vs2,
+ size_t vs1, size_t vl) {
+ return __riscv_vrgather(vm, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vv_bf16m8_m(
+// CHECK-RV64-SAME: <vscale x 32 x i1> [[VM:%.*]], <vscale x 32 x bfloat> [[VS2:%.*]], <vscale x 32 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv32bf16.i64(<vscale x 32 x bfloat> poison, <vscale x 32 x bfloat> [[VS2]], <vscale x 32 x i16> [[VS1]], <vscale x 32 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vv_bf16m8_m(vbool2_t vm, vbfloat16m8_t vs2,
+ vuint16m8_t vs1, size_t vl) {
+ return __riscv_vrgather(vm, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vx_bf16m8_m(
+// CHECK-RV64-SAME: <vscale x 32 x i1> [[VM:%.*]], <vscale x 32 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv32bf16.i64(<vscale x 32 x bfloat> poison, <vscale x 32 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 32 x i1> [[VM]], i64 [[VL]], i64 3)
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vx_bf16m8_m(vbool2_t vm, vbfloat16m8_t vs2,
+ size_t vs1, size_t vl) {
+ return __riscv_vrgather(vm, vs2, vs1, vl);
+}
diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/non-overloaded/vcompress.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/non-overloaded/vcompress.c
new file mode 100644
index 0000000..90160c8
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/non-overloaded/vcompress.c
@@ -0,0 +1,68 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
+// REQUIRES: riscv-registered-target
+// RUN: %clang_cc1 -triple riscv64 -target-feature +zve64x \
+// RUN: -target-feature +zvfbfmin -disable-O0-optnone \
+// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \
+// RUN: FileCheck --check-prefix=CHECK-RV64 %s
+
+#include <riscv_vector.h>
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vcompress_vm_bf16mf4_tu(
+// CHECK-RV64-SAME: <vscale x 1 x bfloat> [[VD:%.*]], <vscale x 1 x bfloat> [[VS2:%.*]], <vscale x 1 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vcompress.nxv1bf16.i64(<vscale x 1 x bfloat> [[VD]], <vscale x 1 x bfloat> [[VS2]], <vscale x 1 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vcompress_vm_bf16mf4_tu(vbfloat16mf4_t vd, vbfloat16mf4_t vs2, vbool64_t vs1, size_t vl) {
+ return __riscv_vcompress_vm_bf16mf4_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vcompress_vm_bf16mf2_tu(
+// CHECK-RV64-SAME: <vscale x 2 x bfloat> [[VD:%.*]], <vscale x 2 x bfloat> [[VS2:%.*]], <vscale x 2 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vcompress.nxv2bf16.i64(<vscale x 2 x bfloat> [[VD]], <vscale x 2 x bfloat> [[VS2]], <vscale x 2 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vcompress_vm_bf16mf2_tu(vbfloat16mf2_t vd, vbfloat16mf2_t vs2, vbool32_t vs1, size_t vl) {
+ return __riscv_vcompress_vm_bf16mf2_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vcompress_vm_bf16m1_tu(
+// CHECK-RV64-SAME: <vscale x 4 x bfloat> [[VD:%.*]], <vscale x 4 x bfloat> [[VS2:%.*]], <vscale x 4 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vcompress.nxv4bf16.i64(<vscale x 4 x bfloat> [[VD]], <vscale x 4 x bfloat> [[VS2]], <vscale x 4 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vcompress_vm_bf16m1_tu(vbfloat16m1_t vd, vbfloat16m1_t vs2, vbool16_t vs1, size_t vl) {
+ return __riscv_vcompress_vm_bf16m1_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vcompress_vm_bf16m2_tu(
+// CHECK-RV64-SAME: <vscale x 8 x bfloat> [[VD:%.*]], <vscale x 8 x bfloat> [[VS2:%.*]], <vscale x 8 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vcompress.nxv8bf16.i64(<vscale x 8 x bfloat> [[VD]], <vscale x 8 x bfloat> [[VS2]], <vscale x 8 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vcompress_vm_bf16m2_tu(vbfloat16m2_t vd, vbfloat16m2_t vs2, vbool8_t vs1, size_t vl) {
+ return __riscv_vcompress_vm_bf16m2_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vcompress_vm_bf16m4_tu(
+// CHECK-RV64-SAME: <vscale x 16 x bfloat> [[VD:%.*]], <vscale x 16 x bfloat> [[VS2:%.*]], <vscale x 16 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vcompress.nxv16bf16.i64(<vscale x 16 x bfloat> [[VD]], <vscale x 16 x bfloat> [[VS2]], <vscale x 16 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vcompress_vm_bf16m4_tu(vbfloat16m4_t vd, vbfloat16m4_t vs2, vbool4_t vs1, size_t vl) {
+ return __riscv_vcompress_vm_bf16m4_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vcompress_vm_bf16m8_tu(
+// CHECK-RV64-SAME: <vscale x 32 x bfloat> [[VD:%.*]], <vscale x 32 x bfloat> [[VS2:%.*]], <vscale x 32 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vcompress.nxv32bf16.i64(<vscale x 32 x bfloat> [[VD]], <vscale x 32 x bfloat> [[VS2]], <vscale x 32 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vcompress_vm_bf16m8_tu(vbfloat16m8_t vd, vbfloat16m8_t vs2, vbool2_t vs1, size_t vl) {
+ return __riscv_vcompress_vm_bf16m8_tu(vd, vs2, vs1, vl);
+}
diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/non-overloaded/vrgather.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/non-overloaded/vrgather.c
new file mode 100644
index 0000000..137ab17
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/non-overloaded/vrgather.c
@@ -0,0 +1,488 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
+// REQUIRES: riscv-registered-target
+// RUN: %clang_cc1 -triple riscv64 -target-feature +zve64x \
+// RUN: -target-feature +zvfbfmin -disable-O0-optnone \
+// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \
+// RUN: FileCheck --check-prefix=CHECK-RV64 %s
+
+#include <riscv_vector.h>
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vv_bf16mf4_tu(
+// CHECK-RV64-SAME: <vscale x 1 x bfloat> [[VD:%.*]], <vscale x 1 x bfloat> [[VS2:%.*]], <vscale x 1 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vv.nxv1bf16.i64(<vscale x 1 x bfloat> [[VD]], <vscale x 1 x bfloat> [[VS2]], <vscale x 1 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vv_bf16mf4_tu(vbfloat16mf4_t vd, vbfloat16mf4_t vs2, vuint16mf4_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16mf4_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vx_bf16mf4_tu(
+// CHECK-RV64-SAME: <vscale x 1 x bfloat> [[VD:%.*]], <vscale x 1 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vx.nxv1bf16.i64(<vscale x 1 x bfloat> [[VD]], <vscale x 1 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vx_bf16mf4_tu(vbfloat16mf4_t vd, vbfloat16mf4_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16mf4_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vv_bf16mf2_tu(
+// CHECK-RV64-SAME: <vscale x 2 x bfloat> [[VD:%.*]], <vscale x 2 x bfloat> [[VS2:%.*]], <vscale x 2 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vv.nxv2bf16.i64(<vscale x 2 x bfloat> [[VD]], <vscale x 2 x bfloat> [[VS2]], <vscale x 2 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vv_bf16mf2_tu(vbfloat16mf2_t vd, vbfloat16mf2_t vs2, vuint16mf2_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16mf2_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vx_bf16mf2_tu(
+// CHECK-RV64-SAME: <vscale x 2 x bfloat> [[VD:%.*]], <vscale x 2 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vx.nxv2bf16.i64(<vscale x 2 x bfloat> [[VD]], <vscale x 2 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vx_bf16mf2_tu(vbfloat16mf2_t vd, vbfloat16mf2_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16mf2_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vv_bf16m1_tu(
+// CHECK-RV64-SAME: <vscale x 4 x bfloat> [[VD:%.*]], <vscale x 4 x bfloat> [[VS2:%.*]], <vscale x 4 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vv.nxv4bf16.i64(<vscale x 4 x bfloat> [[VD]], <vscale x 4 x bfloat> [[VS2]], <vscale x 4 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vv_bf16m1_tu(vbfloat16m1_t vd, vbfloat16m1_t vs2, vuint16m1_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16m1_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vx_bf16m1_tu(
+// CHECK-RV64-SAME: <vscale x 4 x bfloat> [[VD:%.*]], <vscale x 4 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vx.nxv4bf16.i64(<vscale x 4 x bfloat> [[VD]], <vscale x 4 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vx_bf16m1_tu(vbfloat16m1_t vd, vbfloat16m1_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16m1_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vv_bf16m2_tu(
+// CHECK-RV64-SAME: <vscale x 8 x bfloat> [[VD:%.*]], <vscale x 8 x bfloat> [[VS2:%.*]], <vscale x 8 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vv.nxv8bf16.i64(<vscale x 8 x bfloat> [[VD]], <vscale x 8 x bfloat> [[VS2]], <vscale x 8 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vv_bf16m2_tu(vbfloat16m2_t vd, vbfloat16m2_t vs2, vuint16m2_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16m2_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vx_bf16m2_tu(
+// CHECK-RV64-SAME: <vscale x 8 x bfloat> [[VD:%.*]], <vscale x 8 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vx.nxv8bf16.i64(<vscale x 8 x bfloat> [[VD]], <vscale x 8 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vx_bf16m2_tu(vbfloat16m2_t vd, vbfloat16m2_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16m2_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vv_bf16m4_tu(
+// CHECK-RV64-SAME: <vscale x 16 x bfloat> [[VD:%.*]], <vscale x 16 x bfloat> [[VS2:%.*]], <vscale x 16 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vv.nxv16bf16.i64(<vscale x 16 x bfloat> [[VD]], <vscale x 16 x bfloat> [[VS2]], <vscale x 16 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vv_bf16m4_tu(vbfloat16m4_t vd, vbfloat16m4_t vs2, vuint16m4_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16m4_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vx_bf16m4_tu(
+// CHECK-RV64-SAME: <vscale x 16 x bfloat> [[VD:%.*]], <vscale x 16 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vx.nxv16bf16.i64(<vscale x 16 x bfloat> [[VD]], <vscale x 16 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vx_bf16m4_tu(vbfloat16m4_t vd, vbfloat16m4_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16m4_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vv_bf16m8_tu(
+// CHECK-RV64-SAME: <vscale x 32 x bfloat> [[VD:%.*]], <vscale x 32 x bfloat> [[VS2:%.*]], <vscale x 32 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vv.nxv32bf16.i64(<vscale x 32 x bfloat> [[VD]], <vscale x 32 x bfloat> [[VS2]], <vscale x 32 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vv_bf16m8_tu(vbfloat16m8_t vd, vbfloat16m8_t vs2, vuint16m8_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16m8_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vx_bf16m8_tu(
+// CHECK-RV64-SAME: <vscale x 32 x bfloat> [[VD:%.*]], <vscale x 32 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vx.nxv32bf16.i64(<vscale x 32 x bfloat> [[VD]], <vscale x 32 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vx_bf16m8_tu(vbfloat16m8_t vd, vbfloat16m8_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16m8_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vv_bf16mf4_tum(
+// CHECK-RV64-SAME: <vscale x 1 x i1> [[VM:%.*]], <vscale x 1 x bfloat> [[VD:%.*]], <vscale x 1 x bfloat> [[VS2:%.*]], <vscale x 1 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv1bf16.i64(<vscale x 1 x bfloat> [[VD]], <vscale x 1 x bfloat> [[VS2]], <vscale x 1 x i16> [[VS1]], <vscale x 1 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vv_bf16mf4_tum(vbool64_t vm, vbfloat16mf4_t vd, vbfloat16mf4_t vs2, vuint16mf4_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16mf4_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vx_bf16mf4_tum(
+// CHECK-RV64-SAME: <vscale x 1 x i1> [[VM:%.*]], <vscale x 1 x bfloat> [[VD:%.*]], <vscale x 1 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv1bf16.i64(<vscale x 1 x bfloat> [[VD]], <vscale x 1 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 1 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vx_bf16mf4_tum(vbool64_t vm, vbfloat16mf4_t vd, vbfloat16mf4_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16mf4_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vv_bf16mf2_tum(
+// CHECK-RV64-SAME: <vscale x 2 x i1> [[VM:%.*]], <vscale x 2 x bfloat> [[VD:%.*]], <vscale x 2 x bfloat> [[VS2:%.*]], <vscale x 2 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv2bf16.i64(<vscale x 2 x bfloat> [[VD]], <vscale x 2 x bfloat> [[VS2]], <vscale x 2 x i16> [[VS1]], <vscale x 2 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vv_bf16mf2_tum(vbool32_t vm, vbfloat16mf2_t vd, vbfloat16mf2_t vs2, vuint16mf2_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16mf2_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vx_bf16mf2_tum(
+// CHECK-RV64-SAME: <vscale x 2 x i1> [[VM:%.*]], <vscale x 2 x bfloat> [[VD:%.*]], <vscale x 2 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv2bf16.i64(<vscale x 2 x bfloat> [[VD]], <vscale x 2 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 2 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vx_bf16mf2_tum(vbool32_t vm, vbfloat16mf2_t vd, vbfloat16mf2_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16mf2_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vv_bf16m1_tum(
+// CHECK-RV64-SAME: <vscale x 4 x i1> [[VM:%.*]], <vscale x 4 x bfloat> [[VD:%.*]], <vscale x 4 x bfloat> [[VS2:%.*]], <vscale x 4 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv4bf16.i64(<vscale x 4 x bfloat> [[VD]], <vscale x 4 x bfloat> [[VS2]], <vscale x 4 x i16> [[VS1]], <vscale x 4 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vv_bf16m1_tum(vbool16_t vm, vbfloat16m1_t vd, vbfloat16m1_t vs2, vuint16m1_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16m1_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vx_bf16m1_tum(
+// CHECK-RV64-SAME: <vscale x 4 x i1> [[VM:%.*]], <vscale x 4 x bfloat> [[VD:%.*]], <vscale x 4 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv4bf16.i64(<vscale x 4 x bfloat> [[VD]], <vscale x 4 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 4 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vx_bf16m1_tum(vbool16_t vm, vbfloat16m1_t vd, vbfloat16m1_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16m1_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vv_bf16m2_tum(
+// CHECK-RV64-SAME: <vscale x 8 x i1> [[VM:%.*]], <vscale x 8 x bfloat> [[VD:%.*]], <vscale x 8 x bfloat> [[VS2:%.*]], <vscale x 8 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv8bf16.i64(<vscale x 8 x bfloat> [[VD]], <vscale x 8 x bfloat> [[VS2]], <vscale x 8 x i16> [[VS1]], <vscale x 8 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vv_bf16m2_tum(vbool8_t vm, vbfloat16m2_t vd, vbfloat16m2_t vs2, vuint16m2_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16m2_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vx_bf16m2_tum(
+// CHECK-RV64-SAME: <vscale x 8 x i1> [[VM:%.*]], <vscale x 8 x bfloat> [[VD:%.*]], <vscale x 8 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv8bf16.i64(<vscale x 8 x bfloat> [[VD]], <vscale x 8 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 8 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vx_bf16m2_tum(vbool8_t vm, vbfloat16m2_t vd, vbfloat16m2_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16m2_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vv_bf16m4_tum(
+// CHECK-RV64-SAME: <vscale x 16 x i1> [[VM:%.*]], <vscale x 16 x bfloat> [[VD:%.*]], <vscale x 16 x bfloat> [[VS2:%.*]], <vscale x 16 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv16bf16.i64(<vscale x 16 x bfloat> [[VD]], <vscale x 16 x bfloat> [[VS2]], <vscale x 16 x i16> [[VS1]], <vscale x 16 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vv_bf16m4_tum(vbool4_t vm, vbfloat16m4_t vd, vbfloat16m4_t vs2, vuint16m4_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16m4_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vx_bf16m4_tum(
+// CHECK-RV64-SAME: <vscale x 16 x i1> [[VM:%.*]], <vscale x 16 x bfloat> [[VD:%.*]], <vscale x 16 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv16bf16.i64(<vscale x 16 x bfloat> [[VD]], <vscale x 16 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 16 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vx_bf16m4_tum(vbool4_t vm, vbfloat16m4_t vd, vbfloat16m4_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16m4_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vv_bf16m8_tum(
+// CHECK-RV64-SAME: <vscale x 32 x i1> [[VM:%.*]], <vscale x 32 x bfloat> [[VD:%.*]], <vscale x 32 x bfloat> [[VS2:%.*]], <vscale x 32 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv32bf16.i64(<vscale x 32 x bfloat> [[VD]], <vscale x 32 x bfloat> [[VS2]], <vscale x 32 x i16> [[VS1]], <vscale x 32 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vv_bf16m8_tum(vbool2_t vm, vbfloat16m8_t vd, vbfloat16m8_t vs2, vuint16m8_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16m8_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vx_bf16m8_tum(
+// CHECK-RV64-SAME: <vscale x 32 x i1> [[VM:%.*]], <vscale x 32 x bfloat> [[VD:%.*]], <vscale x 32 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv32bf16.i64(<vscale x 32 x bfloat> [[VD]], <vscale x 32 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 32 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vx_bf16m8_tum(vbool2_t vm, vbfloat16m8_t vd, vbfloat16m8_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16m8_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vv_bf16mf4_tumu(
+// CHECK-RV64-SAME: <vscale x 1 x i1> [[VM:%.*]], <vscale x 1 x bfloat> [[VD:%.*]], <vscale x 1 x bfloat> [[VS2:%.*]], <vscale x 1 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv1bf16.i64(<vscale x 1 x bfloat> [[VD]], <vscale x 1 x bfloat> [[VS2]], <vscale x 1 x i16> [[VS1]], <vscale x 1 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vv_bf16mf4_tumu(vbool64_t vm, vbfloat16mf4_t vd, vbfloat16mf4_t vs2, vuint16mf4_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16mf4_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vx_bf16mf4_tumu(
+// CHECK-RV64-SAME: <vscale x 1 x i1> [[VM:%.*]], <vscale x 1 x bfloat> [[VD:%.*]], <vscale x 1 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv1bf16.i64(<vscale x 1 x bfloat> [[VD]], <vscale x 1 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 1 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vx_bf16mf4_tumu(vbool64_t vm, vbfloat16mf4_t vd, vbfloat16mf4_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16mf4_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vv_bf16mf2_tumu(
+// CHECK-RV64-SAME: <vscale x 2 x i1> [[VM:%.*]], <vscale x 2 x bfloat> [[VD:%.*]], <vscale x 2 x bfloat> [[VS2:%.*]], <vscale x 2 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv2bf16.i64(<vscale x 2 x bfloat> [[VD]], <vscale x 2 x bfloat> [[VS2]], <vscale x 2 x i16> [[VS1]], <vscale x 2 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vv_bf16mf2_tumu(vbool32_t vm, vbfloat16mf2_t vd, vbfloat16mf2_t vs2, vuint16mf2_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16mf2_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vx_bf16mf2_tumu(
+// CHECK-RV64-SAME: <vscale x 2 x i1> [[VM:%.*]], <vscale x 2 x bfloat> [[VD:%.*]], <vscale x 2 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv2bf16.i64(<vscale x 2 x bfloat> [[VD]], <vscale x 2 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 2 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vx_bf16mf2_tumu(vbool32_t vm, vbfloat16mf2_t vd, vbfloat16mf2_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16mf2_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vv_bf16m1_tumu(
+// CHECK-RV64-SAME: <vscale x 4 x i1> [[VM:%.*]], <vscale x 4 x bfloat> [[VD:%.*]], <vscale x 4 x bfloat> [[VS2:%.*]], <vscale x 4 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv4bf16.i64(<vscale x 4 x bfloat> [[VD]], <vscale x 4 x bfloat> [[VS2]], <vscale x 4 x i16> [[VS1]], <vscale x 4 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vv_bf16m1_tumu(vbool16_t vm, vbfloat16m1_t vd, vbfloat16m1_t vs2, vuint16m1_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16m1_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vx_bf16m1_tumu(
+// CHECK-RV64-SAME: <vscale x 4 x i1> [[VM:%.*]], <vscale x 4 x bfloat> [[VD:%.*]], <vscale x 4 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv4bf16.i64(<vscale x 4 x bfloat> [[VD]], <vscale x 4 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 4 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vx_bf16m1_tumu(vbool16_t vm, vbfloat16m1_t vd, vbfloat16m1_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16m1_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vv_bf16m2_tumu(
+// CHECK-RV64-SAME: <vscale x 8 x i1> [[VM:%.*]], <vscale x 8 x bfloat> [[VD:%.*]], <vscale x 8 x bfloat> [[VS2:%.*]], <vscale x 8 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv8bf16.i64(<vscale x 8 x bfloat> [[VD]], <vscale x 8 x bfloat> [[VS2]], <vscale x 8 x i16> [[VS1]], <vscale x 8 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vv_bf16m2_tumu(vbool8_t vm, vbfloat16m2_t vd, vbfloat16m2_t vs2, vuint16m2_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16m2_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vx_bf16m2_tumu(
+// CHECK-RV64-SAME: <vscale x 8 x i1> [[VM:%.*]], <vscale x 8 x bfloat> [[VD:%.*]], <vscale x 8 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv8bf16.i64(<vscale x 8 x bfloat> [[VD]], <vscale x 8 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 8 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vx_bf16m2_tumu(vbool8_t vm, vbfloat16m2_t vd, vbfloat16m2_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16m2_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vv_bf16m4_tumu(
+// CHECK-RV64-SAME: <vscale x 16 x i1> [[VM:%.*]], <vscale x 16 x bfloat> [[VD:%.*]], <vscale x 16 x bfloat> [[VS2:%.*]], <vscale x 16 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv16bf16.i64(<vscale x 16 x bfloat> [[VD]], <vscale x 16 x bfloat> [[VS2]], <vscale x 16 x i16> [[VS1]], <vscale x 16 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vv_bf16m4_tumu(vbool4_t vm, vbfloat16m4_t vd, vbfloat16m4_t vs2, vuint16m4_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16m4_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vx_bf16m4_tumu(
+// CHECK-RV64-SAME: <vscale x 16 x i1> [[VM:%.*]], <vscale x 16 x bfloat> [[VD:%.*]], <vscale x 16 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv16bf16.i64(<vscale x 16 x bfloat> [[VD]], <vscale x 16 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 16 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vx_bf16m4_tumu(vbool4_t vm, vbfloat16m4_t vd, vbfloat16m4_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16m4_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vv_bf16m8_tumu(
+// CHECK-RV64-SAME: <vscale x 32 x i1> [[VM:%.*]], <vscale x 32 x bfloat> [[VD:%.*]], <vscale x 32 x bfloat> [[VS2:%.*]], <vscale x 32 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv32bf16.i64(<vscale x 32 x bfloat> [[VD]], <vscale x 32 x bfloat> [[VS2]], <vscale x 32 x i16> [[VS1]], <vscale x 32 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vv_bf16m8_tumu(vbool2_t vm, vbfloat16m8_t vd, vbfloat16m8_t vs2, vuint16m8_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16m8_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vx_bf16m8_tumu(
+// CHECK-RV64-SAME: <vscale x 32 x i1> [[VM:%.*]], <vscale x 32 x bfloat> [[VD:%.*]], <vscale x 32 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv32bf16.i64(<vscale x 32 x bfloat> [[VD]], <vscale x 32 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 32 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vx_bf16m8_tumu(vbool2_t vm, vbfloat16m8_t vd, vbfloat16m8_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16m8_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vv_bf16mf4_mu(
+// CHECK-RV64-SAME: <vscale x 1 x i1> [[VM:%.*]], <vscale x 1 x bfloat> [[VD:%.*]], <vscale x 1 x bfloat> [[VS2:%.*]], <vscale x 1 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv1bf16.i64(<vscale x 1 x bfloat> [[VD]], <vscale x 1 x bfloat> [[VS2]], <vscale x 1 x i16> [[VS1]], <vscale x 1 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vv_bf16mf4_mu(vbool64_t vm, vbfloat16mf4_t vd, vbfloat16mf4_t vs2, vuint16mf4_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16mf4_mu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vx_bf16mf4_mu(
+// CHECK-RV64-SAME: <vscale x 1 x i1> [[VM:%.*]], <vscale x 1 x bfloat> [[VD:%.*]], <vscale x 1 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv1bf16.i64(<vscale x 1 x bfloat> [[VD]], <vscale x 1 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 1 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vx_bf16mf4_mu(vbool64_t vm, vbfloat16mf4_t vd, vbfloat16mf4_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16mf4_mu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vv_bf16mf2_mu(
+// CHECK-RV64-SAME: <vscale x 2 x i1> [[VM:%.*]], <vscale x 2 x bfloat> [[VD:%.*]], <vscale x 2 x bfloat> [[VS2:%.*]], <vscale x 2 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv2bf16.i64(<vscale x 2 x bfloat> [[VD]], <vscale x 2 x bfloat> [[VS2]], <vscale x 2 x i16> [[VS1]], <vscale x 2 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vv_bf16mf2_mu(vbool32_t vm, vbfloat16mf2_t vd, vbfloat16mf2_t vs2, vuint16mf2_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16mf2_mu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vx_bf16mf2_mu(
+// CHECK-RV64-SAME: <vscale x 2 x i1> [[VM:%.*]], <vscale x 2 x bfloat> [[VD:%.*]], <vscale x 2 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv2bf16.i64(<vscale x 2 x bfloat> [[VD]], <vscale x 2 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 2 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vx_bf16mf2_mu(vbool32_t vm, vbfloat16mf2_t vd, vbfloat16mf2_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16mf2_mu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vv_bf16m1_mu(
+// CHECK-RV64-SAME: <vscale x 4 x i1> [[VM:%.*]], <vscale x 4 x bfloat> [[VD:%.*]], <vscale x 4 x bfloat> [[VS2:%.*]], <vscale x 4 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv4bf16.i64(<vscale x 4 x bfloat> [[VD]], <vscale x 4 x bfloat> [[VS2]], <vscale x 4 x i16> [[VS1]], <vscale x 4 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vv_bf16m1_mu(vbool16_t vm, vbfloat16m1_t vd, vbfloat16m1_t vs2, vuint16m1_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16m1_mu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vx_bf16m1_mu(
+// CHECK-RV64-SAME: <vscale x 4 x i1> [[VM:%.*]], <vscale x 4 x bfloat> [[VD:%.*]], <vscale x 4 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv4bf16.i64(<vscale x 4 x bfloat> [[VD]], <vscale x 4 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 4 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vx_bf16m1_mu(vbool16_t vm, vbfloat16m1_t vd, vbfloat16m1_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16m1_mu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vv_bf16m2_mu(
+// CHECK-RV64-SAME: <vscale x 8 x i1> [[VM:%.*]], <vscale x 8 x bfloat> [[VD:%.*]], <vscale x 8 x bfloat> [[VS2:%.*]], <vscale x 8 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv8bf16.i64(<vscale x 8 x bfloat> [[VD]], <vscale x 8 x bfloat> [[VS2]], <vscale x 8 x i16> [[VS1]], <vscale x 8 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vv_bf16m2_mu(vbool8_t vm, vbfloat16m2_t vd, vbfloat16m2_t vs2, vuint16m2_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16m2_mu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vx_bf16m2_mu(
+// CHECK-RV64-SAME: <vscale x 8 x i1> [[VM:%.*]], <vscale x 8 x bfloat> [[VD:%.*]], <vscale x 8 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv8bf16.i64(<vscale x 8 x bfloat> [[VD]], <vscale x 8 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 8 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vx_bf16m2_mu(vbool8_t vm, vbfloat16m2_t vd, vbfloat16m2_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16m2_mu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vv_bf16m4_mu(
+// CHECK-RV64-SAME: <vscale x 16 x i1> [[VM:%.*]], <vscale x 16 x bfloat> [[VD:%.*]], <vscale x 16 x bfloat> [[VS2:%.*]], <vscale x 16 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv16bf16.i64(<vscale x 16 x bfloat> [[VD]], <vscale x 16 x bfloat> [[VS2]], <vscale x 16 x i16> [[VS1]], <vscale x 16 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vv_bf16m4_mu(vbool4_t vm, vbfloat16m4_t vd, vbfloat16m4_t vs2, vuint16m4_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16m4_mu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vx_bf16m4_mu(
+// CHECK-RV64-SAME: <vscale x 16 x i1> [[VM:%.*]], <vscale x 16 x bfloat> [[VD:%.*]], <vscale x 16 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv16bf16.i64(<vscale x 16 x bfloat> [[VD]], <vscale x 16 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 16 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vx_bf16m4_mu(vbool4_t vm, vbfloat16m4_t vd, vbfloat16m4_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16m4_mu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vv_bf16m8_mu(
+// CHECK-RV64-SAME: <vscale x 32 x i1> [[VM:%.*]], <vscale x 32 x bfloat> [[VD:%.*]], <vscale x 32 x bfloat> [[VS2:%.*]], <vscale x 32 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv32bf16.i64(<vscale x 32 x bfloat> [[VD]], <vscale x 32 x bfloat> [[VS2]], <vscale x 32 x i16> [[VS1]], <vscale x 32 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vv_bf16m8_mu(vbool2_t vm, vbfloat16m8_t vd, vbfloat16m8_t vs2, vuint16m8_t vs1, size_t vl) {
+ return __riscv_vrgather_vv_bf16m8_mu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vx_bf16m8_mu(
+// CHECK-RV64-SAME: <vscale x 32 x i1> [[VM:%.*]], <vscale x 32 x bfloat> [[VD:%.*]], <vscale x 32 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv32bf16.i64(<vscale x 32 x bfloat> [[VD]], <vscale x 32 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 32 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vx_bf16m8_mu(vbool2_t vm, vbfloat16m8_t vd, vbfloat16m8_t vs2, size_t vs1, size_t vl) {
+ return __riscv_vrgather_vx_bf16m8_mu(vm, vd, vs2, vs1, vl);
+}
diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/overloaded/vcompress.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/overloaded/vcompress.c
new file mode 100644
index 0000000..079977a
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/overloaded/vcompress.c
@@ -0,0 +1,76 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
+// REQUIRES: riscv-registered-target
+// RUN: %clang_cc1 -triple riscv64 -target-feature +zve64x \
+// RUN: -target-feature +zvfbfmin -disable-O0-optnone \
+// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \
+// RUN: FileCheck --check-prefix=CHECK-RV64 %s
+
+#include <riscv_vector.h>
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vcompress_vm_bf16mf4_tu(
+// CHECK-RV64-SAME: <vscale x 1 x bfloat> [[VD:%.*]], <vscale x 1 x bfloat> [[VS2:%.*]], <vscale x 1 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vcompress.nxv1bf16.i64(<vscale x 1 x bfloat> [[VD]], <vscale x 1 x bfloat> [[VS2]], <vscale x 1 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vcompress_vm_bf16mf4_tu(vbfloat16mf4_t vd,
+ vbfloat16mf4_t vs2, vbool64_t vs1,
+ size_t vl) {
+ return __riscv_vcompress_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vcompress_vm_bf16mf2_tu(
+// CHECK-RV64-SAME: <vscale x 2 x bfloat> [[VD:%.*]], <vscale x 2 x bfloat> [[VS2:%.*]], <vscale x 2 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vcompress.nxv2bf16.i64(<vscale x 2 x bfloat> [[VD]], <vscale x 2 x bfloat> [[VS2]], <vscale x 2 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vcompress_vm_bf16mf2_tu(vbfloat16mf2_t vd,
+ vbfloat16mf2_t vs2, vbool32_t vs1,
+ size_t vl) {
+ return __riscv_vcompress_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vcompress_vm_bf16m1_tu(
+// CHECK-RV64-SAME: <vscale x 4 x bfloat> [[VD:%.*]], <vscale x 4 x bfloat> [[VS2:%.*]], <vscale x 4 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vcompress.nxv4bf16.i64(<vscale x 4 x bfloat> [[VD]], <vscale x 4 x bfloat> [[VS2]], <vscale x 4 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vcompress_vm_bf16m1_tu(vbfloat16m1_t vd, vbfloat16m1_t vs2,
+ vbool16_t vs1, size_t vl) {
+ return __riscv_vcompress_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vcompress_vm_bf16m2_tu(
+// CHECK-RV64-SAME: <vscale x 8 x bfloat> [[VD:%.*]], <vscale x 8 x bfloat> [[VS2:%.*]], <vscale x 8 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vcompress.nxv8bf16.i64(<vscale x 8 x bfloat> [[VD]], <vscale x 8 x bfloat> [[VS2]], <vscale x 8 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vcompress_vm_bf16m2_tu(vbfloat16m2_t vd, vbfloat16m2_t vs2,
+ vbool8_t vs1, size_t vl) {
+ return __riscv_vcompress_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vcompress_vm_bf16m4_tu(
+// CHECK-RV64-SAME: <vscale x 16 x bfloat> [[VD:%.*]], <vscale x 16 x bfloat> [[VS2:%.*]], <vscale x 16 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vcompress.nxv16bf16.i64(<vscale x 16 x bfloat> [[VD]], <vscale x 16 x bfloat> [[VS2]], <vscale x 16 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vcompress_vm_bf16m4_tu(vbfloat16m4_t vd, vbfloat16m4_t vs2,
+ vbool4_t vs1, size_t vl) {
+ return __riscv_vcompress_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vcompress_vm_bf16m8_tu(
+// CHECK-RV64-SAME: <vscale x 32 x bfloat> [[VD:%.*]], <vscale x 32 x bfloat> [[VS2:%.*]], <vscale x 32 x i1> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vcompress.nxv32bf16.i64(<vscale x 32 x bfloat> [[VD]], <vscale x 32 x bfloat> [[VS2]], <vscale x 32 x i1> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vcompress_vm_bf16m8_tu(vbfloat16m8_t vd, vbfloat16m8_t vs2,
+ vbool2_t vs1, size_t vl) {
+ return __riscv_vcompress_tu(vd, vs2, vs1, vl);
+}
diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/overloaded/vrgather.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/overloaded/vrgather.c
new file mode 100644
index 0000000..7a5624a
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-autogenerated/zvfbfmin/policy/overloaded/vrgather.c
@@ -0,0 +1,576 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
+// REQUIRES: riscv-registered-target
+// RUN: %clang_cc1 -triple riscv64 -target-feature +zve64x \
+// RUN: -target-feature +zvfbfmin -disable-O0-optnone \
+// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \
+// RUN: FileCheck --check-prefix=CHECK-RV64 %s
+
+#include <riscv_vector.h>
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vv_bf16mf4_tu(
+// CHECK-RV64-SAME: <vscale x 1 x bfloat> [[VD:%.*]], <vscale x 1 x bfloat> [[VS2:%.*]], <vscale x 1 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vv.nxv1bf16.i64(<vscale x 1 x bfloat> [[VD]], <vscale x 1 x bfloat> [[VS2]], <vscale x 1 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vv_bf16mf4_tu(vbfloat16mf4_t vd,
+ vbfloat16mf4_t vs2, vuint16mf4_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vx_bf16mf4_tu(
+// CHECK-RV64-SAME: <vscale x 1 x bfloat> [[VD:%.*]], <vscale x 1 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vx.nxv1bf16.i64(<vscale x 1 x bfloat> [[VD]], <vscale x 1 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vx_bf16mf4_tu(vbfloat16mf4_t vd,
+ vbfloat16mf4_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vv_bf16mf2_tu(
+// CHECK-RV64-SAME: <vscale x 2 x bfloat> [[VD:%.*]], <vscale x 2 x bfloat> [[VS2:%.*]], <vscale x 2 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vv.nxv2bf16.i64(<vscale x 2 x bfloat> [[VD]], <vscale x 2 x bfloat> [[VS2]], <vscale x 2 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vv_bf16mf2_tu(vbfloat16mf2_t vd,
+ vbfloat16mf2_t vs2, vuint16mf2_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vx_bf16mf2_tu(
+// CHECK-RV64-SAME: <vscale x 2 x bfloat> [[VD:%.*]], <vscale x 2 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vx.nxv2bf16.i64(<vscale x 2 x bfloat> [[VD]], <vscale x 2 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vx_bf16mf2_tu(vbfloat16mf2_t vd,
+ vbfloat16mf2_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vv_bf16m1_tu(
+// CHECK-RV64-SAME: <vscale x 4 x bfloat> [[VD:%.*]], <vscale x 4 x bfloat> [[VS2:%.*]], <vscale x 4 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vv.nxv4bf16.i64(<vscale x 4 x bfloat> [[VD]], <vscale x 4 x bfloat> [[VS2]], <vscale x 4 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vv_bf16m1_tu(vbfloat16m1_t vd, vbfloat16m1_t vs2,
+ vuint16m1_t vs1, size_t vl) {
+ return __riscv_vrgather_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vx_bf16m1_tu(
+// CHECK-RV64-SAME: <vscale x 4 x bfloat> [[VD:%.*]], <vscale x 4 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vx.nxv4bf16.i64(<vscale x 4 x bfloat> [[VD]], <vscale x 4 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vx_bf16m1_tu(vbfloat16m1_t vd, vbfloat16m1_t vs2,
+ size_t vs1, size_t vl) {
+ return __riscv_vrgather_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vv_bf16m2_tu(
+// CHECK-RV64-SAME: <vscale x 8 x bfloat> [[VD:%.*]], <vscale x 8 x bfloat> [[VS2:%.*]], <vscale x 8 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vv.nxv8bf16.i64(<vscale x 8 x bfloat> [[VD]], <vscale x 8 x bfloat> [[VS2]], <vscale x 8 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vv_bf16m2_tu(vbfloat16m2_t vd, vbfloat16m2_t vs2,
+ vuint16m2_t vs1, size_t vl) {
+ return __riscv_vrgather_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vx_bf16m2_tu(
+// CHECK-RV64-SAME: <vscale x 8 x bfloat> [[VD:%.*]], <vscale x 8 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vx.nxv8bf16.i64(<vscale x 8 x bfloat> [[VD]], <vscale x 8 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vx_bf16m2_tu(vbfloat16m2_t vd, vbfloat16m2_t vs2,
+ size_t vs1, size_t vl) {
+ return __riscv_vrgather_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vv_bf16m4_tu(
+// CHECK-RV64-SAME: <vscale x 16 x bfloat> [[VD:%.*]], <vscale x 16 x bfloat> [[VS2:%.*]], <vscale x 16 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vv.nxv16bf16.i64(<vscale x 16 x bfloat> [[VD]], <vscale x 16 x bfloat> [[VS2]], <vscale x 16 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vv_bf16m4_tu(vbfloat16m4_t vd, vbfloat16m4_t vs2,
+ vuint16m4_t vs1, size_t vl) {
+ return __riscv_vrgather_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vx_bf16m4_tu(
+// CHECK-RV64-SAME: <vscale x 16 x bfloat> [[VD:%.*]], <vscale x 16 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vx.nxv16bf16.i64(<vscale x 16 x bfloat> [[VD]], <vscale x 16 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vx_bf16m4_tu(vbfloat16m4_t vd, vbfloat16m4_t vs2,
+ size_t vs1, size_t vl) {
+ return __riscv_vrgather_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vv_bf16m8_tu(
+// CHECK-RV64-SAME: <vscale x 32 x bfloat> [[VD:%.*]], <vscale x 32 x bfloat> [[VS2:%.*]], <vscale x 32 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vv.nxv32bf16.i64(<vscale x 32 x bfloat> [[VD]], <vscale x 32 x bfloat> [[VS2]], <vscale x 32 x i16> [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vv_bf16m8_tu(vbfloat16m8_t vd, vbfloat16m8_t vs2,
+ vuint16m8_t vs1, size_t vl) {
+ return __riscv_vrgather_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vx_bf16m8_tu(
+// CHECK-RV64-SAME: <vscale x 32 x bfloat> [[VD:%.*]], <vscale x 32 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vx.nxv32bf16.i64(<vscale x 32 x bfloat> [[VD]], <vscale x 32 x bfloat> [[VS2]], i64 [[VS1]], i64 [[VL]])
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vx_bf16m8_tu(vbfloat16m8_t vd, vbfloat16m8_t vs2,
+ size_t vs1, size_t vl) {
+ return __riscv_vrgather_tu(vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vv_bf16mf4_tum(
+// CHECK-RV64-SAME: <vscale x 1 x i1> [[VM:%.*]], <vscale x 1 x bfloat> [[VD:%.*]], <vscale x 1 x bfloat> [[VS2:%.*]], <vscale x 1 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv1bf16.i64(<vscale x 1 x bfloat> [[VD]], <vscale x 1 x bfloat> [[VS2]], <vscale x 1 x i16> [[VS1]], <vscale x 1 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vv_bf16mf4_tum(vbool64_t vm, vbfloat16mf4_t vd,
+ vbfloat16mf4_t vs2,
+ vuint16mf4_t vs1, size_t vl) {
+ return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vx_bf16mf4_tum(
+// CHECK-RV64-SAME: <vscale x 1 x i1> [[VM:%.*]], <vscale x 1 x bfloat> [[VD:%.*]], <vscale x 1 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv1bf16.i64(<vscale x 1 x bfloat> [[VD]], <vscale x 1 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 1 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vx_bf16mf4_tum(vbool64_t vm, vbfloat16mf4_t vd,
+ vbfloat16mf4_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vv_bf16mf2_tum(
+// CHECK-RV64-SAME: <vscale x 2 x i1> [[VM:%.*]], <vscale x 2 x bfloat> [[VD:%.*]], <vscale x 2 x bfloat> [[VS2:%.*]], <vscale x 2 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv2bf16.i64(<vscale x 2 x bfloat> [[VD]], <vscale x 2 x bfloat> [[VS2]], <vscale x 2 x i16> [[VS1]], <vscale x 2 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vv_bf16mf2_tum(vbool32_t vm, vbfloat16mf2_t vd,
+ vbfloat16mf2_t vs2,
+ vuint16mf2_t vs1, size_t vl) {
+ return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vx_bf16mf2_tum(
+// CHECK-RV64-SAME: <vscale x 2 x i1> [[VM:%.*]], <vscale x 2 x bfloat> [[VD:%.*]], <vscale x 2 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv2bf16.i64(<vscale x 2 x bfloat> [[VD]], <vscale x 2 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 2 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vx_bf16mf2_tum(vbool32_t vm, vbfloat16mf2_t vd,
+ vbfloat16mf2_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vv_bf16m1_tum(
+// CHECK-RV64-SAME: <vscale x 4 x i1> [[VM:%.*]], <vscale x 4 x bfloat> [[VD:%.*]], <vscale x 4 x bfloat> [[VS2:%.*]], <vscale x 4 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv4bf16.i64(<vscale x 4 x bfloat> [[VD]], <vscale x 4 x bfloat> [[VS2]], <vscale x 4 x i16> [[VS1]], <vscale x 4 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vv_bf16m1_tum(vbool16_t vm, vbfloat16m1_t vd,
+ vbfloat16m1_t vs2, vuint16m1_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vx_bf16m1_tum(
+// CHECK-RV64-SAME: <vscale x 4 x i1> [[VM:%.*]], <vscale x 4 x bfloat> [[VD:%.*]], <vscale x 4 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv4bf16.i64(<vscale x 4 x bfloat> [[VD]], <vscale x 4 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 4 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vx_bf16m1_tum(vbool16_t vm, vbfloat16m1_t vd,
+ vbfloat16m1_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vv_bf16m2_tum(
+// CHECK-RV64-SAME: <vscale x 8 x i1> [[VM:%.*]], <vscale x 8 x bfloat> [[VD:%.*]], <vscale x 8 x bfloat> [[VS2:%.*]], <vscale x 8 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv8bf16.i64(<vscale x 8 x bfloat> [[VD]], <vscale x 8 x bfloat> [[VS2]], <vscale x 8 x i16> [[VS1]], <vscale x 8 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vv_bf16m2_tum(vbool8_t vm, vbfloat16m2_t vd,
+ vbfloat16m2_t vs2, vuint16m2_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vx_bf16m2_tum(
+// CHECK-RV64-SAME: <vscale x 8 x i1> [[VM:%.*]], <vscale x 8 x bfloat> [[VD:%.*]], <vscale x 8 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv8bf16.i64(<vscale x 8 x bfloat> [[VD]], <vscale x 8 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 8 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vx_bf16m2_tum(vbool8_t vm, vbfloat16m2_t vd,
+ vbfloat16m2_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vv_bf16m4_tum(
+// CHECK-RV64-SAME: <vscale x 16 x i1> [[VM:%.*]], <vscale x 16 x bfloat> [[VD:%.*]], <vscale x 16 x bfloat> [[VS2:%.*]], <vscale x 16 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv16bf16.i64(<vscale x 16 x bfloat> [[VD]], <vscale x 16 x bfloat> [[VS2]], <vscale x 16 x i16> [[VS1]], <vscale x 16 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vv_bf16m4_tum(vbool4_t vm, vbfloat16m4_t vd,
+ vbfloat16m4_t vs2, vuint16m4_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vx_bf16m4_tum(
+// CHECK-RV64-SAME: <vscale x 16 x i1> [[VM:%.*]], <vscale x 16 x bfloat> [[VD:%.*]], <vscale x 16 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv16bf16.i64(<vscale x 16 x bfloat> [[VD]], <vscale x 16 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 16 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vx_bf16m4_tum(vbool4_t vm, vbfloat16m4_t vd,
+ vbfloat16m4_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vv_bf16m8_tum(
+// CHECK-RV64-SAME: <vscale x 32 x i1> [[VM:%.*]], <vscale x 32 x bfloat> [[VD:%.*]], <vscale x 32 x bfloat> [[VS2:%.*]], <vscale x 32 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv32bf16.i64(<vscale x 32 x bfloat> [[VD]], <vscale x 32 x bfloat> [[VS2]], <vscale x 32 x i16> [[VS1]], <vscale x 32 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vv_bf16m8_tum(vbool2_t vm, vbfloat16m8_t vd,
+ vbfloat16m8_t vs2, vuint16m8_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vx_bf16m8_tum(
+// CHECK-RV64-SAME: <vscale x 32 x i1> [[VM:%.*]], <vscale x 32 x bfloat> [[VD:%.*]], <vscale x 32 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv32bf16.i64(<vscale x 32 x bfloat> [[VD]], <vscale x 32 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 32 x i1> [[VM]], i64 [[VL]], i64 2)
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vx_bf16m8_tum(vbool2_t vm, vbfloat16m8_t vd,
+ vbfloat16m8_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tum(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vv_bf16mf4_tumu(
+// CHECK-RV64-SAME: <vscale x 1 x i1> [[VM:%.*]], <vscale x 1 x bfloat> [[VD:%.*]], <vscale x 1 x bfloat> [[VS2:%.*]], <vscale x 1 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv1bf16.i64(<vscale x 1 x bfloat> [[VD]], <vscale x 1 x bfloat> [[VS2]], <vscale x 1 x i16> [[VS1]], <vscale x 1 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vv_bf16mf4_tumu(vbool64_t vm, vbfloat16mf4_t vd,
+ vbfloat16mf4_t vs2,
+ vuint16mf4_t vs1, size_t vl) {
+ return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vx_bf16mf4_tumu(
+// CHECK-RV64-SAME: <vscale x 1 x i1> [[VM:%.*]], <vscale x 1 x bfloat> [[VD:%.*]], <vscale x 1 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv1bf16.i64(<vscale x 1 x bfloat> [[VD]], <vscale x 1 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 1 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vx_bf16mf4_tumu(vbool64_t vm, vbfloat16mf4_t vd,
+ vbfloat16mf4_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vv_bf16mf2_tumu(
+// CHECK-RV64-SAME: <vscale x 2 x i1> [[VM:%.*]], <vscale x 2 x bfloat> [[VD:%.*]], <vscale x 2 x bfloat> [[VS2:%.*]], <vscale x 2 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv2bf16.i64(<vscale x 2 x bfloat> [[VD]], <vscale x 2 x bfloat> [[VS2]], <vscale x 2 x i16> [[VS1]], <vscale x 2 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vv_bf16mf2_tumu(vbool32_t vm, vbfloat16mf2_t vd,
+ vbfloat16mf2_t vs2,
+ vuint16mf2_t vs1, size_t vl) {
+ return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vx_bf16mf2_tumu(
+// CHECK-RV64-SAME: <vscale x 2 x i1> [[VM:%.*]], <vscale x 2 x bfloat> [[VD:%.*]], <vscale x 2 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv2bf16.i64(<vscale x 2 x bfloat> [[VD]], <vscale x 2 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 2 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vx_bf16mf2_tumu(vbool32_t vm, vbfloat16mf2_t vd,
+ vbfloat16mf2_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vv_bf16m1_tumu(
+// CHECK-RV64-SAME: <vscale x 4 x i1> [[VM:%.*]], <vscale x 4 x bfloat> [[VD:%.*]], <vscale x 4 x bfloat> [[VS2:%.*]], <vscale x 4 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv4bf16.i64(<vscale x 4 x bfloat> [[VD]], <vscale x 4 x bfloat> [[VS2]], <vscale x 4 x i16> [[VS1]], <vscale x 4 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vv_bf16m1_tumu(vbool16_t vm, vbfloat16m1_t vd,
+ vbfloat16m1_t vs2, vuint16m1_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vx_bf16m1_tumu(
+// CHECK-RV64-SAME: <vscale x 4 x i1> [[VM:%.*]], <vscale x 4 x bfloat> [[VD:%.*]], <vscale x 4 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv4bf16.i64(<vscale x 4 x bfloat> [[VD]], <vscale x 4 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 4 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vx_bf16m1_tumu(vbool16_t vm, vbfloat16m1_t vd,
+ vbfloat16m1_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vv_bf16m2_tumu(
+// CHECK-RV64-SAME: <vscale x 8 x i1> [[VM:%.*]], <vscale x 8 x bfloat> [[VD:%.*]], <vscale x 8 x bfloat> [[VS2:%.*]], <vscale x 8 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv8bf16.i64(<vscale x 8 x bfloat> [[VD]], <vscale x 8 x bfloat> [[VS2]], <vscale x 8 x i16> [[VS1]], <vscale x 8 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vv_bf16m2_tumu(vbool8_t vm, vbfloat16m2_t vd,
+ vbfloat16m2_t vs2, vuint16m2_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vx_bf16m2_tumu(
+// CHECK-RV64-SAME: <vscale x 8 x i1> [[VM:%.*]], <vscale x 8 x bfloat> [[VD:%.*]], <vscale x 8 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv8bf16.i64(<vscale x 8 x bfloat> [[VD]], <vscale x 8 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 8 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vx_bf16m2_tumu(vbool8_t vm, vbfloat16m2_t vd,
+ vbfloat16m2_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vv_bf16m4_tumu(
+// CHECK-RV64-SAME: <vscale x 16 x i1> [[VM:%.*]], <vscale x 16 x bfloat> [[VD:%.*]], <vscale x 16 x bfloat> [[VS2:%.*]], <vscale x 16 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv16bf16.i64(<vscale x 16 x bfloat> [[VD]], <vscale x 16 x bfloat> [[VS2]], <vscale x 16 x i16> [[VS1]], <vscale x 16 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vv_bf16m4_tumu(vbool4_t vm, vbfloat16m4_t vd,
+ vbfloat16m4_t vs2, vuint16m4_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vx_bf16m4_tumu(
+// CHECK-RV64-SAME: <vscale x 16 x i1> [[VM:%.*]], <vscale x 16 x bfloat> [[VD:%.*]], <vscale x 16 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv16bf16.i64(<vscale x 16 x bfloat> [[VD]], <vscale x 16 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 16 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vx_bf16m4_tumu(vbool4_t vm, vbfloat16m4_t vd,
+ vbfloat16m4_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vv_bf16m8_tumu(
+// CHECK-RV64-SAME: <vscale x 32 x i1> [[VM:%.*]], <vscale x 32 x bfloat> [[VD:%.*]], <vscale x 32 x bfloat> [[VS2:%.*]], <vscale x 32 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv32bf16.i64(<vscale x 32 x bfloat> [[VD]], <vscale x 32 x bfloat> [[VS2]], <vscale x 32 x i16> [[VS1]], <vscale x 32 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vv_bf16m8_tumu(vbool2_t vm, vbfloat16m8_t vd,
+ vbfloat16m8_t vs2, vuint16m8_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vx_bf16m8_tumu(
+// CHECK-RV64-SAME: <vscale x 32 x i1> [[VM:%.*]], <vscale x 32 x bfloat> [[VD:%.*]], <vscale x 32 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv32bf16.i64(<vscale x 32 x bfloat> [[VD]], <vscale x 32 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 32 x i1> [[VM]], i64 [[VL]], i64 0)
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vx_bf16m8_tumu(vbool2_t vm, vbfloat16m8_t vd,
+ vbfloat16m8_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_tumu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vv_bf16mf4_mu(
+// CHECK-RV64-SAME: <vscale x 1 x i1> [[VM:%.*]], <vscale x 1 x bfloat> [[VD:%.*]], <vscale x 1 x bfloat> [[VS2:%.*]], <vscale x 1 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv1bf16.i64(<vscale x 1 x bfloat> [[VD]], <vscale x 1 x bfloat> [[VS2]], <vscale x 1 x i16> [[VS1]], <vscale x 1 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vv_bf16mf4_mu(vbool64_t vm, vbfloat16mf4_t vd,
+ vbfloat16mf4_t vs2, vuint16mf4_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vrgather_vx_bf16mf4_mu(
+// CHECK-RV64-SAME: <vscale x 1 x i1> [[VM:%.*]], <vscale x 1 x bfloat> [[VD:%.*]], <vscale x 1 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv1bf16.i64(<vscale x 1 x bfloat> [[VD]], <vscale x 1 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 1 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
+//
+vbfloat16mf4_t test_vrgather_vx_bf16mf4_mu(vbool64_t vm, vbfloat16mf4_t vd,
+ vbfloat16mf4_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vv_bf16mf2_mu(
+// CHECK-RV64-SAME: <vscale x 2 x i1> [[VM:%.*]], <vscale x 2 x bfloat> [[VD:%.*]], <vscale x 2 x bfloat> [[VS2:%.*]], <vscale x 2 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv2bf16.i64(<vscale x 2 x bfloat> [[VD]], <vscale x 2 x bfloat> [[VS2]], <vscale x 2 x i16> [[VS1]], <vscale x 2 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vv_bf16mf2_mu(vbool32_t vm, vbfloat16mf2_t vd,
+ vbfloat16mf2_t vs2, vuint16mf2_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vrgather_vx_bf16mf2_mu(
+// CHECK-RV64-SAME: <vscale x 2 x i1> [[VM:%.*]], <vscale x 2 x bfloat> [[VD:%.*]], <vscale x 2 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv2bf16.i64(<vscale x 2 x bfloat> [[VD]], <vscale x 2 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 2 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
+//
+vbfloat16mf2_t test_vrgather_vx_bf16mf2_mu(vbool32_t vm, vbfloat16mf2_t vd,
+ vbfloat16mf2_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vv_bf16m1_mu(
+// CHECK-RV64-SAME: <vscale x 4 x i1> [[VM:%.*]], <vscale x 4 x bfloat> [[VD:%.*]], <vscale x 4 x bfloat> [[VS2:%.*]], <vscale x 4 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv4bf16.i64(<vscale x 4 x bfloat> [[VD]], <vscale x 4 x bfloat> [[VS2]], <vscale x 4 x i16> [[VS1]], <vscale x 4 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vv_bf16m1_mu(vbool16_t vm, vbfloat16m1_t vd,
+ vbfloat16m1_t vs2, vuint16m1_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vrgather_vx_bf16m1_mu(
+// CHECK-RV64-SAME: <vscale x 4 x i1> [[VM:%.*]], <vscale x 4 x bfloat> [[VD:%.*]], <vscale x 4 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv4bf16.i64(<vscale x 4 x bfloat> [[VD]], <vscale x 4 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 4 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
+//
+vbfloat16m1_t test_vrgather_vx_bf16m1_mu(vbool16_t vm, vbfloat16m1_t vd,
+ vbfloat16m1_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vv_bf16m2_mu(
+// CHECK-RV64-SAME: <vscale x 8 x i1> [[VM:%.*]], <vscale x 8 x bfloat> [[VD:%.*]], <vscale x 8 x bfloat> [[VS2:%.*]], <vscale x 8 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv8bf16.i64(<vscale x 8 x bfloat> [[VD]], <vscale x 8 x bfloat> [[VS2]], <vscale x 8 x i16> [[VS1]], <vscale x 8 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vv_bf16m2_mu(vbool8_t vm, vbfloat16m2_t vd,
+ vbfloat16m2_t vs2, vuint16m2_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vrgather_vx_bf16m2_mu(
+// CHECK-RV64-SAME: <vscale x 8 x i1> [[VM:%.*]], <vscale x 8 x bfloat> [[VD:%.*]], <vscale x 8 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv8bf16.i64(<vscale x 8 x bfloat> [[VD]], <vscale x 8 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 8 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
+//
+vbfloat16m2_t test_vrgather_vx_bf16m2_mu(vbool8_t vm, vbfloat16m2_t vd,
+ vbfloat16m2_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vv_bf16m4_mu(
+// CHECK-RV64-SAME: <vscale x 16 x i1> [[VM:%.*]], <vscale x 16 x bfloat> [[VD:%.*]], <vscale x 16 x bfloat> [[VS2:%.*]], <vscale x 16 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv16bf16.i64(<vscale x 16 x bfloat> [[VD]], <vscale x 16 x bfloat> [[VS2]], <vscale x 16 x i16> [[VS1]], <vscale x 16 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vv_bf16m4_mu(vbool4_t vm, vbfloat16m4_t vd,
+ vbfloat16m4_t vs2, vuint16m4_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vrgather_vx_bf16m4_mu(
+// CHECK-RV64-SAME: <vscale x 16 x i1> [[VM:%.*]], <vscale x 16 x bfloat> [[VD:%.*]], <vscale x 16 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv16bf16.i64(<vscale x 16 x bfloat> [[VD]], <vscale x 16 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 16 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
+//
+vbfloat16m4_t test_vrgather_vx_bf16m4_mu(vbool4_t vm, vbfloat16m4_t vd,
+ vbfloat16m4_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vv_bf16m8_mu(
+// CHECK-RV64-SAME: <vscale x 32 x i1> [[VM:%.*]], <vscale x 32 x bfloat> [[VD:%.*]], <vscale x 32 x bfloat> [[VS2:%.*]], <vscale x 32 x i16> [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vv.mask.nxv32bf16.i64(<vscale x 32 x bfloat> [[VD]], <vscale x 32 x bfloat> [[VS2]], <vscale x 32 x i16> [[VS1]], <vscale x 32 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vv_bf16m8_mu(vbool2_t vm, vbfloat16m8_t vd,
+ vbfloat16m8_t vs2, vuint16m8_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl);
+}
+
+// CHECK-RV64-LABEL: define dso_local <vscale x 32 x bfloat> @test_vrgather_vx_bf16m8_mu(
+// CHECK-RV64-SAME: <vscale x 32 x i1> [[VM:%.*]], <vscale x 32 x bfloat> [[VD:%.*]], <vscale x 32 x bfloat> [[VS2:%.*]], i64 noundef [[VS1:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
+// CHECK-RV64-NEXT: entry:
+// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 32 x bfloat> @llvm.riscv.vrgather.vx.mask.nxv32bf16.i64(<vscale x 32 x bfloat> [[VD]], <vscale x 32 x bfloat> [[VS2]], i64 [[VS1]], <vscale x 32 x i1> [[VM]], i64 [[VL]], i64 1)
+// CHECK-RV64-NEXT: ret <vscale x 32 x bfloat> [[TMP0]]
+//
+vbfloat16m8_t test_vrgather_vx_bf16m8_mu(vbool2_t vm, vbfloat16m8_t vd,
+ vbfloat16m8_t vs2, size_t vs1,
+ size_t vl) {
+ return __riscv_vrgather_mu(vm, vd, vs2, vs1, vl);
+}
diff --git a/clang/test/CodeGen/X86/prefetchi-error.c b/clang/test/CodeGen/X86/prefetchi-error.c
new file mode 100644
index 0000000..31494f7
--- /dev/null
+++ b/clang/test/CodeGen/X86/prefetchi-error.c
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-unknown-unknown -target-feature +prefetchi -fsyntax-only -verify
+
+#include <immintrin.h>
+
+void test_invalid_prefetchi(void* p) {
+ __builtin_ia32_prefetchi(p, 1); // expected-error {{argument value 1 is outside the valid range [2, 3]}}
+}
diff --git a/clang/test/CodeGen/builtin-maximumnum-minimumnum.c b/clang/test/CodeGen/builtin-maximumnum-minimumnum.c
new file mode 100644
index 0000000..ea9d2e7
--- /dev/null
+++ b/clang/test/CodeGen/builtin-maximumnum-minimumnum.c
@@ -0,0 +1,171 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// RUN: %clang_cc1 -x c++ -std=c++20 -disable-llvm-passes -O3 -triple x86_64 %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK
+
+typedef _Float16 half8 __attribute__((ext_vector_type(8)));
+typedef __bf16 bf16x8 __attribute__((ext_vector_type(8)));
+typedef float float4 __attribute__((ext_vector_type(4)));
+typedef double double2 __attribute__((ext_vector_type(2)));
+typedef long double ldouble2 __attribute__((ext_vector_type(2)));
+
+// CHECK-LABEL: define dso_local noundef <8 x half> @_Z7pfmin16Dv8_DF16_S_(
+// CHECK-SAME: <8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <8 x half>, align 16
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <8 x half>, align 16
+// CHECK-NEXT: store <8 x half> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2:![0-9]+]]
+// CHECK-NEXT: store <8 x half> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[TMP0:%.*]] = load <8 x half>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x half>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[ELT_MINIMUMNUM:%.*]] = call <8 x half> @llvm.minimumnum.v8f16(<8 x half> [[TMP0]], <8 x half> [[TMP1]])
+// CHECK-NEXT: ret <8 x half> [[ELT_MINIMUMNUM]]
+//
+half8 pfmin16(half8 a, half8 b) {
+ return __builtin_elementwise_minimumnum(a, b);
+}
+// CHECK-LABEL: define dso_local noundef <8 x bfloat> @_Z8pfmin16bDv8_DF16bS_(
+// CHECK-SAME: <8 x bfloat> noundef [[A:%.*]], <8 x bfloat> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <8 x bfloat>, align 16
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <8 x bfloat>, align 16
+// CHECK-NEXT: store <8 x bfloat> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: store <8 x bfloat> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[TMP0:%.*]] = load <8 x bfloat>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x bfloat>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[ELT_MINIMUMNUM:%.*]] = call <8 x bfloat> @llvm.minimumnum.v8bf16(<8 x bfloat> [[TMP0]], <8 x bfloat> [[TMP1]])
+// CHECK-NEXT: ret <8 x bfloat> [[ELT_MINIMUMNUM]]
+//
+bf16x8 pfmin16b(bf16x8 a, bf16x8 b) {
+ return __builtin_elementwise_minimumnum(a, b);
+}
+// CHECK-LABEL: define dso_local noundef <4 x float> @_Z7pfmin32Dv4_fS_(
+// CHECK-SAME: <4 x float> noundef [[A:%.*]], <4 x float> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: store <4 x float> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: store <4 x float> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[TMP0:%.*]] = load <4 x float>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[ELT_MINIMUMNUM:%.*]] = call <4 x float> @llvm.minimumnum.v4f32(<4 x float> [[TMP0]], <4 x float> [[TMP1]])
+// CHECK-NEXT: ret <4 x float> [[ELT_MINIMUMNUM]]
+//
+float4 pfmin32(float4 a, float4 b) {
+ return __builtin_elementwise_minimumnum(a, b);
+}
+// CHECK-LABEL: define dso_local noundef <2 x double> @_Z7pfmin64Dv2_dS_(
+// CHECK-SAME: <2 x double> noundef [[A:%.*]], <2 x double> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: store <2 x double> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: store <2 x double> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[TMP1:%.*]] = load <2 x double>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[ELT_MINIMUMNUM:%.*]] = call <2 x double> @llvm.minimumnum.v2f64(<2 x double> [[TMP0]], <2 x double> [[TMP1]])
+// CHECK-NEXT: ret <2 x double> [[ELT_MINIMUMNUM]]
+//
+double2 pfmin64(double2 a, double2 b) {
+ return __builtin_elementwise_minimumnum(a, b);
+}
+// CHECK-LABEL: define dso_local noundef <2 x x86_fp80> @_Z7pfmin80Dv2_eS_(
+// CHECK-SAME: ptr noundef byval(<2 x x86_fp80>) align 32 [[TMP0:%.*]], ptr noundef byval(<2 x x86_fp80>) align 32 [[TMP1:%.*]]) #[[ATTR2:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <2 x x86_fp80>, align 32
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <2 x x86_fp80>, align 32
+// CHECK-NEXT: [[A:%.*]] = load <2 x x86_fp80>, ptr [[TMP0]], align 32, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[B:%.*]] = load <2 x x86_fp80>, ptr [[TMP1]], align 32, !tbaa [[TBAA2]]
+// CHECK-NEXT: store <2 x x86_fp80> [[A]], ptr [[A_ADDR]], align 32, !tbaa [[TBAA2]]
+// CHECK-NEXT: store <2 x x86_fp80> [[B]], ptr [[B_ADDR]], align 32, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[TMP2:%.*]] = load <2 x x86_fp80>, ptr [[A_ADDR]], align 32, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[TMP3:%.*]] = load <2 x x86_fp80>, ptr [[B_ADDR]], align 32, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[ELT_MINIMUMNUM:%.*]] = call <2 x x86_fp80> @llvm.minimumnum.v2f80(<2 x x86_fp80> [[TMP2]], <2 x x86_fp80> [[TMP3]])
+// CHECK-NEXT: ret <2 x x86_fp80> [[ELT_MINIMUMNUM]]
+//
+ldouble2 pfmin80(ldouble2 a, ldouble2 b) {
+ return __builtin_elementwise_minimumnum(a, b);
+}
+
+// CHECK-LABEL: define dso_local noundef <8 x half> @_Z7pfmax16Dv8_DF16_S_(
+// CHECK-SAME: <8 x half> noundef [[A:%.*]], <8 x half> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <8 x half>, align 16
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <8 x half>, align 16
+// CHECK-NEXT: store <8 x half> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: store <8 x half> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[TMP0:%.*]] = load <8 x half>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x half>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[ELT_MAXIMUMNUM:%.*]] = call <8 x half> @llvm.maximumnum.v8f16(<8 x half> [[TMP0]], <8 x half> [[TMP1]])
+// CHECK-NEXT: ret <8 x half> [[ELT_MAXIMUMNUM]]
+//
+half8 pfmax16(half8 a, half8 b) {
+ return __builtin_elementwise_maximumnum(a, b);
+}
+// CHECK-LABEL: define dso_local noundef <8 x bfloat> @_Z8pfmax16bDv8_DF16bS_(
+// CHECK-SAME: <8 x bfloat> noundef [[A:%.*]], <8 x bfloat> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <8 x bfloat>, align 16
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <8 x bfloat>, align 16
+// CHECK-NEXT: store <8 x bfloat> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: store <8 x bfloat> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[TMP0:%.*]] = load <8 x bfloat>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[TMP1:%.*]] = load <8 x bfloat>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[ELT_MAXIMUMNUM:%.*]] = call <8 x bfloat> @llvm.maximumnum.v8bf16(<8 x bfloat> [[TMP0]], <8 x bfloat> [[TMP1]])
+// CHECK-NEXT: ret <8 x bfloat> [[ELT_MAXIMUMNUM]]
+//
+bf16x8 pfmax16b(bf16x8 a, bf16x8 b) {
+ return __builtin_elementwise_maximumnum(a, b);
+}
+// CHECK-LABEL: define dso_local noundef <4 x float> @_Z7pfmax32Dv4_fS_(
+// CHECK-SAME: <4 x float> noundef [[A:%.*]], <4 x float> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT: store <4 x float> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: store <4 x float> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[TMP0:%.*]] = load <4 x float>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[ELT_MAXIMUMNUM:%.*]] = call <4 x float> @llvm.maximumnum.v4f32(<4 x float> [[TMP0]], <4 x float> [[TMP1]])
+// CHECK-NEXT: ret <4 x float> [[ELT_MAXIMUMNUM]]
+//
+float4 pfmax32(float4 a, float4 b) {
+ return __builtin_elementwise_maximumnum(a, b);
+}
+// CHECK-LABEL: define dso_local noundef <2 x double> @_Z7pfmax64Dv2_dS_(
+// CHECK-SAME: <2 x double> noundef [[A:%.*]], <2 x double> noundef [[B:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <2 x double>, align 16
+// CHECK-NEXT: store <2 x double> [[A]], ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: store <2 x double> [[B]], ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr [[A_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[TMP1:%.*]] = load <2 x double>, ptr [[B_ADDR]], align 16, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[ELT_MAXIMUMNUM:%.*]] = call <2 x double> @llvm.maximumnum.v2f64(<2 x double> [[TMP0]], <2 x double> [[TMP1]])
+// CHECK-NEXT: ret <2 x double> [[ELT_MAXIMUMNUM]]
+//
+double2 pfmax64(double2 a, double2 b) {
+ return __builtin_elementwise_maximumnum(a, b);
+}
+
+// CHECK-LABEL: define dso_local noundef <2 x x86_fp80> @_Z7pfmax80Dv2_eS_(
+// CHECK-SAME: ptr noundef byval(<2 x x86_fp80>) align 32 [[TMP0:%.*]], ptr noundef byval(<2 x x86_fp80>) align 32 [[TMP1:%.*]]) #[[ATTR2]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <2 x x86_fp80>, align 32
+// CHECK-NEXT: [[B_ADDR:%.*]] = alloca <2 x x86_fp80>, align 32
+// CHECK-NEXT: [[A:%.*]] = load <2 x x86_fp80>, ptr [[TMP0]], align 32, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[B:%.*]] = load <2 x x86_fp80>, ptr [[TMP1]], align 32, !tbaa [[TBAA2]]
+// CHECK-NEXT: store <2 x x86_fp80> [[A]], ptr [[A_ADDR]], align 32, !tbaa [[TBAA2]]
+// CHECK-NEXT: store <2 x x86_fp80> [[B]], ptr [[B_ADDR]], align 32, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[TMP2:%.*]] = load <2 x x86_fp80>, ptr [[A_ADDR]], align 32, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[TMP3:%.*]] = load <2 x x86_fp80>, ptr [[B_ADDR]], align 32, !tbaa [[TBAA2]]
+// CHECK-NEXT: [[ELT_MINIMUMNUM:%.*]] = call <2 x x86_fp80> @llvm.minimumnum.v2f80(<2 x x86_fp80> [[TMP2]], <2 x x86_fp80> [[TMP3]])
+// CHECK-NEXT: ret <2 x x86_fp80> [[ELT_MINIMUMNUM]]
+//
+ldouble2 pfmax80(ldouble2 a, ldouble2 b) {
+ return __builtin_elementwise_minimumnum(a, b);
+}
+
+//.
+// CHECK: [[TBAA2]] = !{[[META3:![0-9]+]], [[META3]], i64 0}
+// CHECK: [[META3]] = !{!"omnipotent char", [[META4:![0-9]+]], i64 0}
+// CHECK: [[META4]] = !{!"Simple C++ TBAA"}
+//.
diff --git a/clang/test/CodeGenCXX/builtin-amdgcn-fence.cpp b/clang/test/CodeGenCXX/builtin-amdgcn-fence.cpp
index 3af5a21..1e977dd 100644
--- a/clang/test/CodeGenCXX/builtin-amdgcn-fence.cpp
+++ b/clang/test/CodeGenCXX/builtin-amdgcn-fence.cpp
@@ -105,7 +105,7 @@ void test_mixed() {
__builtin_amdgcn_fence( __ATOMIC_SEQ_CST, "workgroup", "local", "local", "global", "local", "local");
}
//.
-// CHECK: [[META3]] = !{!"amdgpu-as", !"local"}
-// CHECK: [[META4]] = !{!"amdgpu-as", !"global"}
+// CHECK: [[META3]] = !{!"amdgpu-synchronize-as", !"local"}
+// CHECK: [[META4]] = !{!"amdgpu-synchronize-as", !"global"}
// CHECK: [[META5]] = !{[[META4]], [[META3]]}
//.
diff --git a/clang/test/CodeGenCXX/delete.cpp b/clang/test/CodeGenCXX/delete.cpp
index d5b0dc6..21b9f8c 100644
--- a/clang/test/CodeGenCXX/delete.cpp
+++ b/clang/test/CodeGenCXX/delete.cpp
@@ -76,27 +76,45 @@ namespace test1 {
~A();
};
- // CHECK-LABEL: define{{.*}} void @_ZN5test14testEPA10_A20_NS_1AE(
- void test(A (*arr)[10][20]) {
+ // CHECK-LABEL: define{{.*}} void @_ZN5test11fEPA10_A20_NS_1AE(
+ void f(A (*arr)[10][20]) {
delete [] arr;
// CHECK: icmp eq ptr [[PTR:%.*]], null
// CHECK-NEXT: br i1
- // CHECK: [[BEGIN:%.*]] = getelementptr inbounds [10 x [20 x [[A:%.*]]]], ptr [[PTR]], i32 0, i32 0, i32 0
- // CHECK-NEXT: [[ALLOC:%.*]] = getelementptr inbounds i8, ptr [[BEGIN]], i64 -8
+ // CHECK: [[ALLOC:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 -8
// CHECK-NEXT: [[COUNT:%.*]] = load i64, ptr [[ALLOC]]
- // CHECK: [[END:%.*]] = getelementptr inbounds [[A]], ptr [[BEGIN]], i64 [[COUNT]]
- // CHECK-NEXT: [[ISEMPTY:%.*]] = icmp eq ptr [[BEGIN]], [[END]]
+ // CHECK: [[END:%.*]] = getelementptr inbounds [[A:%.*]], ptr [[PTR]], i64 [[COUNT]]
+ // CHECK-NEXT: [[ISEMPTY:%.*]] = icmp eq ptr [[PTR]], [[END]]
// CHECK-NEXT: br i1 [[ISEMPTY]],
// CHECK: [[PAST:%.*]] = phi ptr [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]
// CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds [[A]], ptr [[PAST]], i64 -1
// CHECK-NEXT: call void @_ZN5test11AD1Ev(ptr {{[^,]*}} [[CUR]])
- // CHECK-NEXT: [[ISDONE:%.*]] = icmp eq ptr [[CUR]], [[BEGIN]]
+ // CHECK-NEXT: [[ISDONE:%.*]] = icmp eq ptr [[CUR]], [[PTR]]
// CHECK-NEXT: br i1 [[ISDONE]]
// CHECK: [[MUL:%.*]] = mul i64 4, [[COUNT]]
// CHECK-NEXT: [[SIZE:%.*]] = add i64 [[MUL]], 8
// CHECK-NEXT: call void @_ZdaPvm(ptr noundef [[ALLOC]], i64 noundef [[SIZE]])
}
+
+ // CHECK-LABEL: define{{.*}} void @_ZN5test11gEPA_NS_1AE(
+ void g(A (*arr)[]) {
+ delete [] arr;
+ // CHECK: icmp eq ptr [[PTR:%.*]], null
+ // CHECK-NEXT: br i1
+
+ // CHECK: [[ALLOC:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 -8
+ // CHECK-NEXT: [[COUNT:%.*]] = load i64, ptr [[ALLOC]]
+ // CHECK: [[END:%.*]] = getelementptr inbounds [[A:%.*]], ptr [[PTR]], i64 [[COUNT]]
+ // CHECK-NEXT: [[ISEMPTY:%.*]] = icmp eq ptr [[PTR]], [[END]]
+ // CHECK-NEXT: br i1 [[ISEMPTY]],
+ // CHECK: [[PAST:%.*]] = phi ptr [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]
+ // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds [[A]], ptr [[PAST]], i64 -1
+ // CHECK-NEXT: call void @_ZN5test11AD1Ev(ptr {{[^,]*}} [[CUR]])
+ // CHECK-NEXT: [[ISDONE:%.*]] = icmp eq ptr [[CUR]], [[PTR]]
+ // CHECK-NEXT: br i1 [[ISDONE]]
+ // CHECK: call void @_ZdaPv(ptr noundef [[ALLOC]])
+ }
}
namespace test2 {
diff --git a/clang/test/CodeGenCXX/microsoft-abi-eh-async.cpp b/clang/test/CodeGenCXX/microsoft-abi-eh-async.cpp
new file mode 100644
index 0000000..b831737
--- /dev/null
+++ b/clang/test/CodeGenCXX/microsoft-abi-eh-async.cpp
@@ -0,0 +1,209 @@
+// REQUIRES: x86-registered-target
+
+// RUN: %clang_cl -c --target=x86_64-windows-msvc /EHa -O2 /GS- \
+// RUN: -Xclang=-import-call-optimization \
+// RUN: /clang:-S /clang:-o- -- %s 2>&1 \
+// RUN: | FileCheck %s
+
+#ifdef __clang__
+#define NO_TAIL __attribute((disable_tail_calls))
+#else
+#define NO_TAIL
+#endif
+
+void might_throw();
+void other_func(int x);
+
+void does_not_throw() noexcept(true);
+
+extern "C" void __declspec(dllimport) some_dll_import();
+
+class HasDtor {
+ int x;
+ char foo[40];
+
+public:
+ explicit HasDtor(int x);
+ ~HasDtor();
+};
+
+class BadError {
+public:
+ int errorCode;
+};
+
+void normal_has_regions() {
+ // CHECK-LABEL: .def "?normal_has_regions@@YAXXZ"
+ // CHECK: .seh_endprologue
+
+ // <-- state -1 (none)
+ {
+ HasDtor hd{42};
+
+ // <-- state goes from -1 to 0
+ // because state changes, we expect the HasDtor::HasDtor() call to have a NOP
+ // CHECK: call "??0HasDtor@@QEAA@H@Z"
+ // CHECK-NEXT: nop
+
+ might_throw();
+ // CHECK: call "?might_throw@@YAXXZ"
+ // CHECK-NEXT: nop
+
+ // <-- state goes from 0 to -1 because we're about to call HasDtor::~HasDtor()
+ // CHECK: call "??1HasDtor@@QEAA@XZ"
+ // <-- state -1
+ }
+
+ // <-- state -1
+ other_func(10);
+ // CHECK: call "?other_func@@YAXH@Z"
+ // CHECK-NEXT: nop
+ // CHECK: .seh_startepilogue
+
+ // <-- state -1
+}
+
+// This tests a tail call to a destructor.
+void case_dtor_arg_empty_body(HasDtor x)
+{
+ // CHECK-LABEL: .def "?case_dtor_arg_empty_body@@YAXVHasDtor@@@Z"
+ // CHECK: jmp "??1HasDtor@@QEAA@XZ"
+}
+
+int case_dtor_arg_empty_with_ret(HasDtor x)
+{
+ // CHECK-LABEL: .def "?case_dtor_arg_empty_with_ret@@YAHVHasDtor@@@Z"
+ // CHECK: .seh_endprologue
+
+ // CHECK: call "??1HasDtor@@QEAA@XZ"
+ // CHECK-NOT: nop
+
+ // The call to HasDtor::~HasDtor() should NOT have a NOP because the
+ // following "mov eax, 100" instruction is in the same EH state.
+
+ return 100;
+
+ // CHECK: mov eax, 100
+ // CHECK: .seh_startepilogue
+ // CHECK: .seh_endepilogue
+ // CHECK: .seh_endproc
+}
+
+int case_noexcept_dtor(HasDtor x) noexcept(true)
+{
+ // CHECK: .def "?case_noexcept_dtor@@YAHVHasDtor@@@Z"
+ // CHECK: call "??1HasDtor@@QEAA@XZ"
+ // CHECK-NEXT: mov eax, 100
+ // CHECK: .seh_startepilogue
+ return 100;
+}
+
+void case_except_simple_call() NO_TAIL
+{
+ does_not_throw();
+}
+// CHECK-LABEL: .def "?case_except_simple_call@@YAXXZ"
+// CHECK: .seh_endprologue
+// CHECK-NEXT: call "?does_not_throw@@YAXXZ"
+// CHECK-NEXT: nop
+// CHECK-NEXT: .seh_startepilogue
+// CHECK: .seh_endproc
+
+void case_noexcept_simple_call() noexcept(true) NO_TAIL
+{
+ does_not_throw();
+}
+// CHECK-LABEL: .def "?case_noexcept_simple_call@@YAXXZ"
+// CHECK: .seh_endprologue
+// CHECK-NEXT: call "?does_not_throw@@YAXXZ"
+// CHECK-NEXT: nop
+// CHECK-NEXT: .seh_startepilogue
+// CHECK: .seh_endepilogue
+// CHECK-NEXT: ret
+// CHECK-NEXT: .seh_endproc
+
+// This tests that the destructor is called right before SEH_BeginEpilogue,
+// but in a function that has a return value. Loading the return value
+// counts as a real instruction, so there is no need for a NOP after the
+// dtor call.
+int case_dtor_arg_calls_no_throw(HasDtor x)
+{
+ does_not_throw(); // no NOP expected
+ return 100;
+}
+// CHECK-LABEL: .def "?case_dtor_arg_calls_no_throw@@YAHVHasDtor@@@Z"
+// CHECK: .seh_endprologue
+// CHECK: "?does_not_throw@@YAXXZ"
+// CHECK-NEXT: nop
+// CHECK: "??1HasDtor@@QEAA@XZ"
+// CHECK-NEXT: mov eax, 100
+// CHECK: .seh_startepilogue
+// CHECK: .seh_endproc
+
+// Check the behavior of CALLs that are at the end of MBBs. If a CALL is within
+// a non-null EH state (state -1) and is at the end of an MBB, then we expect
+// to find an EH_LABEL after the CALL. This causes us to insert a NOP, which
+// is the desired result.
+void case_dtor_runs_after_join(int x) {
+ // CHECK-LABEL: .def "?case_dtor_runs_after_join@@YAXH@Z"
+ // CHECK: .seh_endprologue
+
+ // <-- EH state -1
+
+ // ctor call does not need a NOP, because it has real instructions after it
+ HasDtor hd{42};
+ // CHECK: call "??0HasDtor@@QEAA@H@Z"
+ // CHECK-NEXT: nop
+ // CHECK: test
+
+ // <-- EH state transition from -1 0
+ if (x) {
+ might_throw(); // <-- NOP expected (at end of BB w/ EH_LABEL)
+ // CHECK: call "?might_throw@@YAXXZ"
+ // CHECK-NEXT: nop
+ } else {
+ other_func(10); // <-- NOP expected (at end of BB w/ EH_LABEL)
+ // CHECK: call "?other_func@@YAXH@Z"
+ // CHECK-NEXT: nop
+ }
+ does_not_throw();
+ // <-- EH state transition 0 to -1
+ // ~HasDtor() runs
+
+ // CHECK: .seh_endproc
+
+ // CHECK: "$ip2state$?case_dtor_runs_after_join@@YAXH@Z":
+ // CHECK-NEXT: .long [[func_begin:.Lfunc_begin([0-9]+)@IMGREL]]
+ // CHECK-NEXT: .long -1
+ // CHECK-NEXT: .long [[tmp1:.Ltmp([0-9]+)]]@IMGREL
+ // CHECK-NEXT: .long 0
+ // CHECK-NEXT: .long [[tmp2:.Ltmp([0-9]+)]]@IMGREL
+ // CHECK-NEXT: .long -1
+}
+
+
+// Check the behavior of NOP padding around tail calls.
+// We do not expect to insert NOPs around tail calls.
+// However, the first call (to other_func()) does get a NOP
+// because it comes before .seh_startepilogue.
+void case_tail_call_no_eh(bool b) {
+ // tail call; no NOP padding after JMP
+ if (b) {
+ does_not_throw();
+ // <-- no NOP here
+ return;
+ }
+
+ other_func(20);
+ // <-- NOP does get inserted here
+}
+// CHECK-LABEL: .def "?case_tail_call_no_eh@@YAX_N@Z"
+// CHECK: test
+// CHECK-NEXT: je .LBB
+// CHECK: jmp "?does_not_throw@@YAXXZ"
+// CHECK-SAME: TAILCALL
+// CHECK-NEXT: .LBB
+// CHECK-NEXT: mov ecx, 20
+// CHECK-NEXT: jmp "?other_func@@YAXH@Z"
+// CHECK-SAME: TAILCALL
+// CHECK-NEXT: # -- End function
diff --git a/clang/test/CodeGenCXX/microsoft-abi-eh-disabled.cpp b/clang/test/CodeGenCXX/microsoft-abi-eh-disabled.cpp
new file mode 100644
index 0000000..744f863
--- /dev/null
+++ b/clang/test/CodeGenCXX/microsoft-abi-eh-disabled.cpp
@@ -0,0 +1,140 @@
+// REQUIRES: x86-registered-target
+// RUN: %clang_cl -c --target=x86_64-windows-msvc -EHs-c- -O2 -GS- \
+// RUN: -Xclang=-import-call-optimization \
+// RUN: -clang:-S -clang:-o- -- %s 2>&1 \
+// RUN: | FileCheck %s
+
+#ifdef __clang__
+#define NO_TAIL __attribute((disable_tail_calls))
+#else
+#define NO_TAIL
+#endif
+
+void might_throw();
+void other_func(int x);
+
+void does_not_throw() noexcept(true);
+
+extern "C" void __declspec(dllimport) some_dll_import();
+
+class HasDtor {
+ int x;
+ char foo[40];
+
+public:
+ explicit HasDtor(int x);
+ ~HasDtor();
+};
+
+void normal_has_regions() {
+ {
+ HasDtor hd{42};
+
+ // because state changes, we expect the HasDtor::HasDtor() call to have a NOP
+ might_throw();
+ }
+
+ other_func(10);
+}
+// CHECK-LABEL: .def "?normal_has_regions@@YAXXZ"
+// CHECK: .seh_endprologue
+// CHECK: call "??0HasDtor@@QEAA@H@Z"
+// CHECK-NEXT: call "?might_throw@@YAXXZ"
+// CHECK-NEXT: mov
+// CHECK: call "??1HasDtor@@QEAA@XZ"
+// CHECK-NEXT: mov ecx, 10
+// CHECK-NEXT: call "?other_func@@YAXH@Z"
+// CHECK-NEXT: nop
+// CHECK-NEXT: .seh_startepilogue
+// CHECK-NOT: "$ip2state$?normal_has_regions@@YAXXZ"
+
+// This tests a tail call to a destructor.
+void case_dtor_arg_empty_body(HasDtor x)
+{
+}
+// CHECK-LABEL: .def "?case_dtor_arg_empty_body@@YAXVHasDtor@@@Z"
+// CHECK: jmp "??1HasDtor@@QEAA@XZ"
+
+int case_dtor_arg_empty_with_ret(HasDtor x)
+{
+ // The call to HasDtor::~HasDtor() should NOT have a NOP because the
+ // following "mov eax, 100" instruction is in the same EH state.
+ return 100;
+}
+// CHECK-LABEL: .def "?case_dtor_arg_empty_with_ret@@YAHVHasDtor@@@Z"
+// CHECK: .seh_endprologue
+// CHECK: call "??1HasDtor@@QEAA@XZ"
+// CHECK-NOT: nop
+// CHECK: mov eax, 100
+// CHECK: .seh_startepilogue
+// CHECK: .seh_endepilogue
+// CHECK: .seh_endproc
+
+void case_except_simple_call() NO_TAIL
+{
+ does_not_throw();
+}
+
+// This tests that the destructor is called right before SEH_BeginEpilogue,
+// but in a function that has a return value.
+int case_dtor_arg_calls_no_throw(HasDtor x)
+{
+ does_not_throw(); // no NOP expected
+ return 100;
+}
+
+// Check the behavior of CALLs that are at the end of MBBs. If a CALL is within
+// a non-null EH state (state -1) and is at the end of an MBB, then we expect
+// to find an EH_LABEL after the CALL. This causes us to insert a NOP, which
+// is the desired result.
+void case_dtor_runs_after_join(int x) {
+
+ // ctor call does not need a NOP, because it has real instructions after it
+ HasDtor hd{42};
+
+ if (x) {
+ might_throw();
+ } else {
+ other_func(10);
+ }
+ does_not_throw();
+ // ~HasDtor() runs
+}
+
+// CHECK-LABEL: .def "?case_dtor_runs_after_join@@YAXH@Z"
+// CHECK: .seh_endprologue
+// CHECK: call "??0HasDtor@@QEAA@H@Z"
+// CHECK-NEXT: test
+// CHECK: call "?might_throw@@YAXXZ"
+// CHECK-NEXT: jmp
+// CHECK: call "?other_func@@YAXH@Z"
+// CHECK-NEXT: .LBB
+// CHECK: call "?does_not_throw@@YAXXZ"
+// CHECK-NEXT: lea
+// CHECK-NEXT: call "??1HasDtor@@QEAA@XZ"
+// CHECK-NEXT: nop
+// CHECK-NEXT: .seh_startepilogue
+// CHECK-NOT: "$ip2state$?case_dtor_runs_after_join@@YAXH@Z":
+
+
+// Check the behavior of NOP padding around tail calls.
+// We do not expect to insert NOPs around tail calls.
+// However, the first call (to other_func()) does get a NOP
+// because it comes before .seh_startepilogue.
+void case_tail_call_no_eh() {
+ // ordinary call
+ other_func(10);
+
+ // tail call; no NOP padding after JMP
+ does_not_throw();
+}
+
+// CHECK-LABEL: .def "?case_tail_call_no_eh@@YAXXZ"
+// CHECK: .seh_endprologue
+// CHECK: call "?other_func@@YAXH@Z"
+// CHECK-NEXT: nop
+// CHECK-NEXT: .seh_startepilogue
+// CHECK: .seh_endepilogue
+// CHECK: jmp "?does_not_throw@@YAXXZ"
+// CHECK-NOT: nop
+// CHECK: .seh_endproc
diff --git a/clang/test/CodeGenCXX/microsoft-abi-eh-ip2state.cpp b/clang/test/CodeGenCXX/microsoft-abi-eh-ip2state.cpp
new file mode 100644
index 0000000..0b7b406
--- /dev/null
+++ b/clang/test/CodeGenCXX/microsoft-abi-eh-ip2state.cpp
@@ -0,0 +1,242 @@
+// REQUIRES: x86-registered-target
+// RUN: %clang_cl -c --target=x86_64-windows-msvc -O2 -EHsc -GS- \
+// RUN: -Xclang=-import-call-optimization \
+// RUN: -clang:-S -clang:-o- -- %s 2>&1 \
+// RUN: | FileCheck %s
+
+#ifdef __clang__
+#define NO_TAIL __attribute((disable_tail_calls))
+#else
+#define NO_TAIL
+#endif
+
+void might_throw();
+void other_func(int x);
+
+void does_not_throw() noexcept(true);
+
+extern "C" void __declspec(dllimport) some_dll_import();
+
+class HasDtor {
+ int x;
+ char foo[40];
+
+public:
+ explicit HasDtor(int x);
+ ~HasDtor();
+};
+
+class BadError {
+public:
+ int errorCode;
+};
+
+// Verify that when NOP padding for IP2State is active *and* Import Call
+// Optimization is active that we see both forms of NOP padding.
+void case_calls_dll_import() NO_TAIL {
+ some_dll_import();
+}
+// CHECK-LABEL: .def "?case_calls_dll_import@@YAXXZ"
+// CHECK: .seh_endprologue
+// CHECK: .Limpcall{{[0-9]+}}:
+// CHECK-NEXT: rex64
+// CHECK-NEXT: call __imp_some_dll_import
+// CHECK-NEXT: nop dword ptr {{\[.*\]}}
+// CHECK-NEXT: nop
+// CHECK-NEXT: .seh_startepilogue
+
+void normal_has_regions() {
+
+ // <-- state -1 (none)
+ {
+ HasDtor hd{42};
+
+ // <-- state goes from -1 to 0
+ // because state changes, we expect the HasDtor::HasDtor() call to have a NOP
+
+ might_throw();
+
+ // <-- state goes from 0 to -1 because we're about to call HasDtor::~HasDtor()
+ // <-- state -1
+ }
+
+ // <-- state -1
+ other_func(10);
+
+ // <-- state -1
+}
+// CHECK-LABEL: .def "?normal_has_regions@@YAXXZ"
+// CHECK: .seh_endprologue
+// CHECK: call "??0HasDtor@@QEAA@H@Z"
+// CHECK-NEXT: nop
+// CHECK: call "?might_throw@@YAXXZ"
+// CHECK-NEXT: nop
+// CHECK: call "??1HasDtor@@QEAA@XZ"
+// CHECK: call "?other_func@@YAXH@Z"
+// CHECK-NEXT: nop
+// CHECK: .seh_startepilogue
+
+// This tests a tail call to a destructor.
+void case_dtor_arg_empty_body(HasDtor x)
+{
+}
+// CHECK-LABEL: .def "?case_dtor_arg_empty_body@@YAXVHasDtor@@@Z"
+// CHECK: jmp "??1HasDtor@@QEAA@XZ"
+
+int case_dtor_arg_empty_with_ret(HasDtor x)
+{
+ // CHECK-LABEL: .def "?case_dtor_arg_empty_with_ret@@YAHVHasDtor@@@Z"
+ // CHECK: .seh_endprologue
+
+ // CHECK: call "??1HasDtor@@QEAA@XZ"
+ // CHECK-NOT: nop
+
+ // The call to HasDtor::~HasDtor() should NOT have a NOP because the
+ // following "mov eax, 100" instruction is in the same EH state.
+
+ return 100;
+
+ // CHECK: mov eax, 100
+ // CHECK: .seh_startepilogue
+ // CHECK: .seh_endepilogue
+ // CHECK: .seh_endproc
+}
+
+int case_noexcept_dtor(HasDtor x) noexcept(true)
+{
+ // CHECK: .def "?case_noexcept_dtor@@YAHVHasDtor@@@Z"
+ // CHECK: call "??1HasDtor@@QEAA@XZ"
+ // CHECK-NEXT: mov eax, 100
+ // CHECK-NEXT: .seh_startepilogue
+ return 100;
+}
+
+// Simple call of a function that can throw
+void case_except_simple_call() NO_TAIL
+{
+ might_throw();
+}
+// CHECK-LABEL: .def "?case_except_simple_call@@YAXXZ"
+// CHECK: .seh_endprologue
+// CHECK-NEXT: call "?might_throw@@YAXXZ"
+// CHECK-NEXT: nop
+// CHECK-NEXT: .seh_startepilogue
+
+// Simple call of a function that cannot throw, in a noexcept context.
+void case_noexcept_simple_call() noexcept(true) NO_TAIL
+{
+ does_not_throw();
+}
+// CHECK-LABEL: .def "?case_noexcept_simple_call@@YAXXZ"
+// CHECK: .seh_endprologue
+// CHECK-NEXT: call "?does_not_throw@@YAXXZ"
+// CHECK-NEXT: nop
+// CHECK-NEXT: .seh_startepilogue
+
+
+// This tests that the destructor is called right before SEH_BeginEpilogue,
+// but in a function that has a return value.
+int case_dtor_arg_calls_no_throw(HasDtor x)
+{
+ does_not_throw(); // no NOP expected
+ return 100;
+}
+
+// Check the behavior of CALLs that are at the end of MBBs. If a CALL is within
+// a non-null EH state (state -1) and is at the end of an MBB, then we expect
+// to find an EH_LABEL after the CALL. This causes us to insert a NOP, which
+// is the desired result.
+void case_dtor_runs_after_join(int x) {
+ // CHECK-LABEL: .def "?case_dtor_runs_after_join@@YAXH@Z"
+ // CHECK: .seh_endprologue
+
+ // <-- EH state -1
+
+ // ctor call does not need a NOP, because it has real instructions after it
+ HasDtor hd{42};
+ // CHECK: call "??0HasDtor@@QEAA@H@Z"
+ // CHECK-NEXT: test
+
+ // <-- EH state transition from -1 0
+ if (x) {
+ might_throw(); // <-- NOP expected (at end of BB w/ EH_LABEL)
+ // CHECK: call "?might_throw@@YAXXZ"
+ // CHECK-NEXT: nop
+ } else {
+ other_func(10); // <-- NOP expected (at end of BB w/ EH_LABEL)
+ // CHECK: call "?other_func@@YAXH@Z"
+ // CHECK-NEXT: nop
+ }
+ does_not_throw();
+ // <-- EH state transition 0 to -1
+ // ~HasDtor() runs
+
+ // CHECK: .seh_endproc
+
+ // CHECK: "$ip2state$?case_dtor_runs_after_join@@YAXH@Z":
+ // CHECK-NEXT: .long [[func_begin:.Lfunc_begin([0-9]+)@IMGREL]]
+ // CHECK-NEXT: .long -1
+ // CHECK-NEXT: .long [[tmp1:.Ltmp([0-9]+)]]@IMGREL
+ // CHECK-NEXT: .long 0
+ // CHECK-NEXT: .long [[tmp2:.Ltmp([0-9]+)]]@IMGREL
+ // CHECK-NEXT: .long -1
+}
+
+
+// Check the behavior of NOP padding around tail calls.
+// We do not expect to insert NOPs around tail calls.
+// However, the first call (to other_func()) does get a NOP
+// because it comes before .seh_startepilogue.
+void case_tail_call_no_eh() {
+ // CHECK-LABEL: .def "?case_tail_call_no_eh@@YAXXZ"
+ // CHECK: .seh_endprologue
+
+ // ordinary call
+ other_func(10);
+ // CHECK: call "?other_func@@YAXH@Z"
+ // CHECK-NEXT: nop
+
+ // tail call; no NOP padding after JMP
+ does_not_throw();
+
+ // CHECK: .seh_startepilogue
+ // CHECK: .seh_endepilogue
+ // CHECK: jmp "?does_not_throw@@YAXXZ"
+ // CHECK-NOT: nop
+ // CHECK: .seh_endproc
+}
+
+
+// Check the behavior of a try/catch
+int case_try_catch() {
+ // CHECK-LABEL: .def "?case_try_catch@@YAHXZ"
+ // CHECK: .seh_endprologue
+
+ // Because of the EH_LABELs, the ctor and other_func() get NOPs.
+
+ int result = 0;
+ try {
+ // CHECK: call "??0HasDtor@@QEAA@H@Z"
+ // CHECK-NEXT: nop
+ HasDtor hd{20};
+
+ // CHECK: call "?other_func@@YAXH@Z"
+ // CHECK-NEXT: nop
+ other_func(10);
+
+ // CHECK: call "??1HasDtor@@QEAA@XZ"
+ // CHECK: mov
+ } catch (BadError& e) {
+ result = 1;
+ }
+ return result;
+
+ // CHECK: .seh_endproc
+
+ // CHECK: .def "?dtor$4@?0??case_try_catch@@YAHXZ@4HA"
+ // CHECK: .seh_endprologue
+ // CHECK: call "??1HasDtor@@QEAA@XZ"
+ // CHECK-NEXT: nop
+ // CHECK: .seh_startepilogue
+ // CHECK: .seh_endproc
+}
diff --git a/clang/test/CodeGenHLSL/BasicFeatures/ArrayOutputArguments.hlsl b/clang/test/CodeGenHLSL/BasicFeatures/ArrayOutputArguments.hlsl
index bccfaf5..4571649 100644
--- a/clang/test/CodeGenHLSL/BasicFeatures/ArrayOutputArguments.hlsl
+++ b/clang/test/CodeGenHLSL/BasicFeatures/ArrayOutputArguments.hlsl
@@ -11,7 +11,7 @@ void increment(inout int Arr[2]) {
// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @{{.*}}, i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false)
-// CHECK-NEXT: call void @{{.*}}increment{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]])
+// CHECK-NEXT: call void @{{.*}}increment{{.*}}(ptr noalias noundef align 4 [[Tmp]])
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 [[Tmp]], i32 8, i1 false)
// CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 0
// CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Idx]], align 4
@@ -32,7 +32,7 @@ void fn2(out int Arr[2]) {
// CHECK: [[A:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @{{.*}}, i32 8, i1 false)
-// CHECK-NEXT: call void @{{.*}}fn2{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]])
+// CHECK-NEXT: call void @{{.*}}fn2{{.*}}(ptr noalias noundef align 4 [[Tmp]])
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 [[Tmp]], i32 8, i1 false)
// CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 0
// CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Idx]], align 4
@@ -56,7 +56,7 @@ void nestedCall(inout int Arr[2], uint index) {
// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @{{.*}}, i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false)
-// CHECK-NEXT: call void @{{.*}}nestedCall{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]], i32 noundef 0)
+// CHECK-NEXT: call void @{{.*}}nestedCall{{.*}}(ptr noalias noundef align 4 [[Tmp]], i32 noundef 0)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 [[Tmp]], i32 8, i1 false)
// CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 1
// CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Idx]], align 4
@@ -70,7 +70,7 @@ export int arrayCall3() {
// CHECK-LABEL: outerCall
// CHECK: [[Tmp:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 %{{.*}}, i32 8, i1 false)
-// CHECK-NEXT: call void {{.*}}increment{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]])
+// CHECK-NEXT: call void {{.*}}increment{{.*}}(ptr noalias noundef align 4 [[Tmp]])
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 {{.*}}, ptr align 4 [[Tmp]], i32 8, i1 false)
// CHECK-NEXT: ret void
void outerCall(inout int Arr[2]) {
@@ -82,7 +82,7 @@ void outerCall(inout int Arr[2]) {
// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @{{.*}}, i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false)
-// CHECK-NEXT: call void @{{.*}}outerCall{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]])
+// CHECK-NEXT: call void @{{.*}}outerCall{{.*}}(ptr noalias noundef align 4 [[Tmp]])
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 [[Tmp]], i32 8, i1 false)
// CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 0
// CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Idx]], align 4
@@ -110,7 +110,7 @@ void outerCall2(inout int Arr[2]) {
// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @{{.*}}, i32 8, i1 false)
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false)
-// CHECK-NEXT: call void @{{.*}}outerCall2{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]])
+// CHECK-NEXT: call void @{{.*}}outerCall2{{.*}}(ptr noalias noundef align 4 [[Tmp]])
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 [[Tmp]], i32 8, i1 false)
// CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 0
// CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Idx]], align 4
diff --git a/clang/test/CodeGenOpenCL/amdgpu-features.cl b/clang/test/CodeGenOpenCL/amdgpu-features.cl
index 75e9710..e96dd66 100644
--- a/clang/test/CodeGenOpenCL/amdgpu-features.cl
+++ b/clang/test/CodeGenOpenCL/amdgpu-features.cl
@@ -108,7 +108,7 @@
// GFX1153: "target-features"="+16-bit-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot10-insts,+dot12-insts,+dot5-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32"
// GFX1200: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-buffer-pk-add-bf16-inst,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+ci-insts,+dl-insts,+dot10-insts,+dot11-insts,+dot12-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+fp8-conversion-insts,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx12-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32"
// GFX1201: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-buffer-pk-add-bf16-inst,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+ci-insts,+dl-insts,+dot10-insts,+dot11-insts,+dot12-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+fp8-conversion-insts,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx12-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32"
-// GFX1250: "target-features"="+16-bit-insts,+ashr-pk-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-buffer-pk-add-bf16-inst,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+bf16-trans-insts,+bitop3-insts,+ci-insts,+dl-insts,+dot7-insts,+dot8-insts,+dpp,+fp8-conversion-insts,+fp8e5m3-insts,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx12-insts,+gfx1250-insts,+gfx8-insts,+gfx9-insts,+permlane16-swap,+prng-inst,+setprio-inc-wg-inst,+tanh-insts,+transpose-load-f4f6-insts,+wavefrontsize32
+// GFX1250: "target-features"="+16-bit-insts,+ashr-pk-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-buffer-pk-add-bf16-inst,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+bf16-trans-insts,+bitop3-insts,+ci-insts,+dl-insts,+dot7-insts,+dot8-insts,+dpp,+fp8-conversion-insts,+fp8e5m3-insts,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx12-insts,+gfx1250-insts,+gfx8-insts,+gfx9-insts,+permlane16-swap,+prng-inst,+setprio-inc-wg-inst,+tanh-insts,+transpose-load-f4f6-insts,+vmem-pref-insts,+wavefrontsize32
// GFX1103-W64: "target-features"="+16-bit-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot10-insts,+dot12-insts,+dot5-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize64"
diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250-load-monitor.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250-load-monitor.cl
new file mode 100644
index 0000000..f2552d4
--- /dev/null
+++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250-load-monitor.cl
@@ -0,0 +1,66 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// REQUIRES: amdgpu-registered-target
+// RUN: %clang_cc1 -cl-std=CL2.0 -triple amdgcn-unknown-unknown -target-cpu gfx1250 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-GFX1250
+
+typedef int v2i __attribute__((ext_vector_type(2)));
+typedef int v4i __attribute__((ext_vector_type(4)));
+
+// CHECK-GFX1250-LABEL: @test_amdgcn_global_load_monitor_b32(
+// CHECK-GFX1250-NEXT: entry:
+// CHECK-GFX1250-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.amdgcn.global.load.monitor.b32.i32(ptr addrspace(1) [[INPTR:%.*]], i32 1)
+// CHECK-GFX1250-NEXT: ret i32 [[TMP0]]
+//
+int test_amdgcn_global_load_monitor_b32(global int* inptr)
+{
+ return __builtin_amdgcn_global_load_monitor_b32(inptr, 1);
+}
+
+// CHECK-GFX1250-LABEL: @test_amdgcn_global_load_monitor_b64(
+// CHECK-GFX1250-NEXT: entry:
+// CHECK-GFX1250-NEXT: [[TMP0:%.*]] = tail call <2 x i32> @llvm.amdgcn.global.load.monitor.b64.v2i32(ptr addrspace(1) [[INPTR:%.*]], i32 10)
+// CHECK-GFX1250-NEXT: ret <2 x i32> [[TMP0]]
+//
+v2i test_amdgcn_global_load_monitor_b64(global v2i* inptr)
+{
+ return __builtin_amdgcn_global_load_monitor_b64(inptr, 10);
+}
+
+// CHECK-GFX1250-LABEL: @test_amdgcn_global_load_monitor_b128(
+// CHECK-GFX1250-NEXT: entry:
+// CHECK-GFX1250-NEXT: [[TMP0:%.*]] = tail call <4 x i32> @llvm.amdgcn.global.load.monitor.b128.v4i32(ptr addrspace(1) [[INPTR:%.*]], i32 22)
+// CHECK-GFX1250-NEXT: ret <4 x i32> [[TMP0]]
+//
+v4i test_amdgcn_global_load_monitor_b128(global v4i* inptr)
+{
+ return __builtin_amdgcn_global_load_monitor_b128(inptr, 22);
+}
+
+// CHECK-GFX1250-LABEL: @test_amdgcn_flat_load_monitor_b32(
+// CHECK-GFX1250-NEXT: entry:
+// CHECK-GFX1250-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.amdgcn.flat.load.monitor.b32.i32(ptr [[INPTR:%.*]], i32 27)
+// CHECK-GFX1250-NEXT: ret i32 [[TMP0]]
+//
+int test_amdgcn_flat_load_monitor_b32(int* inptr)
+{
+ return __builtin_amdgcn_flat_load_monitor_b32(inptr, 27);
+}
+
+// CHECK-GFX1250-LABEL: @test_amdgcn_flat_load_monitor_b64(
+// CHECK-GFX1250-NEXT: entry:
+// CHECK-GFX1250-NEXT: [[TMP0:%.*]] = tail call <2 x i32> @llvm.amdgcn.flat.load.monitor.b64.v2i32(ptr [[INPTR:%.*]], i32 1)
+// CHECK-GFX1250-NEXT: ret <2 x i32> [[TMP0]]
+//
+v2i test_amdgcn_flat_load_monitor_b64(v2i* inptr)
+{
+ return __builtin_amdgcn_flat_load_monitor_b64(inptr, 1);
+}
+
+// CHECK-GFX1250-LABEL: @test_amdgcn_flat_load_monitor_b128(
+// CHECK-GFX1250-NEXT: entry:
+// CHECK-GFX1250-NEXT: [[TMP0:%.*]] = tail call <4 x i32> @llvm.amdgcn.flat.load.monitor.b128.v4i32(ptr [[INPTR:%.*]], i32 0)
+// CHECK-GFX1250-NEXT: ret <4 x i32> [[TMP0]]
+//
+v4i test_amdgcn_flat_load_monitor_b128(v4i* inptr)
+{
+ return __builtin_amdgcn_flat_load_monitor_b128(inptr, 0);
+}
diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250-wmma-w32.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250-wmma-w32.cl
index e4ef3de..86c27d4 100644
--- a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250-wmma-w32.cl
+++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250-wmma-w32.cl
@@ -157,6 +157,18 @@ void test_amdgcn_wmma_i32_16x16x64_iu8(global v8i* out, v8i a, v8i b, v8i c)
*out = __builtin_amdgcn_wmma_i32_16x16x64_iu8(0, a, 0, b, c, false, true);
}
+// CHECK-GFX1250-LABEL: @test_amdgcn_wmma_f32_16x16x128_f8f6f4(
+// CHECK-GFX1250-NEXT: entry:
+// CHECK-GFX1250-NEXT: [[TMP0:%.*]] = shufflevector <16 x i32> [[B:%.*]], <16 x i32> poison, <12 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>
+// CHECK-GFX1250-NEXT: [[TMP1:%.*]] = tail call <8 x float> @llvm.amdgcn.wmma.f32.16x16x128.f8f6f4.v8f32.v16i32.v12i32(i32 1, <16 x i32> [[A:%.*]], i32 2, <12 x i32> [[TMP0]], i16 0, <8 x float> [[C:%.*]])
+// CHECK-GFX1250-NEXT: store <8 x float> [[TMP1]], ptr addrspace(1) [[OUT:%.*]], align 32, !tbaa [[TBAA4]]
+// CHECK-GFX1250-NEXT: ret void
+//
+void test_amdgcn_wmma_f32_16x16x128_f8f6f4(global v8f* out, v16i a, v16i b, v8f c)
+{
+ *out = __builtin_amdgcn_wmma_f32_16x16x128_f8f6f4(1, a, 2, b, 0, c);
+}
+
// CHECK-GFX1250-LABEL: @test_amdgcn_wmma_f32_16x16x32_f16(
// CHECK-GFX1250-NEXT: entry:
// CHECK-GFX1250-NEXT: [[TMP0:%.*]] = tail call <8 x float> @llvm.amdgcn.wmma.f32.16x16x32.f16.v8f32.v16f16(i1 false, <16 x half> [[A:%.*]], i1 false, <16 x half> [[B:%.*]], i16 0, <8 x float> [[C:%.*]], i1 false, i1 true)
diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250.cl
index a21862c..81f39f9 100644
--- a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250.cl
+++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250.cl
@@ -440,6 +440,25 @@ void test_permlane16_swap(global uint2* out, uint old, uint src) {
*out = __builtin_amdgcn_permlane16_swap(old, src, false, true);
}
+// CHECK-LABEL: @test_prefetch(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[FPTR_ADDR:%.*]] = alloca ptr, align 8, addrspace(5)
+// CHECK-NEXT: [[GPTR_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5)
+// CHECK-NEXT: [[FPTR_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[FPTR_ADDR]] to ptr
+// CHECK-NEXT: [[GPTR_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[GPTR_ADDR]] to ptr
+// CHECK-NEXT: store ptr [[FPTR:%.*]], ptr [[FPTR_ADDR_ASCAST]], align 8
+// CHECK-NEXT: store ptr addrspace(1) [[GPTR:%.*]], ptr [[GPTR_ADDR_ASCAST]], align 8
+// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[FPTR_ADDR_ASCAST]], align 8
+// CHECK-NEXT: call void @llvm.amdgcn.flat.prefetch(ptr [[TMP0]], i32 0)
+// CHECK-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr [[GPTR_ADDR_ASCAST]], align 8
+// CHECK-NEXT: call void @llvm.amdgcn.global.prefetch(ptr addrspace(1) [[TMP1]], i32 8)
+// CHECK-NEXT: ret void
+//
+void test_prefetch(generic void *fptr, global void *gptr) {
+ __builtin_amdgcn_flat_prefetch(fptr, 0);
+ __builtin_amdgcn_global_prefetch(gptr, 8);
+}
+
// CHECK-LABEL: @test_cvt_f32_fp8_e5m3(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5)
diff --git a/clang/test/DebugInfo/KeyInstructions/asm.c b/clang/test/DebugInfo/KeyInstructions/asm.c
new file mode 100644
index 0000000..2b33016
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/asm.c
@@ -0,0 +1,59 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// RUN: %clang_cc1 -triple aarch64 -target-feature +ls64 -O0 -emit-llvm -x c %s -o - -gkey-instructions -debug-info-kind=line-tables-only -gno-column-info | FileCheck %s
+// Partially copied from clang/test/CodeGen/AArch64/ls64-inline-asm.c
+
+// Check the inline asm call and result store are Key and distinct atoms.
+
+struct foo { unsigned long long x[8]; };
+// CHECK-LABEL: define dso_local void @load(
+// CHECK-SAME: ptr noundef [[OUTPUT:%.*]], ptr noundef [[ADDR:%.*]]) #[[ATTR0:[0-9]+]] !dbg [[DBG5:![0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[OUTPUT_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT: [[ADDR_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT: store ptr [[OUTPUT]], ptr [[OUTPUT_ADDR]], align 8
+// CHECK-NEXT: store ptr [[ADDR]], ptr [[ADDR_ADDR]], align 8
+// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 8, !dbg [[DBG9:![0-9]+]]
+// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ADDR_ADDR]], align 8, !dbg [[DBG9]]
+// CHECK-NEXT: [[TMP2:%.*]] = call i512 asm sideeffect "ld64b $0,[$1]", "=r,r,~{memory}"(ptr [[TMP1]]) #[[ATTR1:[0-9]+]], !dbg [[DBG10:![0-9]+]], !srcloc [[META11:![0-9]+]]
+// CHECK-NEXT: store i512 [[TMP2]], ptr [[TMP0]], align 8, !dbg [[DBG12:![0-9]+]]
+// CHECK-NEXT: ret void, !dbg [[DBG13:![0-9]+]]
+//
+void load(struct foo *output, void *addr) {
+ __asm__ volatile ("ld64b %0,[%1]" : "=r" (*output) : "r" (addr) : "memory");
+}
+
+// CHECK-LABEL: define dso_local void @load2(
+// CHECK-SAME: ptr noundef [[OUTPUT:%.*]], ptr noundef [[ADDR:%.*]]) #[[ATTR0]] !dbg [[DBG14:![0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[OUTPUT_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT: [[ADDR_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT: store ptr [[OUTPUT]], ptr [[OUTPUT_ADDR]], align 8
+// CHECK-NEXT: store ptr [[ADDR]], ptr [[ADDR_ADDR]], align 8
+// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[OUTPUT_ADDR]], align 8, !dbg [[DBG15:![0-9]+]]
+// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ADDR_ADDR]], align 8, !dbg [[DBG15]]
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 asm sideeffect "ld64b $0,[$1]", "=r,r,~{memory}"(ptr [[TMP1]]) #[[ATTR1]], !dbg [[DBG16:![0-9]+]], !srcloc [[META17:![0-9]+]]
+// CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP0]], align 4, !dbg [[DBG18:![0-9]+]]
+// CHECK-NEXT: ret void, !dbg [[DBG19:![0-9]+]]
+//
+void load2(int *output, void *addr) {
+ __asm__ volatile ("ld64b %0,[%1]" : "=r" (*output) : "r" (addr) : "memory");
+}
+//.
+// CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C11, file: [[META1:![0-9]+]], producer: "{{.*}}clang version {{.*}}", isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, splitDebugInlining: false, nameTableKind: None)
+// CHECK: [[META1]] = !DIFile(filename: "{{.*}}<stdin>", directory: {{.*}})
+// CHECK: [[DBG5]] = distinct !DISubprogram(name: "load", scope: [[META6:![0-9]+]], file: [[META6]], line: 21, type: [[META7:![0-9]+]], scopeLine: 21, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], keyInstructions: true)
+// CHECK: [[META6]] = !DIFile(filename: "{{.*}}asm.c", directory: {{.*}})
+// CHECK: [[META7]] = !DISubroutineType(types: [[META8:![0-9]+]])
+// CHECK: [[META8]] = !{}
+// CHECK: [[DBG9]] = !DILocation(line: 22, scope: [[DBG5]])
+// CHECK: [[DBG10]] = !DILocation(line: 22, scope: [[DBG5]], atomGroup: 1, atomRank: 1)
+// CHECK: [[META11]] = !{i64 1458}
+// CHECK: [[DBG12]] = !DILocation(line: 22, scope: [[DBG5]], atomGroup: 2, atomRank: 1)
+// CHECK: [[DBG13]] = !DILocation(line: 23, scope: [[DBG5]], atomGroup: 3, atomRank: 1)
+// CHECK: [[DBG14]] = distinct !DISubprogram(name: "load2", scope: [[META6]], file: [[META6]], line: 38, type: [[META7]], scopeLine: 38, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], keyInstructions: true)
+// CHECK: [[DBG15]] = !DILocation(line: 39, scope: [[DBG14]])
+// CHECK: [[DBG16]] = !DILocation(line: 39, scope: [[DBG14]], atomGroup: 1, atomRank: 1)
+// CHECK: [[META17]] = !{i64 2501}
+// CHECK: [[DBG18]] = !DILocation(line: 39, scope: [[DBG14]], atomGroup: 2, atomRank: 1)
+// CHECK: [[DBG19]] = !DILocation(line: 40, scope: [[DBG14]], atomGroup: 3, atomRank: 1)
+//.
diff --git a/clang/test/DebugInfo/KeyInstructions/goto.c b/clang/test/DebugInfo/KeyInstructions/goto.c
new file mode 100644
index 0000000..ead92e6
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/goto.c
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -x c++ -std=c++17 %s -debug-info-kind=line-tables-only -emit-llvm -o - -gno-column-info \
+// RUN: | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -gkey-instructions -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - -gno-column-info \
+// RUN: | FileCheck %s
+
+// Check the goto branches get Key Instructions metadata.
+void ext();
+void test_goto(void) {
+// CHECK: br label %dst1, !dbg [[G1R1:!.*]]
+ goto dst1;
+dst1:
+ ext();
+
+ void *ptr = &&dst2;
+// CHECK: br label %indirectgoto, !dbg [[G3R1:!.*]]
+ goto *ptr;
+dst2:
+ ext();
+
+// CHECK: br label %dst3, !dbg [[G4R1:!.*]]
+ goto *&&dst3;
+dst3:
+ ext();
+
+ return;
+}
+
+// CHECK: [[G1R1]] = !DILocation(line: 10, scope: ![[#]], atomGroup: 1, atomRank: 1)
+// CHECK: [[G3R1]] = !DILocation(line: 16, scope: ![[#]], atomGroup: 3, atomRank: 1)
+// CHECK: [[G4R1]] = !DILocation(line: 21, scope: ![[#]], atomGroup: 4, atomRank: 1)
diff --git a/clang/test/Driver/amdgpu-hip-system-arch.c b/clang/test/Driver/amdgpu-hip-system-arch.c
index 9c27bc0..12e298a 100644
--- a/clang/test/Driver/amdgpu-hip-system-arch.c
+++ b/clang/test/Driver/amdgpu-hip-system-arch.c
@@ -14,14 +14,14 @@
// RUN: | FileCheck %s --check-prefix=NO-OUTPUT-ERROR
// RUN: not %clang -### --target=x86_64-unknown-linux-gnu -nogpulib --offload-new-driver --offload-arch=native --amdgpu-arch-tool=%t/amdgpu_arch_fail -x hip %s 2>&1 \
// RUN: | FileCheck %s --check-prefix=NO-OUTPUT-ERROR
-// NO-OUTPUT-ERROR: error: cannot determine amdgcn architecture{{.*}}; consider passing it via '--offload-arch'
+// NO-OUTPUT-ERROR: error: cannot determine hip architecture{{.*}}; consider passing it via '--offload-arch'
// case when amdgpu-arch does not return anything with successful execution
// RUN: not %clang -### --target=x86_64-unknown-linux-gnu -nogpulib --offload-arch=native --amdgpu-arch-tool=%t/amdgpu_arch_empty -x hip %s 2>&1 \
// RUN: | FileCheck %s --check-prefix=EMPTY-OUTPUT
// RUN: not %clang -### --target=x86_64-unknown-linux-gnu -nogpulib --offload-new-driver --offload-arch=native --amdgpu-arch-tool=%t/amdgpu_arch_empty -x hip %s 2>&1 \
// RUN: | FileCheck %s --check-prefix=EMPTY-OUTPUT
-// EMPTY-OUTPUT: error: cannot determine amdgcn architecture: No AMD GPU detected in the system; consider passing it via '--offload-arch'
+// EMPTY-OUTPUT: error: cannot determine hip architecture: No GPU detected in the system; consider passing it via '--offload-arch'
// case when amdgpu-arch returns a gfx906 GPU.
// RUN: %clang -### --target=x86_64-unknown-linux-gnu -nogpuinc -nogpulib --offload-arch=native --amdgpu-arch-tool=%t/amdgpu_arch_gfx906 -x hip %s 2>&1 \
@@ -36,4 +36,4 @@
// RUN: --offload-arch=native --amdgpu-arch-tool=%t/amdgpu_arch_gfx906 \
// RUN: -x hip %s 2>&1 | \
// RUN: FileCheck %s --check-prefix=BAD-TIMEOUT
-// BAD-TIMEOUT: clang: error: cannot determine amdgcn architecture: CLANG_TOOLCHAIN_PROGRAM_TIMEOUT expected an integer, got 'foo'; consider passing it via '--offload-arch'; environment variable CLANG_TOOLCHAIN_PROGRAM_TIMEOUT specifies the tool timeout (integer secs, <=0 is infinite)
+// BAD-TIMEOUT: clang: error: cannot determine hip architecture: CLANG_TOOLCHAIN_PROGRAM_TIMEOUT expected an integer, got 'foo'; consider passing it via '--offload-arch'; environment variable CLANG_TOOLCHAIN_PROGRAM_TIMEOUT specifies the tool timeout (integer secs, <=0 is infinite)
diff --git a/clang/test/Driver/baremetal.cpp b/clang/test/Driver/baremetal.cpp
index 4dc3201..adb59e1 100644
--- a/clang/test/Driver/baremetal.cpp
+++ b/clang/test/Driver/baremetal.cpp
@@ -257,7 +257,7 @@
// CHECK-RV64-SAME:"{{.*}}.o"
// CHECK-RV64-SAME: "{{[^"]*}}libclang_rt.builtins.a"
// CHECK-RV64-SAME: "-lc"
-// CHECK-RV64-SAME: "-X" "-o" "{{.*}}.tmp.out"
+// CHECK-RV64-SAME: "-o" "{{.*}}.tmp.out"
// RUN: %clangxx %s -### --target=riscv64-unknown-elf 2>&1 \
// RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf \
@@ -271,7 +271,7 @@
// CHECK-RV64-DEFAULTCXX-SAME: "-lc++" "-lm"
// CHECK-RV64-DEFAULTCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a"
// CHECK-RV64-DEFAULTCXX-SAME: "-lc"
-// CHECK-RV64-DEFAULTCXX-SAME: "-X" "-o" "a.out"
+// CHECK-RV64-DEFAULTCXX-SAME: "-o" "a.out"
// RUN: %clangxx %s -### --target=riscv64-unknown-elf 2>&1 \
// RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf \
@@ -288,7 +288,7 @@
// CHECK-RV64-LIBCXX-SAME: "-lc++" "-lm"
// CHECK-RV64-LIBCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a"
// CHECK-RV64-LIBCXX-SAME: "-lc"
-// CHECK-RV64-LIBCXX-SAME: "-X" "-o" "a.out"
+// CHECK-RV64-LIBCXX-SAME: "-o" "a.out"
// RUN: %clangxx %s -### 2>&1 --target=riscv64-unknown-elf \
// RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf \
@@ -305,7 +305,7 @@
// CHECK-RV64-LIBSTDCXX-SAME: "-lstdc++" "-lm"
// CHECK-RV64-LIBSTDCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a"
// CHECK-RV64-LIBSTDCXX-SAME: "-lc"
-// CHECK-RV64-LIBSTDCXX-SAME: "-X" "-o" "a.out"
+// CHECK-RV64-LIBSTDCXX-SAME: "-o" "a.out"
// RUN: %clang %s -### 2>&1 --target=riscv32-unknown-elf \
// RUN: -L some/directory/user/asked/for \
@@ -325,7 +325,7 @@
// CHECK-RV32-SAME: "{{.*}}.o"
// CHECK-RV32-SAME: "{{[^"]*}}libclang_rt.builtins.a"
// CHECK-RV32-SAME: "-lc"
-// CHECK-RV32-SAME: "-X" "-o" "a.out"
+// CHECK-RV32-SAME: "-o" "a.out"
// RUN: %clangxx %s -### 2>&1 --target=riscv32-unknown-elf \
// RUN: --sysroot=%S/Inputs/basic_riscv32_tree/riscv32-unknown-elf \
@@ -339,7 +339,7 @@
// CHECK-RV32-DEFAULTCXX-SAME: "-lc++" "-lm"
// CHECK-RV32-DEFAULTCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a"
// CHECK-RV32-DEFAULTCXX-SAME: "-lc"
-// CHECK-RV32-DEFAULTCXX-SAME: "-X" "-o" "a.out"
+// CHECK-RV32-DEFAULTCXX-SAME: "-o" "a.out"
// RUN: %clangxx %s -### 2>&1 --target=riscv32-unknown-elf \
// RUN: --sysroot=%S/Inputs/basic_riscv32_tree/riscv32-unknown-elf \
@@ -355,7 +355,7 @@
// CHECK-RV32-LIBCXX-SAME: "{{.*}}.o"
// CHECK-RV32-LIBCXX-SAME: "-lc++" "-lm"
// CHECK-RV32-LIBCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a"
-// CHECK-RV32-LIBCXX-SAME: "-X" "-o" "a.out"
+// CHECK-RV32-LIBCXX-SAME: "-o" "a.out"
// RUN: %clangxx %s -### 2>&1 --target=riscv32-unknown-elf \
// RUN: --sysroot=%S/Inputs/basic_riscv32_tree/riscv32-unknown-elf \
@@ -372,7 +372,7 @@
// CHECK-RV32-LIBSTDCXX-SAME: "-lstdc++" "-lm"
// CHECK-RV32-LIBSTDCXX-SAME: "{{[^"]*}}libclang_rt.builtins.a"
// CHECK-RV32-LIBSTDCXX-SAME: "-lc"
-// CHECK-RV32-LIBSTDCXX-SAME: "-X" "-o" "a.out"
+// CHECK-RV32-LIBSTDCXX-SAME: "-o" "a.out"
// RUN: %clang %s -### 2>&1 --target=riscv64-unknown-elf \
// RUN: -nostdlibinc -nobuiltininc \
diff --git a/clang/test/Driver/cuda-phases.cu b/clang/test/Driver/cuda-phases.cu
index 8b91a1d..220a320 100644
--- a/clang/test/Driver/cuda-phases.cu
+++ b/clang/test/Driver/cuda-phases.cu
@@ -324,8 +324,8 @@
// RUN: -ccc-print-phases --offload-arch=sm_999 -fgpu-rdc -c %s 2>&1 \
// RUN: | FileCheck -check-prefix=INVALID-ARCH %s
// INVALID-ARCH: error: unsupported CUDA gpu architecture: sm_999
-// INVALID-ARCH-NEXT: 0: input, "[[INPUT:.+]]", cuda, (host-cuda)
-// INVALID-ARCH-NEXT: 1: preprocessor, {0}, cuda-cpp-output, (host-cuda)
-// INVALID-ARCH-NEXT: 2: compiler, {1}, ir, (host-cuda)
-// INVALID-ARCH-NEXT: 3: backend, {2}, assembler, (host-cuda)
-// INVALID-ARCH-NEXT: 4: assembler, {3}, object, (host-cuda)
+// INVALID-ARCH: 0: input, "[[INPUT:.+]]", cuda
+// INVALID-ARCH-NEXT: 1: preprocessor, {0}, cuda-cpp-output
+// INVALID-ARCH-NEXT: 2: compiler, {1}, ir
+// INVALID-ARCH-NEXT: 3: backend, {2}, assembler
+// INVALID-ARCH-NEXT: 4: assembler, {3}, object
diff --git a/clang/test/Driver/hip-inputs.hip b/clang/test/Driver/hip-inputs.hip
index 2d4cc31..a8e25ad 100644
--- a/clang/test/Driver/hip-inputs.hip
+++ b/clang/test/Driver/hip-inputs.hip
@@ -15,5 +15,5 @@
// RUN: --hip-link %S/Inputs/hip_multiple_inputs/a.cu 2>&1 \
// RUN: | FileCheck -check-prefix=MIX %s
-// CHECK-NOT: error: mixed CUDA and HIP compilation is not supported
-// MIX: error: mixed CUDA and HIP compilation is not supported
+// CHECK-NOT: error: mixed CUDA and HIP offloading compilation is not supported
+// MIX: error: mixed CUDA and HIP offloading compilation is not supported
diff --git a/clang/test/Driver/hip-invalid-target-id.hip b/clang/test/Driver/hip-invalid-target-id.hip
index 555043f..ad942e4 100644
--- a/clang/test/Driver/hip-invalid-target-id.hip
+++ b/clang/test/Driver/hip-invalid-target-id.hip
@@ -4,7 +4,7 @@
// RUN: --rocm-path=%S/Inputs/rocm \
// RUN: %s 2>&1 | FileCheck -check-prefix=NOPLUS %s
-// NOPLUS: error: invalid target ID 'gfx908xnack'
+// NOPLUS: error: unsupported HIP gpu architecture: gfx908xnack
// RUN: not %clang -### --target=x86_64-linux-gnu \
// RUN: -x hip --offload-arch=gfx900 \
@@ -22,7 +22,7 @@
// RUN: --rocm-path=%S/Inputs/rocm \
// RUN: %s 2>&1 | FileCheck -check-prefix=UNK %s
-// UNK: error: invalid target ID 'gfx908:unknown+'
+// UNK: error: unsupported HIP gpu architecture: gfx900+xnack
// RUN: not %clang -### --target=x86_64-linux-gnu \
// RUN: -x hip --offload-arch=gfx908 \
@@ -31,7 +31,7 @@
// RUN: --rocm-path=%S/Inputs/rocm \
// RUN: %s 2>&1 | FileCheck -check-prefix=MIXED %s
-// MIXED: error: invalid target ID 'gfx908:sramecc+:unknown+'
+// MIXED: error: unsupported HIP gpu architecture: gfx900+xnack
// RUN: not %clang -### --target=x86_64-linux-gnu \
// RUN: -x hip --offload-arch=gfx908 \
@@ -55,7 +55,7 @@
// RUN: --rocm-path=%S/Inputs/rocm \
// RUN: %s 2>&1 | FileCheck -check-prefix=NOCOLON %s
-// NOCOLON: error: invalid target ID 'gfx900+xnack'
+// NOCOLON: error: unsupported HIP gpu architecture: gfx900+xnack
// RUN: not %clang -### --target=x86_64-linux-gnu \
// RUN: -x hip --offload-arch=gfx908 \
diff --git a/clang/test/Driver/hip-options.hip b/clang/test/Driver/hip-options.hip
index 4fb5571..ba23bc2 100644
--- a/clang/test/Driver/hip-options.hip
+++ b/clang/test/Driver/hip-options.hip
@@ -115,11 +115,6 @@
// OMP-NOT: "-cc1"{{.*}} "-triple" "amdgcn-amd-amdhsa" {{.*}} "-fopenmp"
// OMP: "-cc1"{{.*}} "-triple" "x86_64-unknown-linux-gnu" {{.*}} "-fopenmp"
-// RUN: not %clang --target=x86_64-unknown-linux-gnu -nogpuinc -nogpulib \
-// RUN: --offload-arch=gfx906 -fopenmp=libomp -fopenmp-targets=amdgcn %s 2>&1 \
-// RUN: | FileCheck -check-prefix=OMPTGT %s
-// OMPTGT: unsupported option '--offload-targets=' for language mode 'HIP'
-
// Check -Xoffload-linker option is passed to lld.
// RUN: %clang -### --target=x86_64-unknown-linux-gnu -nogpuinc -nogpulib \
diff --git a/clang/test/Driver/hip-phases.hip b/clang/test/Driver/hip-phases.hip
index d8a58b7..0ad5d76 100644
--- a/clang/test/Driver/hip-phases.hip
+++ b/clang/test/Driver/hip-phases.hip
@@ -675,3 +675,25 @@
// DEVICE-ONLY-NEXT: 2: compiler, {1}, ir, (device-hip, gfx90a)
// DEVICE-ONLY-NEXT: 3: backend, {2}, ir, (device-hip, gfx90a)
// DEVICE-ONLY-NEXT: 4: offload, "device-hip (amdgcn-amd-amdhsa:gfx90a)" {3}, none
+
+//
+// Test the new driver bundling SPIR-V targets.
+//
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-new-driver -ccc-print-phases \
+// RUN: --offload-device-only --offload-arch=amdgcnspirv,gfx1030 %s 2>&1 \
+// RUN: | FileCheck -check-prefix=SPIRV-ONLY %s
+// SPIRV-ONLY: 0: input, "[[INPUT:.+]]", hip, (device-hip, gfx1030)
+// SPIRV-ONLY-NEXT: 1: preprocessor, {0}, hip-cpp-output, (device-hip, gfx1030)
+// SPIRV-ONLY-NEXT: 2: compiler, {1}, ir, (device-hip, gfx1030)
+// SPIRV-ONLY-NEXT: 3: backend, {2}, assembler, (device-hip, gfx1030)
+// SPIRV-ONLY-NEXT: 4: assembler, {3}, object, (device-hip, gfx1030)
+// SPIRV-ONLY-NEXT: 5: linker, {4}, image, (device-hip, gfx1030)
+// SPIRV-ONLY-NEXT: 6: offload, "device-hip (amdgcn-amd-amdhsa:gfx1030)" {5}, image
+// SPIRV-ONLY-NEXT: 7: input, "[[INPUT]]", hip, (device-hip, amdgcnspirv)
+// SPIRV-ONLY-NEXT: 8: preprocessor, {7}, hip-cpp-output, (device-hip, amdgcnspirv)
+// SPIRV-ONLY-NEXT: 9: compiler, {8}, ir, (device-hip, amdgcnspirv)
+// SPIRV-ONLY-NEXT: 10: backend, {9}, ir, (device-hip, amdgcnspirv)
+// SPIRV-ONLY-NEXT: 11: linker, {10}, image, (device-hip, amdgcnspirv)
+// SPIRV-ONLY-NEXT: 12: offload, "device-hip (spirv64-amd-amdhsa:amdgcnspirv)" {11}, image
+// SPIRV-ONLY-NEXT: 13: linker, {6, 12}, hip-fatbin, (device-hip)
+// SPIRV-ONLY-NEXT: 14: offload, "device-hip (amdgcn-amd-amdhsa)" {13}, none
diff --git a/clang/test/Driver/invalid-offload-options.cpp b/clang/test/Driver/invalid-offload-options.cpp
index 48d5310..6048a3c 100644
--- a/clang/test/Driver/invalid-offload-options.cpp
+++ b/clang/test/Driver/invalid-offload-options.cpp
@@ -1,29 +1,7 @@
// UNSUPPORTED: system-windows
-// RUN: not %clang -### -x hip --target=x86_64-linux-gnu --offload= \
-// RUN: --hip-path=%S/Inputs/hipspv -nogpuinc -nogpulib %s \
-// RUN: 2>&1 | FileCheck --check-prefix=INVALID-TARGET %s
// RUN: not %clang -### -x hip --target=x86_64-linux-gnu --offload=foo \
// RUN: --hip-path=%S/Inputs/hipspv -nogpuinc -nogpulib %s \
// RUN: 2>&1 | FileCheck --check-prefix=INVALID-TARGET %s
// INVALID-TARGET: error: invalid or unsupported offload target: '{{.*}}'
-
-// In the future we should be able to specify multiple targets for HIP
-// compilation but currently it is not supported.
-//
-// RUN: not %clang -### -x hip --target=x86_64-linux-gnu --offload=foo,bar \
-// RUN: --hip-path=%S/Inputs/hipspv -nogpuinc -nogpulib %s \
-// RUN: 2>&1 | FileCheck --check-prefix=TOO-MANY-TARGETS %s
-// RUN: not %clang -### -x hip --target=x86_64-linux-gnu \
-// RUN: --offload=foo --offload=bar \
-// RUN: --hip-path=%S/Inputs/hipspv -nogpuinc -nogpulib %s \
-// RUN: 2>&1 | FileCheck --check-prefix=TOO-MANY-TARGETS %s
-
-// TOO-MANY-TARGETS: error: only one offload target is supported
-
-// RUN: not %clang -### -x hip --target=x86_64-linux-gnu -nogpuinc -nogpulib \
-// RUN: --offload=amdgcn-amd-amdhsa --offload-arch=gfx900 %s \
-// RUN: 2>&1 | FileCheck --check-prefix=OFFLOAD-ARCH-MIX %s
-
-// OFFLOAD-ARCH-MIX: error: option '--offload-arch' cannot be specified with '--offload'
diff --git a/clang/test/Driver/module-fgen-reduced-bmi.cppm b/clang/test/Driver/module-fgen-reduced-bmi.cppm
index 9bdd4c9..4b893ff 100644
--- a/clang/test/Driver/module-fgen-reduced-bmi.cppm
+++ b/clang/test/Driver/module-fgen-reduced-bmi.cppm
@@ -64,7 +64,8 @@
// RUN: -Wno-missing-reduced-bmi -### 2>&1 | FileCheck Hello.cppm -check-prefix=NO_WARN
//
// RUN: %clang -std=c++20 Hello.cppm --precompile -o Hello.pcm \
-// RUN: -Wno-missing-reduced-bmi -### 2>&1 | FileCheck Hello.cppm -check-prefix=NO_WARN
+// RUN: -fno-modules-reduced-bmi -Wno-missing-reduced-bmi -### 2>&1 | \
+// RUN: FileCheck Hello.cppm -check-prefix=NO_WARN
//--- Hello.cppm
export module Hello;
diff --git a/clang/test/Driver/module-output.cppm b/clang/test/Driver/module-output.cppm
index 7cf0771..197f1d8 100644
--- a/clang/test/Driver/module-output.cppm
+++ b/clang/test/Driver/module-output.cppm
@@ -13,28 +13,29 @@
// Tests that the .pcm file will be generated in the same directory with the specified
// output and the name of the .pcm file should be the same with the input file.
// RUN: %clang -std=c++20 %t/Hello.cppm -fmodule-output -c -o %t/output/Hello.o \
-// RUN: -### 2>&1 | FileCheck %t/Hello.cppm
+// RUN: -fno-modules-reduced-bmi -### 2>&1 | FileCheck %t/Hello.cppm
//
// Tests that the output file will be generated in the input directory if the output
// file is not the corresponding object file.
// RUN: %clang -std=c++20 %t/Hello.cppm %t/AnotherModule.cppm -fmodule-output -o \
-// RUN: %t/output/a.out -### 2>&1 | FileCheck %t/AnotherModule.cppm
+// RUN: %t/output/a.out -fno-modules-reduced-bmi -### 2>&1 | FileCheck %t/AnotherModule.cppm
//
// Tests that clang will reject the command line if it specifies -fmodule-output with
// multiple archs.
// RUN: not %clang %t/Hello.cppm -fmodule-output -arch i386 -arch x86_64 -### \
-// RUN: --target=x86_64-apple-darwin 2>&1 | FileCheck %t/Hello.cppm -check-prefix=MULTIPLE-ARCH
+// RUN: -fno-modules-reduced-bmi --target=x86_64-apple-darwin 2>&1 | FileCheck %t/Hello.cppm \
+// RUN: -check-prefix=MULTIPLE-ARCH
// Tests that the .pcm file will be generated in the same path with the specified one
// in the comamnd line.
// RUN: %clang -std=c++20 %t/Hello.cppm -fmodule-output=%t/pcm/Hello.pcm -o %t/Hello.o \
-// RUN: -c -### 2>&1 | FileCheck %t/Hello.cppm --check-prefix=CHECK-SPECIFIED
+// RUN: -fno-modules-reduced-bmi -c -### 2>&1 | FileCheck %t/Hello.cppm --check-prefix=CHECK-SPECIFIED
//
// RUN: %clang -std=c++20 %t/Hello.cppm -fmodule-output=%t/Hello.pcm -fmodule-output -c -fsyntax-only \
-// RUN: -### 2>&1 | FileCheck %t/Hello.cppm --check-prefix=CHECK-NOT-USED
+// RUN: -fno-modules-reduced-bmi -### 2>&1 | FileCheck %t/Hello.cppm --check-prefix=CHECK-NOT-USED
// Test that we can emit a warning if the type of the input file is not a module interface unit.
-// RUN: %clang -std=c++20 %t/a.cpp -fmodule-output -c -o %t/a.o -### 2>&1 | FileCheck %t/a.cpp
+// RUN: %clang -std=c++20 %t/a.cpp -fmodule-output -fno-modules-reduced-bmi -c -o %t/a.o -### 2>&1 | FileCheck %t/a.cpp
//--- Hello.cppm
export module Hello;
diff --git a/clang/test/Driver/modules.cpp b/clang/test/Driver/modules.cpp
index 088a732..edbe8d8 100644
--- a/clang/test/Driver/modules.cpp
+++ b/clang/test/Driver/modules.cpp
@@ -34,7 +34,7 @@
// Check combining precompile and compile steps works.
//
-// RUN: %clang -std=c++2a -x c++-module %t/foo.cpp -S -o %t/foo2.pcm.o -v 2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE --check-prefix=CHECK-COMPILE
+// RUN: %clang -std=c++2a -x c++-module -fno-modules-reduced-bmi %t/foo.cpp -S -o %t/foo2.pcm.o -v 2>&1 | FileCheck %s --check-prefix=CHECK-PRECOMPILE --check-prefix=CHECK-COMPILE
// Check that .cppm is treated as a module implicitly.
//
diff --git a/clang/test/Driver/nvptx-cuda-system-arch.c b/clang/test/Driver/nvptx-cuda-system-arch.c
index c54eeac..2d4eca8 100644
--- a/clang/test/Driver/nvptx-cuda-system-arch.c
+++ b/clang/test/Driver/nvptx-cuda-system-arch.c
@@ -16,14 +16,14 @@
// RUN: | FileCheck %s --check-prefix=NO-OUTPUT-ERROR
// RUN: not %clang -### --target=x86_64-unknown-linux-gnu -nogpulib --offload-new-driver --offload-arch=native --nvptx-arch-tool=%t/nvptx_arch_fail -x cuda %s 2>&1 \
// RUN: | FileCheck %s --check-prefix=NO-OUTPUT-ERROR
-// NO-OUTPUT-ERROR: error: cannot determine nvptx64 architecture{{.*}}; consider passing it via '--offload-arch'
+// NO-OUTPUT-ERROR: error: cannot determine cuda architecture{{.*}}; consider passing it via '--offload-arch'
// case when nvptx-arch does not return anything with successful execution
// RUN: not %clang -### --target=x86_64-unknown-linux-gnu -nogpulib --offload-arch=native --nvptx-arch-tool=%t/nvptx_arch_empty -x cuda %s 2>&1 \
// RUN: | FileCheck %s --check-prefix=EMPTY-OUTPUT
// RUN: not %clang -### --target=x86_64-unknown-linux-gnu -nogpulib --offload-new-driver --offload-arch=native --nvptx-arch-tool=%t/nvptx_arch_empty -x cuda %s 2>&1 \
// RUN: | FileCheck %s --check-prefix=EMPTY-OUTPUT
-// EMPTY-OUTPUT: error: cannot determine nvptx64 architecture: No NVIDIA GPU detected in the system; consider passing it via '--offload-arch'
+// EMPTY-OUTPUT: error: cannot determine cuda architecture: No GPU detected in the system; consider passing it via '--offload-arch'
// case when nvptx-arch does not return anything with successful execution
// RUN: %clang -### --target=x86_64-unknown-linux-gnu -nogpulib --offload-arch=native --nvptx-arch-tool=%t/nvptx_arch_sm_70 -x cuda --cuda-path=%S/Inputs/CUDA_102/usr/local/cuda %s 2>&1 \
@@ -49,4 +49,4 @@
// RUN: --offload-arch=native --nvptx-arch-tool=%t/nvptx_arch_sm_70 \
// RUN: --cuda-path=%S/Inputs/CUDA_102/usr/local/cuda -x cuda %s 2>&1 | \
// RUN: FileCheck %s --check-prefix=BAD-TIMEOUT
-// BAD-TIMEOUT: clang: error: cannot determine nvptx64 architecture: CLANG_TOOLCHAIN_PROGRAM_TIMEOUT expected an integer, got 'foo'; consider passing it via '--offload-arch'; environment variable CLANG_TOOLCHAIN_PROGRAM_TIMEOUT specifies the tool timeout (integer secs, <=0 is infinite)
+// BAD-TIMEOUT: clang: error: cannot determine cuda architecture: CLANG_TOOLCHAIN_PROGRAM_TIMEOUT expected an integer, got 'foo'; consider passing it via '--offload-arch'; environment variable CLANG_TOOLCHAIN_PROGRAM_TIMEOUT specifies the tool timeout (integer secs, <=0 is infinite)
diff --git a/clang/test/Driver/offload-target.c b/clang/test/Driver/offload-target.c
new file mode 100644
index 0000000..23a2cf2
--- /dev/null
+++ b/clang/test/Driver/offload-target.c
@@ -0,0 +1,22 @@
+// RUN: %clang -### -fsycl --offload-targets=spirv64 -nogpuinc %s -ccc-print-bindings 2>&1 \
+// RUN: | FileCheck %s -check-prefix=SYCL
+// SYCL: "spirv64" - "clang", inputs: ["[[INPUT:.+]]"], output: "[[SYCL_BC:.+]]"
+
+// RUN: %clang -### --offload-targets=amdgcn-amd-amdhsa -nogpulib -nogpuinc -x hip %s -ccc-print-bindings 2>&1 \
+// RUN: | FileCheck %s -check-prefix=HIP
+// HIP: "amdgcn-amd-amdhsa" - "clang", inputs: ["[[INPUT:.+]]"], output: "[[AMD_OBJ:.+]]"
+
+// RUN: %clang -### --offload-targets=nvptx64-nvidia-cuda -nogpulib -nogpuinc -x cuda %s -ccc-print-bindings 2>&1 \
+// RUN: | FileCheck %s -check-prefix=CUDA
+// CUDA: "nvptx64-nvidia-cuda" - "clang", inputs: ["[[INPUT:.+]]"], output: "[[NV_OBJ:.+]]"
+
+// RUN: %clang -### --offload-targets=amdgcn-amd-amdhsa,nvptx64-nvidia-cuda -fopenmp=libomp \
+// RUN: -Xarch_amdgcn --offload-arch=gfx90a -Xarch_nvptx64 --offload-arch=sm_89 \
+// RUN: -nogpulib -nogpuinc %s -ccc-print-bindings 2>&1 \
+// RUN: | FileCheck %s -check-prefix=OPENMP
+// OPENMP: "amdgcn-amd-amdhsa" - "clang", inputs: ["[[INPUT:.+]]"], output: "[[AMD_OBJ:.+]]"
+// OPENMP: "nvptx64-nvidia-cuda" - "clang", inputs: ["[[INPUT]]"], output: "[[NV_OBJ:.+]]"
+
+// RUN: %clang -### --offload-targets=spirv64-amd-amdhsa -nogpulib -nogpuinc -x hip %s -ccc-print-bindings 2>&1 \
+// RUN: | FileCheck %s -check-prefix=HIPSPIRV
+// HIPSPIRV: "spirv64-amd-amdhsa" - "clang", inputs: ["[[INPUT:.+]]"], output: "[[AMD_OBJ:.+]]"
diff --git a/clang/test/Driver/openbsd.c b/clang/test/Driver/openbsd.c
index 6639e9d..1f12cfc 100644
--- a/clang/test/Driver/openbsd.c
+++ b/clang/test/Driver/openbsd.c
@@ -127,9 +127,12 @@
// UNWIND-TABLES: "-funwind-tables=2"
// NO-UNWIND-TABLES-NOT: "-funwind-tables=2"
-// Check that the -X and --no-relax flags are passed to the linker on riscv64
+// Check that the -X and --no-relax flags are passed to the linker
+// RUN: %clang --target=loongarch64-unknown-openbsd -mno-relax -### %s 2>&1 \
+// RUN: | FileCheck --check-prefix=LA64-FLAGS %s
// RUN: %clang --target=riscv64-unknown-openbsd -mno-relax -### %s 2>&1 \
// RUN: | FileCheck -check-prefix=RISCV64-FLAGS %s
+// LA64-FLAGS: "-X" "--no-relax"
// RISCV64-FLAGS: "-X" "--no-relax"
// Check passing LTO flags to the linker
diff --git a/clang/test/Driver/openmp-offload.c b/clang/test/Driver/openmp-offload.c
index 162ff20..64d45f9 100644
--- a/clang/test/Driver/openmp-offload.c
+++ b/clang/test/Driver/openmp-offload.c
@@ -7,7 +7,7 @@
/// Check whether an invalid OpenMP target is specified:
// RUN: not %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'
+// CHK-INVALID-TARGET: error: invalid or unsupported offload target: 'aaa-bbb-ccc-ddd'
/// ###########################################################################
@@ -18,15 +18,6 @@
/// ###########################################################################
-/// Check error for no -fopenmp option
-// RUN: not %clang -### -fopenmp-targets=powerpc64le-ibm-linux-gnu %s 2>&1 \
-// RUN: | FileCheck -check-prefix=CHK-NO-FOPENMP %s
-// RUN: not %clang -### -fopenmp=libgomp -fopenmp-targets=powerpc64le-ibm-linux-gnu %s 2>&1 \
-// RUN: | FileCheck -check-prefix=CHK-NO-FOPENMP %s
-// CHK-NO-FOPENMP: error: '-fopenmp-targets' must be used in conjunction with a '-fopenmp' option compatible with offloading; e.g., '-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
diff --git a/clang/test/Driver/openmp-system-arch.c b/clang/test/Driver/openmp-system-arch.c
index b18ecf3..167b07a 100644
--- a/clang/test/Driver/openmp-system-arch.c
+++ b/clang/test/Driver/openmp-system-arch.c
@@ -24,13 +24,7 @@
// RUN: not %clang -### --target=x86_64-unknown-linux-gnu -nogpulib -fopenmp=libomp --offload-arch=native \
// RUN: --nvptx-arch-tool=%t/nvptx_arch_empty --amdgpu-arch-tool=%t/amdgpu_arch_empty %s 2>&1 \
// RUN: | FileCheck %s --check-prefix=NO-OUTPUT-ERROR
-// RUN: not %clang -### --target=x86_64-unknown-linux-gnu -nogpulib -fopenmp=libomp --offload-arch= \
-// RUN: --nvptx-arch-tool=%t/nvptx_arch_fail --amdgpu-arch-tool=%t/amdgpu_arch_fail %s 2>&1 \
-// RUN: | FileCheck %s --check-prefix=NO-OUTPUT-ERROR
-// RUN: not %clang -### --target=x86_64-unknown-linux-gnu -nogpulib -fopenmp=libomp --offload-arch= \
-// RUN: --nvptx-arch-tool=%t/nvptx_arch_empty --amdgpu-arch-tool=%t/amdgpu_arch_empty %s 2>&1 \
-// RUN: | FileCheck %s --check-prefix=NO-OUTPUT-ERROR
-// NO-OUTPUT-ERROR: error: failed to deduce triple for target architecture 'native'; specify the triple using '-fopenmp-targets' and '-Xopenmp-target' instead
+// NO-OUTPUT-ERROR: error: cannot determine openmp architecture
// case when amdgpu-arch succeeds.
// RUN: %clang -### --target=x86_64-unknown-linux-gnu -nogpulib -fopenmp=libomp --offload-arch=native \
diff --git a/clang/test/Driver/print-multi-selection-flags.c b/clang/test/Driver/print-multi-selection-flags.c
index 8cf8f04bb..b1a0a29 100644
--- a/clang/test/Driver/print-multi-selection-flags.c
+++ b/clang/test/Driver/print-multi-selection-flags.c
@@ -126,3 +126,20 @@
// CHECK-PIE1: -fpie
// CHECK-ROPI: -fropi
// CHECK-RWPI: -frwpi
+
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -Os | FileCheck --check-prefix=CHECK-OPT-OS %s
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -Oz | FileCheck --check-prefix=CHECK-OPT-OZ %s
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a | FileCheck --check-prefix=CHECK-OPT %s
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -O1 | FileCheck --check-prefix=CHECK-OPT %s
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -O2 | FileCheck --check-prefix=CHECK-OPT %s
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -O3 | FileCheck --check-prefix=CHECK-OPT %s
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=aarch64-none-eabi -Os | FileCheck --check-prefix=CHECK-OPT-OS %s
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=aarch64-none-eabi -Oz | FileCheck --check-prefix=CHECK-OPT-OZ %s
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=aarch64-none-eabi | FileCheck --check-prefix=CHECK-OPT %s
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=aarch64-none-eabi -O1 | FileCheck --check-prefix=CHECK-OPT %s
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=aarch64-none-eabi -O2 | FileCheck --check-prefix=CHECK-OPT %s
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=aarch64-none-eabi -O3 | FileCheck --check-prefix=CHECK-OPT %s
+// CHECK-OPT-OZ: -Oz
+// CHECK-OPT-OS: -Os
+// CHECK-OPT-NOT: -Oz
+// CHECK-OPT-NOT: -Os
diff --git a/clang/test/Driver/sparc-target-features.c b/clang/test/Driver/sparc-target-features.c
index a839604..bd17da1 100644
--- a/clang/test/Driver/sparc-target-features.c
+++ b/clang/test/Driver/sparc-target-features.c
@@ -20,6 +20,11 @@
// RUN: %clang --target=sparc -mvis2 %s -### 2>&1 | FileCheck -check-prefix=VIS2 %s
// RUN: %clang --target=sparc -mno-vis2 %s -### 2>&1 | FileCheck -check-prefix=NO-VIS2 %s
+/// Solaris/SPARC defaults to -mvis2
+// RUN: %clang --target=sparc-sun-solaris2.11 %s -### 2>&1 | FileCheck -check-prefix=VIS2 %s
+// RUN: %clang --target=sparc-sun-solaris2.11 -mno-vis2 %s -### 2>&1 | FileCheck -check-prefix=NO-VIS2 %s
+// RUN: %clang --target=sparcv9-sun-solaris2.11 %s -### 2>&1 | FileCheck -check-prefix=VIS2 %s
+// RUN: %clang --target=sparcv9-sun-solaris2.11 -mno-vis2 %s -### 2>&1 | FileCheck -check-prefix=NO-VIS2 %s
// VIS2: "-target-feature" "+vis2"
// NO-VIS2: "-target-feature" "-vis2"
@@ -34,4 +39,8 @@
// SOFT-QUAD-FLOAT: "-target-feature" "-hard-quad-float"
// RUN: %clang --target=sparc -mv8plus %s -### 2>&1 | FileCheck -check-prefix=V8PLUS %s
+/// 32-bit Solaris/SPARC defaults to -mv8plus
+// RUN: %clang --target=sparc-sun-solaris2.11 %s -### 2>&1 | FileCheck -check-prefix=V8PLUS %s
+// RUN: %clang --target=sparc-sun-solaris2.11 -mno-v8plus %s -### 2>&1 | FileCheck -check-prefix=NO-V8PLUS %s
// V8PLUS: "-target-feature" "+v8plus"
+// NO-V8PLUS-NOT: "-target-feature" "+v8plus"
diff --git a/clang/test/Interpreter/fail.cpp b/clang/test/Interpreter/fail.cpp
index 633d927..4963df8 100644
--- a/clang/test/Interpreter/fail.cpp
+++ b/clang/test/Interpreter/fail.cpp
@@ -18,4 +18,11 @@ extern "C" int printf(const char *, ...);
int i = 42;
auto r1 = printf("i = %d\n", i);
// CHECK: i = 42
+
+1aap = 42; // expected-error {{invalid digit 'a' in decimal constant}}
+1aap = 42; i = 5; // expected-error {{invalid digit 'a' in decimal constant}}
+
+printf("i = %d\n", i);
+// CHECK: i = 42
+
%quit
diff --git a/clang/test/Interpreter/pretty-print.c b/clang/test/Interpreter/pretty-print.c
index 56488a1..e1408c0 100644
--- a/clang/test/Interpreter/pretty-print.c
+++ b/clang/test/Interpreter/pretty-print.c
@@ -3,7 +3,7 @@
// RUN: cat %s | clang-repl -Xcc -xc | FileCheck %s
// RUN: cat %s | clang-repl -Xcc -std=c++11 | FileCheck %s
-// UNSUPPORTED: hwasan
+// UNSUPPORTED: hwasan, msan
char c = 'a'; c
diff --git a/clang/test/Interpreter/pretty-print.cpp b/clang/test/Interpreter/pretty-print.cpp
index 612c0bc..e1036ab 100644
--- a/clang/test/Interpreter/pretty-print.cpp
+++ b/clang/test/Interpreter/pretty-print.cpp
@@ -1,6 +1,7 @@
// RUN: clang-repl "int i = 10;" 'extern "C" int printf(const char*,...);' \
// RUN: 'auto r1 = printf("i = %d\n", i);' | FileCheck --check-prefix=CHECK-DRIVER %s
-// UNSUPPORTED: system-aix, system-zos, asan
+// The test is flaky with asan https://github.com/llvm/llvm-project/pull/148701.
+// UNSUPPORTED: system-aix, asan
// CHECK-DRIVER: i = 10
// RUN: cat %s | clang-repl -Xcc -std=c++11 -Xcc -fno-delayed-template-parsing | FileCheck %s
extern "C" int printf(const char*,...);
diff --git a/clang/test/Layout/ms-no-unique-address.cpp b/clang/test/Layout/ms-no-unique-address.cpp
index 51cfd9a..fd92056 100644
--- a/clang/test/Layout/ms-no-unique-address.cpp
+++ b/clang/test/Layout/ms-no-unique-address.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -std=c++2a -fsyntax-only -triple x86_64-windows-msvc -fms-compatibility -fdump-record-layouts %s | FileCheck %s
+// RUN: %clang_cc1 -std=c++2a -fsyntax-only -triple x86_64-uefi -fms-compatibility -fdump-record-layouts %s | FileCheck %s
namespace Empty {
struct A {};
diff --git a/clang/test/Misc/time-passes.c b/clang/test/Misc/time-passes.c
index 370f52e..6afbcd4 100644
--- a/clang/test/Misc/time-passes.c
+++ b/clang/test/Misc/time-passes.c
@@ -19,6 +19,12 @@
// RUN: -ftime-report-json %s -o /dev/null \
// RUN: -mllvm -info-output-file=%t
// RUN: cat %t | FileCheck %s --check-prefixes=JSON
+// Check that -stats-file-timers only outputs pass time info in the stats file
+// and not stderr.
+// RUN: %clang_cc1 -emit-obj -O1 \
+// RUN: %s -o /dev/null \
+// RUN: -stats-file=%t -stats-file-timers 2>&1 | count 0
+// RUN: FileCheck %s -input-file=%t -check-prefixes=JSON
// TIME: Pass execution timing report
// TIME: Total Execution Time:
diff --git a/clang/test/Modules/mingw-exceptions.cppm b/clang/test/Modules/mingw-exceptions.cppm
index db7aa2c..be9d61d 100644
--- a/clang/test/Modules/mingw-exceptions.cppm
+++ b/clang/test/Modules/mingw-exceptions.cppm
@@ -1,5 +1,6 @@
// REQUIRES: x86-registered-target
-// RUN: %clang -target x86_64-windows-gnu -x c++-module -std=gnu++23 -c -o /dev/null -Xclang -disable-llvm-passes %s
+// RUN: %clang -target x86_64-windows-gnu -x c++-module -std=gnu++23 -fno-modules-reduced-bmi \
+// RUN: -c -o /dev/null -Xclang -disable-llvm-passes %s
// Make sure the command succeeds and doesn't break on the -exception-model flag in cc1.
export module empty;
diff --git a/clang/test/OpenMP/copy-gaps-1.cpp b/clang/test/OpenMP/copy-gaps-1.cpp
new file mode 100644
index 0000000..3d4fae3
--- /dev/null
+++ b/clang/test/OpenMP/copy-gaps-1.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -verify -triple x86_64-pc-linux-gnu -fopenmp-targets=amdgcn-amd-amdhsa -fopenmp -emit-llvm %s -o - | FileCheck %s
+// expected-no-diagnostics
+
+struct S {
+ int x;
+ int y;
+ int z;
+ int *p1;
+ int *p2;
+};
+
+struct T : public S {
+ int a;
+ int b;
+ int c;
+};
+
+int main() {
+ T v;
+
+#pragma omp target map(tofrom: v, v.x, v.y, v.z, v.p1[:8], v.a, v.b, v.c)
+ {
+ v.x++;
+ v.y += 2;
+ v.z += 3;
+ v.p1[0] += 4;
+ v.a += 7;
+ v.b += 5;
+ v.c += 6;
+ }
+
+ return 0;
+}
+
+// CHECK: [[CSTSZ:@.+]] = private {{.*}}constant [10 x i64] [i64 0, i64 0, i64 0, i64 4, i64 4, i64 4, i64 32, i64 4, i64 4, i64 4]
+// CHECK: [[CSTTY:@.+]] = private {{.*}}constant [10 x i64] [i64 [[#0x20]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000013]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]]]
+
+// CHECK-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
+// CHECK-DAG: [[KSIZE:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 4
+// CHECK-DAG: store ptr [[SZBASE:%.+]], ptr [[KSIZE]], align 8
+// CHECK-DAG: [[SZBASE]] = getelementptr inbounds [10 x i64], ptr [[SIZES:%[^,]*]], i32 0, i32 0
+
+// Check for filling of four non-constant size elements here: the whole struct
+// size, the (padded) region covering p1 & p2, and the padding at the end of
+// struct T.
+
+// CHECK-DAG: [[STR:%.+]] = getelementptr inbounds [10 x i64], ptr [[SIZES]], i32 0, i32 0
+// CHECK-DAG: store i64 %{{.+}}, ptr [[STR]], align 8
+// CHECK-DAG: [[P1P2:%.+]] = getelementptr inbounds [10 x i64], ptr [[SIZES]], i32 0, i32 1
+// CHECK-DAG: store i64 %{{.+}}, ptr [[P1P2]], align 8
+// CHECK-DAG: [[PAD:%.+]] = getelementptr inbounds [10 x i64], ptr [[SIZES]], i32 0, i32 2
+// CHECK-DAG: store i64 %{{.+}}, ptr [[PAD]], align 8
diff --git a/clang/test/OpenMP/copy-gaps-2.cpp b/clang/test/OpenMP/copy-gaps-2.cpp
new file mode 100644
index 0000000..5bf603a
--- /dev/null
+++ b/clang/test/OpenMP/copy-gaps-2.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -verify -triple x86_64-pc-linux-gnu -fopenmp-targets=amdgcn-amd-amdhsa -fopenmp -emit-llvm %s -o - | FileCheck %s
+// expected-no-diagnostics
+
+struct S {
+ int x;
+ int y;
+ int z;
+};
+
+struct M : public S {
+ int mid;
+};
+
+struct T : public M {
+ int a;
+ int b;
+ int c;
+};
+
+int main() {
+ T v;
+
+#pragma omp target map(tofrom: v, v.y, v.z, v.a)
+ {
+ v.y++;
+ v.z += 2;
+ v.a += 3;
+ v.mid += 5;
+ }
+
+ return 0;
+}
+
+// CHECK: [[CSTSZ:@.+]] = private {{.*}}constant [7 x i64] [i64 0, i64 0, i64 0, i64 0, i64 4, i64 4, i64 4]
+// CHECK: [[CSTTY:@.+]] = private {{.*}}constant [7 x i64] [i64 [[#0x20]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]]]
+
+// CHECK-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
+// CHECK-DAG: [[KSIZE:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 4
+// CHECK-DAG: store ptr [[SZBASE:%.+]], ptr [[KSIZE]], align 8
+// CHECK-DAG: [[SZBASE]] = getelementptr inbounds [7 x i64], ptr [[SIZES:%[^,]*]], i32 0, i32 0
+
+// Fill four non-constant size elements here: the whole struct size, the region
+// covering v.x, the region covering v.mid and the region covering v.b and v.c.
+
+// CHECK-DAG: [[STR:%.+]] = getelementptr inbounds [7 x i64], ptr [[SIZES]], i32 0, i32 0
+// CHECK-DAG: store i64 %{{.+}}, ptr [[STR]], align 8
+// CHECK-DAG: [[X:%.+]] = getelementptr inbounds [7 x i64], ptr [[SIZES]], i32 0, i32 1
+// CHECK-DAG: store i64 %{{.+}}, ptr [[X]], align 8
+// CHECK-DAG: [[MID:%.+]] = getelementptr inbounds [7 x i64], ptr [[SIZES]], i32 0, i32 2
+// CHECK-DAG: store i64 %{{.+}}, ptr [[MID]], align 8
+// CHECK-DAG: [[BC:%.+]] = getelementptr inbounds [7 x i64], ptr [[SIZES]], i32 0, i32 3
+// CHECK-DAG: store i64 %{{.+}}, ptr [[BC]], align 8
diff --git a/clang/test/OpenMP/copy-gaps-3.cpp b/clang/test/OpenMP/copy-gaps-3.cpp
new file mode 100644
index 0000000..5febb18
--- /dev/null
+++ b/clang/test/OpenMP/copy-gaps-3.cpp
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -verify -triple x86_64-pc-linux-gnu -fopenmp-targets=amdgcn-amd-amdhsa -fopenmp -emit-llvm %s -o - | FileCheck %s
+// expected-no-diagnostics
+
+struct S {
+ int x;
+ int y;
+ int z;
+};
+
+struct T : public S {
+ int a;
+ int b;
+ int c;
+};
+
+int main() {
+ T v;
+
+ // This one should have no gap between v.z & v.a.
+#pragma omp target map(tofrom: v, v.y, v.z, v.a)
+ {
+ v.y++;
+ v.z += 2;
+ v.a += 3;
+ }
+
+ return 0;
+}
+
+// CHECK: [[CSTSZ:@.+]] = private {{.*}}constant [6 x i64] [i64 0, i64 0, i64 0, i64 4, i64 4, i64 4]
+// CHECK: [[CSTTY:@.+]] = private {{.*}}constant [6 x i64] [i64 [[#0x20]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]]]
+
+// CHECK-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
+// CHECK-DAG: [[KSIZE:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 4
+// CHECK-DAG: store ptr [[SZBASE:%.+]], ptr [[KSIZE]], align 8
+// CHECK-DAG: [[SZBASE]] = getelementptr inbounds [6 x i64], ptr [[SIZES:%[^,]*]], i32 0, i32 0
+
+// Fill three non-constant size elements here: the whole struct size, the region
+// covering v.x, and the region covering v.b and v.c.
+
+// CHECK-DAG: [[STR:%.+]] = getelementptr inbounds [6 x i64], ptr [[SIZES]], i32 0, i32 0
+// CHECK-DAG: store i64 %{{.+}}, ptr [[STR]], align 8
+// CHECK-DAG: [[X:%.+]] = getelementptr inbounds [6 x i64], ptr [[SIZES]], i32 0, i32 1
+// CHECK-DAG: store i64 %{{.+}}, ptr [[X]], align 8
+// CHECK-DAG: [[BC:%.+]] = getelementptr inbounds [6 x i64], ptr [[SIZES]], i32 0, i32 2
+// CHECK-DAG: store i64 %{{.+}}, ptr [[BC]], align 8
diff --git a/clang/test/OpenMP/copy-gaps-4.cpp b/clang/test/OpenMP/copy-gaps-4.cpp
new file mode 100644
index 0000000..7060fe3
--- /dev/null
+++ b/clang/test/OpenMP/copy-gaps-4.cpp
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -verify -triple x86_64-pc-linux-gnu -fopenmp-targets=amdgcn-amd-amdhsa -fopenmp -emit-llvm %s -o - | FileCheck %s
+// expected-no-diagnostics
+
+struct S {
+ int x;
+ int y;
+ char z; // Hidden padding after here...
+};
+
+struct T : public S {
+ int a;
+ int b;
+ int c;
+};
+
+int main() {
+ T v;
+
+#pragma omp target map(tofrom: v, v.y, v.z, v.a)
+ {
+ v.y++;
+ v.z += 2;
+ v.a += 3;
+ }
+
+ return 0;
+}
+
+// CHECK: [[CSTSZ:@.+]] = private {{.*}}constant [7 x i64] [i64 0, i64 0, i64 0, i64 0, i64 4, i64 1, i64 4]
+// CHECK: [[CSTTY:@.+]] = private {{.*}}constant [7 x i64] [i64 [[#0x20]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]]]
+
+// CHECK-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
+// CHECK-DAG: [[KSIZE:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 4
+// CHECK-DAG: store ptr [[SZBASE:%.+]], ptr [[KSIZE]], align 8
+// CHECK-DAG: [[SZBASE]] = getelementptr inbounds [7 x i64], ptr [[SIZES:%[^,]*]], i32 0, i32 0
+
+// Fill four non-constant size elements here: the whole struct size, the region
+// covering v.x, the region covering padding after v.z and the region covering
+// v.b and v.c.
+
+// CHECK-DAG: [[STR:%.+]] = getelementptr inbounds [7 x i64], ptr [[SIZES]], i32 0, i32 0
+// CHECK-DAG: store i64 %{{.+}}, ptr [[STR]], align 8
+// CHECK-DAG: [[X:%.+]] = getelementptr inbounds [7 x i64], ptr [[SIZES]], i32 0, i32 1
+// CHECK-DAG: store i64 %{{.+}}, ptr [[X]], align 8
+// CHECK-DAG: [[PAD:%.+]] = getelementptr inbounds [7 x i64], ptr [[SIZES]], i32 0, i32 2
+// CHECK-DAG: store i64 %{{.+}}, ptr [[PAD]], align 8
+// CHECK-DAG: [[BC:%.+]] = getelementptr inbounds [7 x i64], ptr [[SIZES]], i32 0, i32 3
+// CHECK-DAG: store i64 %{{.+}}, ptr [[BC]], align 8
diff --git a/clang/test/OpenMP/copy-gaps-5.cpp b/clang/test/OpenMP/copy-gaps-5.cpp
new file mode 100644
index 0000000..fae675d
--- /dev/null
+++ b/clang/test/OpenMP/copy-gaps-5.cpp
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -verify -triple x86_64-pc-linux-gnu -fopenmp-targets=amdgcn-amd-amdhsa -fopenmp -emit-llvm %s -o - | FileCheck %s
+// expected-no-diagnostics
+
+template<typename C>
+struct S {
+ C x;
+ C y;
+ char z; // Hidden padding after here...
+};
+
+template<typename C>
+struct T : public S<C> {
+ C a;
+ C b;
+ C c;
+};
+
+int main() {
+ T<int> v;
+
+#pragma omp target map(tofrom: v, v.y, v.z, v.a)
+ {
+ v.y++;
+ v.z += 2;
+ v.a += 3;
+ }
+
+ return 0;
+}
+
+// CHECK: [[CSTSZ:@.+]] = private {{.*}}constant [7 x i64] [i64 0, i64 0, i64 0, i64 0, i64 4, i64 1, i64 4]
+// CHECK: [[CSTTY:@.+]] = private {{.*}}constant [7 x i64] [i64 [[#0x20]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]]]
+
+// CHECK-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
+// CHECK-DAG: [[KSIZE:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 4
+// CHECK-DAG: store ptr [[SZBASE:%.+]], ptr [[KSIZE]], align 8
+// CHECK-DAG: [[SZBASE]] = getelementptr inbounds [7 x i64], ptr [[SIZES:%[^,]*]], i32 0, i32 0
+
+// Fill four non-constant size elements here: the whole struct size, the region
+// covering v.x, the region covering padding after v.z and the region covering
+// v.b and v.c.
+
+// CHECK-DAG: [[STR:%.+]] = getelementptr inbounds [7 x i64], ptr [[SIZES]], i32 0, i32 0
+// CHECK-DAG: store i64 %{{.+}}, ptr [[STR]], align 8
+// CHECK-DAG: [[X:%.+]] = getelementptr inbounds [7 x i64], ptr [[SIZES]], i32 0, i32 1
+// CHECK-DAG: store i64 %{{.+}}, ptr [[X]], align 8
+// CHECK-DAG: [[PAD:%.+]] = getelementptr inbounds [7 x i64], ptr [[SIZES]], i32 0, i32 2
+// CHECK-DAG: store i64 %{{.+}}, ptr [[PAD]], align 8
+// CHECK-DAG: [[BC:%.+]] = getelementptr inbounds [7 x i64], ptr [[SIZES]], i32 0, i32 3
+// CHECK-DAG: store i64 %{{.+}}, ptr [[BC]], align 8
diff --git a/clang/test/OpenMP/copy-gaps-6.cpp b/clang/test/OpenMP/copy-gaps-6.cpp
new file mode 100644
index 0000000..9c62fde
--- /dev/null
+++ b/clang/test/OpenMP/copy-gaps-6.cpp
@@ -0,0 +1,87 @@
+// RUN: %clang_cc1 -verify -triple x86_64-pc-linux-gnu -fopenmp-targets=amdgcn-amd-amdhsa -fopenmp -emit-llvm %s -o - | FileCheck %s
+// expected-no-diagnostics
+
+struct S {
+ int x;
+ int *arr;
+ int y;
+ int z;
+};
+
+int main() {
+ S v;
+
+#pragma omp target map(tofrom: v, v.x, v.z)
+ {
+ v.x++;
+ v.y += 2;
+ v.z += 3;
+ }
+
+#pragma omp target map(tofrom: v, v.x, v.arr[:1])
+ {
+ v.x++;
+ v.y += 2;
+ v.arr[0] += 2;
+ v.z += 4;
+ }
+
+#pragma omp target map(tofrom: v, v.arr[:1])
+ {
+ v.x++;
+ v.y += 2;
+ v.arr[0] += 2;
+ v.z += 4;
+ }
+
+ return 0;
+}
+
+// CHECK: [[CSTSZ0:@.+]] = private {{.*}}constant [4 x i64] [i64 0, i64 0, i64 4, i64 4]
+// CHECK: [[CSTTY0:@.+]] = private {{.*}}constant [4 x i64] [i64 [[#0x20]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]]]
+
+// CHECK: [[CSTSZ1:@.+]] = private {{.*}}constant [4 x i64] [i64 0, i64 0, i64 4, i64 4]
+// CHECK: [[CSTTY1:@.+]] = private {{.*}}constant [4 x i64] [i64 [[#0x20]], i64 [[#0x1000000000003]], i64 [[#0x1000000000003]], i64 [[#0x1000000000013]]]
+
+// CHECK: [[CSTSZ2:@.+]] = private {{.*}}constant [3 x i64] [i64 0, i64 24, i64 4]
+// CHECK: [[CSTTY2:@.+]] = private {{.*}}constant [3 x i64] [i64 [[#0x20]], i64 [[#0x1000000000003]], i64 [[#0x1000000000013]]]
+
+// CHECK-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
+// CHECK-DAG: [[KSIZE:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 4
+// CHECK-DAG: store ptr [[SZBASE:%.+]], ptr [[KSIZE]], align 8
+// CHECK-DAG: [[SZBASE]] = getelementptr inbounds [4 x i64], ptr [[SIZES:%[^,]*]], i32 0, i32 0
+
+// Fill two non-constant size elements here: the whole struct size, and the
+// region covering v.arr and v.y.
+
+// CHECK-DAG: [[STR:%.+]] = getelementptr inbounds [4 x i64], ptr [[SIZES]], i32 0, i32 0
+// CHECK-DAG: store i64 %{{.+}}, ptr [[STR]], align 8
+// CHECK-DAG: [[ARRY:%.+]] = getelementptr inbounds [4 x i64], ptr [[SIZES]], i32 0, i32 1
+// CHECK-DAG: store i64 %{{.+}}, ptr [[ARRY]], align 8
+
+// CHECK: call void
+
+// CHECK-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
+// CHECK-DAG: [[KSIZE:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 4
+// CHECK-DAG: store ptr [[SZBASE:%.+]], ptr [[KSIZE]], align 8
+// CHECK-DAG: [[SZBASE]] = getelementptr inbounds [4 x i64], ptr [[SIZES:%[^,]*]], i32 0, i32 0
+
+// Fill two non-constant size elements here: the whole struct size, and the
+// region covering v.arr, v.y and v.z.
+
+// CHECK-DAG: [[STR:%.+]] = getelementptr inbounds [4 x i64], ptr [[SIZES]], i32 0, i32 0
+// CHECK-DAG: store i64 %{{.+}}, ptr [[STR]], align 8
+// CHECK-DAG: [[ARRYZ:%.+]] = getelementptr inbounds [4 x i64], ptr [[SIZES]], i32 0, i32 1
+// CHECK-DAG: store i64 %{{.+}}, ptr [[ARRYZ]], align 8
+
+// CHECK: call void
+
+// CHECK-DAG: call i32 @__tgt_target_kernel(ptr @{{.+}}, i64 -1, i32 -1, i32 0, ptr @.{{.+}}.region_id, ptr [[ARGS:%.+]])
+// CHECK-DAG: [[KSIZE:%.+]] = getelementptr inbounds {{.+}}[[ARGS]], i32 0, i32 4
+// CHECK-DAG: store ptr [[SZBASE:%.+]], ptr [[KSIZE]], align 8
+// CHECK-DAG: [[SZBASE]] = getelementptr inbounds [3 x i64], ptr [[SIZES:%[^,]*]], i32 0, i32 0
+
+// Fill one non-constant size element here: the whole struct size.
+
+// CHECK-DAG: [[STR:%.+]] = getelementptr inbounds [3 x i64], ptr [[SIZES]], i32 0, i32 0
+// CHECK-DAG: store i64 %{{.+}}, ptr [[STR]], align 8
diff --git a/clang/test/OpenMP/declare_variant_clauses_ast_print.cpp b/clang/test/OpenMP/declare_variant_clauses_ast_print.cpp
index c14e19c..e98a23e 100644
--- a/clang/test/OpenMP/declare_variant_clauses_ast_print.cpp
+++ b/clang/test/OpenMP/declare_variant_clauses_ast_print.cpp
@@ -38,11 +38,11 @@
#ifndef HEADER
#define HEADER
-void foo_v1(float *AAA, float *BBB, int *I) {return;}
-void foo_v2(float *AAA, float *BBB, int *I) {return;}
-void foo_v3(float *AAA, float *BBB, int *I) {return;}
+void foo_v1(float *AAA, float *BBB, int &CCC, int *I) {return;}
+void foo_v2(float *AAA, float *BBB, int &CCC, int *I) {return;}
+void foo_v3(float *AAA, float *BBB, int &CCC, int *I) {return;}
-//DUMP: FunctionDecl{{.*}} foo 'void (float *, float *, int *)'
+//DUMP: FunctionDecl{{.*}} foo 'void (float *, float *, int &, int *)'
//DUMP: OMPDeclareVariantAttr{{.*}}device={arch(x86, x86_64)}
//DUMP: DeclRefExpr{{.*}}Function{{.*}}foo_v3
//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'I'
@@ -54,9 +54,9 @@ void foo_v3(float *AAA, float *BBB, int *I) {return;}
//DUMP: DeclRefExpr{{.*}}Function{{.*}}foo_v1
//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'AAA'
//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'BBB'
-//PRINT: #pragma omp declare variant(foo_v3) match(construct={dispatch}, device={arch(x86, x86_64)}) adjust_args(nothing:I) adjust_args(need_device_ptr:BBB) adjust_args(need_device_addr:AAA)
+//PRINT: #pragma omp declare variant(foo_v3) match(construct={dispatch}, device={arch(x86, x86_64)}) adjust_args(nothing:I) adjust_args(need_device_ptr:BBB) adjust_args(need_device_addr:CCC)
-//PRINT: #pragma omp declare variant(foo_v2) match(construct={dispatch}, device={arch(ppc)}) adjust_args(need_device_ptr:AAA) adjust_args(need_device_addr:BBB)
+//PRINT: #pragma omp declare variant(foo_v2) match(construct={dispatch}, device={arch(ppc)}) adjust_args(need_device_ptr:AAA) adjust_args(need_device_addr:CCC)
//PRINT: omp declare variant(foo_v1) match(construct={dispatch}, device={arch(arm)}) adjust_args(need_device_ptr:AAA,BBB)
@@ -67,33 +67,33 @@ void foo_v3(float *AAA, float *BBB, int *I) {return;}
#pragma omp declare variant(foo_v2) \
match(construct={dispatch}, device={arch(ppc)}), \
adjust_args(need_device_ptr:AAA) \
- adjust_args(need_device_addr:BBB)
+ adjust_args(need_device_addr:CCC)
#pragma omp declare variant(foo_v3) \
adjust_args(need_device_ptr:BBB) adjust_args(nothing:I) \
- adjust_args(need_device_addr:AAA) \
+ adjust_args(need_device_addr:CCC) \
match(construct={dispatch}, device={arch(x86,x86_64)})
-void foo(float *AAA, float *BBB, int *I) {return;}
+void foo(float *AAA, float *BBB, int &CCC, int *I) {return;}
-void Foo_Var(float *AAA, float *BBB, float *CCC) {return;}
+void Foo_Var(float *AAA, float *BBB, float *&CCC) {return;}
#pragma omp declare variant(Foo_Var) \
match(construct={dispatch}, device={arch(x86_64)}) \
adjust_args(need_device_ptr:AAA) adjust_args(nothing:BBB) \
adjust_args(need_device_addr:CCC)
template<typename T>
-void Foo(T *AAA, T *BBB, T *CCC) {return;}
+void Foo(T *AAA, T *BBB, T *&CCC) {return;}
//PRINT: #pragma omp declare variant(Foo_Var) match(construct={dispatch}, device={arch(x86_64)}) adjust_args(nothing:BBB) adjust_args(need_device_ptr:AAA) adjust_args(need_device_addr:CCC)
-//DUMP: FunctionDecl{{.*}} Foo 'void (T *, T *, T *)'
+//DUMP: FunctionDecl{{.*}} Foo 'void (T *, T *, T *&)'
//DUMP: OMPDeclareVariantAttr{{.*}}device={arch(x86_64)}
//DUMP: DeclRefExpr{{.*}}Function{{.*}}Foo_Var
//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'BBB'
//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'AAA'
//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'CCC'
//
-//DUMP: FunctionDecl{{.*}} Foo 'void (float *, float *, float *)'
+//DUMP: FunctionDecl{{.*}} Foo 'void (float *, float *, float *&)'
//DUMP: OMPDeclareVariantAttr{{.*}}device={arch(x86_64)}
//DUMP: DeclRefExpr{{.*}}Function{{.*}}Foo_Var
//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'BBB'
diff --git a/clang/test/OpenMP/declare_variant_clauses_messages.cpp b/clang/test/OpenMP/declare_variant_clauses_messages.cpp
index bca9148..916d15f 100644
--- a/clang/test/OpenMP/declare_variant_clauses_messages.cpp
+++ b/clang/test/OpenMP/declare_variant_clauses_messages.cpp
@@ -91,6 +91,7 @@ void foo_v1(float *AAA, float *BBB, int *I) { return; }
void foo_v2(float *AAA, float *BBB, int *I) { return; }
void foo_v3(float *AAA, float *BBB, int *I) { return; }
void foo_v4(float *AAA, float *BBB, int *I, omp_interop_t IOp) { return; }
+void foo_v5(float *AAA, float *BBB, int I) { return; }
#if _OPENMP >= 202011 // At least OpenMP 5.1
void vararg_foo(const char *fmt, omp_interop_t it, ...);
@@ -129,6 +130,11 @@ void vararg_bar2(const char *fmt) { return; }
adjust_args(nothing:J) \
match(construct={dispatch}, device={arch(x86,x86_64)})
+// expected-error@+2 {{expected reference type argument on 'adjust_args' clause with 'need_device_addr' modifier}}
+#pragma omp declare variant(foo_v1) \
+ adjust_args(need_device_addr:AAA) \
+ match(construct={dispatch}, device={arch(x86,x86_64)})
+
// expected-error@+2 {{expected reference to one of the parameters of function 'foo'}}
#pragma omp declare variant(foo_v3) \
adjust_args(nothing:Other) \
@@ -218,6 +224,12 @@ void vararg_bar2(const char *fmt) { return; }
void foo(float *AAA, float *BBB, int *I) { return; }
+// expected-error@+2 {{expected reference type argument on 'adjust_args' clause with 'need_device_addr' modifier}}
+#pragma omp declare variant(foo_v5) \
+ adjust_args(need_device_addr:I) \
+ match(construct={dispatch}, device={arch(x86,x86_64)})
+void foo5(float *AAA, float *BBB, int I) { return; }
+
#endif // NO_INTEROP_T_DEF
#ifdef C
diff --git a/clang/test/OpenMP/target_map_array_section_no_length_codegen.cpp b/clang/test/OpenMP/target_map_array_section_no_length_codegen.cpp
new file mode 100644
index 0000000..43fd509
--- /dev/null
+++ b/clang/test/OpenMP/target_map_array_section_no_length_codegen.cpp
@@ -0,0 +1,361 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --include-generated-funcs --replace-value-regex "__omp_offloading_[0-9a-z]+_[0-9a-z]+" "reduction_size[.].+[.]" "pl_cond[.].+[.|,]" --prefix-filecheck-ir-name _ --version 5
+// RUN: %clang_cc1 -verify -triple i386-unknown-unknown -fopenmp -fopenmp-version=60 -fopenmp-targets=i386-pc-linux-gnu -emit-llvm %s -o - | FileCheck %s
+
+// RUN: %clang_cc1 -verify -triple i386-unknown-unknown -fopenmp -fopenmp-version=60 -fopenmp-targets=i386-pc-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -verify -triple i386-unknown-unknown -fopenmp -fopenmp-version=60 -fopenmp-targets=i386-pc-linux-gnu -include-pch %t -emit-llvm %s -o - | FileCheck %s
+
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+void array_section_no_length_map_clause(float *d, int index) {
+ float **f;
+
+ #pragma omp target map(tofrom : d[:])
+ {
+ d[3] += 2;
+ }
+
+ #pragma omp target map(to : d[2:])
+ {
+ d[3] += 3;
+ }
+
+ #pragma omp target map(alloc : f[index][:])
+ {
+ f[index][2] += 4;
+ }
+
+ #pragma omp target map(tofrom : f[index][index+1:])
+ {
+ f[index][index] += 5;
+ }
+}
+#endif
+// CHECK-LABEL: define dso_local void @_Z34array_section_no_length_map_clausePfi(
+// CHECK-SAME: ptr noundef [[D:%.*]], i32 noundef [[INDEX:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[D_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT: [[INDEX_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[F:%.*]] = alloca ptr, align 4
+// CHECK-NEXT: [[DOTOFFLOAD_BASEPTRS:%.*]] = alloca [1 x ptr], align 4
+// CHECK-NEXT: [[DOTOFFLOAD_PTRS:%.*]] = alloca [1 x ptr], align 4
+// CHECK-NEXT: [[DOTOFFLOAD_MAPPERS:%.*]] = alloca [1 x ptr], align 4
+// CHECK-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8
+// CHECK-NEXT: [[DOTOFFLOAD_BASEPTRS2:%.*]] = alloca [1 x ptr], align 4
+// CHECK-NEXT: [[DOTOFFLOAD_PTRS3:%.*]] = alloca [1 x ptr], align 4
+// CHECK-NEXT: [[DOTOFFLOAD_MAPPERS4:%.*]] = alloca [1 x ptr], align 4
+// CHECK-NEXT: [[KERNEL_ARGS5:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
+// CHECK-NEXT: [[INDEX_CASTED:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[DOTOFFLOAD_BASEPTRS11:%.*]] = alloca [3 x ptr], align 4
+// CHECK-NEXT: [[DOTOFFLOAD_PTRS12:%.*]] = alloca [3 x ptr], align 4
+// CHECK-NEXT: [[DOTOFFLOAD_MAPPERS13:%.*]] = alloca [3 x ptr], align 4
+// CHECK-NEXT: [[KERNEL_ARGS14:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
+// CHECK-NEXT: [[INDEX_CASTED17:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[DOTOFFLOAD_BASEPTRS22:%.*]] = alloca [3 x ptr], align 4
+// CHECK-NEXT: [[DOTOFFLOAD_PTRS23:%.*]] = alloca [3 x ptr], align 4
+// CHECK-NEXT: [[DOTOFFLOAD_MAPPERS24:%.*]] = alloca [3 x ptr], align 4
+// CHECK-NEXT: [[DOTOFFLOAD_SIZES:%.*]] = alloca [3 x i64], align 4
+// CHECK-NEXT: [[KERNEL_ARGS25:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8
+// CHECK-NEXT: store ptr [[D]], ptr [[D_ADDR]], align 4
+// CHECK-NEXT: store i32 [[INDEX]], ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[D_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[D_ADDR]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[D_ADDR]], align 4
+// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw float, ptr [[TMP2]], i32 0
+// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK-NEXT: store ptr [[TMP1]], ptr [[TMP3]], align 4
+// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK-NEXT: store ptr [[ARRAYIDX]], ptr [[TMP4]], align 4
+// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS]], i32 0, i32 0
+// CHECK-NEXT: store ptr null, ptr [[TMP5]], align 4
+// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0
+// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0
+// CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
+// CHECK-NEXT: store i32 3, ptr [[TMP8]], align 4
+// CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1
+// CHECK-NEXT: store i32 1, ptr [[TMP9]], align 4
+// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2
+// CHECK-NEXT: store ptr [[TMP6]], ptr [[TMP10]], align 4
+// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 3
+// CHECK-NEXT: store ptr [[TMP7]], ptr [[TMP11]], align 4
+// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 4
+// CHECK-NEXT: store ptr @.offload_sizes, ptr [[TMP12]], align 4
+// CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 5
+// CHECK-NEXT: store ptr @.offload_maptypes, ptr [[TMP13]], align 4
+// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 6
+// CHECK-NEXT: store ptr null, ptr [[TMP14]], align 4
+// CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 7
+// CHECK-NEXT: store ptr null, ptr [[TMP15]], align 4
+// CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 8
+// CHECK-NEXT: store i64 0, ptr [[TMP16]], align 8
+// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 9
+// CHECK-NEXT: store i64 0, ptr [[TMP17]], align 8
+// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 10
+// CHECK-NEXT: store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP18]], align 4
+// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 11
+// CHECK-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP19]], align 4
+// CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 12
+// CHECK-NEXT: store i32 0, ptr [[TMP20]], align 4
+// CHECK-NEXT: [[TMP21:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1:[0-9]+]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l14.region_id, ptr [[KERNEL_ARGS]])
+// CHECK-NEXT: [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
+// CHECK-NEXT: br i1 [[TMP22]], label %[[OMP_OFFLOAD_FAILED:.*]], label %[[OMP_OFFLOAD_CONT:.*]]
+// CHECK: [[OMP_OFFLOAD_FAILED]]:
+// CHECK-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l14(ptr [[TMP0]]) #[[ATTR2:[0-9]+]]
+// CHECK-NEXT: br label %[[OMP_OFFLOAD_CONT]]
+// CHECK: [[OMP_OFFLOAD_CONT]]:
+// CHECK-NEXT: [[TMP23:%.*]] = load ptr, ptr [[D_ADDR]], align 4
+// CHECK-NEXT: [[TMP24:%.*]] = load ptr, ptr [[D_ADDR]], align 4
+// CHECK-NEXT: [[TMP25:%.*]] = load ptr, ptr [[D_ADDR]], align 4
+// CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds nuw float, ptr [[TMP25]], i32 2
+// CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0
+// CHECK-NEXT: store ptr [[TMP24]], ptr [[TMP26]], align 4
+// CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0
+// CHECK-NEXT: store ptr [[ARRAYIDX1]], ptr [[TMP27]], align 4
+// CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_MAPPERS4]], i32 0, i32 0
+// CHECK-NEXT: store ptr null, ptr [[TMP28]], align 4
+// CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0
+// CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0
+// CHECK-NEXT: [[TMP31:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0
+// CHECK-NEXT: store i32 3, ptr [[TMP31]], align 4
+// CHECK-NEXT: [[TMP32:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1
+// CHECK-NEXT: store i32 1, ptr [[TMP32]], align 4
+// CHECK-NEXT: [[TMP33:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2
+// CHECK-NEXT: store ptr [[TMP29]], ptr [[TMP33]], align 4
+// CHECK-NEXT: [[TMP34:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 3
+// CHECK-NEXT: store ptr [[TMP30]], ptr [[TMP34]], align 4
+// CHECK-NEXT: [[TMP35:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 4
+// CHECK-NEXT: store ptr @.offload_sizes.1, ptr [[TMP35]], align 4
+// CHECK-NEXT: [[TMP36:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 5
+// CHECK-NEXT: store ptr @.offload_maptypes.2, ptr [[TMP36]], align 4
+// CHECK-NEXT: [[TMP37:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 6
+// CHECK-NEXT: store ptr null, ptr [[TMP37]], align 4
+// CHECK-NEXT: [[TMP38:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 7
+// CHECK-NEXT: store ptr null, ptr [[TMP38]], align 4
+// CHECK-NEXT: [[TMP39:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 8
+// CHECK-NEXT: store i64 0, ptr [[TMP39]], align 8
+// CHECK-NEXT: [[TMP40:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 9
+// CHECK-NEXT: store i64 0, ptr [[TMP40]], align 8
+// CHECK-NEXT: [[TMP41:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 10
+// CHECK-NEXT: store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP41]], align 4
+// CHECK-NEXT: [[TMP42:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 11
+// CHECK-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP42]], align 4
+// CHECK-NEXT: [[TMP43:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 12
+// CHECK-NEXT: store i32 0, ptr [[TMP43]], align 4
+// CHECK-NEXT: [[TMP44:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l19.region_id, ptr [[KERNEL_ARGS5]])
+// CHECK-NEXT: [[TMP45:%.*]] = icmp ne i32 [[TMP44]], 0
+// CHECK-NEXT: br i1 [[TMP45]], label %[[OMP_OFFLOAD_FAILED6:.*]], label %[[OMP_OFFLOAD_CONT7:.*]]
+// CHECK: [[OMP_OFFLOAD_FAILED6]]:
+// CHECK-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l19(ptr [[TMP23]]) #[[ATTR2]]
+// CHECK-NEXT: br label %[[OMP_OFFLOAD_CONT7]]
+// CHECK: [[OMP_OFFLOAD_CONT7]]:
+// CHECK-NEXT: [[TMP46:%.*]] = load ptr, ptr [[F]], align 4
+// CHECK-NEXT: [[TMP47:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT: store i32 [[TMP47]], ptr [[INDEX_CASTED]], align 4
+// CHECK-NEXT: [[TMP48:%.*]] = load i32, ptr [[INDEX_CASTED]], align 4
+// CHECK-NEXT: [[TMP49:%.*]] = load ptr, ptr [[F]], align 4
+// CHECK-NEXT: [[TMP50:%.*]] = load ptr, ptr [[F]], align 4
+// CHECK-NEXT: [[TMP51:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT: [[ARRAYIDX8:%.*]] = getelementptr inbounds ptr, ptr [[TMP50]], i32 [[TMP51]]
+// CHECK-NEXT: [[TMP52:%.*]] = load ptr, ptr [[F]], align 4
+// CHECK-NEXT: [[TMP53:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT: [[ARRAYIDX9:%.*]] = getelementptr inbounds ptr, ptr [[TMP52]], i32 [[TMP53]]
+// CHECK-NEXT: [[TMP54:%.*]] = load ptr, ptr [[ARRAYIDX9]], align 4
+// CHECK-NEXT: [[ARRAYIDX10:%.*]] = getelementptr inbounds nuw float, ptr [[TMP54]], i32 0
+// CHECK-NEXT: [[TMP55:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0
+// CHECK-NEXT: store ptr [[TMP49]], ptr [[TMP55]], align 4
+// CHECK-NEXT: [[TMP56:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0
+// CHECK-NEXT: store ptr [[ARRAYIDX8]], ptr [[TMP56]], align 4
+// CHECK-NEXT: [[TMP57:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 0
+// CHECK-NEXT: store ptr null, ptr [[TMP57]], align 4
+// CHECK-NEXT: [[TMP58:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 1
+// CHECK-NEXT: store ptr [[ARRAYIDX8]], ptr [[TMP58]], align 4
+// CHECK-NEXT: [[TMP59:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 1
+// CHECK-NEXT: store ptr [[ARRAYIDX10]], ptr [[TMP59]], align 4
+// CHECK-NEXT: [[TMP60:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 1
+// CHECK-NEXT: store ptr null, ptr [[TMP60]], align 4
+// CHECK-NEXT: [[TMP61:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 2
+// CHECK-NEXT: store i32 [[TMP48]], ptr [[TMP61]], align 4
+// CHECK-NEXT: [[TMP62:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 2
+// CHECK-NEXT: store i32 [[TMP48]], ptr [[TMP62]], align 4
+// CHECK-NEXT: [[TMP63:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS13]], i32 0, i32 2
+// CHECK-NEXT: store ptr null, ptr [[TMP63]], align 4
+// CHECK-NEXT: [[TMP64:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0
+// CHECK-NEXT: [[TMP65:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0
+// CHECK-NEXT: [[TMP66:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0
+// CHECK-NEXT: store i32 3, ptr [[TMP66]], align 4
+// CHECK-NEXT: [[TMP67:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1
+// CHECK-NEXT: store i32 3, ptr [[TMP67]], align 4
+// CHECK-NEXT: [[TMP68:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2
+// CHECK-NEXT: store ptr [[TMP64]], ptr [[TMP68]], align 4
+// CHECK-NEXT: [[TMP69:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 3
+// CHECK-NEXT: store ptr [[TMP65]], ptr [[TMP69]], align 4
+// CHECK-NEXT: [[TMP70:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 4
+// CHECK-NEXT: store ptr @.offload_sizes.3, ptr [[TMP70]], align 4
+// CHECK-NEXT: [[TMP71:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 5
+// CHECK-NEXT: store ptr @.offload_maptypes.4, ptr [[TMP71]], align 4
+// CHECK-NEXT: [[TMP72:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 6
+// CHECK-NEXT: store ptr null, ptr [[TMP72]], align 4
+// CHECK-NEXT: [[TMP73:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 7
+// CHECK-NEXT: store ptr null, ptr [[TMP73]], align 4
+// CHECK-NEXT: [[TMP74:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 8
+// CHECK-NEXT: store i64 0, ptr [[TMP74]], align 8
+// CHECK-NEXT: [[TMP75:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 9
+// CHECK-NEXT: store i64 0, ptr [[TMP75]], align 8
+// CHECK-NEXT: [[TMP76:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 10
+// CHECK-NEXT: store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP76]], align 4
+// CHECK-NEXT: [[TMP77:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 11
+// CHECK-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP77]], align 4
+// CHECK-NEXT: [[TMP78:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 12
+// CHECK-NEXT: store i32 0, ptr [[TMP78]], align 4
+// CHECK-NEXT: [[TMP79:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l24.region_id, ptr [[KERNEL_ARGS14]])
+// CHECK-NEXT: [[TMP80:%.*]] = icmp ne i32 [[TMP79]], 0
+// CHECK-NEXT: br i1 [[TMP80]], label %[[OMP_OFFLOAD_FAILED15:.*]], label %[[OMP_OFFLOAD_CONT16:.*]]
+// CHECK: [[OMP_OFFLOAD_FAILED15]]:
+// CHECK-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l24(ptr [[TMP46]], i32 [[TMP48]]) #[[ATTR2]]
+// CHECK-NEXT: br label %[[OMP_OFFLOAD_CONT16]]
+// CHECK: [[OMP_OFFLOAD_CONT16]]:
+// CHECK-NEXT: [[TMP81:%.*]] = load ptr, ptr [[F]], align 4
+// CHECK-NEXT: [[TMP82:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT: store i32 [[TMP82]], ptr [[INDEX_CASTED17]], align 4
+// CHECK-NEXT: [[TMP83:%.*]] = load i32, ptr [[INDEX_CASTED17]], align 4
+// CHECK-NEXT: [[TMP84:%.*]] = load ptr, ptr [[F]], align 4
+// CHECK-NEXT: [[TMP85:%.*]] = load ptr, ptr [[F]], align 4
+// CHECK-NEXT: [[TMP86:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT: [[ARRAYIDX18:%.*]] = getelementptr inbounds ptr, ptr [[TMP85]], i32 [[TMP86]]
+// CHECK-NEXT: [[TMP87:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP87]], 1
+// CHECK-NEXT: [[TMP88:%.*]] = load ptr, ptr [[F]], align 4
+// CHECK-NEXT: [[TMP89:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT: [[ARRAYIDX19:%.*]] = getelementptr inbounds ptr, ptr [[TMP88]], i32 [[TMP89]]
+// CHECK-NEXT: [[TMP90:%.*]] = load ptr, ptr [[ARRAYIDX19]], align 4
+// CHECK-NEXT: [[ARRAYIDX20:%.*]] = getelementptr inbounds nuw float, ptr [[TMP90]], i32 [[ADD]]
+// CHECK-NEXT: [[TMP91:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT: [[ADD21:%.*]] = add nsw i32 [[TMP91]], 1
+// CHECK-NEXT: [[TMP92:%.*]] = mul nuw i32 [[ADD21]], 4
+// CHECK-NEXT: [[TMP93:%.*]] = icmp ugt i32 4, [[TMP92]]
+// CHECK-NEXT: [[TMP94:%.*]] = sub nuw i32 4, [[TMP92]]
+// CHECK-NEXT: [[TMP95:%.*]] = select i1 [[TMP93]], i32 [[TMP94]], i32 0
+// CHECK-NEXT: [[TMP96:%.*]] = sext i32 [[TMP95]] to i64
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[DOTOFFLOAD_SIZES]], ptr align 4 @.offload_sizes.5, i32 24, i1 false)
+// CHECK-NEXT: [[TMP97:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 0
+// CHECK-NEXT: store ptr [[TMP84]], ptr [[TMP97]], align 4
+// CHECK-NEXT: [[TMP98:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 0
+// CHECK-NEXT: store ptr [[ARRAYIDX18]], ptr [[TMP98]], align 4
+// CHECK-NEXT: [[TMP99:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS24]], i32 0, i32 0
+// CHECK-NEXT: store ptr null, ptr [[TMP99]], align 4
+// CHECK-NEXT: [[TMP100:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 1
+// CHECK-NEXT: store ptr [[ARRAYIDX18]], ptr [[TMP100]], align 4
+// CHECK-NEXT: [[TMP101:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 1
+// CHECK-NEXT: store ptr [[ARRAYIDX20]], ptr [[TMP101]], align 4
+// CHECK-NEXT: [[TMP102:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 1
+// CHECK-NEXT: store i64 [[TMP96]], ptr [[TMP102]], align 4
+// CHECK-NEXT: [[TMP103:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS24]], i32 0, i32 1
+// CHECK-NEXT: store ptr null, ptr [[TMP103]], align 4
+// CHECK-NEXT: [[TMP104:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 2
+// CHECK-NEXT: store i32 [[TMP83]], ptr [[TMP104]], align 4
+// CHECK-NEXT: [[TMP105:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 2
+// CHECK-NEXT: store i32 [[TMP83]], ptr [[TMP105]], align 4
+// CHECK-NEXT: [[TMP106:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_MAPPERS24]], i32 0, i32 2
+// CHECK-NEXT: store ptr null, ptr [[TMP106]], align 4
+// CHECK-NEXT: [[TMP107:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 0
+// CHECK-NEXT: [[TMP108:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 0
+// CHECK-NEXT: [[TMP109:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0
+// CHECK-NEXT: [[TMP110:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 0
+// CHECK-NEXT: store i32 3, ptr [[TMP110]], align 4
+// CHECK-NEXT: [[TMP111:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 1
+// CHECK-NEXT: store i32 3, ptr [[TMP111]], align 4
+// CHECK-NEXT: [[TMP112:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 2
+// CHECK-NEXT: store ptr [[TMP107]], ptr [[TMP112]], align 4
+// CHECK-NEXT: [[TMP113:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 3
+// CHECK-NEXT: store ptr [[TMP108]], ptr [[TMP113]], align 4
+// CHECK-NEXT: [[TMP114:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 4
+// CHECK-NEXT: store ptr [[TMP109]], ptr [[TMP114]], align 4
+// CHECK-NEXT: [[TMP115:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 5
+// CHECK-NEXT: store ptr @.offload_maptypes.6, ptr [[TMP115]], align 4
+// CHECK-NEXT: [[TMP116:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 6
+// CHECK-NEXT: store ptr null, ptr [[TMP116]], align 4
+// CHECK-NEXT: [[TMP117:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 7
+// CHECK-NEXT: store ptr null, ptr [[TMP117]], align 4
+// CHECK-NEXT: [[TMP118:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 8
+// CHECK-NEXT: store i64 0, ptr [[TMP118]], align 8
+// CHECK-NEXT: [[TMP119:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 9
+// CHECK-NEXT: store i64 0, ptr [[TMP119]], align 8
+// CHECK-NEXT: [[TMP120:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 10
+// CHECK-NEXT: store [3 x i32] [i32 -1, i32 0, i32 0], ptr [[TMP120]], align 4
+// CHECK-NEXT: [[TMP121:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 11
+// CHECK-NEXT: store [3 x i32] zeroinitializer, ptr [[TMP121]], align 4
+// CHECK-NEXT: [[TMP122:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS25]], i32 0, i32 12
+// CHECK-NEXT: store i32 0, ptr [[TMP122]], align 4
+// CHECK-NEXT: [[TMP123:%.*]] = call i32 @__tgt_target_kernel(ptr @[[GLOB1]], i64 -1, i32 -1, i32 0, ptr @.{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l29.region_id, ptr [[KERNEL_ARGS25]])
+// CHECK-NEXT: [[TMP124:%.*]] = icmp ne i32 [[TMP123]], 0
+// CHECK-NEXT: br i1 [[TMP124]], label %[[OMP_OFFLOAD_FAILED26:.*]], label %[[OMP_OFFLOAD_CONT27:.*]]
+// CHECK: [[OMP_OFFLOAD_FAILED26]]:
+// CHECK-NEXT: call void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l29(ptr [[TMP81]], i32 [[TMP83]]) #[[ATTR2]]
+// CHECK-NEXT: br label %[[OMP_OFFLOAD_CONT27]]
+// CHECK: [[OMP_OFFLOAD_CONT27]]:
+// CHECK-NEXT: ret void
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l14(
+// CHECK-SAME: ptr noundef [[D:%.*]]) #[[ATTR1:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[D_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT: store ptr [[D]], ptr [[D_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[D_ADDR]], align 4
+// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, ptr [[TMP0]], i32 3
+// CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[ARRAYIDX]], align 4
+// CHECK-NEXT: [[ADD:%.*]] = fadd float [[TMP1]], 2.000000e+00
+// CHECK-NEXT: store float [[ADD]], ptr [[ARRAYIDX]], align 4
+// CHECK-NEXT: ret void
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l19(
+// CHECK-SAME: ptr noundef [[D:%.*]]) #[[ATTR1]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[D_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT: store ptr [[D]], ptr [[D_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[D_ADDR]], align 4
+// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, ptr [[TMP0]], i32 3
+// CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[ARRAYIDX]], align 4
+// CHECK-NEXT: [[ADD:%.*]] = fadd float [[TMP1]], 3.000000e+00
+// CHECK-NEXT: store float [[ADD]], ptr [[ARRAYIDX]], align 4
+// CHECK-NEXT: ret void
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l24(
+// CHECK-SAME: ptr noundef [[F:%.*]], i32 noundef [[INDEX:%.*]]) #[[ATTR1]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[F_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT: [[INDEX_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store ptr [[F]], ptr [[F_ADDR]], align 4
+// CHECK-NEXT: store i32 [[INDEX]], ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[F_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[TMP0]], i32 [[TMP1]]
+// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[ARRAYIDX]], align 4
+// CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds float, ptr [[TMP2]], i32 2
+// CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[ARRAYIDX1]], align 4
+// CHECK-NEXT: [[ADD:%.*]] = fadd float [[TMP3]], 4.000000e+00
+// CHECK-NEXT: store float [[ADD]], ptr [[ARRAYIDX1]], align 4
+// CHECK-NEXT: ret void
+//
+//
+// CHECK-LABEL: define internal void @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z34array_section_no_length_map_clausePfi_l29(
+// CHECK-SAME: ptr noundef [[F:%.*]], i32 noundef [[INDEX:%.*]]) #[[ATTR1]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[F_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT: [[INDEX_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store ptr [[F]], ptr [[F_ADDR]], align 4
+// CHECK-NEXT: store i32 [[INDEX]], ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[F_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[TMP0]], i32 [[TMP1]]
+// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[ARRAYIDX]], align 4
+// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds float, ptr [[TMP2]], i32 [[TMP3]]
+// CHECK-NEXT: [[TMP4:%.*]] = load float, ptr [[ARRAYIDX1]], align 4
+// CHECK-NEXT: [[ADD:%.*]] = fadd float [[TMP4]], 5.000000e+00
+// CHECK-NEXT: store float [[ADD]], ptr [[ARRAYIDX1]], align 4
+// CHECK-NEXT: ret void
+//
diff --git a/clang/test/OpenMP/target_map_codegen_35.cpp b/clang/test/OpenMP/target_map_codegen_35.cpp
index afa0965..c4fc49c 100644
--- a/clang/test/OpenMP/target_map_codegen_35.cpp
+++ b/clang/test/OpenMP/target_map_codegen_35.cpp
@@ -27,11 +27,11 @@ public:
void foo();
};
-// CK35-DAG: [[SIZE_TO:@.+]] = private {{.*}}constant [4 x i64] [i64 0, i64 0, i64 0, i64 8]
+// CK35-DAG: [[SIZE_TO:@.+]] = private {{.*}}constant [3 x i64] [i64 0, i64 0, i64 8]
// TARGET_PARAM = 0x20
// MEMBER_OF_1 | TO = 0x1000000000001
// MEMBER_OF_1 | PTR_AND_OBJ | TO = 0x1000000000011
-// CK35-DAG: [[MTYPE_TO:@.+]] = {{.+}}constant [4 x i64] [i64 [[#0x20]], i64 [[#0x1000000000001]], i64 [[#0x1000000000001]], i64 [[#0x1000000000011]]]
+// CK35-DAG: [[MTYPE_TO:@.+]] = {{.+}}constant [3 x i64] [i64 [[#0x20]], i64 [[#0x1000000000001]], i64 [[#0x1000000000011]]]
// CK35-DAG: [[SIZE_FROM:@.+]] = private {{.*}}constant [2 x i64] [i64 0, i64 8]
// TARGET_PARAM = 0x20
// MEMBER_OF_1 | PTR_AND_OBJ | FROM = 0x1000000000012
@@ -86,35 +86,14 @@ void ref_map() {
// CK35-DAG: [[B_BEGIN_INTPTR]] = ptrtoint ptr [[B_BEGIN_VOID:%.+]] to i64
// CK35-DAG: [[B_ADDR:%.+]] = getelementptr inbounds nuw %class.S, ptr [[S_ADDR]], i32 0, i32 1
- // pass MEMBER_OF_1 | TO {&s, &s.b+1, ((ptr)(&s+1)-(ptr)(&s.b+1))} to copy the data of remainder of s.
+ // pass MEMBER_OF_1 | PTR_AND_OBJ | TO {&s, &s.b, 8|4} to copy the data of s.b.
// CK35-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2
// CK35-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2
- // CK35-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2
// CK35-DAG: store ptr [[S_ADDR]], ptr [[BP2]],
- // CK35-DAG: store ptr [[B_END:%.+]], ptr [[P2]],
- // CK35-DAG: store i64 [[REM_SIZE:%.+]], ptr [[S2]],
-
- // CK35-DAG: [[B_END]] = getelementptr ptr, ptr [[B_ADDR]], i{{.+}} 1
-
- // CK35-DAG: [[REM_SIZE]] = sdiv exact i64 [[SZ:%.+]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
- // CK35-DAG: [[SZ]] = sub i64 [[S_END_INTPTR:%.+]], [[B_END_INTPTR:%.+]]
- // CK35-DAG: [[B_END_INTPTR]] = ptrtoint ptr [[B_END_VOID:%.+]] to i64
- // CK35-DAG: [[S_END_INTPTR]] = ptrtoint ptr [[S_END_VOID:%.+]] to i64
- // CK35-DAG: [[S_END_VOID]] = getelementptr i8, ptr [[S_LAST:%.+]], i{{.+}} 1
- // CK35-64-DAG: [[S_LAST]] = getelementptr i8, ptr [[S_VOIDPTR:%.+]], i64 15
- // CK35-32-DAG: [[S_LAST]] = getelementptr i8, ptr [[S_VOIDPTR:%.+]], i32 7
-
- // pass MEMBER_OF_1 | PTR_AND_OBJ | TO {&s, &s.b, 8|4} to copy the data of s.b.
-
- // CK35-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 3
- // CK35-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 3
-
-
- // CK35-DAG: store ptr [[S_ADDR]], ptr [[BP3]],
- // CK35-DAG: store ptr [[B_ADDR:%.+]], ptr [[P3]],
+ // CK35-DAG: store ptr [[B_ADDR:%.+]], ptr [[P2]],
// CK35-DAG: [[B_ADDR]] = load ptr, ptr [[B_REF:%.+]], align {{[0-9]+}}, !nonnull !{{[0-9]+}}, !align !{{[0-9]+}}
// CK35-DAG: [[B_REF]] = getelementptr inbounds nuw %class.S, ptr [[S_ADDR]], i32 0, i32 1
diff --git a/clang/test/OpenMP/target_map_messages.cpp b/clang/test/OpenMP/target_map_messages.cpp
index 4a026584..0ee70be 100644
--- a/clang/test/OpenMP/target_map_messages.cpp
+++ b/clang/test/OpenMP/target_map_messages.cpp
@@ -122,9 +122,9 @@ struct SA {
{}
#pragma omp target map(always, tofrom: c,f[1:2])
{}
- #pragma omp target 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 map(always, tofrom: c[:],f) // lt60-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
{}
- #pragma omp target 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 map(always, tofrom: c,f[:]) // lt60-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
{}
#pragma omp target map(always) // expected-error {{use of undeclared identifier 'always'}}
{}
@@ -134,9 +134,9 @@ struct SA {
{}
#pragma omp target map(self, tofrom: c,f[1:2]) // lt60-error {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}}
{}
- #pragma omp target map(self, tofrom: c[:],f) // lt60-error {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ #pragma omp target map(self, tofrom: c[:],f) // lt60-error {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} // lt60-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
{}
- #pragma omp target map(self, tofrom: c,f[:]) // lt60-error {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ #pragma omp target map(self, tofrom: c,f[:]) // lt60-error {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}} // lt60-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
{}
#pragma omp target map(close, tofrom: c,f)
{}
@@ -144,9 +144,9 @@ struct SA {
{}
#pragma omp target map(close, tofrom: c,f[1:2])
{}
- #pragma omp target map(close, tofrom: c[:],f) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ #pragma omp target map(close, tofrom: c[:],f) // lt60-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
{}
- #pragma omp target map(close, tofrom: c,f[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ #pragma omp target map(close, tofrom: c,f[:]) // lt60-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
{}
#pragma omp target map(close) // expected-error {{use of undeclared identifier 'close'}}
{}
@@ -159,11 +159,11 @@ struct SA {
// lt51-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}}
#pragma omp target map(present, tofrom: c,f[1:2])
{}
- // expected-error@+2 {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ // lt60-error@+2 {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
// lt51-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}}
#pragma omp target map(present, tofrom: c[:],f)
{}
- // expected-error@+2 {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ // lt60-error@+2 {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
// lt51-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}}
#pragma omp target map(present, tofrom: c,f[:])
{}
@@ -190,14 +190,14 @@ struct SA {
{}
// ge60-error@+5 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator', 'self}}
// ge52-error@+4 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}}
- // expected-error@+3 {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ // lt60-error@+3 {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
// ge51-omp-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}}
// lt51-omp-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}}
#pragma omp target map(ompx_hold, tofrom: c[:],f)
{}
// ge60-error@+5 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator', 'self}}
// ge52-error@+4 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present', 'iterator'}}
- // expected-error@+3 {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+ // lt60-error@+3 {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
// ge51-omp-error@+2 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper', 'present'}}
// lt51-omp-error@+1 {{incorrect map type modifier, expected one of: 'always', 'close', 'mapper'}}
#pragma omp target map(ompx_hold, tofrom: c,f[:])
@@ -448,7 +448,7 @@ void SAclient(int arg) {
{}
#pragma omp target map(mptr[:1][:2] [0:2]) // expected-error {{array section does not specify contiguous storage}}
{}
-#pragma omp target 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 map(mptr[:1][:] [0:2]) // lt60-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
{}
#pragma omp target map(mptr[:2][:1] [0:2]) // expected-error {{array section does not specify contiguous storage}}
{}
@@ -517,7 +517,7 @@ void SAclient(int arg) {
{}
#pragma omp target map(r.S.Ptr [4:5])
{}
-#pragma omp target map(r.S.Ptr[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+#pragma omp target map(r.S.Ptr[:]) // lt60-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
{}
#pragma omp target map((p + 1)->A) // lt50-error {{expected expression containing only member accesses and/or array sections based on named variables}}
{}
diff --git a/clang/test/Preprocessor/arm-acle-6.4.c b/clang/test/Preprocessor/arm-acle-6.4.c
index 2c8f486..48deba7 100644
--- a/clang/test/Preprocessor/arm-acle-6.4.c
+++ b/clang/test/Preprocessor/arm-acle-6.4.c
@@ -188,6 +188,37 @@
// RUN: %clang --target=arm-arm-none-eabi -mcpu=cortex-m33 -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-M-DSP
// RUN: %clang --target=arm-arm-none-eabi -march=armv8m.main+dsp -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-M-DSP
+// RUN: %clang -target arm-none-linux-eabi -march=armv8m.base -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-V8M-BASE
+
+// CHECK-V8M-BASE-NOT: __ARM_ARCH_ISA_ARM
+// CHECK-V8M-BASE-NOT: __ARM_FEATURE_DSP
+// CHECK-V8M-BASE-NOT: __ARM_FEATURE_SIMD32
+// CHECK-V8M-BASE: __ARM_ARCH 8
+// CHECK-V8M-BASE: __ARM_ARCH_ISA_THUMB 1
+// CHECK-V8M-BASE: __ARM_ARCH_PROFILE 'M'
+// CHECK-V8M-BASE: __ARM_FEATURE_CLZ 1
+// CHECK-V8M-BASE: __ARM_FEATURE_IDIV 1
+// CHECK-V8M-BASE: __ARM_FEATURE_LDREX 0x7
+// CHECK-V8M-BASE: __ARM_FEATURE_QBIT 1
+// CHECK-V8M-BASE: __ARM_FEATURE_SAT
+// CHECK-V8M-BASE-NOT: __ARM_FEATURE_UNALIGNED
+
+// RUN: %clang -target arm-none-linux-eabi -march=armv8m.main -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-V8M-MAIN
+// RUN: %clang -target arm-none-linux-eabi -march=armv8.1m.main -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-V8M-MAIN
+
+// CHECK-V8M-MAIN-NOT: __ARM_ARCH_ISA_ARM
+// CHECK-V8M-MAIN-NOT: __ARM_FEATURE_DSP
+// CHECK-V8M-MAIN-NOT: __ARM_FEATURE_SIMD32
+// CHECK-V8M-MAIN: __ARM_ARCH 8
+// CHECK-V8M-MAIN: __ARM_ARCH_ISA_THUMB 2
+// CHECK-V8M-MAIN: __ARM_ARCH_PROFILE 'M'
+// CHECK-V8M-MAIN: __ARM_FEATURE_CLZ 1
+// CHECK-V8M-MAIN: __ARM_FEATURE_IDIV 1
+// CHECK-V8M-MAIN: __ARM_FEATURE_LDREX 0x7
+// CHECK-V8M-MAIN: __ARM_FEATURE_QBIT 1
+// CHECK-V8M-MAIN: __ARM_FEATURE_SAT 1
+// CHECK-V8M-MAIN: __ARM_FEATURE_UNALIGNED 1
+
// CHECK-M-DSP: __ARM_FEATURE_DSP 1
// CHECK-M-DSP: __ARM_FEATURE_SIMD32 1
diff --git a/clang/test/Preprocessor/init-mips.c b/clang/test/Preprocessor/init-mips.c
index 4fead33..125872a 100644
--- a/clang/test/Preprocessor/init-mips.c
+++ b/clang/test/Preprocessor/init-mips.c
@@ -80,10 +80,10 @@
// MIPS32BE:#define __INTMAX_MAX__ 9223372036854775807LL
// MIPS32BE:#define __INTMAX_TYPE__ long long int
// MIPS32BE:#define __INTMAX_WIDTH__ 64
-// MIPS32BE:#define __INTPTR_FMTd__ "ld"
-// MIPS32BE:#define __INTPTR_FMTi__ "li"
-// MIPS32BE:#define __INTPTR_MAX__ 2147483647L
-// MIPS32BE:#define __INTPTR_TYPE__ long int
+// MIPS32BE:#define __INTPTR_FMTd__ "d"
+// MIPS32BE:#define __INTPTR_FMTi__ "i"
+// MIPS32BE:#define __INTPTR_MAX__ 2147483647
+// MIPS32BE:#define __INTPTR_TYPE__ int
// MIPS32BE:#define __INTPTR_WIDTH__ 32
// MIPS32BE:#define __INT_FAST16_FMTd__ "hd"
// MIPS32BE:#define __INT_FAST16_FMTi__ "hi"
@@ -185,8 +185,8 @@
// MIPS32BE:#define __UINTMAX_MAX__ 18446744073709551615ULL
// MIPS32BE:#define __UINTMAX_TYPE__ long long unsigned int
// MIPS32BE:#define __UINTMAX_WIDTH__ 64
-// MIPS32BE:#define __UINTPTR_MAX__ 4294967295UL
-// MIPS32BE:#define __UINTPTR_TYPE__ long unsigned int
+// MIPS32BE:#define __UINTPTR_MAX__ 4294967295U
+// MIPS32BE:#define __UINTPTR_TYPE__ unsigned int
// MIPS32BE:#define __UINTPTR_WIDTH__ 32
// MIPS32BE:#define __UINT_FAST16_MAX__ 65535
// MIPS32BE:#define __UINT_FAST16_TYPE__ unsigned short
@@ -300,10 +300,10 @@
// MIPS32EL:#define __INTMAX_MAX__ 9223372036854775807LL
// MIPS32EL:#define __INTMAX_TYPE__ long long int
// MIPS32EL:#define __INTMAX_WIDTH__ 64
-// MIPS32EL:#define __INTPTR_FMTd__ "ld"
-// MIPS32EL:#define __INTPTR_FMTi__ "li"
-// MIPS32EL:#define __INTPTR_MAX__ 2147483647L
-// MIPS32EL:#define __INTPTR_TYPE__ long int
+// MIPS32EL:#define __INTPTR_FMTd__ "d"
+// MIPS32EL:#define __INTPTR_FMTi__ "i"
+// MIPS32EL:#define __INTPTR_MAX__ 2147483647
+// MIPS32EL:#define __INTPTR_TYPE__ int
// MIPS32EL:#define __INTPTR_WIDTH__ 32
// MIPS32EL:#define __INT_FAST16_FMTd__ "hd"
// MIPS32EL:#define __INT_FAST16_FMTi__ "hi"
@@ -402,8 +402,8 @@
// MIPS32EL:#define __UINTMAX_MAX__ 18446744073709551615ULL
// MIPS32EL:#define __UINTMAX_TYPE__ long long unsigned int
// MIPS32EL:#define __UINTMAX_WIDTH__ 64
-// MIPS32EL:#define __UINTPTR_MAX__ 4294967295UL
-// MIPS32EL:#define __UINTPTR_TYPE__ long unsigned int
+// MIPS32EL:#define __UINTPTR_MAX__ 4294967295U
+// MIPS32EL:#define __UINTPTR_TYPE__ unsigned int
// MIPS32EL:#define __UINTPTR_WIDTH__ 32
// MIPS32EL:#define __UINT_FAST16_MAX__ 65535
// MIPS32EL:#define __UINT_FAST16_TYPE__ unsigned short
@@ -547,10 +547,10 @@
// MIPSN32BE: #define __INTMAX_MAX__ 9223372036854775807LL
// MIPSN32BE: #define __INTMAX_TYPE__ long long int
// MIPSN32BE: #define __INTMAX_WIDTH__ 64
-// MIPSN32BE: #define __INTPTR_FMTd__ "ld"
-// MIPSN32BE: #define __INTPTR_FMTi__ "li"
-// MIPSN32BE: #define __INTPTR_MAX__ 2147483647L
-// MIPSN32BE: #define __INTPTR_TYPE__ long int
+// MIPSN32BE: #define __INTPTR_FMTd__ "d"
+// MIPSN32BE: #define __INTPTR_FMTi__ "i"
+// MIPSN32BE: #define __INTPTR_MAX__ 2147483647
+// MIPSN32BE: #define __INTPTR_TYPE__ int
// MIPSN32BE: #define __INTPTR_WIDTH__ 32
// MIPSN32BE: #define __INT_FAST16_FMTd__ "hd"
// MIPSN32BE: #define __INT_FAST16_FMTi__ "hi"
@@ -684,12 +684,12 @@
// MIPSN32BE: #define __UINTMAX_MAX__ 18446744073709551615ULL
// MIPSN32BE: #define __UINTMAX_TYPE__ long long unsigned int
// MIPSN32BE: #define __UINTMAX_WIDTH__ 64
-// MIPSN32BE: #define __UINTPTR_FMTX__ "lX"
-// MIPSN32BE: #define __UINTPTR_FMTo__ "lo"
-// MIPSN32BE: #define __UINTPTR_FMTu__ "lu"
-// MIPSN32BE: #define __UINTPTR_FMTx__ "lx"
-// MIPSN32BE: #define __UINTPTR_MAX__ 4294967295UL
-// MIPSN32BE: #define __UINTPTR_TYPE__ long unsigned int
+// MIPSN32BE: #define __UINTPTR_FMTX__ "X"
+// MIPSN32BE: #define __UINTPTR_FMTo__ "o"
+// MIPSN32BE: #define __UINTPTR_FMTu__ "u"
+// MIPSN32BE: #define __UINTPTR_FMTx__ "x"
+// MIPSN32BE: #define __UINTPTR_MAX__ 4294967295U
+// MIPSN32BE: #define __UINTPTR_TYPE__ unsigned int
// MIPSN32BE: #define __UINTPTR_WIDTH__ 32
// MIPSN32BE: #define __UINT_FAST16_FMTX__ "hX"
// MIPSN32BE: #define __UINT_FAST16_FMTo__ "ho"
@@ -864,10 +864,10 @@
// MIPSN32EL: #define __INTMAX_MAX__ 9223372036854775807LL
// MIPSN32EL: #define __INTMAX_TYPE__ long long int
// MIPSN32EL: #define __INTMAX_WIDTH__ 64
-// MIPSN32EL: #define __INTPTR_FMTd__ "ld"
-// MIPSN32EL: #define __INTPTR_FMTi__ "li"
-// MIPSN32EL: #define __INTPTR_MAX__ 2147483647L
-// MIPSN32EL: #define __INTPTR_TYPE__ long int
+// MIPSN32EL: #define __INTPTR_FMTd__ "d"
+// MIPSN32EL: #define __INTPTR_FMTi__ "i"
+// MIPSN32EL: #define __INTPTR_MAX__ 2147483647
+// MIPSN32EL: #define __INTPTR_TYPE__ int
// MIPSN32EL: #define __INTPTR_WIDTH__ 32
// MIPSN32EL: #define __INT_FAST16_FMTd__ "hd"
// MIPSN32EL: #define __INT_FAST16_FMTi__ "hi"
@@ -1001,12 +1001,12 @@
// MIPSN32EL: #define __UINTMAX_MAX__ 18446744073709551615ULL
// MIPSN32EL: #define __UINTMAX_TYPE__ long long unsigned int
// MIPSN32EL: #define __UINTMAX_WIDTH__ 64
-// MIPSN32EL: #define __UINTPTR_FMTX__ "lX"
-// MIPSN32EL: #define __UINTPTR_FMTo__ "lo"
-// MIPSN32EL: #define __UINTPTR_FMTu__ "lu"
-// MIPSN32EL: #define __UINTPTR_FMTx__ "lx"
-// MIPSN32EL: #define __UINTPTR_MAX__ 4294967295UL
-// MIPSN32EL: #define __UINTPTR_TYPE__ long unsigned int
+// MIPSN32EL: #define __UINTPTR_FMTX__ "X"
+// MIPSN32EL: #define __UINTPTR_FMTo__ "o"
+// MIPSN32EL: #define __UINTPTR_FMTu__ "u"
+// MIPSN32EL: #define __UINTPTR_FMTx__ "x"
+// MIPSN32EL: #define __UINTPTR_MAX__ 4294967295U
+// MIPSN32EL: #define __UINTPTR_TYPE__ unsigned int
// MIPSN32EL: #define __UINTPTR_WIDTH__ 32
// MIPSN32EL: #define __UINT_FAST16_FMTX__ "hX"
// MIPSN32EL: #define __UINT_FAST16_FMTo__ "ho"
diff --git a/clang/test/Preprocessor/pragma-pushpop-macro-diag.c b/clang/test/Preprocessor/pragma-pushpop-macro-diag.c
new file mode 100644
index 0000000..293cb82
--- /dev/null
+++ b/clang/test/Preprocessor/pragma-pushpop-macro-diag.c
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -fms-extensions %s -fsyntax-only -verify
+
+#pragma push_macro("") // expected-warning {{'#pragma push_macro' expected a non-empty string}}
+#pragma pop_macro("") // expected-warning {{'#pragma pop_macro' expected a non-empty string}}
diff --git a/clang/test/Preprocessor/pragma-pushpop-macro.c b/clang/test/Preprocessor/pragma-pushpop-macro.c
index 0aee074..238e3ed 100644
--- a/clang/test/Preprocessor/pragma-pushpop-macro.c
+++ b/clang/test/Preprocessor/pragma-pushpop-macro.c
@@ -56,3 +56,6 @@ int P;
// CHECK: int pmy2 = 4
// CHECK: int Q;
// CHECK: int P;
+
+#pragma push_macro("")
+#pragma pop_macro("")
diff --git a/clang/test/Preprocessor/stdint.c b/clang/test/Preprocessor/stdint.c
index 899ff59..9f982a3 100644
--- a/clang/test/Preprocessor/stdint.c
+++ b/clang/test/Preprocessor/stdint.c
@@ -350,8 +350,8 @@
// MIPS:typedef int8_t int_fast8_t;
// MIPS:typedef uint8_t uint_fast8_t;
//
-// MIPS:typedef long int intptr_t;
-// MIPS:typedef long unsigned int uintptr_t;
+// MIPS:typedef int intptr_t;
+// MIPS:typedef unsigned int uintptr_t;
//
// MIPS:typedef long long int intmax_t;
// MIPS:typedef long long unsigned int uintmax_t;
@@ -396,9 +396,9 @@
// MIPS:INT_FAST64_MAX_ 9223372036854775807LL
// MIPS:UINT_FAST64_MAX_ 18446744073709551615ULL
//
-// MIPS:INTPTR_MIN_ (-2147483647L -1)
-// MIPS:INTPTR_MAX_ 2147483647L
-// MIPS:UINTPTR_MAX_ 4294967295UL
+// MIPS:INTPTR_MIN_ (-2147483647 -1)
+// MIPS:INTPTR_MAX_ 2147483647
+// MIPS:UINTPTR_MAX_ 4294967295U
// MIPS:PTRDIFF_MIN_ (-2147483647 -1)
// MIPS:PTRDIFF_MAX_ 2147483647
// MIPS:SIZE_MAX_ 4294967295U
diff --git a/clang/test/Sema/builtins-elementwise-math.c b/clang/test/Sema/builtins-elementwise-math.c
index 01057b3..8548d3b 100644
--- a/clang/test/Sema/builtins-elementwise-math.c
+++ b/clang/test/Sema/builtins-elementwise-math.c
@@ -386,6 +386,96 @@ void test_builtin_elementwise_minimum(int i, short s, float f, double d, float4
// expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was '_Complex float')}}
}
+void test_builtin_elementwise_maximumnum(int i, short s, float f, double d, float4 fv, double4 dv, int3 iv, unsigned3 uv, int *p) {
+ i = __builtin_elementwise_maximumnum(p, d);
+ // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int *')}}
+
+ struct Foo foo = __builtin_elementwise_maximumnum(d, d);
+ // expected-error@-1 {{initializing 'struct Foo' with an expression of incompatible type 'double'}}
+
+ i = __builtin_elementwise_maximumnum(i);
+ // expected-error@-1 {{too few arguments to function call, expected 2, have 1}}
+
+ i = __builtin_elementwise_maximumnum();
+ // expected-error@-1 {{too few arguments to function call, expected 2, have 0}}
+
+ i = __builtin_elementwise_maximumnum(i, i, i);
+ // expected-error@-1 {{too many arguments to function call, expected 2, have 3}}
+
+ i = __builtin_elementwise_maximumnum(fv, iv);
+ // expected-error@-1 {{arguments are of different types ('float4' (vector of 4 'float' values) vs 'int3' (vector of 3 'int' values))}}
+
+ i = __builtin_elementwise_maximumnum(uv, iv);
+ // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'unsigned3' (vector of 3 'unsigned int' values))}}
+
+ dv = __builtin_elementwise_maximumnum(fv, dv);
+ // expected-error@-1 {{arguments are of different types ('float4' (vector of 4 'float' values) vs 'double4' (vector of 4 'double' values))}}
+
+ d = __builtin_elementwise_maximumnum(f, d);
+ // expected-error@-1 {{arguments are of different types ('float' vs 'double')}}
+
+ fv = __builtin_elementwise_maximumnum(fv, fv);
+
+ i = __builtin_elementwise_maximumnum(iv, iv);
+ // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int3' (vector of 3 'int' values))}}
+
+ i = __builtin_elementwise_maximumnum(i, i);
+ // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int')}}
+
+ int A[10];
+ A = __builtin_elementwise_maximumnum(A, A);
+ // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int *')}}
+
+ _Complex float c1, c2;
+ c1 = __builtin_elementwise_maximumnum(c1, c2);
+ // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was '_Complex float')}}
+}
+
+void test_builtin_elementwise_minimumnum(int i, short s, float f, double d, float4 fv, double4 dv, int3 iv, unsigned3 uv, int *p) {
+ i = __builtin_elementwise_minimumnum(p, d);
+ // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int *')}}
+
+ struct Foo foo = __builtin_elementwise_minimumnum(d, d);
+ // expected-error@-1 {{initializing 'struct Foo' with an expression of incompatible type 'double'}}
+
+ i = __builtin_elementwise_minimumnum(i);
+ // expected-error@-1 {{too few arguments to function call, expected 2, have 1}}
+
+ i = __builtin_elementwise_minimumnum();
+ // expected-error@-1 {{too few arguments to function call, expected 2, have 0}}
+
+ i = __builtin_elementwise_minimumnum(i, i, i);
+ // expected-error@-1 {{too many arguments to function call, expected 2, have 3}}
+
+ i = __builtin_elementwise_minimumnum(fv, iv);
+ // expected-error@-1 {{arguments are of different types ('float4' (vector of 4 'float' values) vs 'int3' (vector of 3 'int' values))}}
+
+ i = __builtin_elementwise_minimumnum(uv, iv);
+ // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'unsigned3' (vector of 3 'unsigned int' values))}}
+
+ dv = __builtin_elementwise_minimumnum(fv, dv);
+ // expected-error@-1 {{arguments are of different types ('float4' (vector of 4 'float' values) vs 'double4' (vector of 4 'double' values))}}
+
+ d = __builtin_elementwise_minimumnum(f, d);
+ // expected-error@-1 {{arguments are of different types ('float' vs 'double')}}
+
+ fv = __builtin_elementwise_minimumnum(fv, fv);
+
+ i = __builtin_elementwise_minimumnum(iv, iv);
+ // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int3' (vector of 3 'int' values))}}
+
+ i = __builtin_elementwise_minimumnum(i, i);
+ // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int')}}
+
+ int A[10];
+ A = __builtin_elementwise_minimumnum(A, A);
+ // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was 'int *')}}
+
+ _Complex float c1, c2;
+ c1 = __builtin_elementwise_minimumnum(c1, c2);
+ // expected-error@-1 {{1st argument must be a scalar or vector of floating-point types (was '_Complex float')}}
+}
+
void test_builtin_elementwise_bitreverse(int i, float f, double d, float4 v, int3 iv, unsigned u, unsigned4 uv) {
struct Foo s = __builtin_elementwise_bitreverse(i);
diff --git a/clang/test/Sema/implicit-special-member-deprecated.cpp b/clang/test/Sema/implicit-special-member-deprecated.cpp
new file mode 100644
index 0000000..8e23404
--- /dev/null
+++ b/clang/test/Sema/implicit-special-member-deprecated.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -std=c++20 -Wdeprecated-declarations -verify %s
+
+struct A {
+ [[deprecated("use something else")]] int x = 42; // expected-note {{marked deprecated here}}
+};
+
+A makeDefaultA() { return {}; } // ctor is implicit → no warn
+A copyA(const A &a) { return a; } // copy-ctor implicit → no warn
+
+void assignA() {
+ A a, b;
+ a = b; // copy-assign implicit → no warn
+}
+
+void useA() {
+ A a;
+ (void)a.x; // expected-warning {{is deprecated}}
+}
+
+// Explicitly-defaulted ctor – now silent
+struct B {
+ [[deprecated]] int y;
+ B() = default; // no warning under new policy
+};
diff --git a/clang/test/Sema/unsupported-arm-streaming.cpp b/clang/test/Sema/unsupported-arm-streaming.cpp
new file mode 100644
index 0000000..8693dd6
--- /dev/null
+++ b/clang/test/Sema/unsupported-arm-streaming.cpp
@@ -0,0 +1,3 @@
+// RUN: %clang_cc1 -x c -triple x86_64-pc-linux-gnu -fsyntax-only -verify %s
+
+void arm_streaming(void) __arm_streaming {} // expected-error {{'__arm_streaming' is not supported on this target}}
diff --git a/clang/test/Sema/warn-fortify-source.c b/clang/test/Sema/warn-fortify-source.c
index f48ea09..216878c 100644
--- a/clang/test/Sema/warn-fortify-source.c
+++ b/clang/test/Sema/warn-fortify-source.c
@@ -3,6 +3,11 @@
// RUN: %clang_cc1 -xc++ -triple x86_64-apple-macosx10.14.0 %s -verify
// RUN: %clang_cc1 -xc++ -triple x86_64-apple-macosx10.14.0 %s -verify -DUSE_BUILTINS
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.14.0 %s -verify -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.14.0 %s -verify -DUSE_BUILTINS -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -xc++ -triple x86_64-apple-macosx10.14.0 %s -verify -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -xc++ -triple x86_64-apple-macosx10.14.0 %s -verify -DUSE_BUILTINS -fexperimental-new-constant-interpreter
+
typedef unsigned long size_t;
#ifdef __cplusplus
diff --git a/clang/test/Sema/warn-lifetime-safety-dataflow.cpp b/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
index 0e98904ade..2b934ac 100644
--- a/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -mllvm -debug-only=LifetimeFacts,LifetimeLoanPropagation -Wexperimental-lifetime-safety %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -fexperimental-lifetime-safety -mllvm -debug-only=LifetimeFacts -Wexperimental-lifetime-safety %s 2>&1 | FileCheck %s
// REQUIRES: asserts
struct MyObj {
@@ -19,10 +19,6 @@ MyObj* return_local_addr() {
// CHECK: ReturnOfOrigin (OriginID: [[O_RET_VAL]])
// CHECK: Expire (LoanID: [[L_X]])
}
-// CHECK: LoanPropagation results:
-// CHECK-DAG: Origin [[O_ADDR_X]] contains Loan [[L_X]]
-// CHECK-DAG: Origin [[O_P]] contains Loan [[L_X]]
-// CHECK-DAG: Origin [[O_RET_VAL]] contains Loan [[L_X]]
// Pointer Assignment and Return
@@ -47,15 +43,6 @@ MyObj* assign_and_return_local_addr() {
// CHECK: ReturnOfOrigin (OriginID: [[O_PTR2_RVAL_2]])
// CHECK: Expire (LoanID: [[L_Y]])
}
-// CHECK: LoanPropagation results:
-// CHECK-DAG: Origin [[O_ADDR_Y]] contains Loan [[L_Y]]
-// CHECK-DAG: Origin [[O_PTR1]] contains Loan [[L_Y]]
-// CHECK-DAG: Origin [[O_PTR2]] contains Loan [[L_Y]]
-// CHECK-DAG: Origin [[O_PTR1_RVAL]] contains Loan [[L_Y]]
-// CHECK-DAG: Origin [[O_PTR1_RVAL_2]] contains Loan [[L_Y]]
-// CHECK-DAG: Origin [[O_PTR2_RVAL]] contains Loan [[L_Y]]
-// CHECK-DAG: Origin [[O_PTR2_RVAL_2]] contains Loan [[L_Y]]
-
// Return of Non-Pointer Type
// CHECK-LABEL: Function: return_int_val
@@ -65,8 +52,6 @@ int return_int_val() {
return x;
}
// CHECK-NEXT: End of Block
-// CHECK: LoanPropagation results:
-// CHECK: <empty>
// Loan Expiration (Automatic Variable, C++)
@@ -79,9 +64,6 @@ void loan_expires_cpp() {
// CHECK: AssignOrigin (DestID: [[O_POBJ:[0-9]+]], SrcID: [[O_ADDR_OBJ]])
// CHECK: Expire (LoanID: [[L_OBJ]])
}
-// CHECK: LoanPropagation results:
-// CHECK-DAG: Origin [[O_ADDR_OBJ]] contains Loan [[L_OBJ]]
-// CHECK-DAG: Origin [[O_POBJ]] contains Loan [[L_OBJ]]
// FIXME: No expire for Trivial Destructors
@@ -96,10 +78,6 @@ void loan_expires_trivial() {
// CHECK-NEXT: End of Block
// FIXME: Add check for Expire once trivial destructors are handled for expiration.
}
-// CHECK: LoanPropagation results:
-// CHECK-DAG: Origin [[O_ADDR_TRIVIAL_OBJ]] contains Loan [[L_TRIVIAL_OBJ]]
-// CHECK-DAG: Origin [[O_PTOBJ]] contains Loan [[L_TRIVIAL_OBJ]]
-
// CHECK-LABEL: Function: conditional
void conditional(bool condition) {
@@ -119,13 +97,6 @@ void conditional(bool condition) {
// CHECK: AssignOrigin (DestID: [[O_P_RVAL:[0-9]+]], SrcID: [[O_P]])
// CHECK: AssignOrigin (DestID: [[O_Q:[0-9]+]], SrcID: [[O_P_RVAL]])
}
-// CHECK: LoanPropagation results:
-// CHECK-DAG: Origin [[O_ADDR_A]] contains Loan [[L_A]]
-// CHECK-DAG: Origin [[O_ADDR_B]] contains Loan [[L_B]]
-// CHECK-DAG: Origin [[O_P]] contains Loan [[L_A]]
-// CHECK-DAG: Origin [[O_P]] contains Loan [[L_B]]
-// CHECK-DAG: Origin [[O_Q]] contains Loan [[L_A]]
-// CHECK-DAG: Origin [[O_Q]] contains Loan [[L_B]]
// CHECK-LABEL: Function: pointers_in_a_cycle
@@ -161,25 +132,6 @@ void pointers_in_a_cycle(bool condition) {
// CHECK: AssignOrigin (DestID: [[O_P3]], SrcID: [[O_TEMP_RVAL]])
}
}
-// At the end of the analysis, the origins for the pointers involved in the cycle
-// (p1, p2, p3, temp) should all contain the loans from v1, v2, and v3 at the fixed point.
-// CHECK: LoanPropagation results:
-// CHECK-DAG: Origin [[O_P1]] contains Loan [[L_V1]]
-// CHECK-DAG: Origin [[O_P1]] contains Loan [[L_V2]]
-// CHECK-DAG: Origin [[O_P1]] contains Loan [[L_V3]]
-// CHECK-DAG: Origin [[O_P2]] contains Loan [[L_V1]]
-// CHECK-DAG: Origin [[O_P2]] contains Loan [[L_V2]]
-// CHECK-DAG: Origin [[O_P2]] contains Loan [[L_V3]]
-// CHECK-DAG: Origin [[O_P3]] contains Loan [[L_V1]]
-// CHECK-DAG: Origin [[O_P3]] contains Loan [[L_V2]]
-// CHECK-DAG: Origin [[O_P3]] contains Loan [[L_V3]]
-// CHECK-DAG: Origin [[O_TEMP]] contains Loan [[L_V1]]
-// CHECK-DAG: Origin [[O_TEMP]] contains Loan [[L_V2]]
-// CHECK-DAG: Origin [[O_TEMP]] contains Loan [[L_V3]]
-// CHECK-DAG: Origin [[O_ADDR_V1]] contains Loan [[L_V1]]
-// CHECK-DAG: Origin [[O_ADDR_V2]] contains Loan [[L_V2]]
-// CHECK-DAG: Origin [[O_ADDR_V3]] contains Loan [[L_V3]]
-
// CHECK-LABEL: Function: overwrite_origin
void overwrite_origin() {
@@ -195,10 +147,6 @@ void overwrite_origin() {
// CHECK: Expire (LoanID: [[L_S2]])
// CHECK: Expire (LoanID: [[L_S1]])
}
-// CHECK: LoanPropagation results:
-// CHECK: Origin [[O_P]] contains Loan [[L_S2]]
-// CHECK-NOT: Origin [[O_P]] contains Loan [[L_S1]]
-
// CHECK-LABEL: Function: reassign_to_null
void reassign_to_null() {
@@ -213,8 +161,6 @@ void reassign_to_null() {
}
// FIXME: Have a better representation for nullptr than just an empty origin.
// It should be a separate loan and origin kind.
-// CHECK: LoanPropagation results:
-// CHECK: Origin [[O_P]] contains no loans
// CHECK-LABEL: Function: reassign_in_if
@@ -235,11 +181,6 @@ void reassign_in_if(bool condition) {
// CHECK: Expire (LoanID: [[L_S2]])
// CHECK: Expire (LoanID: [[L_S1]])
}
-// CHECK: LoanPropagation results:
-// CHECK-DAG: Origin [[O_P]] contains Loan [[L_S1]]
-// CHECK-DAG: Origin [[O_P]] contains Loan [[L_S2]]
-// CHECK-DAG: Origin [[O_ADDR_S1]] contains Loan [[L_S1]]
-// CHECK-DAG: Origin [[O_ADDR_S2]] contains Loan [[L_S2]]
// CHECK-LABEL: Function: assign_in_switch
@@ -276,14 +217,6 @@ void assign_in_switch(int mode) {
// CHECK-DAG: Expire (LoanID: [[L_S2]])
// CHECK-DAG: Expire (LoanID: [[L_S1]])
}
-// CHECK: LoanPropagation results:
-// CHECK-DAG: Origin [[O_P]] contains Loan [[L_S1]]
-// CHECK-DAG: Origin [[O_P]] contains Loan [[L_S2]]
-// CHECK-DAG: Origin [[O_P]] contains Loan [[L_S3]]
-// CHECK-DAG: Origin [[O_ADDR_S1]] contains Loan [[L_S1]]
-// CHECK-DAG: Origin [[O_ADDR_S2]] contains Loan [[L_S2]]
-// CHECK-DAG: Origin [[O_ADDR_S3]] contains Loan [[L_S3]]
-
// CHECK-LABEL: Function: loan_in_loop
void loan_in_loop(bool condition) {
@@ -299,10 +232,6 @@ void loan_in_loop(bool condition) {
// CHECK: Expire (LoanID: [[L_INNER]])
}
}
-// CHECK: LoanPropagation results:
-// CHECK-DAG: Origin [[O_P]] contains Loan [[L_INNER]]
-// CHECK-DAG: Origin [[O_ADDR_INNER]] contains Loan [[L_INNER]]
-
// CHECK-LABEL: Function: loop_with_break
void loop_with_break(int count) {
@@ -326,13 +255,6 @@ void loop_with_break(int count) {
// CHECK: Expire (LoanID: [[L_S1]])
}
-// CHECK-LABEL: LoanPropagation results:
-// CHECK-DAG: Origin [[O_P]] contains Loan [[L_S1]]
-// CHECK-DAG: Origin [[O_P]] contains Loan [[L_S2]]
-// CHECK-DAG: Origin [[O_ADDR_S1]] contains Loan [[L_S1]]
-// CHECK-DAG: Origin [[O_ADDR_S2]] contains Loan [[L_S2]]
-
-
// CHECK-LABEL: Function: nested_scopes
void nested_scopes() {
MyObj* p = nullptr;
@@ -355,13 +277,6 @@ void nested_scopes() {
// CHECK: Expire (LoanID: [[L_OUTER]])
}
-// CHECK-LABEL: LoanPropagation results:
-// CHECK-DAG: Origin [[O_P]] contains Loan [[L_INNER]]
-// CHECK-DAG: Origin [[O_ADDR_INNER]] contains Loan [[L_INNER]]
-// CHECK-DAG: Origin [[O_ADDR_OUTER]] contains Loan [[L_OUTER]]
-// CHECK-NOT: Origin [[O_P]] contains Loan [[L_OUTER]]
-
-
// CHECK-LABEL: Function: pointer_indirection
void pointer_indirection() {
int a;
diff --git a/clang/test/SemaCXX/attr-target-clones-riscv.cpp b/clang/test/SemaCXX/attr-target-clones-riscv.cpp
index 102bb4b..7648284 100644
--- a/clang/test/SemaCXX/attr-target-clones-riscv.cpp
+++ b/clang/test/SemaCXX/attr-target-clones-riscv.cpp
@@ -9,6 +9,9 @@ void __attribute__((target_clones("default", "mtune=sifive-u74"))) mtune() {}
// expected-warning@+1 {{version list contains duplicate entries}}
void __attribute__((target_clones("default", "arch=+c", "arch=+c"))) dupVersion() {}
+// expected-warning@+1 {{version list contains duplicate entries}}
+void __attribute__((target_clones(" default", "default "))) dupDefault() {}
+
// expected-warning@+1 {{unsupported '' in the 'target_clones' attribute string; 'target_clones' attribute ignored}}
void __attribute__((target_clones("default", ""))) emptyVersion() {}
diff --git a/clang/test/SemaCXX/constant-expression-p2280r4.cpp b/clang/test/SemaCXX/constant-expression-p2280r4.cpp
index 16f5f82..312a778 100644
--- a/clang/test/SemaCXX/constant-expression-p2280r4.cpp
+++ b/clang/test/SemaCXX/constant-expression-p2280r4.cpp
@@ -383,3 +383,17 @@ namespace enable_if_2 {
}
}
}
+
+namespace GH150015 {
+ extern int (& c)[8]; // interpreter-note {{declared here}}
+ constexpr int x = c <= c+8; // interpreter-error {{constexpr variable 'x' must be initialized by a constant expression}} \
+ // interpreter-note {{initializer of 'c' is unknown}}
+
+ struct X {};
+ struct Y {};
+ struct Z : X, Y {};
+ extern Z &z; // interpreter-note{{declared here}}
+ constexpr int bases = (void*)(X*)&z <= (Y*)&z; // expected-error {{constexpr variable 'bases' must be initialized by a constant expression}} \
+ // nointerpreter-note {{comparison of addresses of subobjects of different base classes has unspecified value}} \
+ // interpreter-note {{initializer of 'z' is unknown}}
+}
diff --git a/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp b/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp
index 726cfa3..a064401 100644
--- a/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp
+++ b/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -std=c++2a %s -verify=unsupported -triple x86_64-linux-gnu
// RUN: %clang_cc1 -std=c++2a %s -verify -triple x86_64-windows -fms-compatibility
+// RUN: %clang_cc1 -std=c++2a %s -verify -triple x86_64-uefi -fms-compatibility
[[msvc::no_unique_address]] int a; // expected-error {{only applies to non-bit-field non-static data members}} unsupported-warning {{unknown}}
[[msvc::no_unique_address]] void f(); // expected-error {{only applies to non-bit-field non-static data members}} unsupported-warning {{unknown}}
diff --git a/clang/test/SemaCXX/wreturn-always-throws.cpp b/clang/test/SemaCXX/wreturn-always-throws.cpp
index addcadd..df7689f 100644
--- a/clang/test/SemaCXX/wreturn-always-throws.cpp
+++ b/clang/test/SemaCXX/wreturn-always-throws.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -fexceptions -Wreturn-type -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -fexceptions -Wreturn-type -Winvalid-noreturn -verify %s
// expected-no-diagnostics
namespace std {
@@ -44,3 +44,22 @@ void testTemplates() {
throwErrorTemplate("ERROR");
(void)ensureZeroTemplate(42);
}
+
+// Ensure that explicit specialization of a member function does not inherit
+// the warning from the primary template.
+
+template<typename T>
+struct S {
+ void f();
+ void g();
+};
+
+template<typename T>
+void S<T>::f() { throw 0; }
+template<>
+void S<int>::f() {}
+
+template<typename T>
+void S<T>::g() {}
+template<>
+void S<int>::g() { throw 0; }
diff --git a/clang/test/SemaOpenACC/atomic-construct.cpp b/clang/test/SemaOpenACC/atomic-construct.cpp
index eba2559..10c85c2 100644
--- a/clang/test/SemaOpenACC/atomic-construct.cpp
+++ b/clang/test/SemaOpenACC/atomic-construct.cpp
@@ -1098,7 +1098,7 @@ void AtomicCaptureTemplateCompound(T LHS, T RHS) {
{
LHS--;
// expected-error@-3{{statement associated with OpenACC 'atomic capture' directive is invalid}}
- // expected-note@+1{{variable on right hand side of assignment('RHS') must match variable used in unary expression('LHS') from the first statement}}
+ // expected-note@+1{{sub-expression on right hand side of assignment('RHS') must match sub-expression used in unary expression('LHS') from the first statement}}
LHS = RHS;
}
@@ -1128,7 +1128,7 @@ void AtomicCaptureTemplateCompound(T LHS, T RHS) {
{
LHS *= 1;
// expected-error@-3{{statement associated with OpenACC 'atomic capture' directive is invalid}}
- // expected-note@+1{{variable on right hand side of assignment('RHS') must match variable used on left hand side of compound assignment('LHS') from the first statement}}
+ // expected-note@+1{{sub-expression on right hand side of assignment('RHS') must match sub-expression used on left hand side of compound assignment('LHS') from the first statement}}
LHS = RHS;
}
#pragma acc atomic capture
@@ -1157,7 +1157,7 @@ void AtomicCaptureTemplateCompound(T LHS, T RHS) {
{
LHS = LHS * 1;
// expected-error@-3{{statement associated with OpenACC 'atomic capture' directive is invalid}}
- // expected-note@+1{{variable on right hand side of assignment('RHS') must match variable used on left hand side of assignment('LHS') from the first statement}}
+ // expected-note@+1{{sub-expression on right hand side of assignment('RHS') must match sub-expression used on left hand side of assignment('LHS') from the first statement}}
RHS = RHS;
}
#pragma acc atomic capture
@@ -1186,7 +1186,7 @@ void AtomicCaptureTemplateCompound(T LHS, T RHS) {
{
LHS = LHS | 1;
// expected-error@-3{{statement associated with OpenACC 'atomic capture' directive is invalid}}
- // expected-note@+1{{variable on right hand side of assignment('RHS') must match variable used on left hand side of assignment('LHS') from the first statement}}
+ // expected-note@+1{{sub-expression on right hand side of assignment('RHS') must match sub-expression used on left hand side of assignment('LHS') from the first statement}}
RHS = RHS;
}
#pragma acc atomic capture
@@ -1255,7 +1255,7 @@ void AtomicCaptureTemplateCompound(T LHS, T RHS) {
{
LHS = RHS;
// expected-error@-3{{statement associated with OpenACC 'atomic capture' directive is invalid}}
- // expected-note@+1{{variable on left hand side of assignment('LHS') must match variable used on right hand side of assignment('RHS') from the first statement}}
+ // expected-note@+1{{sub-expression on left hand side of assignment('LHS') must match sub-expression used on right hand side of assignment('RHS') from the first statement}}
LHS = 1;
}
@@ -1294,7 +1294,7 @@ void AtomicCaptureTemplateCompound(T LHS, T RHS) {
{
LHS = RHS;
// expected-error@-3{{statement associated with OpenACC 'atomic capture' directive is invalid}}
- // expected-note@+1{{variable in unary expression('LHS') must match variable used on right hand side of assignment('RHS') from the first statement}}
+ // expected-note@+1{{sub-expression in unary expression('LHS') must match sub-expression used on right hand side of assignment('RHS') from the first statement}}
LHS++;
}
}
@@ -1352,7 +1352,7 @@ void AtomicCaptureTemplateCompound2(T LHS, T RHS) {
{
LHS--;
// expected-error@-3{{statement associated with OpenACC 'atomic capture' directive is invalid}}
- // expected-note@+1{{variable on right hand side of assignment('RHS') must match variable used in unary expression('LHS') from the first statement}}
+ // expected-note@+1{{sub-expression on right hand side of assignment('RHS') must match sub-expression used in unary expression('LHS') from the first statement}}
LHS = RHS;
}
@@ -1384,7 +1384,7 @@ void AtomicCaptureTemplateCompound2(T LHS, T RHS) {
{
LHS *= 1;
// expected-error@-3{{statement associated with OpenACC 'atomic capture' directive is invalid}}
- // expected-note@+1{{variable on right hand side of assignment('RHS') must match variable used on left hand side of compound assignment('LHS') from the first statement}}
+ // expected-note@+1{{sub-expression on right hand side of assignment('RHS') must match sub-expression used on left hand side of compound assignment('LHS') from the first statement}}
LHS = RHS;
}
#pragma acc atomic capture
@@ -1415,7 +1415,7 @@ void AtomicCaptureTemplateCompound2(T LHS, T RHS) {
{
LHS = LHS * 1;
// expected-error@-3{{statement associated with OpenACC 'atomic capture' directive is invalid}}
- // expected-note@+1{{variable on right hand side of assignment('RHS') must match variable used on left hand side of assignment('LHS') from the first statement}}
+ // expected-note@+1{{sub-expression on right hand side of assignment('RHS') must match sub-expression used on left hand side of assignment('LHS') from the first statement}}
RHS = RHS;
}
#pragma acc atomic capture
@@ -1446,7 +1446,7 @@ void AtomicCaptureTemplateCompound2(T LHS, T RHS) {
{
LHS = LHS | 1;
// expected-error@-3{{statement associated with OpenACC 'atomic capture' directive is invalid}}
- // expected-note@+1{{variable on right hand side of assignment('RHS') must match variable used on left hand side of assignment('LHS') from the first statement}}
+ // expected-note@+1{{sub-expression on right hand side of assignment('RHS') must match sub-expression used on left hand side of assignment('LHS') from the first statement}}
RHS = RHS;
}
#pragma acc atomic capture
@@ -1523,7 +1523,7 @@ void AtomicCaptureTemplateCompound2(T LHS, T RHS) {
{
LHS = RHS;
// expected-error@-3{{statement associated with OpenACC 'atomic capture' directive is invalid}}
- // expected-note@+1{{variable on left hand side of assignment('LHS') must match variable used on right hand side of assignment('RHS') from the first statement}}
+ // expected-note@+1{{sub-expression on left hand side of assignment('LHS') must match sub-expression used on right hand side of assignment('RHS') from the first statement}}
LHS = 1;
}
@@ -1570,7 +1570,7 @@ void AtomicCaptureTemplateCompound2(T LHS, T RHS) {
{
LHS = RHS;
// expected-error@-3{{statement associated with OpenACC 'atomic capture' directive is invalid}}
- // expected-note@+1{{variable in unary expression('LHS') must match variable used on right hand side of assignment('RHS') from the first statement}}
+ // expected-note@+1{{sub-expression in unary expression('LHS') must match sub-expression used on right hand side of assignment('RHS') from the first statement}}
LHS++;
}
}
@@ -1629,7 +1629,7 @@ void AtomicCaptureCompound(int LHS, int RHS) {
{
LHS--;
// expected-error@-3{{statement associated with OpenACC 'atomic capture' directive is invalid}}
- // expected-note@+1{{variable on right hand side of assignment('RHS') must match variable used in unary expression('LHS') from the first statement}}
+ // expected-note@+1{{sub-expression on right hand side of assignment('RHS') must match sub-expression used in unary expression('LHS') from the first statement}}
LHS = RHS;
}
@@ -1666,7 +1666,7 @@ void AtomicCaptureCompound(int LHS, int RHS) {
{
LHS *= 1;
// expected-error@-3{{statement associated with OpenACC 'atomic capture' directive is invalid}}
- // expected-note@+1{{variable on right hand side of assignment('RHS') must match variable used on left hand side of compound assignment('LHS') from the first statement}}
+ // expected-note@+1{{sub-expression on right hand side of assignment('RHS') must match sub-expression used on left hand side of compound assignment('LHS') from the first statement}}
LHS = RHS;
}
#pragma acc atomic capture
@@ -1702,7 +1702,7 @@ void AtomicCaptureCompound(int LHS, int RHS) {
{
LHS = LHS * 1;
// expected-error@-3{{statement associated with OpenACC 'atomic capture' directive is invalid}}
- // expected-note@+1{{variable on right hand side of assignment('RHS') must match variable used on left hand side of assignment('LHS') from the first statement}}
+ // expected-note@+1{{sub-expression on right hand side of assignment('RHS') must match sub-expression used on left hand side of assignment('LHS') from the first statement}}
RHS = RHS;
}
#pragma acc atomic capture
@@ -1738,7 +1738,7 @@ void AtomicCaptureCompound(int LHS, int RHS) {
{
LHS = LHS | 1;
// expected-error@-3{{statement associated with OpenACC 'atomic capture' directive is invalid}}
- // expected-note@+1{{variable on right hand side of assignment('RHS') must match variable used on left hand side of assignment('LHS') from the first statement}}
+ // expected-note@+1{{sub-expression on right hand side of assignment('RHS') must match sub-expression used on left hand side of assignment('LHS') from the first statement}}
RHS = RHS;
}
#pragma acc atomic capture
@@ -1815,7 +1815,7 @@ void AtomicCaptureCompound(int LHS, int RHS) {
{
LHS = RHS;
// expected-error@-3{{statement associated with OpenACC 'atomic capture' directive is invalid}}
- // expected-note@+1{{variable on left hand side of assignment('LHS') must match variable used on right hand side of assignment('RHS') from the first statement}}
+ // expected-note@+1{{sub-expression on left hand side of assignment('LHS') must match sub-expression used on right hand side of assignment('RHS') from the first statement}}
LHS = 1;
}
@@ -1861,7 +1861,23 @@ void AtomicCaptureCompound(int LHS, int RHS) {
{
LHS = RHS;
// expected-error@-3{{statement associated with OpenACC 'atomic capture' directive is invalid}}
- // expected-note@+1{{variable in unary expression('LHS') must match variable used on right hand side of assignment('RHS') from the first statement}}
+ // expected-note@+1{{sub-expression in unary expression('LHS') must match sub-expression used on right hand side of assignment('RHS') from the first statement}}
LHS++;
}
+
+ // Example from UDel test suite, which wasn't working because of irrelevant
+ // parens, make sure we work with these. This should not diagnose.
+ typedef double real_t;
+ int * distribution;
+ real_t *a;
+ real_t *b;
+ int *c;
+ for (int x = 0; x < 5; ++x) {
+#pragma acc atomic capture
+ {
+ c[x] = distribution[(int) (a[x]*b[x]/10)];
+ (distribution[(int)(a[x]*b[x]/10)])--;
+ }
+ }
+
}
diff --git a/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx1250-param.cl b/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx1250-param.cl
index 9711b3b..3247380 100644
--- a/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx1250-param.cl
+++ b/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx1250-param.cl
@@ -1,6 +1,7 @@
// REQUIRES: amdgpu-registered-target
-// RUN: %clang_cc1 -triple amdgcn-- -target-cpu gfx1250 -verify -S -o - %s
+// RUN: %clang_cc1 -cl-std=CL2.0 -triple amdgcn-- -target-cpu gfx1250 -verify -S -o - %s
+typedef int v2i __attribute__((ext_vector_type(2)));
typedef int v4i __attribute__((ext_vector_type(4)));
typedef int v8i __attribute__((ext_vector_type(8)));
@@ -28,6 +29,17 @@ void test__builtin_amdgcn_cvt_f16_bf8(int a, int b) {
__builtin_amdgcn_cvt_f16_bf8(a, b); // expected-error {{'__builtin_amdgcn_cvt_f16_bf8' must be a constant integer}}
}
+void test_amdgcn_load_monitor(global int* b32gaddr, global v2i* b64gaddr, global v4i* b128gaddr, int *b32faddr, v2i* b64faddr, v4i *b128faddr,
+ global int* b32out, global v2i* b64out, global v4i* b128out, int cpol)
+{
+ *b32out = __builtin_amdgcn_global_load_monitor_b32(b32gaddr, cpol); // expected-error {{'__builtin_amdgcn_global_load_monitor_b32' must be a constant integer}}
+ *b64out = __builtin_amdgcn_global_load_monitor_b64(b64gaddr, cpol); // expected-error {{'__builtin_amdgcn_global_load_monitor_b64' must be a constant integer}}
+ *b128out = __builtin_amdgcn_global_load_monitor_b128(b128gaddr, cpol); // expected-error {{'__builtin_amdgcn_global_load_monitor_b128' must be a constant integer}}
+ *b32out = __builtin_amdgcn_flat_load_monitor_b32(b32faddr, cpol); // expected-error {{'__builtin_amdgcn_flat_load_monitor_b32' must be a constant integer}}
+ *b64out = __builtin_amdgcn_flat_load_monitor_b64(b64faddr, cpol); // expected-error {{'__builtin_amdgcn_flat_load_monitor_b64' must be a constant integer}}
+ *b128out = __builtin_amdgcn_flat_load_monitor_b128(b128faddr, cpol); // expected-error {{'__builtin_amdgcn_flat_load_monitor_b128' must be a constant integer}}
+}
+
void test_amdgcn_tensor_load_store(v4i sg0, v8i sg1, v4i sg2, v4i sg3, int cpol)
{
__builtin_amdgcn_tensor_load_to_lds(sg0, sg1, sg2, sg3, cpol); // expected-error {{'__builtin_amdgcn_tensor_load_to_lds' must be a constant integer}}
@@ -36,6 +48,11 @@ void test_amdgcn_tensor_load_store(v4i sg0, v8i sg1, v4i sg2, v4i sg3, int cpol)
__builtin_amdgcn_tensor_store_from_lds_d2(sg0, sg1, cpol); // expected-error {{'__builtin_amdgcn_tensor_store_from_lds_d2' must be a constant integer}}
}
+void test_prefetch(generic void *fptr, global void *gptr, int cpol) {
+ __builtin_amdgcn_flat_prefetch(fptr, cpol); // expected-error {{'__builtin_amdgcn_flat_prefetch' must be a constant integer}}
+ __builtin_amdgcn_global_prefetch(gptr, cpol); // expected-error {{'__builtin_amdgcn_global_prefetch' must be a constant integer}}
+}
+
void test_cvt_f32_fp8_e5m3(global int* out, int a)
{
*out = __builtin_amdgcn_cvt_f32_fp8_e5m3(a, a); // expected-error {{'__builtin_amdgcn_cvt_f32_fp8_e5m3' must be a constant integer}}
diff --git a/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx1250-wmma-w32-param.cl b/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx1250-wmma-w32-param.cl
index 55d705e..8aa7c34 100644
--- a/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx1250-wmma-w32-param.cl
+++ b/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx1250-wmma-w32-param.cl
@@ -114,6 +114,13 @@ void test_amdgcn_wmma_i32_16x16x64_iu8(global v8i* out, v8i a, v8i b, v8i c, int
*out = __builtin_amdgcn_wmma_i32_16x16x64_iu8(0, a, 0, b, c, false, mod); // expected-error {{'__builtin_amdgcn_wmma_i32_16x16x64_iu8' must be a constant integer}}
}
+void test_amdgcn_wmma_f32_16x16x128_f8f6f4(global v8f* out, v16i a, v16i b, v8f c, int mod)
+{
+ *out = __builtin_amdgcn_wmma_f32_16x16x128_f8f6f4(mod, a, 2, b, 0, c); // expected-error {{'__builtin_amdgcn_wmma_f32_16x16x128_f8f6f4' must be a constant integer}}
+ *out = __builtin_amdgcn_wmma_f32_16x16x128_f8f6f4(1, a, mod, b, 0, c); // expected-error {{'__builtin_amdgcn_wmma_f32_16x16x128_f8f6f4' must be a constant integer}}
+ *out = __builtin_amdgcn_wmma_f32_16x16x128_f8f6f4(1, a, 2, b, mod, c); // expected-error {{'__builtin_amdgcn_wmma_f32_16x16x128_f8f6f4' must be a constant integer}}
+}
+
void test_amdgcn_wmma_f32_16x16x32_f16(global v8f* out, v16h a, v16h b, v8f c, int mod)
{
*out = __builtin_amdgcn_wmma_f32_16x16x32_f16(mod, a, 0, b, 0, c, false, false); // expected-error {{'__builtin_amdgcn_wmma_f32_16x16x32_f16' must be a constant integer}}
diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp
index 62a4f95..663bc98 100644
--- a/clang/test/SemaTemplate/concepts.cpp
+++ b/clang/test/SemaTemplate/concepts.cpp
@@ -1250,3 +1250,11 @@ static_assert(!D<Priv>::has, "Private should be invisible.");
static_assert(!D<Prot>::has, "Protected should be invisible.");
}
+
+
+namespace GH149986 {
+template <typename T> concept PerfectSquare = [](){} // expected-note 2{{here}}
+([](auto) { return true; }) < PerfectSquare <class T>;
+// expected-error@-1 {{declaration of 'T' shadows template parameter}} \
+// expected-error@-1 {{a concept definition cannot refer to itself}}
+}
diff --git a/clang/test/SemaTemplate/deduction-guide.cpp b/clang/test/SemaTemplate/deduction-guide.cpp
index 0953f647..f6bc6ee 100644
--- a/clang/test/SemaTemplate/deduction-guide.cpp
+++ b/clang/test/SemaTemplate/deduction-guide.cpp
@@ -966,3 +966,19 @@ Expand<Type, Invocable<>> _{};
// CHECK-NEXT: | `-ParmVarDecl {{.+}} 'T...' pack
}
+
+namespace GH134613 {
+template <typename R> struct Foo {
+ using value_type = R;
+
+ Foo() = default;
+ Foo(Foo<Foo<R>> &&rhs) {}
+};
+
+void main() {
+ auto r1 = Foo(Foo<Foo<int>>{});
+
+ static_assert(__is_same(decltype(r1)::value_type, int));
+}
+
+}
diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp
index 2c17f28..9b1e390 100644
--- a/clang/tools/driver/cc1_main.cpp
+++ b/clang/tools/driver/cc1_main.cpp
@@ -304,7 +304,7 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
*IOFile << "{\n";
llvm::TimerGroup::printAllJSONValues(*IOFile, "");
*IOFile << "\n}\n";
- } else {
+ } else if (!Clang->getCodeGenOpts().TimePassesStatsFile) {
llvm::TimerGroup::printAll(*IOFile);
}
llvm::TimerGroup::clearAll();
diff --git a/clang/unittests/Analysis/CMakeLists.txt b/clang/unittests/Analysis/CMakeLists.txt
index 059a748..52e7d28 100644
--- a/clang/unittests/Analysis/CMakeLists.txt
+++ b/clang/unittests/Analysis/CMakeLists.txt
@@ -4,6 +4,7 @@ add_clang_unittest(ClangAnalysisTests
CloneDetectionTest.cpp
ExprMutationAnalyzerTest.cpp
IntervalPartitionTest.cpp
+ LifetimeSafetyTest.cpp
MacroExpansionContextTest.cpp
UnsafeBufferUsageTest.cpp
CLANG_LIBS
diff --git a/clang/unittests/Analysis/LifetimeSafetyTest.cpp b/clang/unittests/Analysis/LifetimeSafetyTest.cpp
new file mode 100644
index 0000000..a48dc45
--- /dev/null
+++ b/clang/unittests/Analysis/LifetimeSafetyTest.cpp
@@ -0,0 +1,710 @@
+//===- LifetimeSafetyTest.cpp - Lifetime Safety Tests -*---------- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Testing/TestAST.h"
+#include "llvm/ADT/StringMap.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <optional>
+#include <vector>
+
+namespace clang::lifetimes::internal {
+namespace {
+
+using namespace ast_matchers;
+using ::testing::UnorderedElementsAreArray;
+
+// A helper class to run the full lifetime analysis on a piece of code
+// and provide an interface for querying the results.
+class LifetimeTestRunner {
+public:
+ LifetimeTestRunner(llvm::StringRef Code) {
+ std::string FullCode = R"(
+ #define POINT(name) void("__lifetime_test_point_" #name)
+ struct MyObj { ~MyObj() {} int i; };
+ )";
+ FullCode += Code.str();
+
+ AST = std::make_unique<clang::TestAST>(FullCode);
+ ASTCtx = &AST->context();
+
+ // Find the target function using AST matchers.
+ auto MatchResult =
+ match(functionDecl(hasName("target")).bind("target"), *ASTCtx);
+ auto *FD = selectFirst<FunctionDecl>("target", MatchResult);
+ if (!FD) {
+ ADD_FAILURE() << "Test case must have a function named 'target'";
+ return;
+ }
+ AnalysisCtx = std::make_unique<AnalysisDeclContext>(nullptr, FD);
+ CFG::BuildOptions &BuildOptions = AnalysisCtx->getCFGBuildOptions();
+ BuildOptions.setAllAlwaysAdd();
+ BuildOptions.AddImplicitDtors = true;
+ BuildOptions.AddTemporaryDtors = true;
+
+ // Run the main analysis.
+ Analysis = std::make_unique<LifetimeSafetyAnalysis>(*AnalysisCtx);
+ Analysis->run();
+
+ AnnotationToPointMap = Analysis->getTestPoints();
+ }
+
+ LifetimeSafetyAnalysis &getAnalysis() { return *Analysis; }
+ ASTContext &getASTContext() { return *ASTCtx; }
+
+ ProgramPoint getProgramPoint(llvm::StringRef Annotation) {
+ auto It = AnnotationToPointMap.find(Annotation);
+ if (It == AnnotationToPointMap.end()) {
+ ADD_FAILURE() << "Annotation '" << Annotation << "' not found.";
+ return nullptr;
+ }
+ return It->second;
+ }
+
+private:
+ std::unique_ptr<TestAST> AST;
+ ASTContext *ASTCtx = nullptr;
+ std::unique_ptr<AnalysisDeclContext> AnalysisCtx;
+ std::unique_ptr<LifetimeSafetyAnalysis> Analysis;
+ llvm::StringMap<ProgramPoint> AnnotationToPointMap;
+};
+
+// A convenience wrapper that uses the LifetimeSafetyAnalysis public API.
+class LifetimeTestHelper {
+public:
+ LifetimeTestHelper(LifetimeTestRunner &Runner)
+ : Runner(Runner), Analysis(Runner.getAnalysis()) {}
+
+ std::optional<OriginID> getOriginForDecl(llvm::StringRef VarName) {
+ auto *VD = findDecl<ValueDecl>(VarName);
+ if (!VD)
+ return std::nullopt;
+ auto OID = Analysis.getOriginIDForDecl(VD);
+ if (!OID)
+ ADD_FAILURE() << "Origin for '" << VarName << "' not found.";
+ return OID;
+ }
+
+ std::optional<LoanID> getLoanForVar(llvm::StringRef VarName) {
+ auto *VD = findDecl<VarDecl>(VarName);
+ if (!VD)
+ return std::nullopt;
+ std::vector<LoanID> LID = Analysis.getLoanIDForVar(VD);
+ if (LID.empty()) {
+ ADD_FAILURE() << "Loan for '" << VarName << "' not found.";
+ return std::nullopt;
+ }
+ // TODO: Support retrieving more than one loans to a var.
+ if (LID.size() > 1) {
+ ADD_FAILURE() << "More than 1 loans found for '" << VarName;
+ return std::nullopt;
+ }
+ return LID[0];
+ }
+
+ std::optional<LoanSet> getLoansAtPoint(OriginID OID,
+ llvm::StringRef Annotation) {
+ ProgramPoint PP = Runner.getProgramPoint(Annotation);
+ if (!PP)
+ return std::nullopt;
+ return Analysis.getLoansAtPoint(OID, PP);
+ }
+
+ std::optional<LoanSet> getExpiredLoansAtPoint(llvm::StringRef Annotation) {
+ ProgramPoint PP = Runner.getProgramPoint(Annotation);
+ if (!PP)
+ return std::nullopt;
+ return Analysis.getExpiredLoansAtPoint(PP);
+ }
+
+private:
+ template <typename DeclT> DeclT *findDecl(llvm::StringRef Name) {
+ auto &Ctx = Runner.getASTContext();
+ auto Results = match(valueDecl(hasName(Name)).bind("v"), Ctx);
+ if (Results.empty()) {
+ ADD_FAILURE() << "Declaration '" << Name << "' not found in AST.";
+ return nullptr;
+ }
+ return const_cast<DeclT *>(selectFirst<DeclT>("v", Results));
+ }
+
+ LifetimeTestRunner &Runner;
+ LifetimeSafetyAnalysis &Analysis;
+};
+
+// ========================================================================= //
+// GTest Matchers & Fixture
+// ========================================================================= //
+
+// A helper class to represent a set of loans, identified by variable names.
+class LoanSetInfo {
+public:
+ LoanSetInfo(const std::vector<std::string> &Vars, LifetimeTestHelper &H)
+ : LoanVars(Vars), Helper(H) {}
+ std::vector<std::string> LoanVars;
+ LifetimeTestHelper &Helper;
+};
+
+// It holds the name of the origin variable and a reference to the helper.
+class OriginInfo {
+public:
+ OriginInfo(llvm::StringRef OriginVar, LifetimeTestHelper &Helper)
+ : OriginVar(OriginVar), Helper(Helper) {}
+ llvm::StringRef OriginVar;
+ LifetimeTestHelper &Helper;
+};
+
+/// Matcher to verify the set of loans held by an origin at a specific
+/// program point.
+///
+/// This matcher is intended to be used with an \c OriginInfo object.
+///
+/// \param LoanVars A vector of strings, where each string is the name of a
+/// variable expected to be the source of a loan.
+/// \param Annotation A string identifying the program point (created with
+/// POINT()) where the check should be performed.
+MATCHER_P2(HasLoansToImpl, LoanVars, Annotation, "") {
+ const OriginInfo &Info = arg;
+ std::optional<OriginID> OIDOpt = Info.Helper.getOriginForDecl(Info.OriginVar);
+ if (!OIDOpt) {
+ *result_listener << "could not find origin for '" << Info.OriginVar.str()
+ << "'";
+ return false;
+ }
+
+ std::optional<LoanSet> ActualLoansSetOpt =
+ Info.Helper.getLoansAtPoint(*OIDOpt, Annotation);
+ if (!ActualLoansSetOpt) {
+ *result_listener << "could not get a valid loan set at point '"
+ << Annotation << "'";
+ return false;
+ }
+ std::vector<LoanID> ActualLoans(ActualLoansSetOpt->begin(),
+ ActualLoansSetOpt->end());
+
+ std::vector<LoanID> ExpectedLoans;
+ for (const auto &LoanVar : LoanVars) {
+ std::optional<LoanID> ExpectedLIDOpt = Info.Helper.getLoanForVar(LoanVar);
+ if (!ExpectedLIDOpt) {
+ *result_listener << "could not find loan for var '" << LoanVar << "'";
+ return false;
+ }
+ ExpectedLoans.push_back(*ExpectedLIDOpt);
+ }
+
+ return ExplainMatchResult(UnorderedElementsAreArray(ExpectedLoans),
+ ActualLoans, result_listener);
+}
+
+/// Matcher to verify that the complete set of expired loans at a program point
+/// matches the expected loan set.
+MATCHER_P(AreExpiredAt, Annotation, "") {
+ const LoanSetInfo &Info = arg;
+ auto &Helper = Info.Helper;
+
+ auto ActualExpiredSetOpt = Helper.getExpiredLoansAtPoint(Annotation);
+ if (!ActualExpiredSetOpt) {
+ *result_listener << "could not get a valid expired loan set at point '"
+ << Annotation << "'";
+ return false;
+ }
+ std::vector<LoanID> ActualExpiredLoans(ActualExpiredSetOpt->begin(),
+ ActualExpiredSetOpt->end());
+ std::vector<LoanID> ExpectedExpiredLoans;
+ for (const auto &VarName : Info.LoanVars) {
+ auto LoanIDOpt = Helper.getLoanForVar(VarName);
+ if (!LoanIDOpt) {
+ *result_listener << "could not find a loan for variable '" << VarName
+ << "'";
+ return false;
+ }
+ ExpectedExpiredLoans.push_back(*LoanIDOpt);
+ }
+ return ExplainMatchResult(UnorderedElementsAreArray(ExpectedExpiredLoans),
+ ActualExpiredLoans, result_listener);
+}
+
+// Base test fixture to manage the runner and helper.
+class LifetimeAnalysisTest : public ::testing::Test {
+protected:
+ void SetupTest(llvm::StringRef Code) {
+ Runner = std::make_unique<LifetimeTestRunner>(Code);
+ Helper = std::make_unique<LifetimeTestHelper>(*Runner);
+ }
+
+ OriginInfo Origin(llvm::StringRef OriginVar) {
+ return OriginInfo(OriginVar, *Helper);
+ }
+
+ /// Factory function that hides the std::vector creation.
+ LoanSetInfo LoansTo(std::initializer_list<std::string> LoanVars) {
+ return LoanSetInfo({LoanVars}, *Helper);
+ }
+
+ /// A convenience helper for asserting that no loans are expired.
+ LoanSetInfo NoLoans() { return LoansTo({}); }
+
+ // Factory function that hides the std::vector creation.
+ auto HasLoansTo(std::initializer_list<std::string> LoanVars,
+ const char *Annotation) {
+ return HasLoansToImpl(std::vector<std::string>(LoanVars), Annotation);
+ }
+
+ std::unique_ptr<LifetimeTestRunner> Runner;
+ std::unique_ptr<LifetimeTestHelper> Helper;
+};
+
+// ========================================================================= //
+// TESTS
+// ========================================================================= //
+
+TEST_F(LifetimeAnalysisTest, SimpleLoanAndOrigin) {
+ SetupTest(R"(
+ void target() {
+ int x;
+ int* p = &x;
+ POINT(p1);
+ }
+ )");
+ EXPECT_THAT(Origin("p"), HasLoansTo({"x"}, "p1"));
+}
+
+TEST_F(LifetimeAnalysisTest, OverwriteOrigin) {
+ SetupTest(R"(
+ void target() {
+ MyObj s1, s2;
+
+ MyObj* p = &s1;
+ POINT(after_s1);
+
+ p = &s2;
+ POINT(after_s2);
+ }
+ )");
+ EXPECT_THAT(Origin("p"), HasLoansTo({"s1"}, "after_s1"));
+ EXPECT_THAT(Origin("p"), HasLoansTo({"s2"}, "after_s2"));
+}
+
+TEST_F(LifetimeAnalysisTest, ConditionalLoan) {
+ SetupTest(R"(
+ void target(bool cond) {
+ int a, b;
+ int *p = nullptr;
+ if (cond) {
+ p = &a;
+ POINT(after_then);
+ } else {
+ p = &b;
+ POINT(after_else);
+ }
+ POINT(after_if);
+ }
+ )");
+ EXPECT_THAT(Origin("p"), HasLoansTo({"a"}, "after_then"));
+ EXPECT_THAT(Origin("p"), HasLoansTo({"b"}, "after_else"));
+ EXPECT_THAT(Origin("p"), HasLoansTo({"a", "b"}, "after_if"));
+}
+
+TEST_F(LifetimeAnalysisTest, PointerChain) {
+ SetupTest(R"(
+ void target() {
+ MyObj y;
+ MyObj* ptr1 = &y;
+ POINT(p1);
+
+ MyObj* ptr2 = ptr1;
+ POINT(p2);
+
+ ptr2 = ptr1;
+ POINT(p3);
+
+ ptr2 = ptr2; // Self assignment
+ POINT(p4);
+ }
+ )");
+ EXPECT_THAT(Origin("ptr1"), HasLoansTo({"y"}, "p1"));
+ EXPECT_THAT(Origin("ptr2"), HasLoansTo({"y"}, "p2"));
+ EXPECT_THAT(Origin("ptr2"), HasLoansTo({"y"}, "p3"));
+ EXPECT_THAT(Origin("ptr2"), HasLoansTo({"y"}, "p4"));
+}
+
+TEST_F(LifetimeAnalysisTest, ReassignToNull) {
+ SetupTest(R"(
+ void target() {
+ MyObj s1;
+ MyObj* p = &s1;
+ POINT(before_null);
+ p = nullptr;
+ POINT(after_null);
+ }
+ )");
+ EXPECT_THAT(Origin("p"), HasLoansTo({"s1"}, "before_null"));
+ EXPECT_THAT(Origin("p"), HasLoansTo({}, "after_null"));
+}
+
+TEST_F(LifetimeAnalysisTest, ReassignInIf) {
+ SetupTest(R"(
+ void target(bool condition) {
+ MyObj s1, s2;
+ MyObj* p = &s1;
+ POINT(before_if);
+ if (condition) {
+ p = &s2;
+ POINT(after_reassign);
+ }
+ POINT(after_if);
+ }
+ )");
+ EXPECT_THAT(Origin("p"), HasLoansTo({"s1"}, "before_if"));
+ EXPECT_THAT(Origin("p"), HasLoansTo({"s2"}, "after_reassign"));
+ EXPECT_THAT(Origin("p"), HasLoansTo({"s1", "s2"}, "after_if"));
+}
+
+TEST_F(LifetimeAnalysisTest, AssignInSwitch) {
+ SetupTest(R"(
+ void target(int mode) {
+ MyObj s1, s2, s3;
+ MyObj* p = nullptr;
+ switch (mode) {
+ case 1:
+ p = &s1;
+ POINT(case1);
+ break;
+ case 2:
+ p = &s2;
+ POINT(case2);
+ break;
+ default:
+ p = &s3;
+ POINT(case3);
+ break;
+ }
+ POINT(after_switch);
+ }
+ )");
+ EXPECT_THAT(Origin("p"), HasLoansTo({"s1"}, "case1"));
+ EXPECT_THAT(Origin("p"), HasLoansTo({"s2"}, "case2"));
+ EXPECT_THAT(Origin("p"), HasLoansTo({"s3"}, "case3"));
+ EXPECT_THAT(Origin("p"), HasLoansTo({"s1", "s2", "s3"}, "after_switch"));
+}
+
+TEST_F(LifetimeAnalysisTest, LoanInLoop) {
+ SetupTest(R"(
+ void target(bool condition) {
+ MyObj* p = nullptr;
+ while (condition) {
+ POINT(start_loop);
+ MyObj inner;
+ p = &inner;
+ POINT(end_loop);
+ }
+ POINT(after_loop);
+ }
+ )");
+ EXPECT_THAT(Origin("p"), HasLoansTo({"inner"}, "start_loop"));
+ EXPECT_THAT(LoansTo({"inner"}), AreExpiredAt("start_loop"));
+
+ EXPECT_THAT(Origin("p"), HasLoansTo({"inner"}, "end_loop"));
+ EXPECT_THAT(NoLoans(), AreExpiredAt("end_loop"));
+
+ EXPECT_THAT(Origin("p"), HasLoansTo({"inner"}, "after_loop"));
+ EXPECT_THAT(LoansTo({"inner"}), AreExpiredAt("after_loop"));
+}
+
+TEST_F(LifetimeAnalysisTest, LoopWithBreak) {
+ SetupTest(R"(
+ void target(int count) {
+ MyObj s1;
+ MyObj s2;
+ MyObj* p = &s1;
+ POINT(before_loop);
+ for (int i = 0; i < count; ++i) {
+ if (i == 5) {
+ p = &s2;
+ POINT(inside_if);
+ break;
+ }
+ POINT(after_if);
+ }
+ POINT(after_loop);
+ }
+ )");
+ EXPECT_THAT(Origin("p"), HasLoansTo({"s1"}, "before_loop"));
+ EXPECT_THAT(Origin("p"), HasLoansTo({"s2"}, "inside_if"));
+ // At the join point after if, s2 cannot make it to p without the if.
+ EXPECT_THAT(Origin("p"), HasLoansTo({"s1"}, "after_if"));
+ // At the join point after the loop, p could hold a loan to s1 (if the loop
+ // completed normally) or to s2 (if the loop was broken).
+ EXPECT_THAT(Origin("p"), HasLoansTo({"s1", "s2"}, "after_loop"));
+}
+
+TEST_F(LifetimeAnalysisTest, PointersInACycle) {
+ SetupTest(R"(
+ void target(bool condition) {
+ MyObj v1, v2, v3;
+ MyObj *p1 = &v1, *p2 = &v2, *p3 = &v3;
+
+ POINT(before_while);
+ while (condition) {
+ MyObj* temp = p1;
+ p1 = p2;
+ p2 = p3;
+ p3 = temp;
+ }
+ POINT(after_loop);
+ }
+ )");
+ EXPECT_THAT(Origin("p1"), HasLoansTo({"v1"}, "before_while"));
+ EXPECT_THAT(Origin("p2"), HasLoansTo({"v2"}, "before_while"));
+ EXPECT_THAT(Origin("p3"), HasLoansTo({"v3"}, "before_while"));
+
+ // At the fixed point after the loop, all pointers could point to any of
+ // the three variables.
+ EXPECT_THAT(Origin("p1"), HasLoansTo({"v1", "v2", "v3"}, "after_loop"));
+ EXPECT_THAT(Origin("p2"), HasLoansTo({"v1", "v2", "v3"}, "after_loop"));
+ EXPECT_THAT(Origin("p3"), HasLoansTo({"v1", "v2", "v3"}, "after_loop"));
+ EXPECT_THAT(Origin("temp"), HasLoansTo({"v1", "v2", "v3"}, "after_loop"));
+}
+
+TEST_F(LifetimeAnalysisTest, PointersAndExpirationInACycle) {
+ SetupTest(R"(
+ void target(bool condition) {
+ MyObj v1, v2;
+ MyObj *p1 = &v1, *p2 = &v2;
+
+ POINT(before_while);
+ while (condition) {
+ POINT(in_loop_before_temp);
+ MyObj temp;
+ p1 = &temp;
+ POINT(in_loop_after_temp);
+
+ MyObj* q = p1;
+ p1 = p2;
+ p2 = q;
+ }
+ POINT(after_loop);
+ }
+ )");
+ EXPECT_THAT(Origin("p1"), HasLoansTo({"v1"}, "before_while"));
+ EXPECT_THAT(Origin("p2"), HasLoansTo({"v2"}, "before_while"));
+ EXPECT_THAT(NoLoans(), AreExpiredAt("before_while"));
+
+ EXPECT_THAT(Origin("p1"),
+ HasLoansTo({"v1", "v2", "temp"}, "in_loop_before_temp"));
+ EXPECT_THAT(Origin("p2"), HasLoansTo({"v2", "temp"}, "in_loop_before_temp"));
+ EXPECT_THAT(LoansTo({"temp"}), AreExpiredAt("in_loop_before_temp"));
+
+ EXPECT_THAT(Origin("p1"), HasLoansTo({"temp"}, "in_loop_after_temp"));
+ EXPECT_THAT(Origin("p2"), HasLoansTo({"v2", "temp"}, "in_loop_after_temp"));
+ EXPECT_THAT(NoLoans(), AreExpiredAt("in_loop_after_temp"));
+
+ EXPECT_THAT(Origin("p1"), HasLoansTo({"v1", "v2", "temp"}, "after_loop"));
+ EXPECT_THAT(Origin("p2"), HasLoansTo({"v2", "temp"}, "after_loop"));
+ EXPECT_THAT(LoansTo({"temp"}), AreExpiredAt("after_loop"));
+}
+
+TEST_F(LifetimeAnalysisTest, NestedScopes) {
+ SetupTest(R"(
+ void target() {
+ MyObj* p = nullptr;
+ {
+ MyObj outer;
+ p = &outer;
+ POINT(before_inner_scope);
+ {
+ MyObj inner;
+ p = &inner;
+ POINT(inside_inner_scope);
+ } // inner expires
+ POINT(after_inner_scope);
+ } // outer expires
+ }
+ )");
+ EXPECT_THAT(Origin("p"), HasLoansTo({"outer"}, "before_inner_scope"));
+ EXPECT_THAT(Origin("p"), HasLoansTo({"inner"}, "inside_inner_scope"));
+ EXPECT_THAT(Origin("p"), HasLoansTo({"inner"}, "after_inner_scope"));
+}
+
+TEST_F(LifetimeAnalysisTest, SimpleExpiry) {
+ SetupTest(R"(
+ void target() {
+ MyObj* p = nullptr;
+ {
+ MyObj s;
+ p = &s;
+ POINT(before_expiry);
+ } // s goes out of scope here
+ POINT(after_expiry);
+ }
+ )");
+ EXPECT_THAT(NoLoans(), AreExpiredAt("before_expiry"));
+ EXPECT_THAT(LoansTo({"s"}), AreExpiredAt("after_expiry"));
+}
+
+TEST_F(LifetimeAnalysisTest, NestedExpiry) {
+ SetupTest(R"(
+ void target() {
+ MyObj s1;
+ MyObj* p = &s1;
+ POINT(before_inner);
+ {
+ MyObj s2;
+ p = &s2;
+ POINT(in_inner);
+ } // s2 expires
+ POINT(after_inner);
+ }
+ )");
+ EXPECT_THAT(NoLoans(), AreExpiredAt("before_inner"));
+ EXPECT_THAT(NoLoans(), AreExpiredAt("in_inner"));
+ EXPECT_THAT(LoansTo({"s2"}), AreExpiredAt("after_inner"));
+}
+
+TEST_F(LifetimeAnalysisTest, ConditionalExpiry) {
+ SetupTest(R"(
+ void target(bool cond) {
+ MyObj s1;
+ MyObj* p = &s1;
+ POINT(before_if);
+ if (cond) {
+ MyObj s2;
+ p = &s2;
+ POINT(then_block);
+ } // s2 expires here
+ POINT(after_if);
+ }
+ )");
+ EXPECT_THAT(NoLoans(), AreExpiredAt("before_if"));
+ EXPECT_THAT(NoLoans(), AreExpiredAt("then_block"));
+ EXPECT_THAT(LoansTo({"s2"}), AreExpiredAt("after_if"));
+}
+
+TEST_F(LifetimeAnalysisTest, LoopExpiry) {
+ SetupTest(R"(
+ void target() {
+ MyObj *p = nullptr;
+ for (int i = 0; i < 2; ++i) {
+ POINT(start_loop);
+ MyObj s;
+ p = &s;
+ POINT(end_loop);
+ } // s expires here on each iteration
+ POINT(after_loop);
+ }
+ )");
+ EXPECT_THAT(LoansTo({"s"}), AreExpiredAt("start_loop"));
+ EXPECT_THAT(NoLoans(), AreExpiredAt("end_loop"));
+ EXPECT_THAT(LoansTo({"s"}), AreExpiredAt("after_loop"));
+}
+
+TEST_F(LifetimeAnalysisTest, MultipleExpiredLoans) {
+ SetupTest(R"(
+ void target() {
+ MyObj *p1, *p2, *p3;
+ {
+ MyObj s1;
+ p1 = &s1;
+ POINT(p1);
+ } // s1 expires
+ POINT(p2);
+ {
+ MyObj s2;
+ p2 = &s2;
+ MyObj s3;
+ p3 = &s3;
+ POINT(p3);
+ } // s2, s3 expire
+ POINT(p4);
+ }
+ )");
+ EXPECT_THAT(NoLoans(), AreExpiredAt("p1"));
+ EXPECT_THAT(LoansTo({"s1"}), AreExpiredAt("p2"));
+ EXPECT_THAT(LoansTo({"s1"}), AreExpiredAt("p3"));
+ EXPECT_THAT(LoansTo({"s1", "s2", "s3"}), AreExpiredAt("p4"));
+}
+
+TEST_F(LifetimeAnalysisTest, GotoJumpsOutOfScope) {
+ SetupTest(R"(
+ void target(bool cond) {
+ MyObj *p = nullptr;
+ {
+ MyObj s;
+ p = &s;
+ POINT(before_goto);
+ if (cond) {
+ goto end;
+ }
+ } // `s` expires here on the path that doesn't jump
+ POINT(after_scope);
+ end:
+ POINT(after_goto);
+ }
+ )");
+ EXPECT_THAT(NoLoans(), AreExpiredAt("before_goto"));
+ EXPECT_THAT(LoansTo({"s"}), AreExpiredAt("after_scope"));
+ EXPECT_THAT(LoansTo({"s"}), AreExpiredAt("after_goto"));
+}
+
+TEST_F(LifetimeAnalysisTest, ContinueInLoop) {
+ SetupTest(R"(
+ void target(int count) {
+ MyObj *p = nullptr;
+ MyObj outer;
+ p = &outer;
+ POINT(before_loop);
+
+ for (int i = 0; i < count; ++i) {
+ if (i % 2 == 0) {
+ MyObj s_even;
+ p = &s_even;
+ POINT(in_even_iter);
+ continue;
+ }
+ MyObj s_odd;
+ p = &s_odd;
+ POINT(in_odd_iter);
+ }
+ POINT(after_loop);
+ }
+ )");
+ EXPECT_THAT(NoLoans(), AreExpiredAt("before_loop"));
+ EXPECT_THAT(LoansTo({"s_odd"}), AreExpiredAt("in_even_iter"));
+ EXPECT_THAT(LoansTo({"s_even"}), AreExpiredAt("in_odd_iter"));
+ EXPECT_THAT(LoansTo({"s_even", "s_odd"}), AreExpiredAt("after_loop"));
+}
+
+TEST_F(LifetimeAnalysisTest, ReassignedPointerThenOriginalExpires) {
+ SetupTest(R"(
+ void target() {
+ MyObj* p = nullptr;
+ {
+ MyObj s1;
+ p = &s1;
+ POINT(p_has_s1);
+ {
+ MyObj s2;
+ p = &s2;
+ POINT(p_has_s2);
+ }
+ POINT(p_after_s2_expires);
+ } // s1 expires here.
+ POINT(p_after_s1_expires);
+ }
+ )");
+ EXPECT_THAT(NoLoans(), AreExpiredAt("p_has_s1"));
+ EXPECT_THAT(NoLoans(), AreExpiredAt("p_has_s2"));
+ EXPECT_THAT(LoansTo({"s2"}), AreExpiredAt("p_after_s2_expires"));
+ EXPECT_THAT(LoansTo({"s1", "s2"}), AreExpiredAt("p_after_s1_expires"));
+}
+
+} // anonymous namespace
+} // namespace clang::lifetimes::internal
diff --git a/clang/unittests/Format/BracesInserterTest.cpp b/clang/unittests/Format/BracesInserterTest.cpp
index e0c447d..572e53e 100644
--- a/clang/unittests/Format/BracesInserterTest.cpp
+++ b/clang/unittests/Format/BracesInserterTest.cpp
@@ -257,9 +257,9 @@ TEST_F(BracesInserterTest, InsertBracesRange) {
FormatStyle Style = getLLVMStyle();
Style.InsertBraces = true;
- const StringRef Code("while (a)\n"
- " if (b)\n"
- " return;");
+ constexpr StringRef Code("while (a)\n"
+ " if (b)\n"
+ " return;");
verifyFormat("while (a) {\n"
" if (b)\n"
diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index 65d8b36..9de3cca 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -249,6 +249,7 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions,
AfterFunctionDefinitionName);
CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterIfMacros);
+ CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterNot);
CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterOverloadedOperator);
CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterPlacementOperator);
CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, BeforeNonEmptyParentheses);
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 0bc1c6d..c20d099 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -3185,7 +3185,7 @@ TEST_F(FormatTest, FormatsLabels) {
// The opening brace may either be on the same unwrapped line as the colon or
// on a separate one. The formatter should recognize both.
Style = getLLVMStyle();
- Style.BreakBeforeBraces = FormatStyle::BraceBreakingStyle::BS_Allman;
+ Style.BreakBeforeBraces = FormatStyle::BS_Allman;
verifyFormat("{\n"
" some_code();\n"
"test_label:\n"
@@ -3206,7 +3206,7 @@ TEST_F(FormatTest, FormatsLabels) {
TEST_F(FormatTest, MultiLineControlStatements) {
FormatStyle Style = getLLVMStyleWithColumns(20);
- Style.BreakBeforeBraces = FormatStyle::BraceBreakingStyle::BS_Custom;
+ Style.BreakBeforeBraces = FormatStyle::BS_Custom;
Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_MultiLine;
// Short lines should keep opening brace on same line.
verifyFormat("if (foo) {\n"
@@ -3441,7 +3441,7 @@ TEST_F(FormatTest, MultiLineControlStatements) {
TEST_F(FormatTest, BeforeWhile) {
FormatStyle Style = getLLVMStyle();
- Style.BreakBeforeBraces = FormatStyle::BraceBreakingStyle::BS_Custom;
+ Style.BreakBeforeBraces = FormatStyle::BS_Custom;
verifyFormat("do {\n"
" foo();\n"
@@ -4803,12 +4803,13 @@ TEST_F(FormatTest, FormatsInlineASM) {
"int i;");
auto Style = getLLVMStyleWithColumns(0);
- const StringRef Code1{"asm(\"xyz\" : \"=a\"(a), \"=d\"(b) : \"a\"(data));"};
- const StringRef Code2{"asm(\"xyz\"\n"
- " : \"=a\"(a), \"=d\"(b)\n"
- " : \"a\"(data));"};
- const StringRef Code3{"asm(\"xyz\" : \"=a\"(a), \"=d\"(b)\n"
- " : \"a\"(data));"};
+ constexpr StringRef Code1(
+ "asm(\"xyz\" : \"=a\"(a), \"=d\"(b) : \"a\"(data));");
+ constexpr StringRef Code2("asm(\"xyz\"\n"
+ " : \"=a\"(a), \"=d\"(b)\n"
+ " : \"a\"(data));");
+ constexpr StringRef Code3("asm(\"xyz\" : \"=a\"(a), \"=d\"(b)\n"
+ " : \"a\"(data));");
Style.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline;
verifyFormat(Code1, Style);
@@ -6681,6 +6682,17 @@ TEST_F(FormatTest, EscapedNewlines) {
" int x(int a);",
AlignLeft);
+ // Escaped with a trigraph. The program just has to avoid crashing.
+ verifyNoCrash("#define A \?\?/\n"
+ "int i;\?\?/\n"
+ " int j;");
+ verifyNoCrash("#define A \?\?/\r\n"
+ "int i;\?\?/\r\n"
+ " int j;");
+ verifyNoCrash("#define A \?\?/\n"
+ "int i;",
+ getGoogleStyle(FormatStyle::LK_CSharp));
+
// CRLF line endings
verifyFormat("#define A \\\r\n int i; \\\r\n int j;",
"#define A \\\r\nint i;\\\r\n int j;", Narrow);
@@ -6693,16 +6705,16 @@ TEST_F(FormatTest, EscapedNewlines) {
" int x(int a);",
AlignLeft);
- constexpr StringRef Code{"#define A \\\n"
+ constexpr StringRef Code("#define A \\\n"
" int a123; \\\n"
" int a; \\\n"
- " int a1234;"};
+ " int a1234;");
verifyFormat(Code, AlignLeft);
- constexpr StringRef Code2{"#define A \\\n"
+ constexpr StringRef Code2("#define A \\\n"
" int a123; \\\n"
" int a; \\\n"
- " int a1234;"};
+ " int a1234;");
auto LastLine = getLLVMStyle();
LastLine.AlignEscapedNewlines = FormatStyle::ENAS_LeftWithLastLine;
verifyFormat(Code2, LastLine);
@@ -7771,6 +7783,16 @@ TEST_F(FormatTest, ConstructorInitializers) {
"Constructor() :\n"
" // Comment forcing unwanted break.\n"
" aaaa(aaaa) {}");
+
+ // Braced initializers with trailing commas.
+ verifyFormat("MyClass::MyClass()\n"
+ " : aaaa{\n"
+ " 0,\n"
+ " },\n"
+ " bbbb{\n"
+ " 0,\n"
+ " } {}",
+ "MyClass::MyClass():aaaa{0,},bbbb{0,}{}");
}
TEST_F(FormatTest, AllowAllConstructorInitializersOnNextLine) {
@@ -12091,15 +12113,17 @@ TEST_F(FormatTest, UnderstandsFunctionRefQualification) {
Prefix = "void a() const &;\n"
"void b() const &;\n";
verifyFormat(Prefix + "int *x;", Prefix + "int* x;", DerivePointerAlignment);
+
+ verifyGoogleFormat("MACRO(int*, std::function<void() &&>);");
}
TEST_F(FormatTest, PointerAlignmentFallback) {
FormatStyle Style = getLLVMStyle();
Style.DerivePointerAlignment = true;
- const StringRef Code("int* p;\n"
- "int *q;\n"
- "int * r;");
+ constexpr StringRef Code("int* p;\n"
+ "int *q;\n"
+ "int * r;");
EXPECT_EQ(Style.PointerAlignment, FormatStyle::PAS_Right);
verifyFormat("int *p;\n"
@@ -15014,7 +15038,7 @@ TEST_F(FormatTest, PullTrivialFunctionDefinitionsIntoSingleLine) {
" aaaaaaaaaaaaaaaaaa,\n"
" aaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) {}");
- constexpr StringRef Code{"void foo() { /* Empty */ }"};
+ constexpr StringRef Code("void foo() { /* Empty */ }");
verifyFormat(Code);
verifyFormat(Code, "void foo() { /* Empty */\n"
"}");
@@ -17652,6 +17676,12 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
verifyFormat("int x = int (y);", SomeSpace2);
verifyFormat("auto lambda = []() { return 0; };", SomeSpace2);
+ auto Style = getLLVMStyle();
+ Style.SpaceBeforeParens = FormatStyle::SBPO_Custom;
+ EXPECT_FALSE(Style.SpaceBeforeParensOptions.AfterNot);
+ Style.SpaceBeforeParensOptions.AfterNot = true;
+ verifyFormat("return not (a || b);", Style);
+
FormatStyle SpaceAfterOverloadedOperator = getLLVMStyle();
SpaceAfterOverloadedOperator.SpaceBeforeParens = FormatStyle::SBPO_Custom;
SpaceAfterOverloadedOperator.SpaceBeforeParensOptions
@@ -23779,7 +23809,7 @@ TEST_F(FormatTest, FormatsLambdas) {
LLVMWithBeforeLambdaBody.BreakBeforeBraces = FormatStyle::BS_Custom;
LLVMWithBeforeLambdaBody.BraceWrapping.BeforeLambdaBody = true;
LLVMWithBeforeLambdaBody.AllowShortLambdasOnASingleLine =
- FormatStyle::ShortLambdaStyle::SLS_None;
+ FormatStyle::SLS_None;
verifyFormat("FctWithOneNestedLambdaInline_SLS_None(\n"
" []()\n"
" {\n"
@@ -23815,7 +23845,7 @@ TEST_F(FormatTest, FormatsLambdas) {
LLVMWithBeforeLambdaBody);
LLVMWithBeforeLambdaBody.AllowShortLambdasOnASingleLine =
- FormatStyle::ShortLambdaStyle::SLS_Empty;
+ FormatStyle::SLS_Empty;
verifyFormat("FctWithOneNestedLambdaInline_SLS_Empty(\n"
" []()\n"
" {\n"
@@ -23862,7 +23892,7 @@ TEST_F(FormatTest, FormatsLambdas) {
LLVMWithBeforeLambdaBody);
LLVMWithBeforeLambdaBody.AllowShortLambdasOnASingleLine =
- FormatStyle::ShortLambdaStyle::SLS_Inline;
+ FormatStyle::SLS_Inline;
verifyFormat("FctWithOneNestedLambdaInline_SLS_Inline([]() { return 17; });",
LLVMWithBeforeLambdaBody);
verifyFormat("FctWithOneNestedLambdaEmpty_SLS_Inline([]() {});",
@@ -23893,7 +23923,7 @@ TEST_F(FormatTest, FormatsLambdas) {
LLVMWithBeforeLambdaBody);
LLVMWithBeforeLambdaBody.AllowShortLambdasOnASingleLine =
- FormatStyle::ShortLambdaStyle::SLS_All;
+ FormatStyle::SLS_All;
verifyFormat("FctWithOneNestedLambdaInline_SLS_All([]() { return 17; });",
LLVMWithBeforeLambdaBody);
verifyFormat("FctWithOneNestedLambdaEmpty_SLS_All([]() {});",
@@ -24025,7 +24055,7 @@ TEST_F(FormatTest, FormatsLambdas) {
LLVMWithBeforeLambdaBody);
LLVMWithBeforeLambdaBody.AllowShortLambdasOnASingleLine =
- FormatStyle::ShortLambdaStyle::SLS_None;
+ FormatStyle::SLS_None;
verifyFormat("auto select = [this]() -> const Library::Object *\n"
"{\n"
@@ -24273,7 +24303,7 @@ TEST_F(FormatTest, LambdaWithLineComments) {
LLVMWithBeforeLambdaBody.BreakBeforeBraces = FormatStyle::BS_Custom;
LLVMWithBeforeLambdaBody.BraceWrapping.BeforeLambdaBody = true;
LLVMWithBeforeLambdaBody.AllowShortLambdasOnASingleLine =
- FormatStyle::ShortLambdaStyle::SLS_All;
+ FormatStyle::SLS_All;
verifyFormat("auto k = []() { return; }", LLVMWithBeforeLambdaBody);
verifyFormat("auto k = []() // comment\n"
@@ -27244,7 +27274,7 @@ TEST_F(FormatTest, IndentAccessModifiers) {
TEST_F(FormatTest, LimitlessStringsAndComments) {
auto Style = getLLVMStyleWithColumns(0);
- constexpr StringRef Code =
+ constexpr StringRef Code(
"/**\n"
" * This is a multiline comment with quite some long lines, at least for "
"the LLVM Style.\n"
@@ -27265,7 +27295,7 @@ TEST_F(FormatTest, LimitlessStringsAndComments) {
" const std::string SmallString = \"Hello World\";\n"
" // Small line comment\n"
" return String.size() > SmallString.size();\n"
- "}";
+ "}");
verifyNoChange(Code, Style);
}
@@ -28371,10 +28401,15 @@ TEST_F(FormatTest, BreakAfterAttributes) {
"Foo &operator-(Foo &);",
Style);
- Style.ReferenceAlignment = FormatStyle::ReferenceAlignmentStyle::RAS_Left;
+ Style.ReferenceAlignment = FormatStyle::RAS_Left;
verifyFormat("[[nodiscard]]\n"
"Foo& operator-(Foo&);",
Style);
+
+ Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
+ verifyFormat("[[deprecated]]\n"
+ "void f() = delete;",
+ Style);
}
TEST_F(FormatTest, InsertNewlineAtEOF) {
@@ -28384,9 +28419,9 @@ TEST_F(FormatTest, InsertNewlineAtEOF) {
verifyNoChange("int i;\n", Style);
verifyFormat("int i;\n", "int i;", Style);
- constexpr StringRef Code{"namespace {\n"
+ constexpr StringRef Code("namespace {\n"
"int i;\n"
- "} // namespace"};
+ "} // namespace");
verifyFormat(Code.str() + '\n', Code, Style,
{tooling::Range(19, 13)}); // line 3
}
@@ -28395,7 +28430,7 @@ TEST_F(FormatTest, KeepEmptyLinesAtEOF) {
FormatStyle Style = getLLVMStyle();
Style.KeepEmptyLines.AtEndOfFile = true;
- const StringRef Code{"int i;\n\n"};
+ constexpr StringRef Code("int i;\n\n");
verifyNoChange(Code, Style);
verifyFormat(Code, "int i;\n\n\n", Style);
}
@@ -28628,8 +28663,8 @@ TEST_F(FormatTest, PPDirectivesAndCommentsInBracedInit) {
}
TEST_F(FormatTest, BreakAdjacentStringLiterals) {
- constexpr StringRef Code{
- "return \"Code\" \"\\0\\52\\26\\55\\55\\0\" \"x013\" \"\\02\\xBA\";"};
+ constexpr StringRef Code(
+ "return \"Code\" \"\\0\\52\\26\\55\\55\\0\" \"x013\" \"\\02\\xBA\";");
verifyFormat("return \"Code\"\n"
" \"\\0\\52\\26\\55\\55\\0\"\n"
@@ -29040,9 +29075,9 @@ TEST_F(FormatTest, KeepFormFeed) {
auto Style = getLLVMStyle();
Style.KeepFormFeed = true;
- constexpr StringRef NoFormFeed{"int i;\n"
+ constexpr StringRef NoFormFeed("int i;\n"
"\n"
- "void f();"};
+ "void f();");
verifyFormat(NoFormFeed,
"int i;\n"
" \f\n"
@@ -29064,9 +29099,9 @@ TEST_F(FormatTest, KeepFormFeed) {
"void f();\f",
Style);
- constexpr StringRef FormFeed{"int i;\n"
+ constexpr StringRef FormFeed("int i;\n"
"\f\n"
- "void f();"};
+ "void f();");
verifyNoChange(FormFeed, Style);
Style.LineEnding = FormatStyle::LE_LF;
@@ -29076,10 +29111,10 @@ TEST_F(FormatTest, KeepFormFeed) {
"void f();",
Style);
- constexpr StringRef FormFeedBeforeEmptyLine{"int i;\n"
+ constexpr StringRef FormFeedBeforeEmptyLine("int i;\n"
"\f\n"
"\n"
- "void f();"};
+ "void f();");
Style.MaxEmptyLinesToKeep = 2;
verifyFormat(FormFeedBeforeEmptyLine,
"int i;\n"
diff --git a/clang/unittests/Format/FormatTestComments.cpp b/clang/unittests/Format/FormatTestComments.cpp
index 8870755..69026bc 100644
--- a/clang/unittests/Format/FormatTestComments.cpp
+++ b/clang/unittests/Format/FormatTestComments.cpp
@@ -1120,11 +1120,11 @@ TEST_F(FormatTestComments, KeepsLevelOfCommentBeforePPDirective) {
" }\n"
"}"));
- const StringRef Code("void func() {\n"
- " // clang-format off\n"
- " #define KV(value) #value, value\n"
- " // clang-format on\n"
- "}");
+ constexpr StringRef Code("void func() {\n"
+ " // clang-format off\n"
+ " #define KV(value) #value, value\n"
+ " // clang-format on\n"
+ "}");
verifyNoChange(Code);
auto Style = getLLVMStyle();
diff --git a/clang/unittests/Format/FormatTestJava.cpp b/clang/unittests/Format/FormatTestJava.cpp
index ca5aba0..1275564 100644
--- a/clang/unittests/Format/FormatTestJava.cpp
+++ b/clang/unittests/Format/FormatTestJava.cpp
@@ -631,17 +631,17 @@ TEST_F(FormatTestJava, SwitchExpression) {
"});",
Style);
- constexpr StringRef Code1{"i = switch (day) {\n"
+ constexpr StringRef Code1("i = switch (day) {\n"
" case THURSDAY, SATURDAY -> 8;\n"
" case WEDNESDAY -> 9;\n"
" default -> 0;\n"
- "};"};
+ "};");
verifyFormat(Code1, Style);
Style.IndentCaseLabels = true;
verifyFormat(Code1, Style);
- constexpr StringRef Code2{"i = switch (day) {\n"
+ constexpr StringRef Code2("i = switch (day) {\n"
" case THURSDAY, SATURDAY -> {\n"
" foo();\n"
" yield 8;\n"
@@ -653,17 +653,17 @@ TEST_F(FormatTestJava, SwitchExpression) {
" default -> {\n"
" yield 0;\n"
" }\n"
- "};"};
+ "};");
verifyFormat(Code2, Style);
Style.IndentCaseLabels = false;
verifyFormat(Code2, Style);
- constexpr StringRef Code3{"switch (day) {\n"
+ constexpr StringRef Code3("switch (day) {\n"
"case THURSDAY, SATURDAY -> i = 8;\n"
"case WEDNESDAY -> i = 9;\n"
"default -> i = 0;\n"
- "};"};
+ "};");
verifyFormat(Code3, Style);
Style.IndentCaseLabels = true;
diff --git a/clang/unittests/Format/FormatTestSelective.cpp b/clang/unittests/Format/FormatTestSelective.cpp
index 0b7ac21..1a01153 100644
--- a/clang/unittests/Format/FormatTestSelective.cpp
+++ b/clang/unittests/Format/FormatTestSelective.cpp
@@ -672,15 +672,14 @@ TEST_F(FormatTestSelective, FormatMacroRegardlessOfPreviousIndent) {
// need to be adapted.
Style = getLLVMStyle();
- const StringRef Code{" class Foo {\n"
- " void test() {\n"
- " #ifdef 1\n"
- " #define some\n" // format this line
- " #endif\n"
- " }};"};
-
- EXPECT_EQ(Style.IndentPPDirectives,
- FormatStyle::PPDirectiveIndentStyle::PPDIS_None);
+ constexpr StringRef Code(" class Foo {\n"
+ " void test() {\n"
+ " #ifdef 1\n"
+ " #define some\n" // format this line
+ " #endif\n"
+ " }};");
+
+ EXPECT_EQ(Style.IndentPPDirectives, FormatStyle::PPDIS_None);
EXPECT_EQ(" class Foo {\n"
" void test() {\n"
" #ifdef 1\n"
@@ -689,8 +688,7 @@ TEST_F(FormatTestSelective, FormatMacroRegardlessOfPreviousIndent) {
" }};", // Ditto: Bug?
format(Code, 57, 0));
- Style.IndentPPDirectives =
- FormatStyle::PPDirectiveIndentStyle::PPDIS_BeforeHash;
+ Style.IndentPPDirectives = FormatStyle::PPDIS_BeforeHash;
EXPECT_EQ(" class Foo {\n"
" void test() {\n"
" #ifdef 1\n"
@@ -699,8 +697,7 @@ TEST_F(FormatTestSelective, FormatMacroRegardlessOfPreviousIndent) {
" }};",
format(Code, 57, 0));
- Style.IndentPPDirectives =
- FormatStyle::PPDirectiveIndentStyle::PPDIS_AfterHash;
+ Style.IndentPPDirectives = FormatStyle::PPDIS_AfterHash;
EXPECT_EQ(" class Foo {\n"
" void test() {\n"
" #ifdef 1\n"
diff --git a/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp b/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp
index b1e42e9..8681c3d 100644
--- a/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp
+++ b/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp
@@ -24,7 +24,7 @@ TEST_F(IntegerLiteralSeparatorTest, SingleQuoteAsSeparator) {
EXPECT_EQ(Style.IntegerLiteralSeparator.Decimal, 0);
EXPECT_EQ(Style.IntegerLiteralSeparator.Hex, 0);
- const StringRef Binary("b = 0b10011'11'0110'1u;");
+ constexpr StringRef Binary("b = 0b10011'11'0110'1u;");
verifyFormat(Binary, Style);
Style.IntegerLiteralSeparator.Binary = -1;
verifyFormat("b = 0b100111101101u;", Binary, Style);
@@ -33,14 +33,14 @@ TEST_F(IntegerLiteralSeparatorTest, SingleQuoteAsSeparator) {
Style.IntegerLiteralSeparator.Binary = 4;
verifyFormat("b = 0b1001'1110'1101u;", Binary, Style);
- const StringRef Decimal("d = 184467'440737'0'95505'92Ull;");
+ constexpr StringRef Decimal("d = 184467'440737'0'95505'92Ull;");
verifyFormat(Decimal, Style);
Style.IntegerLiteralSeparator.Decimal = -1;
verifyFormat("d = 18446744073709550592Ull;", Decimal, Style);
Style.IntegerLiteralSeparator.Decimal = 3;
verifyFormat("d = 18'446'744'073'709'550'592Ull;", Decimal, Style);
- const StringRef Hex("h = 0xDEAD'BEEF'DE'AD'BEE'Fuz;");
+ constexpr StringRef Hex("h = 0xDEAD'BEEF'DE'AD'BEE'Fuz;");
verifyFormat(Hex, Style);
Style.IntegerLiteralSeparator.Hex = -1;
verifyFormat("h = 0xDEADBEEFDEADBEEFuz;", Hex, Style);
@@ -87,9 +87,9 @@ TEST_F(IntegerLiteralSeparatorTest, SingleQuoteAsSeparator) {
TEST_F(IntegerLiteralSeparatorTest, UnderscoreAsSeparator) {
FormatStyle Style = getLLVMStyle();
- const StringRef Binary("B = 0B10011_11_0110_1;");
- const StringRef Decimal("d = 184467_440737_0_95505_92;");
- const StringRef Hex("H = 0XDEAD_BEEF_DE_AD_BEE_F;");
+ constexpr StringRef Binary("B = 0B10011_11_0110_1;");
+ constexpr StringRef Decimal("d = 184467_440737_0_95505_92;");
+ constexpr StringRef Hex("H = 0XDEAD_BEEF_DE_AD_BEE_F;");
auto TestUnderscore = [&](auto Language) {
Style.Language = Language;
@@ -173,16 +173,16 @@ TEST_F(IntegerLiteralSeparatorTest, FixRanges) {
FormatStyle Style = getLLVMStyle();
Style.IntegerLiteralSeparator.Decimal = 3;
- const StringRef Code("i = -12'34;\n"
- "// clang-format off\n"
- "j = 123'4;\n"
- "// clang-format on\n"
- "k = +1'23'4;");
- const StringRef Expected("i = -1'234;\n"
+ constexpr StringRef Code("i = -12'34;\n"
"// clang-format off\n"
"j = 123'4;\n"
"// clang-format on\n"
- "k = +1'234;");
+ "k = +1'23'4;");
+ constexpr StringRef Expected("i = -1'234;\n"
+ "// clang-format off\n"
+ "j = 123'4;\n"
+ "// clang-format on\n"
+ "k = +1'234;");
verifyFormat(Expected, Code, Style);
diff --git a/clang/unittests/Format/SortIncludesTest.cpp b/clang/unittests/Format/SortIncludesTest.cpp
index 5194d65..48ecd5d 100644
--- a/clang/unittests/Format/SortIncludesTest.cpp
+++ b/clang/unittests/Format/SortIncludesTest.cpp
@@ -1084,10 +1084,10 @@ TEST_F(SortIncludesTest, DoNotSortLikelyXml) {
}
TEST_F(SortIncludesTest, DoNotSortCSharp) {
- constexpr StringRef Code{"const string expectedDataStruct = @\"\n"
+ constexpr StringRef Code("const string expectedDataStruct = @\"\n"
" #include <b.h>\n"
" #include <a.h>\n"
- " \";"};
+ " \";");
FmtStyle.Language = FormatStyle::LK_CSharp;
EXPECT_TRUE(sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a.cs").empty());
}
diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp
index ce7787e..7f99655 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -618,7 +618,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsStructs) {
EXPECT_TOKEN(Tokens[19], tok::l_brace, TT_StructLBrace);
EXPECT_TOKEN(Tokens[20], tok::r_brace, TT_StructRBrace);
- constexpr StringRef Code{"struct EXPORT StructName {};"};
+ constexpr StringRef Code("struct EXPORT StructName {};");
Tokens = annotate(Code);
ASSERT_EQ(Tokens.size(), 7u) << Tokens;
@@ -3958,7 +3958,7 @@ TEST_F(TokenAnnotatorTest, SplitPenalty) {
}
TEST_F(TokenAnnotatorTest, TemplateName) {
- constexpr StringRef Code{"return Foo < A || B > (C ^ D);"};
+ constexpr StringRef Code("return Foo < A || B > (C ^ D);");
auto Tokens = annotate(Code);
ASSERT_EQ(Tokens.size(), 14u) << Tokens;
diff --git a/clang/unittests/Interpreter/InterpreterTest.cpp b/clang/unittests/Interpreter/InterpreterTest.cpp
index fb9e98d..768058b 100644
--- a/clang/unittests/Interpreter/InterpreterTest.cpp
+++ b/clang/unittests/Interpreter/InterpreterTest.cpp
@@ -160,12 +160,12 @@ TEST_F(InterpreterTest, UndoCommand) {
// Fail to undo.
auto Err1 = Interp->Undo();
- EXPECT_EQ("Operation failed. Too many undos",
+ EXPECT_EQ("Operation failed. No input left to undo",
llvm::toString(std::move(Err1)));
auto Err2 = Interp->Parse("int foo = 42;");
EXPECT_TRUE(!!Err2);
auto Err3 = Interp->Undo(2);
- EXPECT_EQ("Operation failed. Too many undos",
+ EXPECT_EQ("Operation failed. Wanted to undo 2 inputs, only have 1.",
llvm::toString(std::move(Err3)));
// Succeed to undo.
@@ -392,9 +392,6 @@ TEST_F(InterpreterTest, Value) {
EXPECT_EQ(V9.getKind(), Value::K_PtrOrObj);
EXPECT_TRUE(V9.isManuallyAlloc());
- if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).isSystemZ())
- GTEST_SKIP(); // Enum printing is broken for unknown reasons on SystemZ.
-
Value V10;
llvm::cantFail(Interp->ParseAndExecute(
"enum D : unsigned int {Zero = 0, One}; One", &V10));
diff --git a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
index 4b24800..4d08f8d 100644
--- a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
+++ b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
@@ -136,15 +136,13 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseEmptyTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test no diagnostics produced
Consumer->setNoDiag();
ASSERT_FALSE(Parser.parse());
- ASSERT_EQ((int)Elements.size(), 0);
+ ASSERT_EQ((int)Parser.getElements().size(), 0);
ASSERT_TRUE(Consumer->isSatisfied());
}
@@ -172,15 +170,14 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test no diagnostics produced
Consumer->setNoDiag();
ASSERT_FALSE(Parser.parse());
+ auto Elements = Parser.getElements();
// First Descriptor Table with 4 elements
RootElement Elem = Elements[0].getElement();
ASSERT_TRUE(std::holds_alternative<DescriptorTableClause>(Elem));
@@ -277,15 +274,14 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test no diagnostics produced
Consumer->setNoDiag();
ASSERT_FALSE(Parser.parse());
+ auto Elements = Parser.getElements();
ASSERT_EQ(Elements.size(), 2u);
// Check default values are as expected
@@ -364,15 +360,14 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseFloatsTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test no diagnostics produced
Consumer->setNoDiag();
ASSERT_FALSE(Parser.parse());
+ auto Elements = Parser.getElements();
RootElement Elem = Elements[0].getElement();
ASSERT_TRUE(std::holds_alternative<StaticSampler>(Elem));
ASSERT_FLOAT_EQ(std::get<StaticSampler>(Elem).MipLODBias, 0.f);
@@ -441,15 +436,14 @@ TEST_F(ParseHLSLRootSignatureTest, ValidSamplerFlagsTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test no diagnostics produced
Consumer->setNoDiag();
ASSERT_FALSE(Parser.parse());
+ auto Elements = Parser.getElements();
RootElement Elem = Elements[0].getElement();
ASSERT_TRUE(std::holds_alternative<DescriptorTableClause>(Elem));
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Type, ClauseType::Sampler);
@@ -474,15 +468,14 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseRootConsantsTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test no diagnostics produced
Consumer->setNoDiag();
ASSERT_FALSE(Parser.parse());
+ auto Elements = Parser.getElements();
ASSERT_EQ(Elements.size(), 2u);
RootElement Elem = Elements[0].getElement();
@@ -533,15 +526,14 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseRootFlagsTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test no diagnostics produced
Consumer->setNoDiag();
ASSERT_FALSE(Parser.parse());
+ auto Elements = Parser.getElements();
ASSERT_EQ(Elements.size(), 3u);
RootElement Elem = Elements[0].getElement();
@@ -588,15 +580,14 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseRootDescriptorsTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test no diagnostics produced
Consumer->setNoDiag();
ASSERT_FALSE(Parser.parse());
+ auto Elements = Parser.getElements();
ASSERT_EQ(Elements.size(), 4u);
RootElement Elem = Elements[0].getElement();
@@ -664,9 +655,7 @@ TEST_F(ParseHLSLRootSignatureTest, ValidTrailingCommaTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test no diagnostics produced
Consumer->setNoDiag();
@@ -697,15 +686,14 @@ TEST_F(ParseHLSLRootSignatureTest, ValidVersion10Test) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_0, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_0, Signature, *PP);
// Test no diagnostics produced
Consumer->setNoDiag();
ASSERT_FALSE(Parser.parse());
+ auto Elements = Parser.getElements();
auto DefRootDescriptorFlag = llvm::dxbc::RootDescriptorFlags::DataVolatile;
RootElement Elem = Elements[0].getElement();
ASSERT_TRUE(std::holds_alternative<RootDescriptor>(Elem));
@@ -770,15 +758,14 @@ TEST_F(ParseHLSLRootSignatureTest, ValidVersion11Test) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test no diagnostics produced
Consumer->setNoDiag();
ASSERT_FALSE(Parser.parse());
+ auto Elements = Parser.getElements();
RootElement Elem = Elements[0].getElement();
ASSERT_TRUE(std::holds_alternative<RootDescriptor>(Elem));
ASSERT_EQ(std::get<RootDescriptor>(Elem).Type, DescriptorType::CBuffer);
@@ -838,9 +825,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidParseUnexpectedTokenTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_expected_either);
@@ -860,9 +845,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidParseInvalidTokenTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced - invalid token
Consumer->setExpected(diag::err_hlsl_invalid_token);
@@ -882,9 +865,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidParseUnexpectedEndOfStreamTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced - expected '(' after DescriptorTable
Consumer->setExpected(diag::err_expected_after);
@@ -909,9 +890,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidMissingDTParameterTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_rootsig_missing_param);
@@ -933,9 +912,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidMissingRDParameterTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_rootsig_missing_param);
@@ -957,9 +934,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidMissingRCParameterTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_rootsig_missing_param);
@@ -983,9 +958,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRepeatedMandatoryDTParameterTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_rootsig_repeat_param);
@@ -1007,9 +980,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRepeatedMandatoryRCParameterTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_rootsig_repeat_param);
@@ -1033,9 +1004,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRepeatedOptionalDTParameterTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_rootsig_repeat_param);
@@ -1061,9 +1030,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRepeatedOptionalRCParameterTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_rootsig_repeat_param);
@@ -1086,9 +1053,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidLexOverflowedNumberTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_number_literal_overflow);
@@ -1110,9 +1075,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidParseOverflowedNegativeNumberTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_number_literal_overflow);
@@ -1133,9 +1096,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidLexOverflowedFloatTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_number_literal_overflow);
@@ -1156,9 +1117,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidLexNegOverflowedFloatTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_number_literal_overflow);
@@ -1179,9 +1138,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidLexOverflowedDoubleTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_number_literal_overflow);
@@ -1202,9 +1159,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidLexUnderflowFloatTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_number_literal_underflow);
@@ -1228,9 +1183,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidNonZeroFlagsTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_rootsig_non_zero_flag);
@@ -1253,9 +1206,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRootElementMissingCommaTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_expected_either);
@@ -1280,9 +1231,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidDescriptorTableMissingCommaTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_expected_either);
@@ -1307,9 +1256,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRootConstantParamsCommaTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_expected_either);
@@ -1334,9 +1281,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRootDescriptorParamsCommaTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_expected_either);
@@ -1363,9 +1308,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidDescriptorClauseParamsCommaTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_expected_either);
@@ -1390,9 +1333,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidStaticSamplerCommaTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_expected_either);
@@ -1414,9 +1355,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRootDescriptorParamTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_invalid_token);
@@ -1441,9 +1380,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidDescriptorTableParamTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_invalid_token);
@@ -1467,9 +1404,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidDescriptorTableClauseParamTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_invalid_token);
@@ -1496,9 +1431,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidStaticSamplerParamTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_invalid_token);
@@ -1523,9 +1456,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidVisibilityValueTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_invalid_token);
@@ -1549,9 +1480,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRegisterValueTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_invalid_token);
@@ -1576,9 +1505,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidFilterValueTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_invalid_token);
@@ -1603,9 +1530,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidTextureAddressModeValueTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_invalid_token);
@@ -1630,9 +1555,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidComparisonFuncValueTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_invalid_token);
@@ -1657,9 +1580,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidStaticBorderColorValueTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_invalid_token);
@@ -1681,9 +1602,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRootFlagsValueTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_invalid_token);
@@ -1705,9 +1624,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidRootDescriptorFlagsValueTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_invalid_token);
@@ -1733,9 +1650,7 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidDescriptorRangeFlagsValueTest) {
TrivialModuleLoader ModLoader;
auto PP = createPP(Source, ModLoader);
- SmallVector<RootSignatureElement> Elements;
- hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Elements,
- Signature, *PP);
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
// Test correct diagnostic produced
Consumer->setExpected(diag::err_hlsl_invalid_token);
diff --git a/clang/unittests/StaticAnalyzer/BlockEntranceCallbackTest.cpp b/clang/unittests/StaticAnalyzer/BlockEntranceCallbackTest.cpp
index 0f05c39..d15bec0 100644
--- a/clang/unittests/StaticAnalyzer/BlockEntranceCallbackTest.cpp
+++ b/clang/unittests/StaticAnalyzer/BlockEntranceCallbackTest.cpp
@@ -91,8 +91,7 @@ void addBlockEntranceTester(AnalysisASTConsumer &AnalysisConsumer,
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
Registry.addChecker(&registerChecker<BlockEntranceCallbackTester>,
&shouldAlwaysRegister, "test.BlockEntranceTester",
- "EmptyDescription", "EmptyDocsUri",
- /*IsHidden=*/false);
+ "EmptyDescription");
});
}
@@ -102,8 +101,7 @@ void addBranchConditionTester(AnalysisASTConsumer &AnalysisConsumer,
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
Registry.addChecker(&registerChecker<BranchConditionCallbackTester>,
&shouldAlwaysRegister, "test.BranchConditionTester",
- "EmptyDescription", "EmptyDocsUri",
- /*IsHidden=*/false);
+ "EmptyDescription");
});
}
diff --git a/clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp b/clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp
index 0ef63b0..fc50f00 100644
--- a/clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp
+++ b/clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp
@@ -120,7 +120,7 @@ public:
std::move(ExpectedDiags), Compiler.getSourceManager()));
AnalysisConsumer->AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
Registry.addChecker<InterestingnessTestChecker>("test.Interestingness",
- "Description", "");
+ "MockDescription");
});
Compiler.getAnalyzerOpts().CheckersAndPackages = {
{"test.Interestingness", true}};
diff --git a/clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp b/clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp
index 4cb6bd3..e2007a9 100644
--- a/clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp
+++ b/clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp
@@ -616,8 +616,8 @@ void addCallDescChecker(AnalysisASTConsumer &AnalysisConsumer,
AnalyzerOptions &AnOpts) {
AnOpts.CheckersAndPackages = {{"test.CallDescChecker", true}};
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
- Registry.addChecker<CallDescChecker>("test.CallDescChecker", "Description",
- "");
+ Registry.addChecker<CallDescChecker>("test.CallDescChecker",
+ "MockDescription");
});
}
diff --git a/clang/unittests/StaticAnalyzer/CallEventTest.cpp b/clang/unittests/StaticAnalyzer/CallEventTest.cpp
index 2843572e..8b5289e 100644
--- a/clang/unittests/StaticAnalyzer/CallEventTest.cpp
+++ b/clang/unittests/StaticAnalyzer/CallEventTest.cpp
@@ -56,7 +56,7 @@ void addCXXDeallocatorChecker(AnalysisASTConsumer &AnalysisConsumer,
AnOpts.CheckersAndPackages = {{"test.CXXDeallocator", true}};
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
Registry.addChecker<CXXDeallocatorChecker>("test.CXXDeallocator",
- "Description", "");
+ "MockDescription");
});
}
diff --git a/clang/unittests/StaticAnalyzer/ConflictingEvalCallsTest.cpp b/clang/unittests/StaticAnalyzer/ConflictingEvalCallsTest.cpp
index e410cca..cffdbf1 100644
--- a/clang/unittests/StaticAnalyzer/ConflictingEvalCallsTest.cpp
+++ b/clang/unittests/StaticAnalyzer/ConflictingEvalCallsTest.cpp
@@ -33,10 +33,8 @@ void addEvalFooCheckers(AnalysisASTConsumer &AnalysisConsumer,
AnOpts.CheckersAndPackages = {{"test.EvalFoo1", true},
{"test.EvalFoo2", true}};
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
- Registry.addChecker<EvalCallFoo1>("test.EvalFoo1", "EmptyDescription",
- "EmptyDocsUri");
- Registry.addChecker<EvalCallFoo2>("test.EvalFoo2", "EmptyDescription",
- "EmptyDocsUri");
+ Registry.addChecker<EvalCallFoo1>("test.EvalFoo1", "MockDescription");
+ Registry.addChecker<EvalCallFoo2>("test.EvalFoo2", "MockDescription");
});
}
} // namespace
diff --git a/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp b/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp
index b6eeb9c..12be228 100644
--- a/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp
+++ b/clang/unittests/StaticAnalyzer/ExprEngineVisitTest.cpp
@@ -78,7 +78,7 @@ void addExprEngineVisitPreChecker(AnalysisASTConsumer &AnalysisConsumer,
AnOpts.CheckersAndPackages = {{"ExprEngineVisitPreChecker", true}};
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
Registry.addChecker<ExprEngineVisitPreChecker>("ExprEngineVisitPreChecker",
- "Desc", "DocsURI");
+ "MockDescription");
});
}
@@ -87,7 +87,7 @@ void addExprEngineVisitPostChecker(AnalysisASTConsumer &AnalysisConsumer,
AnOpts.CheckersAndPackages = {{"ExprEngineVisitPostChecker", true}};
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
Registry.addChecker<ExprEngineVisitPostChecker>(
- "ExprEngineVisitPostChecker", "Desc", "DocsURI");
+ "ExprEngineVisitPostChecker", "MockDescription");
});
}
@@ -95,8 +95,8 @@ void addMemAccessChecker(AnalysisASTConsumer &AnalysisConsumer,
AnalyzerOptions &AnOpts) {
AnOpts.CheckersAndPackages = {{"MemAccessChecker", true}};
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
- Registry.addChecker<MemAccessChecker>("MemAccessChecker", "Desc",
- "DocsURI");
+ Registry.addChecker<MemAccessChecker>("MemAccessChecker",
+ "MockDescription");
});
}
diff --git a/clang/unittests/StaticAnalyzer/FalsePositiveRefutationBRVisitorTest.cpp b/clang/unittests/StaticAnalyzer/FalsePositiveRefutationBRVisitorTest.cpp
index 8f0a96d..146797f 100644
--- a/clang/unittests/StaticAnalyzer/FalsePositiveRefutationBRVisitorTest.cpp
+++ b/clang/unittests/StaticAnalyzer/FalsePositiveRefutationBRVisitorTest.cpp
@@ -92,8 +92,8 @@ void addFalsePositiveGenerator(AnalysisASTConsumer &AnalysisConsumer,
AnOpts.CheckersAndPackages = {{"test.FalsePositiveGenerator", true},
{"debug.ViewExplodedGraph", false}};
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
- Registry.addChecker<FalsePositiveGenerator>(
- "test.FalsePositiveGenerator", "EmptyDescription", "EmptyDocsUri");
+ Registry.addChecker<FalsePositiveGenerator>("test.FalsePositiveGenerator",
+ "MockDescription");
});
}
diff --git a/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp b/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp
index 0f6e49b..7b837f3 100644
--- a/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp
+++ b/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp
@@ -46,7 +46,7 @@ void addDescriptiveNameChecker(AnalysisASTConsumer &AnalysisConsumer,
AnOpts.CheckersAndPackages = {{"DescriptiveNameChecker", true}};
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
Registry.addChecker<DescriptiveNameChecker>("DescriptiveNameChecker",
- "Desc", "DocsURI");
+ "MockDescription");
});
}
diff --git a/clang/unittests/StaticAnalyzer/NoStateChangeFuncVisitorTest.cpp b/clang/unittests/StaticAnalyzer/NoStateChangeFuncVisitorTest.cpp
index a903342..68d2678 100644
--- a/clang/unittests/StaticAnalyzer/NoStateChangeFuncVisitorTest.cpp
+++ b/clang/unittests/StaticAnalyzer/NoStateChangeFuncVisitorTest.cpp
@@ -140,7 +140,7 @@ void addNonThoroughStatefulChecker(AnalysisASTConsumer &AnalysisConsumer,
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
Registry
.addChecker<StatefulChecker<NonThoroughErrorNotPreventedFuncVisitor>>(
- "test.StatefulChecker", "Description", "");
+ "test.StatefulChecker", "MockDescription");
});
}
@@ -233,7 +233,7 @@ void addThoroughStatefulChecker(AnalysisASTConsumer &AnalysisConsumer,
AnOpts.CheckersAndPackages = {{"test.StatefulChecker", true}};
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
Registry.addChecker<StatefulChecker<ThoroughErrorNotPreventedFuncVisitor>>(
- "test.StatefulChecker", "Description", "");
+ "test.StatefulChecker", "MockDescription");
});
}
diff --git a/clang/unittests/StaticAnalyzer/ObjcBug-124477.cpp b/clang/unittests/StaticAnalyzer/ObjcBug-124477.cpp
index 51bd332..ab78090 100644
--- a/clang/unittests/StaticAnalyzer/ObjcBug-124477.cpp
+++ b/clang/unittests/StaticAnalyzer/ObjcBug-124477.cpp
@@ -37,7 +37,7 @@ void addFlagFlipperChecker(AnalysisASTConsumer &AnalysisConsumer,
AnOpts.CheckersAndPackages = {{"test.FlipFlagOnCheckLocation", true}};
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
Registry.addChecker<FlipFlagOnCheckLocation>("test.FlipFlagOnCheckLocation",
- "Description", "");
+ "MockDescription");
});
}
diff --git a/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp b/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
index 454eee9..e17d107 100644
--- a/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
+++ b/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
@@ -44,7 +44,7 @@ void addCustomChecker(AnalysisASTConsumer &AnalysisConsumer,
AnalyzerOptions &AnOpts) {
AnOpts.CheckersAndPackages = {{"test.CustomChecker", true}};
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
- Registry.addChecker<CustomChecker>("test.CustomChecker", "Description", "");
+ Registry.addChecker<CustomChecker>("test.CustomChecker", "MockDescription");
});
}
@@ -73,8 +73,8 @@ void addLocIncDecChecker(AnalysisASTConsumer &AnalysisConsumer,
AnalyzerOptions &AnOpts) {
AnOpts.CheckersAndPackages = {{"test.LocIncDecChecker", true}};
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
- Registry.addChecker<CustomChecker>("test.LocIncDecChecker", "Description",
- "");
+ Registry.addChecker<CustomChecker>("test.LocIncDecChecker",
+ "MockDescription");
});
}
@@ -119,10 +119,10 @@ bool shouldRegisterCheckerRegistrationOrderPrinter(const CheckerManager &mgr) {
void addCheckerRegistrationOrderPrinter(CheckerRegistry &Registry) {
Registry.addChecker(registerCheckerRegistrationOrderPrinter,
shouldRegisterCheckerRegistrationOrderPrinter,
- "test.RegistrationOrder", "Description", "", false);
+ "test.RegistrationOrder", "Description");
}
-#define UNITTEST_CHECKER(CHECKER_NAME, DIAG_MSG) \
+#define UNITTEST_CHECKER(CHECKER_NAME) \
class CHECKER_NAME : public Checker<check::PreStmt<DeclStmt>> { \
public: \
void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {} \
@@ -137,11 +137,11 @@ void addCheckerRegistrationOrderPrinter(CheckerRegistry &Registry) {
} \
void add##CHECKER_NAME(CheckerRegistry &Registry) { \
Registry.addChecker(register##CHECKER_NAME, shouldRegister##CHECKER_NAME, \
- "test." #CHECKER_NAME, "Description", "", false); \
+ "test." #CHECKER_NAME, "Description"); \
}
-UNITTEST_CHECKER(StrongDep, "Strong")
-UNITTEST_CHECKER(Dep, "Dep")
+UNITTEST_CHECKER(StrongDep)
+UNITTEST_CHECKER(Dep)
bool shouldRegisterStrongFALSE(const CheckerManager &mgr) {
return false;
@@ -154,7 +154,7 @@ void addDep(AnalysisASTConsumer &AnalysisConsumer,
{"test.RegistrationOrder", true}};
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
Registry.addChecker(registerStrongDep, shouldRegisterStrongFALSE,
- "test.Strong", "Description", "", false);
+ "test.Strong", "Description");
addStrongDep(Registry);
addDep(Registry);
addCheckerRegistrationOrderPrinter(Registry);
@@ -172,7 +172,7 @@ TEST(RegisterDeps, UnsatisfiedDependency) {
// Weak checker dependencies.
//===----------------------------------------------------------------------===//
-UNITTEST_CHECKER(WeakDep, "Weak")
+UNITTEST_CHECKER(WeakDep)
void addWeakDepCheckerBothEnabled(AnalysisASTConsumer &AnalysisConsumer,
AnalyzerOptions &AnOpts) {
@@ -225,8 +225,8 @@ void addWeakDepCheckerDepUnspecified(AnalysisASTConsumer &AnalysisConsumer,
});
}
-UNITTEST_CHECKER(WeakDep2, "Weak2")
-UNITTEST_CHECKER(Dep2, "Dep2")
+UNITTEST_CHECKER(WeakDep2)
+UNITTEST_CHECKER(Dep2)
void addWeakDepHasWeakDep(AnalysisASTConsumer &AnalysisConsumer,
AnalyzerOptions &AnOpts) {
diff --git a/clang/unittests/StaticAnalyzer/SValSimplifyerTest.cpp b/clang/unittests/StaticAnalyzer/SValSimplifyerTest.cpp
index 85cfe2c..4331ffc 100644
--- a/clang/unittests/StaticAnalyzer/SValSimplifyerTest.cpp
+++ b/clang/unittests/StaticAnalyzer/SValSimplifyerTest.cpp
@@ -68,8 +68,7 @@ static void addSimplifyChecker(AnalysisASTConsumer &AnalysisConsumer,
AnalyzerOptions &AnOpts) {
AnOpts.CheckersAndPackages = {{"SimplifyChecker", true}};
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
- Registry.addChecker<SimplifyChecker>("SimplifyChecker", "EmptyDescription",
- "EmptyDocsUri");
+ Registry.addChecker<SimplifyChecker>("SimplifyChecker", "MockDescription");
});
}
diff --git a/clang/unittests/StaticAnalyzer/SValTest.cpp b/clang/unittests/StaticAnalyzer/SValTest.cpp
index d8897b0..58e9a8d 100644
--- a/clang/unittests/StaticAnalyzer/SValTest.cpp
+++ b/clang/unittests/StaticAnalyzer/SValTest.cpp
@@ -139,10 +139,10 @@ class SValTest : public testing::TestWithParam<TestClangConfig> {};
\
void add##NAME##SValCollector(AnalysisASTConsumer &AnalysisConsumer, \
AnalyzerOptions &AnOpts) { \
- AnOpts.CheckersAndPackages = {{"test.##NAME##SValCollector", true}}; \
+ AnOpts.CheckersAndPackages = {{"test." #NAME "SValColl", true}}; \
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { \
- Registry.addChecker<NAME##SValCollector>("test.##NAME##SValCollector", \
- "Description", ""); \
+ Registry.addChecker<NAME##SValCollector>("test." #NAME "SValColl", \
+ "MockDescription"); \
}); \
} \
\
diff --git a/clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp b/clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp
index 5fc084a..0cb3c59 100644
--- a/clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp
+++ b/clang/unittests/StaticAnalyzer/TestReturnValueUnderConstruction.cpp
@@ -49,9 +49,9 @@ void addTestReturnValueUnderConstructionChecker(
AnOpts.CheckersAndPackages =
{{"test.TestReturnValueUnderConstruction", true}};
AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
- Registry.addChecker<TestReturnValueUnderConstructionChecker>(
- "test.TestReturnValueUnderConstruction", "", "");
- });
+ Registry.addChecker<TestReturnValueUnderConstructionChecker>(
+ "test.TestReturnValueUnderConstruction", "MockDescription");
+ });
}
TEST(TestReturnValueUnderConstructionChecker,