From cfe-commits at lists.llvm.org Mon Nov 10 00:10:01 2025 From: cfe-commits at lists.llvm.org (via cfe-commits) Date: Mon, 10 Nov 2025 00:10:01 -0800 (PST) Subject: [clang] f613801 - [RISCV][llvm] Support Smpmpmt version 0.6 (#166322) Message-ID: <69119dd9.050a0220.c61c3.199e@mx.google.com> Author: Brandon Wu Date: 2025-11-10T16:09:57+08:00 New Revision: f6138015ef17b0c522a1b60299659ef1587bb8d0 URL: https://github.com/llvm/llvm-project/commit/f6138015ef17b0c522a1b60299659ef1587bb8d0 DIFF: https://github.com/llvm/llvm-project/commit/f6138015ef17b0c522a1b60299659ef1587bb8d0.diff LOG: [RISCV][llvm] Support Smpmpmt version 0.6 (#166322) spec: https://github.com/riscv/riscv-isa-manual/blob/smpmpmt/src/smpmpmt.adoc Co-Authored-by: Jesse Huang Added: Modified: clang/test/Driver/print-supported-extensions-riscv.c clang/test/Preprocessor/riscv-target-features.c llvm/docs/RISCVUsage.rst llvm/lib/Target/RISCV/RISCVFeatures.td llvm/test/CodeGen/RISCV/attributes.ll llvm/test/CodeGen/RISCV/features-info.ll llvm/test/MC/RISCV/attribute-arch.s llvm/unittests/TargetParser/RISCVISAInfoTest.cpp Removed: ################################################################################ diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c index cb812736786a9..681c912bd1612 100644 --- a/clang/test/Driver/print-supported-extensions-riscv.c +++ b/clang/test/Driver/print-supported-extensions-riscv.c @@ -227,6 +227,7 @@ // CHECK-NEXT: zvfofp8min 0.2 'Zvfofp8min' (Vector OFP8 Converts) // CHECK-NEXT: zvkgs 0.7 'Zvkgs' (Vector-Scalar GCM instructions for Cryptography) // CHECK-NEXT: zvqdotq 0.0 'Zvqdotq' (Vector quad widening 4D Dot Product) +// CHECK-NEXT: smpmpmt 0.6 'Smpmpmt' (PMP-based Memory Types Extension) // CHECK-NEXT: svukte 0.3 'Svukte' (Address-Independent Latency of User-Mode Faults to Supervisor Addresses) // CHECK-NEXT: xqccmp 0.3 'Xqccmp' (Qualcomm 16-bit Push/Pop and Double Moves) // CHECK-NEXT: xqcia 0.7 'Xqcia' (Qualcomm uC Arithmetic Extension) diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c index 77731a9776be8..56c738bc007fb 100644 --- a/clang/test/Preprocessor/riscv-target-features.c +++ b/clang/test/Preprocessor/riscv-target-features.c @@ -40,6 +40,7 @@ // CHECK-NOT: __riscv_smepmp {{.*$}} // CHECK-NOT: __riscv_smmpm{{.*$}} // CHECK-NOT: __riscv_smnpm{{.*$}} +// CHECK-NOT: __riscv_smpmpmt {{.*$}} // CHECK-NOT: __riscv_smrnmi {{.*$}} // CHECK-NOT: __riscv_smstateen {{.*$}} // CHECK-NOT: __riscv_ssaia {{.*$}} @@ -1333,6 +1334,14 @@ // RUN: -o - | FileCheck --check-prefix=CHECK-SMEPMP-EXT %s // CHECK-SMEPMP-EXT: __riscv_smepmp 1000000{{$}} +// RUN: %clang --target=riscv32 -menable-experimental-extensions \ +// RUN: -march=rv32ismpmpmt0p6 -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-SMPMPMT %s +// RUN: %clang --target=riscv64 -menable-experimental-extensions \ +// RUN: -march=rv64ismpmpmt0p6 -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-SMPMPMT %s +// CHECK-SMPMPMT: __riscv_smpmpmt 6000{{$}} + // RUN: %clang --target=riscv32 \ // RUN: -march=rv32ismrnmi1p0 -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-SMRNMI-EXT %s diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst index d03f383a92b3b..a21f03d389444 100644 --- a/llvm/docs/RISCVUsage.rst +++ b/llvm/docs/RISCVUsage.rst @@ -351,6 +351,9 @@ The primary goal of experimental support is to assist in the process of ratifica ``experimental-zvqdotq`` LLVM implements the `0.0.1 draft specification `__. +``experimental-smpmpmt`` + LLVM implements the `0.6 draft specification `__. + To use an experimental extension from `clang`, you must add `-menable-experimental-extensions` to the command line, and specify the exact version of the experimental extension you are using. To use an experimental extension with LLVM's internal developer tools (e.g. `llc`, `llvm-objdump`, `llvm-mc`), you must prefix the extension name with `experimental-`. Note that you don't need to specify the version with internal tools, and shouldn't include the `experimental-` prefix with `clang`. Vendor Extensions diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td index 5b72334f58d45..0b964c4808d8a 100644 --- a/llvm/lib/Target/RISCV/RISCVFeatures.td +++ b/llvm/lib/Target/RISCV/RISCVFeatures.td @@ -956,6 +956,9 @@ def FeatureStdExtSsdbltrp def FeatureStdExtSmepmp : RISCVExtension<1, 0, "Enhanced Physical Memory Protection">; +def FeatureStdExtSmpmpmt + : RISCVExperimentalExtension<0, 6, "PMP-based Memory Types Extension">; + def FeatureStdExtSmrnmi : RISCVExtension<1, 0, "Resumable Non-Maskable Interrupts">; def HasStdExtSmrnmi : Predicate<"Subtarget->hasStdExtSmrnmi()">, diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll index 22c2d8102b5ca..f26d4f09c92fb 100644 --- a/llvm/test/CodeGen/RISCV/attributes.ll +++ b/llvm/test/CodeGen/RISCV/attributes.ll @@ -125,6 +125,7 @@ ; RUN: llc -mtriple=riscv32 -mattr=+smcdeleg %s -o - | FileCheck --check-prefixes=CHECK,RV32SMCDELEG %s ; RUN: llc -mtriple=riscv32 -mattr=+smcntrpmf %s -o - | FileCheck --check-prefixes=CHECK,RV32SMCNTRPMF %s ; RUN: llc -mtriple=riscv32 -mattr=+smepmp %s -o - | FileCheck --check-prefixes=CHECK,RV32SMEPMP %s +; RUN: llc -mtriple=riscv32 -mattr=+experimental-smpmpmt %s -o - | FileCheck --check-prefixes=CHECK,RV32SMPMPMT %s ; RUN: llc -mtriple=riscv32 -mattr=+smrnmi %s -o - | FileCheck --check-prefixes=CHECK,RV32SMRNMI %s ; RUN: llc -mtriple=riscv32 -mattr=+zfbfmin %s -o - | FileCheck --check-prefixes=CHECK,RV32ZFBFMIN %s ; RUN: llc -mtriple=riscv32 -mattr=+experimental-zvfbfa %s -o - | FileCheck --check-prefixes=CHECK,RV32ZVFBFA %s @@ -275,6 +276,7 @@ ; RUN: llc -mtriple=riscv64 -mattr=+smcdeleg %s -o - | FileCheck --check-prefixes=CHECK,RV64SMCDELEG %s ; RUN: llc -mtriple=riscv64 -mattr=+smcntrpmf %s -o - | FileCheck --check-prefixes=CHECK,RV64SMCNTRPMF %s ; RUN: llc -mtriple=riscv64 -mattr=+smepmp %s -o - | FileCheck --check-prefixes=CHECK,RV64SMEPMP %s +; RUN: llc -mtriple=riscv64 -mattr=+experimental-smpmpmt %s -o - | FileCheck --check-prefixes=CHECK,RV64SMPMPMT %s ; RUN: llc -mtriple=riscv64 -mattr=+smrnmi %s -o - | FileCheck --check-prefixes=CHECK,RV64SMRNMI %s ; RUN: llc -mtriple=riscv64 -mattr=+zfbfmin %s -o - | FileCheck --check-prefixes=CHECK,RV64ZFBFMIN %s ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zvfbfa %s -o - | FileCheck --check-prefixes=CHECK,RV64ZVFBFA %s @@ -439,6 +441,7 @@ ; RV32SMCDELEG: .attribute 5, "rv32i2p1_smcdeleg1p0" ; RV32SMCNTRPMF: .attribute 5, "rv32i2p1_smcntrpmf1p0" ; RV32SMEPMP: .attribute 5, "rv32i2p1_smepmp1p0" +; RV32SMPMPMT: .attribute 5, "rv32i2p1_smpmpmt0p6" ; RV32SMRNMI: .attribute 5, "rv32i2p1_smrnmi1p0" ; RV32ZFBFMIN: .attribute 5, "rv32i2p1_f2p2_zicsr2p0_zfbfmin1p0" ; RV32ZVFBFA: .attribute 5, "rv32i2p1_f2p2_zicsr2p0_zfbfmin1p0_zve32f1p0_zve32x1p0_zvfbfa0p1_zvl32b1p0" @@ -587,6 +590,7 @@ ; RV64SMCDELEG: .attribute 5, "rv64i2p1_smcdeleg1p0" ; RV64SMCNTRPMF: .attribute 5, "rv64i2p1_smcntrpmf1p0" ; RV64SMEPMP: .attribute 5, "rv64i2p1_smepmp1p0" +; RV64SMPMPMT: .attribute 5, "rv64i2p1_smpmpmt0p6" ; RV64SMRNMI: .attribute 5, "rv64i2p1_smrnmi1p0" ; RV64ZFBFMIN: .attribute 5, "rv64i2p1_f2p2_zicsr2p0_zfbfmin1p0" ; RV64ZVFBFA: .attribute 5, "rv64i2p1_f2p2_zicsr2p0_zfbfmin1p0_zve32f1p0_zve32x1p0_zvfbfa0p1_zvl32b1p0" diff --git a/llvm/test/CodeGen/RISCV/features-info.ll b/llvm/test/CodeGen/RISCV/features-info.ll index cf44af608542c..3d9906fdcbeb3 100644 --- a/llvm/test/CodeGen/RISCV/features-info.ll +++ b/llvm/test/CodeGen/RISCV/features-info.ll @@ -27,6 +27,7 @@ ; CHECK-NEXT: experimental - Experimental intrinsics. ; CHECK-NEXT: experimental-p - 'P' ('Base P' (Packed SIMD)). ; CHECK-NEXT: experimental-rvm23u32 - RISC-V experimental-rvm23u32 profile. +; CHECK-NEXT: experimental-smpmpmt - 'Smpmpmt' (PMP-based Memory Types Extension). ; CHECK-NEXT: experimental-svukte - 'Svukte' (Address-Independent Latency of User-Mode Faults to Supervisor Addresses). ; CHECK-NEXT: experimental-xqccmp - 'Xqccmp' (Qualcomm 16-bit Push/Pop and Double Moves). ; CHECK-NEXT: experimental-xqcia - 'Xqcia' (Qualcomm uC Arithmetic Extension). diff --git a/llvm/test/MC/RISCV/attribute-arch.s b/llvm/test/MC/RISCV/attribute-arch.s index 111616df254d3..e41c9eac982a7 100644 --- a/llvm/test/MC/RISCV/attribute-arch.s +++ b/llvm/test/MC/RISCV/attribute-arch.s @@ -348,6 +348,9 @@ .attribute arch, "rv32i_smepmp1p0" # CHECK: attribute 5, "rv32i2p1_smepmp1p0" +.attribute arch, "rv32i_smpmpmt0p6" +# CHECK: attribute 5, "rv32i2p1_smpmpmt0p6" + .attribute arch, "rv32i_smrnmi1p0" # CHECK: attribute 5, "rv32i2p1_smrnmi1p0" diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp index bfc127530570d..c55cd94048cc5 100644 --- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp +++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp @@ -1204,6 +1204,7 @@ Experimental extensions zvfofp8min 0.2 zvkgs 0.7 zvqdotq 0.0 + smpmpmt 0.6 svukte 0.3 xqccmp 0.3 xqcia 0.7 From cfe-commits at lists.llvm.org Mon Nov 10 00:10:05 2025 From: cfe-commits at lists.llvm.org (Brandon Wu via cfe-commits) Date: Mon, 10 Nov 2025 00:10:05 -0800 (PST) Subject: [clang] [llvm] [RISCV][llvm] Support Smpmpmt version 0.6 (PR #166322) In-Reply-To: Message-ID: <69119ddd.170a0220.15b865.e0b9@mx.google.com> https://github.com/4vtomat closed https://github.com/llvm/llvm-project/pull/166322 From cfe-commits at lists.llvm.org Mon Nov 10 00:10:59 2025 From: cfe-commits at lists.llvm.org (Sam Elliott via cfe-commits) Date: Mon, 10 Nov 2025 00:10:59 -0800 (PST) Subject: [clang] [llvm] [Clang] Add diagnostic reasoning for unsatisfied is_destructible trait (PR #166967) In-Reply-To: Message-ID: <69119e13.630a0220.3266e7.876b@mx.google.com> lenary wrote: This seems to have some GISel changes that aren't relevant? https://github.com/llvm/llvm-project/pull/166967 From cfe-commits at lists.llvm.org Mon Nov 10 00:22:19 2025 From: cfe-commits at lists.llvm.org (via cfe-commits) Date: Mon, 10 Nov 2025 00:22:19 -0800 (PST) Subject: [clang] [Headers][X86] Allow AVX512 masked arithmetic intrinsics to be used in constexpr (PR #162816) In-Reply-To: Message-ID: <6911a0bb.050a0220.1428de.0b12@mx.google.com> ================ @@ -3598,6 +3598,27 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, return APInt::getAllOnes(DstBits); }); + case clang::X86::BI__builtin_ia32_selectss_128: + case clang::X86::BI__builtin_ia32_selectsd_128: { + const unsigned N = + Call->getArg(1)->getType()->getAs()->getNumElements(); + + const Pointer &W = S.Stk.pop(); + const Pointer &A = S.Stk.pop(); + APSInt U = popToAPSInt(S, Call->getArg(0)); + const Pointer &Dst = S.Stk.peek(); + + const bool TakeA0 = U.getZExtValue() & 1ULL; + + for (unsigned i = 0; i < N; ++i) + Dst.elem(i) = W.elem(i); + if (TakeA0) + Dst.elem(0) = A.elem(0); + + Dst.initializeAllElements(); + return true; + } ---------------- woruyu wrote: Done! https://github.com/llvm/llvm-project/pull/162816 From cfe-commits at lists.llvm.org Mon Nov 10 00:23:06 2025 From: cfe-commits at lists.llvm.org (via cfe-commits) Date: Mon, 10 Nov 2025 00:23:06 -0800 (PST) Subject: [clang] [Headers][X86] Allow AVX512 masked arithmetic intrinsics to be used in constexpr (PR #162816) In-Reply-To: Message-ID: <6911a0ea.170a0220.960fa.df60@mx.google.com> https://github.com/woruyu updated https://github.com/llvm/llvm-project/pull/162816 >From a14bb33c6b9bc57b1a3019e22e34ab88f68bc4da Mon Sep 17 00:00:00 2001 From: liuzhenya Date: Sun, 9 Nov 2025 22:22:50 -1000 Subject: [PATCH] [Headers][X86] Allow AVX512 masked arithmetic ss/sd intrinsics to be used in constexpr --- clang/include/clang/Basic/BuiltinsX86.td | 2 +- clang/lib/AST/ByteCode/InterpBuiltin.cpp | 24 +++++++ clang/lib/AST/ExprConstant.cpp | 22 +++++++ clang/lib/Headers/avx512fintrin.h | 64 +++++++++---------- clang/test/CodeGen/X86/avx512f-builtins.c | 32 ++++++++++ clang/test/CodeGen/X86/builtin_test_helpers.h | 10 +++ 6 files changed, 121 insertions(+), 33 deletions(-) diff --git a/clang/include/clang/Basic/BuiltinsX86.td b/clang/include/clang/Basic/BuiltinsX86.td index edff241a98738..ee1060dff5497 100644 --- a/clang/include/clang/Basic/BuiltinsX86.td +++ b/clang/include/clang/Basic/BuiltinsX86.td @@ -4128,7 +4128,7 @@ let Features = "avx512bf16", Attributes = [NoThrow, Const, RequiredVectorWidth<1 def selectsbf_128 : X86Builtin<"_Vector<8, __bf16>(unsigned char, _Vector<8, __bf16>, _Vector<8, __bf16>)">; } -let Features = "avx512f", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in { +let Features = "avx512f", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in { def selectss_128 : X86Builtin<"_Vector<4, float>(unsigned char, _Vector<4, float>, _Vector<4, float>)">; def selectsd_128 : X86Builtin<"_Vector<2, double>(unsigned char, _Vector<2, double>, _Vector<2, double>)">; } diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 0ef130c0a55df..0f0e3e87b1e8a 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -2419,6 +2419,27 @@ static bool interp__builtin_elementwise_int_unaryop( return false; } +static bool interp__builtin_select_scalar(InterpState &S, + const CallExpr *Call) { + unsigned N = + Call->getArg(1)->getType()->getAs()->getNumElements(); + + const Pointer &W = S.Stk.pop(); + const Pointer &A = S.Stk.pop(); + APSInt U = popToAPSInt(S, Call->getArg(0)); + const Pointer &Dst = S.Stk.peek(); + + bool TakeA0 = U.getZExtValue() & 1ULL; + + for (unsigned I = 0; I < N; ++I) + Dst.elem(I) = W.elem(I); + if (TakeA0) + Dst.elem(0) = A.elem(0); + + Dst.initializeAllElements(); + return true; +} + static bool interp__builtin_elementwise_int_binop( InterpState &S, CodePtr OpPC, const CallExpr *Call, llvm::function_ref Fn) { @@ -4205,6 +4226,9 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, return APInt::getAllOnes(DstBits); }); + case clang::X86::BI__builtin_ia32_selectss_128: + case clang::X86::BI__builtin_ia32_selectsd_128: + return interp__builtin_select_scalar(S, Call); case clang::X86::BI__builtin_ia32_vprotbi: case clang::X86::BI__builtin_ia32_vprotdi: case clang::X86::BI__builtin_ia32_vprotqi: diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 972d9fe3b5e4f..2f11b1d23f9a3 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -12264,6 +12264,24 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) { return Success(APValue(ResultElements.data(), SourceLen), E); }; + auto EvalSelectScalar = [&](unsigned Len) -> bool { + APSInt Mask; + APValue AVal, WVal; + if (!EvaluateInteger(E->getArg(0), Mask, Info) || + !EvaluateAsRValue(Info, E->getArg(1), AVal) || + !EvaluateAsRValue(Info, E->getArg(2), WVal)) + return false; + + bool TakeA0 = (Mask.getZExtValue() & 1u) != 0; + SmallVector Res; + Res.reserve(Len); + Res.push_back(TakeA0 ? AVal.getVectorElt(0) : WVal.getVectorElt(0)); + for (unsigned i = 1; i < Len; ++i) + Res.push_back(WVal.getVectorElt(i)); + APValue V(Res.data(), Res.size()); + return Success(V, E); + }; + switch (E->getBuiltinCallee()) { default: return false; @@ -12567,6 +12585,10 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) { return APInt((Src).trunc(DstBits)); return APInt::getAllOnes(DstBits); }); + case clang::X86::BI__builtin_ia32_selectss_128: + return EvalSelectScalar(4); + case clang::X86::BI__builtin_ia32_selectsd_128: + return EvalSelectScalar(2); case clang::X86::BI__builtin_ia32_pmuldq128: case clang::X86::BI__builtin_ia32_pmuldq256: case clang::X86::BI__builtin_ia32_pmuldq512: diff --git a/clang/lib/Headers/avx512fintrin.h b/clang/lib/Headers/avx512fintrin.h index 997e9608e112f..5a9e045ac3add 100644 --- a/clang/lib/Headers/avx512fintrin.h +++ b/clang/lib/Headers/avx512fintrin.h @@ -1834,14 +1834,14 @@ _mm512_maskz_abs_epi32(__mmask16 __U, __m512i __A) { (__v16si)_mm512_setzero_si512()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS128 -_mm_mask_add_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { +static __inline__ __m128 __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_mask_add_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { __A = _mm_add_ss(__A, __B); return __builtin_ia32_selectss_128(__U, __A, __W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS128 -_mm_maskz_add_ss(__mmask8 __U,__m128 __A, __m128 __B) { +static __inline__ __m128 __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_maskz_add_ss(__mmask8 __U, __m128 __A, __m128 __B) { __A = _mm_add_ss(__A, __B); return __builtin_ia32_selectss_128(__U, __A, _mm_setzero_ps()); } @@ -1864,14 +1864,14 @@ _mm_maskz_add_ss(__mmask8 __U,__m128 __A, __m128 __B) { (__v4sf)_mm_setzero_ps(), \ (__mmask8)(U), (int)(R))) -static __inline__ __m128d __DEFAULT_FN_ATTRS128 -_mm_mask_add_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) { +static __inline__ __m128d __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_mask_add_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { __A = _mm_add_sd(__A, __B); return __builtin_ia32_selectsd_128(__U, __A, __W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS128 -_mm_maskz_add_sd(__mmask8 __U,__m128d __A, __m128d __B) { +static __inline__ __m128d __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_maskz_add_sd(__mmask8 __U, __m128d __A, __m128d __B) { __A = _mm_add_sd(__A, __B); return __builtin_ia32_selectsd_128(__U, __A, _mm_setzero_pd()); } @@ -1949,14 +1949,14 @@ _mm512_maskz_add_ps(__mmask16 __U, __m512 __A, __m512 __B) { (__v16sf)_mm512_add_round_ps((A), (B), (R)), \ (__v16sf)_mm512_setzero_ps())) -static __inline__ __m128 __DEFAULT_FN_ATTRS128 -_mm_mask_sub_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { +static __inline__ __m128 __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_mask_sub_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { __A = _mm_sub_ss(__A, __B); return __builtin_ia32_selectss_128(__U, __A, __W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS128 -_mm_maskz_sub_ss(__mmask8 __U,__m128 __A, __m128 __B) { +static __inline__ __m128 __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_maskz_sub_ss(__mmask8 __U, __m128 __A, __m128 __B) { __A = _mm_sub_ss(__A, __B); return __builtin_ia32_selectss_128(__U, __A, _mm_setzero_ps()); } @@ -1978,14 +1978,14 @@ _mm_maskz_sub_ss(__mmask8 __U,__m128 __A, __m128 __B) { (__v4sf)_mm_setzero_ps(), \ (__mmask8)(U), (int)(R))) -static __inline__ __m128d __DEFAULT_FN_ATTRS128 -_mm_mask_sub_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) { +static __inline__ __m128d __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_mask_sub_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { __A = _mm_sub_sd(__A, __B); return __builtin_ia32_selectsd_128(__U, __A, __W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS128 -_mm_maskz_sub_sd(__mmask8 __U,__m128d __A, __m128d __B) { +static __inline__ __m128d __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_maskz_sub_sd(__mmask8 __U, __m128d __A, __m128d __B) { __A = _mm_sub_sd(__A, __B); return __builtin_ia32_selectsd_128(__U, __A, _mm_setzero_pd()); } @@ -2064,14 +2064,14 @@ _mm512_maskz_sub_ps(__mmask16 __U, __m512 __A, __m512 __B) { (__v16sf)_mm512_sub_round_ps((A), (B), (R)), \ (__v16sf)_mm512_setzero_ps())) -static __inline__ __m128 __DEFAULT_FN_ATTRS128 -_mm_mask_mul_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { +static __inline__ __m128 __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_mask_mul_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { __A = _mm_mul_ss(__A, __B); return __builtin_ia32_selectss_128(__U, __A, __W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS128 -_mm_maskz_mul_ss(__mmask8 __U,__m128 __A, __m128 __B) { +static __inline__ __m128 __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_maskz_mul_ss(__mmask8 __U, __m128 __A, __m128 __B) { __A = _mm_mul_ss(__A, __B); return __builtin_ia32_selectss_128(__U, __A, _mm_setzero_ps()); } @@ -2093,14 +2093,14 @@ _mm_maskz_mul_ss(__mmask8 __U,__m128 __A, __m128 __B) { (__v4sf)_mm_setzero_ps(), \ (__mmask8)(U), (int)(R))) -static __inline__ __m128d __DEFAULT_FN_ATTRS128 -_mm_mask_mul_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) { +static __inline__ __m128d __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_mask_mul_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { __A = _mm_mul_sd(__A, __B); return __builtin_ia32_selectsd_128(__U, __A, __W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS128 -_mm_maskz_mul_sd(__mmask8 __U,__m128d __A, __m128d __B) { +static __inline__ __m128d __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_maskz_mul_sd(__mmask8 __U, __m128d __A, __m128d __B) { __A = _mm_mul_sd(__A, __B); return __builtin_ia32_selectsd_128(__U, __A, _mm_setzero_pd()); } @@ -2179,14 +2179,14 @@ _mm512_maskz_mul_ps(__mmask16 __U, __m512 __A, __m512 __B) { (__v16sf)_mm512_mul_round_ps((A), (B), (R)), \ (__v16sf)_mm512_setzero_ps())) -static __inline__ __m128 __DEFAULT_FN_ATTRS128 -_mm_mask_div_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { +static __inline__ __m128 __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_mask_div_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { __A = _mm_div_ss(__A, __B); return __builtin_ia32_selectss_128(__U, __A, __W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS128 -_mm_maskz_div_ss(__mmask8 __U,__m128 __A, __m128 __B) { +static __inline__ __m128 __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_maskz_div_ss(__mmask8 __U, __m128 __A, __m128 __B) { __A = _mm_div_ss(__A, __B); return __builtin_ia32_selectss_128(__U, __A, _mm_setzero_ps()); } @@ -2209,14 +2209,14 @@ _mm_maskz_div_ss(__mmask8 __U,__m128 __A, __m128 __B) { (__v4sf)_mm_setzero_ps(), \ (__mmask8)(U), (int)(R))) -static __inline__ __m128d __DEFAULT_FN_ATTRS128 -_mm_mask_div_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) { +static __inline__ __m128d __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_mask_div_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { __A = _mm_div_sd(__A, __B); return __builtin_ia32_selectsd_128(__U, __A, __W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS128 -_mm_maskz_div_sd(__mmask8 __U,__m128d __A, __m128d __B) { +static __inline__ __m128d __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_maskz_div_sd(__mmask8 __U, __m128d __A, __m128d __B) { __A = _mm_div_sd(__A, __B); return __builtin_ia32_selectsd_128(__U, __A, _mm_setzero_pd()); } diff --git a/clang/test/CodeGen/X86/avx512f-builtins.c b/clang/test/CodeGen/X86/avx512f-builtins.c index 17778b52d3671..26296f474466a 100644 --- a/clang/test/CodeGen/X86/avx512f-builtins.c +++ b/clang/test/CodeGen/X86/avx512f-builtins.c @@ -3302,6 +3302,8 @@ __m128 test_mm_mask_add_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_mask_add_ss(__W,__U,__A,__B); } +TEST_CONSTEXPR(match_v4sf(_mm_mask_add_ss((__m128)(__v4sf){10.0f, 100.0f, 200.0f, 300.0f}, 0x1,(__m128)(__v4sf){1.25f, 3.0f, 4.0f, 5.0f},(__m128)(__v4sf){2.75f, 6.0f, 7.0f, 8.0f}),4.0f, 100.0f, 200.0f, 300.0f)); + __m128 test_mm_maskz_add_ss(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK-LABEL: test_mm_maskz_add_ss // CHECK-NOT: @llvm.x86.avx512.mask.add.ss.round @@ -3317,6 +3319,8 @@ __m128 test_mm_maskz_add_ss(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_maskz_add_ss(__U,__A,__B); } +TEST_CONSTEXPR(match_v4sf(_mm_maskz_add_ss(0x1, (__m128)(__v4sf){1.25f, 3.0f, 4.0f, 5.0f}, (__m128)(__v4sf){2.75f, 6.0f, 7.0f, 8.0f}), 4.0f, 0.0f, 0.0f, 0.0f)); + __m128d test_mm_add_round_sd(__m128d __A, __m128d __B) { // CHECK-LABEL: test_mm_add_round_sd // CHECK: @llvm.x86.avx512.mask.add.sd.round @@ -3347,6 +3351,8 @@ __m128d test_mm_mask_add_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_mask_add_sd(__W,__U,__A,__B); } +TEST_CONSTEXPR(match_v2df(_mm_mask_add_sd((__m128d)(__v2df){10.0, 999.0}, 0x1, (__m128d)(__v2df){5.5, 77.0}, (__m128d)(__v2df){0.25, 88.0}), 5.75, 999.0)); + __m128d test_mm_maskz_add_sd(__mmask8 __U, __m128d __A, __m128d __B) { // CHECK-LABEL: test_mm_maskz_add_sd // CHECK-NOT: @llvm.x86.avx512.mask.add.sd.round @@ -3362,6 +3368,8 @@ __m128d test_mm_maskz_add_sd(__mmask8 __U, __m128d __A, __m128d __B) { // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_maskz_add_sd(__U,__A,__B); } +TEST_CONSTEXPR(match_v2df(_mm_maskz_add_sd(0x1, (__m128d)(__v2df){5.5, 77.0}, (__m128d)(__v2df){0.25, 88.0}), 5.75, 0.0)); + __m512d test_mm512_sub_round_pd(__m512d __A, __m512d __B) { // CHECK-LABEL: test_mm512_sub_round_pd // CHECK: @llvm.x86.avx512.sub.pd.512 @@ -3450,6 +3458,8 @@ __m128 test_mm_mask_sub_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_mask_sub_ss(__W,__U,__A,__B); } +TEST_CONSTEXPR(match_v4sf(_mm_mask_sub_ss((__m128)(__v4sf){-1.0f, 10.0f, 20.0f, 30.0f}, 0x1, (__m128)(__v4sf){7.0f, 3.0f, 4.0f, 5.0f}, (__m128)(__v4sf){2.5f, 6.0f, 7.0f, 8.0f}), 4.5f, 10.0f, 20.0f, 30.0f)); + __m128 test_mm_maskz_sub_ss(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK-LABEL: test_mm_maskz_sub_ss // CHECK-NOT: @llvm.x86.avx512.mask.sub.ss.round @@ -3465,6 +3475,8 @@ __m128 test_mm_maskz_sub_ss(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_maskz_sub_ss(__U,__A,__B); } +TEST_CONSTEXPR(match_v4sf(_mm_maskz_sub_ss(0x1, (__m128)(__v4sf){7.0f, 3.0f, 4.0f, 5.0f}, (__m128)(__v4sf){2.5f, 6.0f, 7.0f, 8.0f}), 4.5f, 0.0f, 0.0f, 0.0f)); + __m128d test_mm_sub_round_sd(__m128d __A, __m128d __B) { // CHECK-LABEL: test_mm_sub_round_sd // CHECK: @llvm.x86.avx512.mask.sub.sd.round @@ -3495,6 +3507,8 @@ __m128d test_mm_mask_sub_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_mask_sub_sd(__W,__U,__A,__B); } +TEST_CONSTEXPR(match_v2df(_mm_mask_sub_sd((__m128d)(__v2df){-1.0, 111.0}, 0x1, (__m128d)(__v2df){9.0, 70.0}, (__m128d)(__v2df){3.5, 80.0}), 5.5, 111.0)); + __m128d test_mm_maskz_sub_sd(__mmask8 __U, __m128d __A, __m128d __B) { // CHECK-LABEL: test_mm_maskz_sub_sd // CHECK-NOT: @llvm.x86.avx512.mask.sub.sd.round @@ -3510,6 +3524,8 @@ __m128d test_mm_maskz_sub_sd(__mmask8 __U, __m128d __A, __m128d __B) { // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_maskz_sub_sd(__U,__A,__B); } +TEST_CONSTEXPR(match_v2df(_mm_maskz_sub_sd(0x1, (__m128d)(__v2df){9.0, 70.0}, (__m128d)(__v2df){3.5, 80.0}), 5.5, 0.0)); + __m512d test_mm512_mul_round_pd(__m512d __A, __m512d __B) { // CHECK-LABEL: test_mm512_mul_round_pd // CHECK: @llvm.x86.avx512.mul.pd.512 @@ -3598,6 +3614,8 @@ __m128 test_mm_mask_mul_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_mask_mul_ss(__W,__U,__A,__B); } +TEST_CONSTEXPR(match_v4sf(_mm_mask_mul_ss((__m128)(__v4sf){42.0f, -1.0f, -2.0f, -3.0f}, 0x1, (__m128)(__v4sf){6.0f, 9.0f, 9.0f, 9.0f}, (__m128)(__v4sf){7.0f, 8.0f, 8.0f, 8.0f}), 42.0f, -1.0f, -2.0f, -3.0f)); + __m128 test_mm_maskz_mul_ss(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK-LABEL: test_mm_maskz_mul_ss // CHECK-NOT: @llvm.x86.avx512.mask.mul.ss.round @@ -3613,6 +3631,8 @@ __m128 test_mm_maskz_mul_ss(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_maskz_mul_ss(__U,__A,__B); } +TEST_CONSTEXPR(match_v4sf(_mm_maskz_mul_ss(0x1, (__m128)(__v4sf){6.0f, 9.0f, 9.0f, 9.0f}, (__m128)(__v4sf){7.0f, 8.0f, 8.0f, 8.0f}), 42.0f, 0.0f, 0.0f, 0.0f)); + __m128d test_mm_mul_round_sd(__m128d __A, __m128d __B) { // CHECK-LABEL: test_mm_mul_round_sd // CHECK: @llvm.x86.avx512.mask.mul.sd.round @@ -3643,6 +3663,8 @@ __m128d test_mm_mask_mul_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_mask_mul_sd(__W,__U,__A,__B); } +TEST_CONSTEXPR(match_v2df(_mm_mask_mul_sd((__m128d)(__v2df){123.0, -9.0}, 0x1, (__m128d)(__v2df){2.5, 1.0}, (__m128d)(__v2df){4.0, 2.0}), 10.0, -9.0)); + __m128d test_mm_maskz_mul_sd(__mmask8 __U, __m128d __A, __m128d __B) { // CHECK-LABEL: test_mm_maskz_mul_sd // CHECK-NOT: @llvm.x86.avx512.mask.mul.sd.round @@ -3658,6 +3680,8 @@ __m128d test_mm_maskz_mul_sd(__mmask8 __U, __m128d __A, __m128d __B) { // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_maskz_mul_sd(__U,__A,__B); } +TEST_CONSTEXPR(match_v2df(_mm_maskz_mul_sd(0x1, (__m128d)(__v2df){2.5, 1.0}, (__m128d)(__v2df){4.0, 2.0}), 10.0, 0.0)); + __m512d test_mm512_div_round_pd(__m512d __A, __m512d __B) { // CHECK-LABEL: test_mm512_div_round_pd // CHECK: @llvm.x86.avx512.div.pd.512 @@ -3757,6 +3781,8 @@ __m128 test_mm_mask_div_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_mask_div_ss(__W,__U,__A,__B); } +TEST_CONSTEXPR(match_v4sf(_mm_mask_div_ss((__m128)(__v4sf){-7.0f, 5.0f, 6.0f, 7.0f}, 0x1, (__m128)(__v4sf){9.0f, 1.0f, 1.0f, 1.0f}, (__m128)(__v4sf){3.0f, 2.0f, 2.0f, 2.0f}), 3.0f, 5.0f, 6.0f, 7.0f)); + __m128 test_mm_maskz_div_ss(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK-LABEL: test_mm_maskz_div_ss // CHECK: extractelement <4 x float> %{{.*}}, i32 0 @@ -3771,6 +3797,8 @@ __m128 test_mm_maskz_div_ss(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_maskz_div_ss(__U,__A,__B); } +TEST_CONSTEXPR(match_v4sf(_mm_maskz_div_ss(0x1, (__m128)(__v4sf){9.0f, 1.0f, 1.0f, 1.0f}, (__m128)(__v4sf){3.0f, 2.0f, 2.0f, 2.0f}), 3.0f, 0.0f, 0.0f, 0.0f)); + __m128d test_mm_div_round_sd(__m128d __A, __m128d __B) { // CHECK-LABEL: test_mm_div_round_sd // CHECK: @llvm.x86.avx512.mask.div.sd.round @@ -3800,6 +3828,8 @@ __m128d test_mm_mask_div_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_mask_div_sd(__W,__U,__A,__B); } +TEST_CONSTEXPR(match_v2df(_mm_mask_div_sd((__m128d)(__v2df){-8.0, 44.0}, 0x1, (__m128d)(__v2df){8.0, 10.0}, (__m128d)(__v2df){2.0, 20.0}), 4.0, 44.0)); + __m128d test_mm_maskz_div_sd(__mmask8 __U, __m128d __A, __m128d __B) { // CHECK-LABEL: test_mm_maskz_div_sd // CHECK: extractelement <2 x double> %{{.*}}, i32 0 @@ -3814,6 +3844,8 @@ __m128d test_mm_maskz_div_sd(__mmask8 __U, __m128d __A, __m128d __B) { // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_maskz_div_sd(__U,__A,__B); } +TEST_CONSTEXPR(match_v2df(_mm_maskz_div_sd(0x1, (__m128d)(__v2df){8.0, 10.0}, (__m128d)(__v2df){2.0, 20.0}), 4.0, 0.0)); + __m128 test_mm_max_round_ss(__m128 __A, __m128 __B) { // CHECK-LABEL: test_mm_max_round_ss // CHECK: @llvm.x86.avx512.mask.max.ss.round diff --git a/clang/test/CodeGen/X86/builtin_test_helpers.h b/clang/test/CodeGen/X86/builtin_test_helpers.h index fcaf360626a2d..a0ef6d3028aa9 100644 --- a/clang/test/CodeGen/X86/builtin_test_helpers.h +++ b/clang/test/CodeGen/X86/builtin_test_helpers.h @@ -80,6 +80,11 @@ constexpr bool match_v2du(__m128i _v, unsigned long long a, unsigned long long b return v[0] == a && v[1] == b; } +constexpr bool match_v2df(__m128d _v, double a, double b){ + __v2df v = (__v2df)_v; + return v[0] == a && v[1] == b; +} + constexpr bool match_v4si(__m128i _v, int a, int b, int c, int d) { __v4si v = (__v4si)_v; return v[0] == a && v[1] == b && v[2] == c && v[3] == d; @@ -90,6 +95,11 @@ constexpr bool match_v4su(__m128i _v, unsigned a, unsigned b, unsigned c, unsign return v[0] == a && v[1] == b && v[2] == c && v[3] == d; } +constexpr bool match_v4sf(__m128 _v, float a, float b, float c, float d) { + __v4sf v = (__v4sf)_v; + return v[0] == a && v[1] == b && v[2] == c && v[3] == d; +} + constexpr bool match_v8hi(__m128i _v, short a, short b, short c, short d, short e, short f, short g, short h) { __v8hi v = (__v8hi)_v; return v[0] == a && v[1] == b && v[2] == c && v[3] == d && v[4] == e && v[5] == f && v[6] == g && v[7] == h; From cfe-commits at lists.llvm.org Mon Nov 10 00:24:34 2025 From: cfe-commits at lists.llvm.org (via cfe-commits) Date: Mon, 10 Nov 2025 00:24:34 -0800 (PST) Subject: [clang] [Headers][X86] Allow AVX512 masked arithmetic intrinsics to be used in constexpr (PR #162816) In-Reply-To: Message-ID: <6911a142.170a0220.1fd60e.fcb7@mx.google.com> https://github.com/woruyu edited https://github.com/llvm/llvm-project/pull/162816 From cfe-commits at lists.llvm.org Mon Nov 10 00:24:45 2025 From: cfe-commits at lists.llvm.org (via cfe-commits) Date: Mon, 10 Nov 2025 00:24:45 -0800 (PST) Subject: [clang] [Headers][X86] Allow AVX512 masked arithmetic ss/sd intrinsics to be used in constexpr (PR #162816) In-Reply-To: Message-ID: <6911a14d.050a0220.3002a3.d2ce@mx.google.com> https://github.com/woruyu edited https://github.com/llvm/llvm-project/pull/162816 From cfe-commits at lists.llvm.org Mon Nov 10 00:26:10 2025 From: cfe-commits at lists.llvm.org (via cfe-commits) Date: Mon, 10 Nov 2025 00:26:10 -0800 (PST) Subject: [clang] [Headers][X86] Allow AVX512 masked arithmetic ss/sd intrinsics to be used in constexpr (PR #162816) In-Reply-To: Message-ID: <6911a1a2.170a0220.33a934.e9e0@mx.google.com> https://github.com/woruyu updated https://github.com/llvm/llvm-project/pull/162816 >From a14bb33c6b9bc57b1a3019e22e34ab88f68bc4da Mon Sep 17 00:00:00 2001 From: liuzhenya Date: Sun, 9 Nov 2025 22:22:50 -1000 Subject: [PATCH 1/2] [Headers][X86] Allow AVX512 masked arithmetic ss/sd intrinsics to be used in constexpr --- clang/include/clang/Basic/BuiltinsX86.td | 2 +- clang/lib/AST/ByteCode/InterpBuiltin.cpp | 24 +++++++ clang/lib/AST/ExprConstant.cpp | 22 +++++++ clang/lib/Headers/avx512fintrin.h | 64 +++++++++---------- clang/test/CodeGen/X86/avx512f-builtins.c | 32 ++++++++++ clang/test/CodeGen/X86/builtin_test_helpers.h | 10 +++ 6 files changed, 121 insertions(+), 33 deletions(-) diff --git a/clang/include/clang/Basic/BuiltinsX86.td b/clang/include/clang/Basic/BuiltinsX86.td index edff241a98738..ee1060dff5497 100644 --- a/clang/include/clang/Basic/BuiltinsX86.td +++ b/clang/include/clang/Basic/BuiltinsX86.td @@ -4128,7 +4128,7 @@ let Features = "avx512bf16", Attributes = [NoThrow, Const, RequiredVectorWidth<1 def selectsbf_128 : X86Builtin<"_Vector<8, __bf16>(unsigned char, _Vector<8, __bf16>, _Vector<8, __bf16>)">; } -let Features = "avx512f", Attributes = [NoThrow, Const, RequiredVectorWidth<128>] in { +let Features = "avx512f", Attributes = [NoThrow, Const, Constexpr, RequiredVectorWidth<128>] in { def selectss_128 : X86Builtin<"_Vector<4, float>(unsigned char, _Vector<4, float>, _Vector<4, float>)">; def selectsd_128 : X86Builtin<"_Vector<2, double>(unsigned char, _Vector<2, double>, _Vector<2, double>)">; } diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 0ef130c0a55df..0f0e3e87b1e8a 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -2419,6 +2419,27 @@ static bool interp__builtin_elementwise_int_unaryop( return false; } +static bool interp__builtin_select_scalar(InterpState &S, + const CallExpr *Call) { + unsigned N = + Call->getArg(1)->getType()->getAs()->getNumElements(); + + const Pointer &W = S.Stk.pop(); + const Pointer &A = S.Stk.pop(); + APSInt U = popToAPSInt(S, Call->getArg(0)); + const Pointer &Dst = S.Stk.peek(); + + bool TakeA0 = U.getZExtValue() & 1ULL; + + for (unsigned I = 0; I < N; ++I) + Dst.elem(I) = W.elem(I); + if (TakeA0) + Dst.elem(0) = A.elem(0); + + Dst.initializeAllElements(); + return true; +} + static bool interp__builtin_elementwise_int_binop( InterpState &S, CodePtr OpPC, const CallExpr *Call, llvm::function_ref Fn) { @@ -4205,6 +4226,9 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, return APInt::getAllOnes(DstBits); }); + case clang::X86::BI__builtin_ia32_selectss_128: + case clang::X86::BI__builtin_ia32_selectsd_128: + return interp__builtin_select_scalar(S, Call); case clang::X86::BI__builtin_ia32_vprotbi: case clang::X86::BI__builtin_ia32_vprotdi: case clang::X86::BI__builtin_ia32_vprotqi: diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 972d9fe3b5e4f..2f11b1d23f9a3 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -12264,6 +12264,24 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) { return Success(APValue(ResultElements.data(), SourceLen), E); }; + auto EvalSelectScalar = [&](unsigned Len) -> bool { + APSInt Mask; + APValue AVal, WVal; + if (!EvaluateInteger(E->getArg(0), Mask, Info) || + !EvaluateAsRValue(Info, E->getArg(1), AVal) || + !EvaluateAsRValue(Info, E->getArg(2), WVal)) + return false; + + bool TakeA0 = (Mask.getZExtValue() & 1u) != 0; + SmallVector Res; + Res.reserve(Len); + Res.push_back(TakeA0 ? AVal.getVectorElt(0) : WVal.getVectorElt(0)); + for (unsigned i = 1; i < Len; ++i) + Res.push_back(WVal.getVectorElt(i)); + APValue V(Res.data(), Res.size()); + return Success(V, E); + }; + switch (E->getBuiltinCallee()) { default: return false; @@ -12567,6 +12585,10 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) { return APInt((Src).trunc(DstBits)); return APInt::getAllOnes(DstBits); }); + case clang::X86::BI__builtin_ia32_selectss_128: + return EvalSelectScalar(4); + case clang::X86::BI__builtin_ia32_selectsd_128: + return EvalSelectScalar(2); case clang::X86::BI__builtin_ia32_pmuldq128: case clang::X86::BI__builtin_ia32_pmuldq256: case clang::X86::BI__builtin_ia32_pmuldq512: diff --git a/clang/lib/Headers/avx512fintrin.h b/clang/lib/Headers/avx512fintrin.h index 997e9608e112f..5a9e045ac3add 100644 --- a/clang/lib/Headers/avx512fintrin.h +++ b/clang/lib/Headers/avx512fintrin.h @@ -1834,14 +1834,14 @@ _mm512_maskz_abs_epi32(__mmask16 __U, __m512i __A) { (__v16si)_mm512_setzero_si512()); } -static __inline__ __m128 __DEFAULT_FN_ATTRS128 -_mm_mask_add_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { +static __inline__ __m128 __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_mask_add_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { __A = _mm_add_ss(__A, __B); return __builtin_ia32_selectss_128(__U, __A, __W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS128 -_mm_maskz_add_ss(__mmask8 __U,__m128 __A, __m128 __B) { +static __inline__ __m128 __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_maskz_add_ss(__mmask8 __U, __m128 __A, __m128 __B) { __A = _mm_add_ss(__A, __B); return __builtin_ia32_selectss_128(__U, __A, _mm_setzero_ps()); } @@ -1864,14 +1864,14 @@ _mm_maskz_add_ss(__mmask8 __U,__m128 __A, __m128 __B) { (__v4sf)_mm_setzero_ps(), \ (__mmask8)(U), (int)(R))) -static __inline__ __m128d __DEFAULT_FN_ATTRS128 -_mm_mask_add_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) { +static __inline__ __m128d __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_mask_add_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { __A = _mm_add_sd(__A, __B); return __builtin_ia32_selectsd_128(__U, __A, __W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS128 -_mm_maskz_add_sd(__mmask8 __U,__m128d __A, __m128d __B) { +static __inline__ __m128d __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_maskz_add_sd(__mmask8 __U, __m128d __A, __m128d __B) { __A = _mm_add_sd(__A, __B); return __builtin_ia32_selectsd_128(__U, __A, _mm_setzero_pd()); } @@ -1949,14 +1949,14 @@ _mm512_maskz_add_ps(__mmask16 __U, __m512 __A, __m512 __B) { (__v16sf)_mm512_add_round_ps((A), (B), (R)), \ (__v16sf)_mm512_setzero_ps())) -static __inline__ __m128 __DEFAULT_FN_ATTRS128 -_mm_mask_sub_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { +static __inline__ __m128 __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_mask_sub_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { __A = _mm_sub_ss(__A, __B); return __builtin_ia32_selectss_128(__U, __A, __W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS128 -_mm_maskz_sub_ss(__mmask8 __U,__m128 __A, __m128 __B) { +static __inline__ __m128 __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_maskz_sub_ss(__mmask8 __U, __m128 __A, __m128 __B) { __A = _mm_sub_ss(__A, __B); return __builtin_ia32_selectss_128(__U, __A, _mm_setzero_ps()); } @@ -1978,14 +1978,14 @@ _mm_maskz_sub_ss(__mmask8 __U,__m128 __A, __m128 __B) { (__v4sf)_mm_setzero_ps(), \ (__mmask8)(U), (int)(R))) -static __inline__ __m128d __DEFAULT_FN_ATTRS128 -_mm_mask_sub_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) { +static __inline__ __m128d __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_mask_sub_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { __A = _mm_sub_sd(__A, __B); return __builtin_ia32_selectsd_128(__U, __A, __W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS128 -_mm_maskz_sub_sd(__mmask8 __U,__m128d __A, __m128d __B) { +static __inline__ __m128d __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_maskz_sub_sd(__mmask8 __U, __m128d __A, __m128d __B) { __A = _mm_sub_sd(__A, __B); return __builtin_ia32_selectsd_128(__U, __A, _mm_setzero_pd()); } @@ -2064,14 +2064,14 @@ _mm512_maskz_sub_ps(__mmask16 __U, __m512 __A, __m512 __B) { (__v16sf)_mm512_sub_round_ps((A), (B), (R)), \ (__v16sf)_mm512_setzero_ps())) -static __inline__ __m128 __DEFAULT_FN_ATTRS128 -_mm_mask_mul_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { +static __inline__ __m128 __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_mask_mul_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { __A = _mm_mul_ss(__A, __B); return __builtin_ia32_selectss_128(__U, __A, __W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS128 -_mm_maskz_mul_ss(__mmask8 __U,__m128 __A, __m128 __B) { +static __inline__ __m128 __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_maskz_mul_ss(__mmask8 __U, __m128 __A, __m128 __B) { __A = _mm_mul_ss(__A, __B); return __builtin_ia32_selectss_128(__U, __A, _mm_setzero_ps()); } @@ -2093,14 +2093,14 @@ _mm_maskz_mul_ss(__mmask8 __U,__m128 __A, __m128 __B) { (__v4sf)_mm_setzero_ps(), \ (__mmask8)(U), (int)(R))) -static __inline__ __m128d __DEFAULT_FN_ATTRS128 -_mm_mask_mul_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) { +static __inline__ __m128d __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_mask_mul_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { __A = _mm_mul_sd(__A, __B); return __builtin_ia32_selectsd_128(__U, __A, __W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS128 -_mm_maskz_mul_sd(__mmask8 __U,__m128d __A, __m128d __B) { +static __inline__ __m128d __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_maskz_mul_sd(__mmask8 __U, __m128d __A, __m128d __B) { __A = _mm_mul_sd(__A, __B); return __builtin_ia32_selectsd_128(__U, __A, _mm_setzero_pd()); } @@ -2179,14 +2179,14 @@ _mm512_maskz_mul_ps(__mmask16 __U, __m512 __A, __m512 __B) { (__v16sf)_mm512_mul_round_ps((A), (B), (R)), \ (__v16sf)_mm512_setzero_ps())) -static __inline__ __m128 __DEFAULT_FN_ATTRS128 -_mm_mask_div_ss(__m128 __W, __mmask8 __U,__m128 __A, __m128 __B) { +static __inline__ __m128 __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_mask_div_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { __A = _mm_div_ss(__A, __B); return __builtin_ia32_selectss_128(__U, __A, __W); } -static __inline__ __m128 __DEFAULT_FN_ATTRS128 -_mm_maskz_div_ss(__mmask8 __U,__m128 __A, __m128 __B) { +static __inline__ __m128 __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_maskz_div_ss(__mmask8 __U, __m128 __A, __m128 __B) { __A = _mm_div_ss(__A, __B); return __builtin_ia32_selectss_128(__U, __A, _mm_setzero_ps()); } @@ -2209,14 +2209,14 @@ _mm_maskz_div_ss(__mmask8 __U,__m128 __A, __m128 __B) { (__v4sf)_mm_setzero_ps(), \ (__mmask8)(U), (int)(R))) -static __inline__ __m128d __DEFAULT_FN_ATTRS128 -_mm_mask_div_sd(__m128d __W, __mmask8 __U,__m128d __A, __m128d __B) { +static __inline__ __m128d __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_mask_div_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) { __A = _mm_div_sd(__A, __B); return __builtin_ia32_selectsd_128(__U, __A, __W); } -static __inline__ __m128d __DEFAULT_FN_ATTRS128 -_mm_maskz_div_sd(__mmask8 __U,__m128d __A, __m128d __B) { +static __inline__ __m128d __DEFAULT_FN_ATTRS128_CONSTEXPR +_mm_maskz_div_sd(__mmask8 __U, __m128d __A, __m128d __B) { __A = _mm_div_sd(__A, __B); return __builtin_ia32_selectsd_128(__U, __A, _mm_setzero_pd()); } diff --git a/clang/test/CodeGen/X86/avx512f-builtins.c b/clang/test/CodeGen/X86/avx512f-builtins.c index 17778b52d3671..26296f474466a 100644 --- a/clang/test/CodeGen/X86/avx512f-builtins.c +++ b/clang/test/CodeGen/X86/avx512f-builtins.c @@ -3302,6 +3302,8 @@ __m128 test_mm_mask_add_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_mask_add_ss(__W,__U,__A,__B); } +TEST_CONSTEXPR(match_v4sf(_mm_mask_add_ss((__m128)(__v4sf){10.0f, 100.0f, 200.0f, 300.0f}, 0x1,(__m128)(__v4sf){1.25f, 3.0f, 4.0f, 5.0f},(__m128)(__v4sf){2.75f, 6.0f, 7.0f, 8.0f}),4.0f, 100.0f, 200.0f, 300.0f)); + __m128 test_mm_maskz_add_ss(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK-LABEL: test_mm_maskz_add_ss // CHECK-NOT: @llvm.x86.avx512.mask.add.ss.round @@ -3317,6 +3319,8 @@ __m128 test_mm_maskz_add_ss(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_maskz_add_ss(__U,__A,__B); } +TEST_CONSTEXPR(match_v4sf(_mm_maskz_add_ss(0x1, (__m128)(__v4sf){1.25f, 3.0f, 4.0f, 5.0f}, (__m128)(__v4sf){2.75f, 6.0f, 7.0f, 8.0f}), 4.0f, 0.0f, 0.0f, 0.0f)); + __m128d test_mm_add_round_sd(__m128d __A, __m128d __B) { // CHECK-LABEL: test_mm_add_round_sd // CHECK: @llvm.x86.avx512.mask.add.sd.round @@ -3347,6 +3351,8 @@ __m128d test_mm_mask_add_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_mask_add_sd(__W,__U,__A,__B); } +TEST_CONSTEXPR(match_v2df(_mm_mask_add_sd((__m128d)(__v2df){10.0, 999.0}, 0x1, (__m128d)(__v2df){5.5, 77.0}, (__m128d)(__v2df){0.25, 88.0}), 5.75, 999.0)); + __m128d test_mm_maskz_add_sd(__mmask8 __U, __m128d __A, __m128d __B) { // CHECK-LABEL: test_mm_maskz_add_sd // CHECK-NOT: @llvm.x86.avx512.mask.add.sd.round @@ -3362,6 +3368,8 @@ __m128d test_mm_maskz_add_sd(__mmask8 __U, __m128d __A, __m128d __B) { // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_maskz_add_sd(__U,__A,__B); } +TEST_CONSTEXPR(match_v2df(_mm_maskz_add_sd(0x1, (__m128d)(__v2df){5.5, 77.0}, (__m128d)(__v2df){0.25, 88.0}), 5.75, 0.0)); + __m512d test_mm512_sub_round_pd(__m512d __A, __m512d __B) { // CHECK-LABEL: test_mm512_sub_round_pd // CHECK: @llvm.x86.avx512.sub.pd.512 @@ -3450,6 +3458,8 @@ __m128 test_mm_mask_sub_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_mask_sub_ss(__W,__U,__A,__B); } +TEST_CONSTEXPR(match_v4sf(_mm_mask_sub_ss((__m128)(__v4sf){-1.0f, 10.0f, 20.0f, 30.0f}, 0x1, (__m128)(__v4sf){7.0f, 3.0f, 4.0f, 5.0f}, (__m128)(__v4sf){2.5f, 6.0f, 7.0f, 8.0f}), 4.5f, 10.0f, 20.0f, 30.0f)); + __m128 test_mm_maskz_sub_ss(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK-LABEL: test_mm_maskz_sub_ss // CHECK-NOT: @llvm.x86.avx512.mask.sub.ss.round @@ -3465,6 +3475,8 @@ __m128 test_mm_maskz_sub_ss(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_maskz_sub_ss(__U,__A,__B); } +TEST_CONSTEXPR(match_v4sf(_mm_maskz_sub_ss(0x1, (__m128)(__v4sf){7.0f, 3.0f, 4.0f, 5.0f}, (__m128)(__v4sf){2.5f, 6.0f, 7.0f, 8.0f}), 4.5f, 0.0f, 0.0f, 0.0f)); + __m128d test_mm_sub_round_sd(__m128d __A, __m128d __B) { // CHECK-LABEL: test_mm_sub_round_sd // CHECK: @llvm.x86.avx512.mask.sub.sd.round @@ -3495,6 +3507,8 @@ __m128d test_mm_mask_sub_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_mask_sub_sd(__W,__U,__A,__B); } +TEST_CONSTEXPR(match_v2df(_mm_mask_sub_sd((__m128d)(__v2df){-1.0, 111.0}, 0x1, (__m128d)(__v2df){9.0, 70.0}, (__m128d)(__v2df){3.5, 80.0}), 5.5, 111.0)); + __m128d test_mm_maskz_sub_sd(__mmask8 __U, __m128d __A, __m128d __B) { // CHECK-LABEL: test_mm_maskz_sub_sd // CHECK-NOT: @llvm.x86.avx512.mask.sub.sd.round @@ -3510,6 +3524,8 @@ __m128d test_mm_maskz_sub_sd(__mmask8 __U, __m128d __A, __m128d __B) { // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_maskz_sub_sd(__U,__A,__B); } +TEST_CONSTEXPR(match_v2df(_mm_maskz_sub_sd(0x1, (__m128d)(__v2df){9.0, 70.0}, (__m128d)(__v2df){3.5, 80.0}), 5.5, 0.0)); + __m512d test_mm512_mul_round_pd(__m512d __A, __m512d __B) { // CHECK-LABEL: test_mm512_mul_round_pd // CHECK: @llvm.x86.avx512.mul.pd.512 @@ -3598,6 +3614,8 @@ __m128 test_mm_mask_mul_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_mask_mul_ss(__W,__U,__A,__B); } +TEST_CONSTEXPR(match_v4sf(_mm_mask_mul_ss((__m128)(__v4sf){42.0f, -1.0f, -2.0f, -3.0f}, 0x1, (__m128)(__v4sf){6.0f, 9.0f, 9.0f, 9.0f}, (__m128)(__v4sf){7.0f, 8.0f, 8.0f, 8.0f}), 42.0f, -1.0f, -2.0f, -3.0f)); + __m128 test_mm_maskz_mul_ss(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK-LABEL: test_mm_maskz_mul_ss // CHECK-NOT: @llvm.x86.avx512.mask.mul.ss.round @@ -3613,6 +3631,8 @@ __m128 test_mm_maskz_mul_ss(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_maskz_mul_ss(__U,__A,__B); } +TEST_CONSTEXPR(match_v4sf(_mm_maskz_mul_ss(0x1, (__m128)(__v4sf){6.0f, 9.0f, 9.0f, 9.0f}, (__m128)(__v4sf){7.0f, 8.0f, 8.0f, 8.0f}), 42.0f, 0.0f, 0.0f, 0.0f)); + __m128d test_mm_mul_round_sd(__m128d __A, __m128d __B) { // CHECK-LABEL: test_mm_mul_round_sd // CHECK: @llvm.x86.avx512.mask.mul.sd.round @@ -3643,6 +3663,8 @@ __m128d test_mm_mask_mul_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_mask_mul_sd(__W,__U,__A,__B); } +TEST_CONSTEXPR(match_v2df(_mm_mask_mul_sd((__m128d)(__v2df){123.0, -9.0}, 0x1, (__m128d)(__v2df){2.5, 1.0}, (__m128d)(__v2df){4.0, 2.0}), 10.0, -9.0)); + __m128d test_mm_maskz_mul_sd(__mmask8 __U, __m128d __A, __m128d __B) { // CHECK-LABEL: test_mm_maskz_mul_sd // CHECK-NOT: @llvm.x86.avx512.mask.mul.sd.round @@ -3658,6 +3680,8 @@ __m128d test_mm_maskz_mul_sd(__mmask8 __U, __m128d __A, __m128d __B) { // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_maskz_mul_sd(__U,__A,__B); } +TEST_CONSTEXPR(match_v2df(_mm_maskz_mul_sd(0x1, (__m128d)(__v2df){2.5, 1.0}, (__m128d)(__v2df){4.0, 2.0}), 10.0, 0.0)); + __m512d test_mm512_div_round_pd(__m512d __A, __m512d __B) { // CHECK-LABEL: test_mm512_div_round_pd // CHECK: @llvm.x86.avx512.div.pd.512 @@ -3757,6 +3781,8 @@ __m128 test_mm_mask_div_ss(__m128 __W, __mmask8 __U, __m128 __A, __m128 __B) { // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_mask_div_ss(__W,__U,__A,__B); } +TEST_CONSTEXPR(match_v4sf(_mm_mask_div_ss((__m128)(__v4sf){-7.0f, 5.0f, 6.0f, 7.0f}, 0x1, (__m128)(__v4sf){9.0f, 1.0f, 1.0f, 1.0f}, (__m128)(__v4sf){3.0f, 2.0f, 2.0f, 2.0f}), 3.0f, 5.0f, 6.0f, 7.0f)); + __m128 test_mm_maskz_div_ss(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK-LABEL: test_mm_maskz_div_ss // CHECK: extractelement <4 x float> %{{.*}}, i32 0 @@ -3771,6 +3797,8 @@ __m128 test_mm_maskz_div_ss(__mmask8 __U, __m128 __A, __m128 __B) { // CHECK-NEXT: insertelement <4 x float> %{{.*}}, float %{{.*}}, i64 0 return _mm_maskz_div_ss(__U,__A,__B); } +TEST_CONSTEXPR(match_v4sf(_mm_maskz_div_ss(0x1, (__m128)(__v4sf){9.0f, 1.0f, 1.0f, 1.0f}, (__m128)(__v4sf){3.0f, 2.0f, 2.0f, 2.0f}), 3.0f, 0.0f, 0.0f, 0.0f)); + __m128d test_mm_div_round_sd(__m128d __A, __m128d __B) { // CHECK-LABEL: test_mm_div_round_sd // CHECK: @llvm.x86.avx512.mask.div.sd.round @@ -3800,6 +3828,8 @@ __m128d test_mm_mask_div_sd(__m128d __W, __mmask8 __U, __m128d __A, __m128d __B) // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_mask_div_sd(__W,__U,__A,__B); } +TEST_CONSTEXPR(match_v2df(_mm_mask_div_sd((__m128d)(__v2df){-8.0, 44.0}, 0x1, (__m128d)(__v2df){8.0, 10.0}, (__m128d)(__v2df){2.0, 20.0}), 4.0, 44.0)); + __m128d test_mm_maskz_div_sd(__mmask8 __U, __m128d __A, __m128d __B) { // CHECK-LABEL: test_mm_maskz_div_sd // CHECK: extractelement <2 x double> %{{.*}}, i32 0 @@ -3814,6 +3844,8 @@ __m128d test_mm_maskz_div_sd(__mmask8 __U, __m128d __A, __m128d __B) { // CHECK-NEXT: insertelement <2 x double> %{{.*}}, double %{{.*}}, i64 0 return _mm_maskz_div_sd(__U,__A,__B); } +TEST_CONSTEXPR(match_v2df(_mm_maskz_div_sd(0x1, (__m128d)(__v2df){8.0, 10.0}, (__m128d)(__v2df){2.0, 20.0}), 4.0, 0.0)); + __m128 test_mm_max_round_ss(__m128 __A, __m128 __B) { // CHECK-LABEL: test_mm_max_round_ss // CHECK: @llvm.x86.avx512.mask.max.ss.round diff --git a/clang/test/CodeGen/X86/builtin_test_helpers.h b/clang/test/CodeGen/X86/builtin_test_helpers.h index fcaf360626a2d..a0ef6d3028aa9 100644 --- a/clang/test/CodeGen/X86/builtin_test_helpers.h +++ b/clang/test/CodeGen/X86/builtin_test_helpers.h @@ -80,6 +80,11 @@ constexpr bool match_v2du(__m128i _v, unsigned long long a, unsigned long long b return v[0] == a && v[1] == b; } +constexpr bool match_v2df(__m128d _v, double a, double b){ + __v2df v = (__v2df)_v; + return v[0] == a && v[1] == b; +} + constexpr bool match_v4si(__m128i _v, int a, int b, int c, int d) { __v4si v = (__v4si)_v; return v[0] == a && v[1] == b && v[2] == c && v[3] == d; @@ -90,6 +95,11 @@ constexpr bool match_v4su(__m128i _v, unsigned a, unsigned b, unsigned c, unsign return v[0] == a && v[1] == b && v[2] == c && v[3] == d; } +constexpr bool match_v4sf(__m128 _v, float a, float b, float c, float d) { + __v4sf v = (__v4sf)_v; + return v[0] == a && v[1] == b && v[2] == c && v[3] == d; +} + constexpr bool match_v8hi(__m128i _v, short a, short b, short c, short d, short e, short f, short g, short h) { __v8hi v = (__v8hi)_v; return v[0] == a && v[1] == b && v[2] == c && v[3] == d && v[4] == e && v[5] == f && v[6] == g && v[7] == h; >From 679c6e69949eb062da9a0ba6aa2b588342c95bb8 Mon Sep 17 00:00:00 2001 From: liuzhenya Date: Sun, 9 Nov 2025 22:25:54 -1000 Subject: [PATCH 2/2] fix: format --- clang/lib/AST/ExprConstant.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 2f11b1d23f9a3..9724237b715cf 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -12585,7 +12585,7 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) { return APInt((Src).trunc(DstBits)); return APInt::getAllOnes(DstBits); }); - case clang::X86::BI__builtin_ia32_selectss_128: + case clang::X86::BI__builtin_ia32_selectss_128: return EvalSelectScalar(4); case clang::X86::BI__builtin_ia32_selectsd_128: return EvalSelectScalar(2); From cfe-commits at lists.llvm.org Mon Nov 10 00:26:42 2025 From: cfe-commits at lists.llvm.org (via cfe-commits) Date: Mon, 10 Nov 2025 00:26:42 -0800 (PST) Subject: [clang-tools-extra] 4b433cb - [clang-tidy] Rename 'cert-err60-cpp' to 'bugprone-exception-copy-constructor-throws' (#164061) Message-ID: <6911a1c2.050a0220.14bf82.092d@mx.google.com> Author: Baranov Victor Date: 2025-11-10T11:26:38+03:00 New Revision: 4b433cbdeec7870fac318222d280dd0294ee34e3 URL: https://github.com/llvm/llvm-project/commit/4b433cbdeec7870fac318222d280dd0294ee34e3 DIFF: https://github.com/llvm/llvm-project/commit/4b433cbdeec7870fac318222d280dd0294ee34e3.diff LOG: [clang-tidy] Rename 'cert-err60-cpp' to 'bugprone-exception-copy-constructor-throws' (#164061) Closes https://github.com/llvm/llvm-project/issues/157299. --------- Co-authored-by: Victor Chernyakin Added: clang-tools-extra/clang-tidy/bugprone/ExceptionCopyConstructorThrowsCheck.cpp clang-tools-extra/clang-tidy/bugprone/ExceptionCopyConstructorThrowsCheck.h clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-copy-constructor-throws.rst clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-copy-constructor-throws.cpp Modified: clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp clang-tools-extra/clang-tidy/cert/CMakeLists.txt clang-tools-extra/docs/ReleaseNotes.rst clang-tools-extra/docs/clang-tidy/checks/cert/err60-cpp.rst clang-tools-extra/docs/clang-tidy/checks/list.rst Removed: clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.cpp clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.h clang-tools-extra/test/clang-tidy/checkers/cert/throw-exception-type.cpp ################################################################################ diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp index baea231f6e060..3ba1532334e4a 100644 --- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp @@ -30,6 +30,7 @@ #include "DynamicStaticInitializersCheck.h" #include "EasilySwappableParametersCheck.h" #include "EmptyCatchCheck.h" +#include "ExceptionCopyConstructorThrowsCheck.h" #include "ExceptionEscapeCheck.h" #include "FloatLoopCounterCheck.h" #include "FoldInitTypeCheck.h" @@ -155,6 +156,8 @@ class BugproneModule : public ClangTidyModule { CheckFactories.registerCheck( "bugprone-easily-swappable-parameters"); CheckFactories.registerCheck("bugprone-empty-catch"); + CheckFactories.registerCheck( + "bugprone-exception-copy-constructor-throws"); CheckFactories.registerCheck( "bugprone-exception-escape"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt index aacaa61888147..49c467aa5090c 100644 --- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt @@ -26,6 +26,7 @@ add_clang_library(clangTidyBugproneModule STATIC DynamicStaticInitializersCheck.cpp EasilySwappableParametersCheck.cpp EmptyCatchCheck.cpp + ExceptionCopyConstructorThrowsCheck.cpp ExceptionEscapeCheck.cpp FloatLoopCounterCheck.cpp FoldInitTypeCheck.cpp diff --git a/clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ExceptionCopyConstructorThrowsCheck.cpp similarity index 75% rename from clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.cpp rename to clang-tools-extra/clang-tidy/bugprone/ExceptionCopyConstructorThrowsCheck.cpp index 2225a90aeece1..73658459b8e26 100644 --- a/clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ExceptionCopyConstructorThrowsCheck.cpp @@ -6,15 +6,16 @@ // //===----------------------------------------------------------------------===// -#include "ThrownExceptionTypeCheck.h" +#include "ExceptionCopyConstructorThrowsCheck.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" using namespace clang::ast_matchers; -namespace clang::tidy::cert { +namespace clang::tidy::bugprone { -void ThrownExceptionTypeCheck::registerMatchers(MatchFinder *Finder) { +void ExceptionCopyConstructorThrowsCheck::registerMatchers( + MatchFinder *Finder) { Finder->addMatcher( traverse( TK_AsIs, @@ -25,10 +26,11 @@ void ThrownExceptionTypeCheck::registerMatchers(MatchFinder *Finder) { this); } -void ThrownExceptionTypeCheck::check(const MatchFinder::MatchResult &Result) { +void ExceptionCopyConstructorThrowsCheck::check( + const MatchFinder::MatchResult &Result) { const auto *E = Result.Nodes.getNodeAs("expr"); diag(E->getExprLoc(), "thrown exception type is not nothrow copy constructible"); } -} // namespace clang::tidy::cert +} // namespace clang::tidy::bugprone diff --git a/clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.h b/clang-tools-extra/clang-tidy/bugprone/ExceptionCopyConstructorThrowsCheck.h similarity index 58% rename from clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.h rename to clang-tools-extra/clang-tidy/bugprone/ExceptionCopyConstructorThrowsCheck.h index 41a5145209686..f1d7cca0e5bad 100644 --- a/clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/ExceptionCopyConstructorThrowsCheck.h @@ -6,20 +6,20 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_THROWNEXCEPTIONTYPECHECK_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_THROWNEXCEPTIONTYPECHECK_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_EXCEPTIONCOPYCONSTRUCTORTHROWSCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_EXCEPTIONCOPYCONSTRUCTORTHROWSCHECK_H #include "../ClangTidyCheck.h" -namespace clang::tidy::cert { +namespace clang::tidy::bugprone { /// Checks whether a thrown object is nothrow copy constructible. /// /// For the user-facing documentation see: -/// https://clang.llvm.org/extra/clang-tidy/checks/cert/err60-cpp.html -class ThrownExceptionTypeCheck : public ClangTidyCheck { +/// https://clang.llvm.org/extra/clang-tidy/checks/bugprone/exception-copy-constructor-throws.html +class ExceptionCopyConstructorThrowsCheck : public ClangTidyCheck { public: - ThrownExceptionTypeCheck(StringRef Name, ClangTidyContext *Context) + ExceptionCopyConstructorThrowsCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context) {} bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { return LangOpts.CPlusPlus; @@ -28,6 +28,6 @@ class ThrownExceptionTypeCheck : public ClangTidyCheck { void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; -} // namespace clang::tidy::cert +} // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_THROWNEXCEPTIONTYPECHECK_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_EXCEPTIONCOPYCONSTRUCTORTHROWSCHECK_H diff --git a/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp b/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp index 2f6fc4db46545..6dbcecee1e023 100644 --- a/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp @@ -13,6 +13,7 @@ #include "../bugprone/CommandProcessorCheck.h" #include "../bugprone/CopyConstructorMutatesArgumentCheck.h" #include "../bugprone/DefaultOperatorNewOnOveralignedTypeCheck.h" +#include "../bugprone/ExceptionCopyConstructorThrowsCheck.h" #include "../bugprone/FloatLoopCounterCheck.h" #include "../bugprone/PointerArithmeticOnPolymorphicObjectCheck.h" #include "../bugprone/RawMemoryCallOnNonTrivialTypeCheck.h" @@ -41,7 +42,6 @@ #include "../readability/UppercaseLiteralSuffixCheck.h" #include "LimitedRandomnessCheck.h" #include "ProperlySeededRandomGeneratorCheck.h" -#include "ThrownExceptionTypeCheck.h" namespace { @@ -262,7 +262,8 @@ class CERTModule : public ClangTidyModule { "cert-err52-cpp"); CheckFactories.registerCheck( "cert-err58-cpp"); - CheckFactories.registerCheck("cert-err60-cpp"); + CheckFactories.registerCheck( + "cert-err60-cpp"); CheckFactories.registerCheck( "cert-err61-cpp"); // MEM diff --git a/clang-tools-extra/clang-tidy/cert/CMakeLists.txt b/clang-tools-extra/clang-tidy/cert/CMakeLists.txt index 5abb47277e78f..81015a02023ba 100644 --- a/clang-tools-extra/clang-tidy/cert/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/cert/CMakeLists.txt @@ -7,7 +7,6 @@ add_clang_library(clangTidyCERTModule STATIC CERTTidyModule.cpp LimitedRandomnessCheck.cpp ProperlySeededRandomGeneratorCheck.cpp - ThrownExceptionTypeCheck.cpp LINK_LIBS clangTidy diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 48a2a1f5d39d5..c233301a08f36 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -269,6 +269,10 @@ New check aliases ` keeping initial check as an alias to the new one. +- Renamed :doc:`cert-err60-cpp ` to + :doc:`bugprone-exception-copy-constructor-throws + ` + - Renamed :doc:`cert-flp30-c ` to :doc:`bugprone-float-loop-counter ` diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-copy-constructor-throws.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-copy-constructor-throws.rst new file mode 100644 index 0000000000000..8c3becf80a541 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-copy-constructor-throws.rst @@ -0,0 +1,31 @@ +.. title:: clang-tidy - bugprone-exception-copy-constructor-throws + +bugprone-exception-copy-constructor-throws +========================================== + +Checks whether a thrown object's copy constructor can throw. + +Exception objects are required to be copy constructible in C++. However, an +exception's copy constructor should not throw to avoid potential issues when +unwinding the stack. If an exception is thrown during stack unwinding (such +as from a copy constructor of an exception object), the program will +terminate via ``std::terminate``. + +.. code-block:: c++ + + class SomeException { + public: + SomeException() = default; + SomeException(const SomeException&) { /* may throw */ } + }; + + void f() { + throw SomeException(); // warning: thrown exception type's copy constructor can throw + } + +References +---------- + +This check corresponds to the CERT C++ Coding Standard rule +`ERR60-CPP. Exception objects must be nothrow copy constructible +`_. \ No newline at end of file diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/err60-cpp.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/err60-cpp.rst index 9fcb840fc06f8..8d6dd1bf4b9b7 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/err60-cpp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/err60-cpp.rst @@ -1,11 +1,14 @@ .. title:: clang-tidy - cert-err60-cpp +.. meta:: + :http-equiv=refresh: 5;URL=../bugprone/exception-copy-constructor-throws.html cert-err60-cpp ============== -This check flags all throw expressions where the exception object is not nothrow -copy constructible. +The `cert-err60-cpp` check is an alias, please see +`bugprone-exception-copy-constructor-throws <../bugprone/exception-copy-constructor-throws.html>`_ +for more information. This check corresponds to the CERT C++ Coding Standard rule `ERR60-CPP. Exception objects must be nothrow copy constructible -`_. +`_. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index e2875604af72b..3b0ff3ef33365 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -98,6 +98,7 @@ Clang-Tidy Checks :doc:`bugprone-dynamic-static-initializers `, :doc:`bugprone-easily-swappable-parameters `, :doc:`bugprone-empty-catch `, + :doc:`bugprone-exception-copy-constructor-throws `, :doc:`bugprone-exception-escape `, :doc:`bugprone-float-loop-counter `, :doc:`bugprone-fold-init-type `, @@ -180,6 +181,7 @@ Clang-Tidy Checks :doc:`bugprone-virtual-near-miss `, "Yes" :doc:`cert-err33-c `, :doc:`cert-err60-cpp `, + :doc:`cert-flp30-c `, :doc:`cert-msc50-cpp `, :doc:`cert-msc51-cpp `, :doc:`cert-oop58-cpp `, @@ -449,6 +451,7 @@ Check aliases :doc:`cert-err34-c `, :doc:`bugprone-unchecked-string-to-number-conversion `, :doc:`cert-err52-cpp `, :doc:`modernize-avoid-setjmp-longjmp `, :doc:`cert-err58-cpp `, :doc:`bugprone-throwing-static-initialization `, + :doc:`cert-err60-cpp `, :doc:`bugprone-exception-copy-constructor-throws `, :doc:`cert-err61-cpp `, :doc:`misc-throw-by-value-catch-by-reference `, :doc:`cert-exp42-c `, :doc:`bugprone-suspicious-memory-comparison `, :doc:`cert-fio38-c `, :doc:`misc-non-copyable-objects `, diff --git a/clang-tools-extra/test/clang-tidy/checkers/cert/throw-exception-type.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-copy-constructor-throws.cpp similarity index 93% rename from clang-tools-extra/test/clang-tidy/checkers/cert/throw-exception-type.cpp rename to clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-copy-constructor-throws.cpp index 34ca83795c397..7e2d586175c1b 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cert/throw-exception-type.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-copy-constructor-throws.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy -std=c++11,c++14 %s cert-err60-cpp %t -- -- -fcxx-exceptions +// RUN: %check_clang_tidy -std=c++11,c++14 %s bugprone-exception-copy-constructor-throws %t -- -- -fcxx-exceptions // FIXME: Split off parts of this test that rely on dynamic exception // specifications, and run this test in all language modes. // FIXME: Fix the checker to work in C++17 or later mode. @@ -92,7 +92,7 @@ void f() { throw U(); // ok throw V(); // ok throw W(); // match, noexcept(false) - // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible [cert-err60-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible [bugprone-exception-copy-constructor-throws] throw X(); // match, no noexcept clause, nontrivial // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible throw Y(); // ok From cfe-commits at lists.llvm.org Mon Nov 10 00:26:46 2025 From: cfe-commits at lists.llvm.org (Baranov Victor via cfe-commits) Date: Mon, 10 Nov 2025 00:26:46 -0800 (PST) Subject: [clang-tools-extra] [clang-tidy] Rename 'cert-err60-cpp' to 'bugprone-exception-copy-constructor-throws' (PR #164061) In-Reply-To: Message-ID: <6911a1c6.170a0220.35fb81.02a3@mx.google.com> https://github.com/vbvictor closed https://github.com/llvm/llvm-project/pull/164061 From cfe-commits at lists.llvm.org Mon Nov 10 00:29:05 2025 From: cfe-commits at lists.llvm.org (via cfe-commits) Date: Mon, 10 Nov 2025 00:29:05 -0800 (PST) Subject: [clang] [Headers][X86] Allow AVX512 masked arithmetic ss/sd intrinsics to be used in constexpr (PR #162816) In-Reply-To: Message-ID: <6911a251.170a0220.15d7e4.ec9f@mx.google.com> woruyu wrote: @RKSimon, I'm ready to reslove this issue with several PR, this PR just finished ss/sd intrinsics part. Like this, ``` avx512fintrin.h _mm_mask_add_ss / _mm_maskz_add_ss _mm_mask_add_sd / _mm_maskz_add_sd _mm_mask_sub_ss / _mm_maskz_sub_ss _mm_mask_sub_sd / _mm_maskz_sub_sd _mm_mask_mul_ss / _mm_maskz_mul_ss _mm_mask_mul_sd / _mm_maskz_mul_sd _mm_mask_div_ss / _mm_maskz_div_ss _mm_mask_div_sd / _mm_maskz_div_sd ``` https://github.com/llvm/llvm-project/pull/162816 From cfe-commits at lists.llvm.org Mon Nov 10 00:29:23 2025 From: cfe-commits at lists.llvm.org (via cfe-commits) Date: Mon, 10 Nov 2025 00:29:23 -0800 (PST) Subject: [clang] [llvm] [Clang] Add diagnostic reasoning for unsatisfied is_destructible trait (PR #166967) In-Reply-To: Message-ID: <6911a263.170a0220.35b647.2cc4@mx.google.com> https://github.com/AnushaK6 closed https://github.com/llvm/llvm-project/pull/166967 From cfe-commits at lists.llvm.org Mon Nov 10 00:38:26 2025 From: cfe-commits at lists.llvm.org (Baranov Victor via cfe-commits) Date: Mon, 10 Nov 2025 00:38:26 -0800 (PST) Subject: [clang] [clang-tools-extra] [clang-tidy] Add `IgnoreValueCalls` option to bugprone-unchecked-optional-access (PR #167209) In-Reply-To: Message-ID: <6911a482.170a0220.336205.e5f7@mx.google.com> ================ @@ -1153,26 +1153,30 @@ auto buildDiagnoseMatchSwitch( // FIXME: Evaluate the efficiency of matchers. If using matchers results in a // lot of duplicated work (e.g. string comparisons), consider providing APIs // that avoid it through memoization. - auto IgnorableOptional = ignorableOptional(Options); - return CFGMatchSwitchBuilder< - const Environment, - llvm::SmallVector>() - // optional::value - .CaseOfCFGStmt( - valueCall(IgnorableOptional), - [](const CXXMemberCallExpr *E, const MatchFinder::MatchResult &, - const Environment &Env) { - return diagnoseUnwrapCall(E->getImplicitObjectArgument(), Env); - }) + const auto IgnorableOptional = ignorableOptional(Options); + ---------------- vbvictor wrote: We should preserve comments above `CaseOfCFGStmt` https://github.com/llvm/llvm-project/pull/167209 From cfe-commits at lists.llvm.org Mon Nov 10 00:38:26 2025 From: cfe-commits at lists.llvm.org (Baranov Victor via cfe-commits) Date: Mon, 10 Nov 2025 00:38:26 -0800 (PST) Subject: [clang] [clang-tools-extra] [clang-tidy] Add `IgnoreValueCalls` option to bugprone-unchecked-optional-access (PR #167209) In-Reply-To: Message-ID: <6911a482.a70a0220.1ab7d.0f73@mx.google.com> ================ @@ -1153,26 +1153,30 @@ auto buildDiagnoseMatchSwitch( // FIXME: Evaluate the efficiency of matchers. If using matchers results in a // lot of duplicated work (e.g. string comparisons), consider providing APIs // that avoid it through memoization. - auto IgnorableOptional = ignorableOptional(Options); - return CFGMatchSwitchBuilder< - const Environment, - llvm::SmallVector>() - // optional::value - .CaseOfCFGStmt( - valueCall(IgnorableOptional), - [](const CXXMemberCallExpr *E, const MatchFinder::MatchResult &, - const Environment &Env) { - return diagnoseUnwrapCall(E->getImplicitObjectArgument(), Env); - }) + const auto IgnorableOptional = ignorableOptional(Options); + + auto Builder = CFGMatchSwitchBuilder< + const Environment, + llvm::SmallVector>() + .CaseOfCFGStmt( + valueOperatorCall(IgnorableOptional), + [](const CallExpr *E, const MatchFinder::MatchResult &, + const Environment &Env) { + return diagnoseUnwrapCall(E->getArg(0), Env); + }); + + if (!Options.IgnoreValueCalls) { + return std::move(Builder) ---------------- vbvictor wrote: Could we not return here but only add one more `CaseOfCFGStmt` and return only once at the end of the function? The rationale is if we are to add completely new `CaseOfCFGStmt` to builder, then we would need to modify both returns or make more transformations. Be better leave code in flexible way to change in the future https://github.com/llvm/llvm-project/pull/167209 From cfe-commits at lists.llvm.org Mon Nov 10 00:38:26 2025 From: cfe-commits at lists.llvm.org (Baranov Victor via cfe-commits) Date: Mon, 10 Nov 2025 00:38:26 -0800 (PST) Subject: [clang] [clang-tools-extra] [clang-tidy] Add `IgnoreValueCalls` option to bugprone-unchecked-optional-access (PR #167209) In-Reply-To: Message-ID: <6911a482.170a0220.1773fd.dc6f@mx.google.com> ================ @@ -46,6 +46,13 @@ struct UncheckedOptionalAccessModelOptions { /// are confident in this const accessor caching, we shouldn't need the /// IgnoreSmartPointerDereference option anymore. bool IgnoreSmartPointerDereference = false; + + /// In generating diagnostics, ignore calls to `optional::value()`. + /// + /// Projects that intentionally use `value()` as a guarded access pattern may + /// set this to true to suppress diagnostics for `value()` while continuing to + /// diagnose UB-prone operator accesses (`operator*`, `operator->`). ---------------- vbvictor wrote: I'm not sure whatever this is needed, since it's internal documentation that users would not see anyway. https://github.com/llvm/llvm-project/pull/167209 From cfe-commits at lists.llvm.org Mon Nov 10 00:38:36 2025 From: cfe-commits at lists.llvm.org (Baranov Victor via cfe-commits) Date: Mon, 10 Nov 2025 00:38:36 -0800 (PST) Subject: [clang] [clang-tools-extra] [clang-tidy] Add `IgnoreValueCalls` option to bugprone-unchecked-optional-access (PR #167209) In-Reply-To: Message-ID: <6911a48c.170a0220.a90ef.e9b3@mx.google.com> https://github.com/vbvictor edited https://github.com/llvm/llvm-project/pull/167209 From cfe-commits at lists.llvm.org Mon Nov 10 00:41:25 2025 From: cfe-commits at lists.llvm.org (via cfe-commits) Date: Mon, 10 Nov 2025 00:41:25 -0800 (PST) Subject: [clang-tools-extra] eaa889a - [clang-tidy] Add fine-graded configuration for 'bugprone-exception-escape' (#164081) Message-ID: <6911a535.170a0220.1df318.8204@mx.google.com> Author: Baranov Victor Date: 2025-11-10T11:41:21+03:00 New Revision: eaa889ab1791618eddc6a22d777750ac936b65a1 URL: https://github.com/llvm/llvm-project/commit/eaa889ab1791618eddc6a22d777750ac936b65a1 DIFF: https://github.com/llvm/llvm-project/commit/eaa889ab1791618eddc6a22d777750ac936b65a1.diff LOG: [clang-tidy] Add fine-graded configuration for 'bugprone-exception-escape' (#164081) Need these options to complete https://github.com/llvm/llvm-project/issues/160825, but I think it's generally beneficial to fine-tune this check. --------- Co-authored-by: EugeneZelenko Co-authored-by: Victor Chernyakin Added: clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-options.cpp Modified: clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.h clang-tools-extra/docs/ReleaseNotes.rst clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-escape.rst Removed: ################################################################################ diff --git a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp index 837a86ff8655e..b7de8395ffa05 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp @@ -36,13 +36,22 @@ ExceptionEscapeCheck::ExceptionEscapeCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), RawFunctionsThatShouldNotThrow(Options.get( "FunctionsThatShouldNotThrow", "")), - RawIgnoredExceptions(Options.get("IgnoredExceptions", "")) { + RawIgnoredExceptions(Options.get("IgnoredExceptions", "")), + RawCheckedSwapFunctions( + Options.get("CheckedSwapFunctions", "swap,iter_swap,iter_move")), + CheckDestructors(Options.get("CheckDestructors", true)), + CheckMoveMemberFunctions(Options.get("CheckMoveMemberFunctions", true)), + CheckMain(Options.get("CheckMain", true)), + CheckNothrowFunctions(Options.get("CheckNothrowFunctions", true)) { llvm::SmallVector FunctionsThatShouldNotThrowVec, - IgnoredExceptionsVec; + IgnoredExceptionsVec, CheckedSwapFunctionsVec; RawFunctionsThatShouldNotThrow.split(FunctionsThatShouldNotThrowVec, ",", -1, false); FunctionsThatShouldNotThrow.insert_range(FunctionsThatShouldNotThrowVec); + RawCheckedSwapFunctions.split(CheckedSwapFunctionsVec, ",", -1, false); + CheckedSwapFunctions.insert_range(CheckedSwapFunctionsVec); + llvm::StringSet<> IgnoredExceptions; RawIgnoredExceptions.split(IgnoredExceptionsVec, ",", -1, false); IgnoredExceptions.insert_range(IgnoredExceptionsVec); @@ -54,20 +63,33 @@ void ExceptionEscapeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "FunctionsThatShouldNotThrow", RawFunctionsThatShouldNotThrow); Options.store(Opts, "IgnoredExceptions", RawIgnoredExceptions); + Options.store(Opts, "CheckedSwapFunctions", RawCheckedSwapFunctions); + Options.store(Opts, "CheckDestructors", CheckDestructors); + Options.store(Opts, "CheckMoveMemberFunctions", CheckMoveMemberFunctions); + Options.store(Opts, "CheckMain", CheckMain); + Options.store(Opts, "CheckNothrowFunctions", CheckNothrowFunctions); } void ExceptionEscapeCheck::registerMatchers(MatchFinder *Finder) { + auto MatchIf = [](bool Enabled, const auto &Matcher) { + ast_matchers::internal::Matcher Nothing = unless(anything()); + return Enabled ? Matcher : Nothing; + }; Finder->addMatcher( functionDecl( isDefinition(), - anyOf(isNoThrow(), - allOf(anyOf(cxxDestructorDecl(), - cxxConstructorDecl(isMoveConstructor()), - cxxMethodDecl(isMoveAssignmentOperator()), isMain(), - allOf(hasAnyName("swap", "iter_swap", "iter_move"), - hasAtLeastOneParameter())), - unless(isExplicitThrow())), - isEnabled(FunctionsThatShouldNotThrow))) + anyOf( + MatchIf(CheckNothrowFunctions, isNoThrow()), + allOf(anyOf(MatchIf(CheckDestructors, cxxDestructorDecl()), + MatchIf( + CheckMoveMemberFunctions, + anyOf(cxxConstructorDecl(isMoveConstructor()), + cxxMethodDecl(isMoveAssignmentOperator()))), + MatchIf(CheckMain, isMain()), + allOf(isEnabled(CheckedSwapFunctions), + hasAtLeastOneParameter())), + unless(isExplicitThrow())), + isEnabled(FunctionsThatShouldNotThrow))) .bind("thrower"), this); } diff --git a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.h b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.h index 31d9e85082c52..c3bf4a4335273 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.h @@ -35,8 +35,15 @@ class ExceptionEscapeCheck : public ClangTidyCheck { private: StringRef RawFunctionsThatShouldNotThrow; StringRef RawIgnoredExceptions; + StringRef RawCheckedSwapFunctions; + + const bool CheckDestructors; + const bool CheckMoveMemberFunctions; + const bool CheckMain; + const bool CheckNothrowFunctions; llvm::StringSet<> FunctionsThatShouldNotThrow; + llvm::StringSet<> CheckedSwapFunctions; utils::ExceptionAnalyzer Tracer; }; diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index c233301a08f36..f3d5b6f43a227 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -306,7 +306,9 @@ Changes in existing checks exceptions from captures are now diagnosed, exceptions in the bodies of lambdas that aren't actually invoked are not. Additionally, fixed an issue where the check wouldn't diagnose throws in arguments to functions or - constructors. + constructors. Added fine-grained configuration via options + `CheckDestructors`, `CheckMoveMemberFunctions`, `CheckMain`, + `CheckedSwapFunctions`, and `CheckNothrowFunctions`. - Improved :doc:`bugprone-infinite-loop ` check by adding detection for diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-escape.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-escape.rst index 182fade7f47a0..7eaa333d5403a 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-escape.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-escape.rst @@ -35,6 +35,31 @@ WARNING! This check may be expensive on large source files. Options ------- +.. option:: CheckDestructors + + When `true`, destructors are analyzed to not throw exceptions. + Default value is `true`. + +.. option:: CheckMoveMemberFunctions + + When `true`, move constructors and move assignment operators are analyzed + to not throw exceptions. Default value is `true`. + +.. option:: CheckMain + + When `true`, the ``main()`` function is analyzed to not throw exceptions. + Default value is `true`. + +.. option:: CheckNothrowFunctions + + When `true`, functions marked with ``noexcept`` or ``throw()`` exception + specifications are analyzed to not throw exceptions. Default value is `true`. + +.. option:: CheckedSwapFunctions + + Comma-separated list of swap function names which should not throw exceptions. + Default value is `swap,iter_swap,iter_move`. + .. option:: FunctionsThatShouldNotThrow Comma separated list containing function names which should not throw. An diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-options.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-options.cpp new file mode 100644 index 0000000000000..48c9bacd1b2e5 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-options.cpp @@ -0,0 +1,47 @@ +// RUN: %check_clang_tidy -std=c++11-or-later %s bugprone-exception-escape %t -- \ +// RUN: -config="{CheckOptions: { \ +// RUN: bugprone-exception-escape.CheckDestructors: false, \ +// RUN: bugprone-exception-escape.CheckMoveMemberFunctions: false, \ +// RUN: bugprone-exception-escape.CheckMain: false, \ +// RUN: bugprone-exception-escape.CheckedSwapFunctions: '', \ +// RUN: bugprone-exception-escape.CheckNothrowFunctions: false \ +// RUN: }}" \ +// RUN: -- -fexceptions + +// CHECK-MESSAGES-NOT: warning: + +struct destructor { + ~destructor() { + throw 1; + } +}; + +struct move { + move(move&&) { throw 42; } + move& operator=(move&&) { throw 42; } +}; + +void swap(int&, int&) { + throw 1; +} + +void iter_swap(int&, int&) { + throw 1; +} + +void iter_move(int&) { + throw 1; +} + +void nothrow_func() throw() { + throw 1; +} + +void noexcept_func() noexcept { + throw 1; +} + +int main() { + throw 1; + return 0; +} From cfe-commits at lists.llvm.org Mon Nov 10 00:41:29 2025 From: cfe-commits at lists.llvm.org (Baranov Victor via cfe-commits) Date: Mon, 10 Nov 2025 00:41:29 -0800 (PST) Subject: [clang-tools-extra] [clang-tidy] Add fine-graded configuration for 'bugprone-exception-escape' (PR #164081) In-Reply-To: Message-ID: <6911a539.170a0220.ab9da.7da3@mx.google.com> https://github.com/vbvictor closed https://github.com/llvm/llvm-project/pull/164081 From cfe-commits at lists.llvm.org Mon Nov 10 00:48:58 2025 From: cfe-commits at lists.llvm.org (Vassil Vassilev via cfe-commits) Date: Mon, 10 Nov 2025 00:48:58 -0800 (PST) Subject: [clang] [clang-repl] Fix inconsistent flushing between in-process and out-of-process (PR #166368) In-Reply-To: Message-ID: <6911a6fa.050a0220.29a300.11c1@mx.google.com> ================ @@ -352,6 +352,20 @@ int main(int argc, const char **argv) { Interp = ExitOnErr(clang::Interpreter::create(std::move(CI), Config)); } + if (Config.IsOutOfProcess) { ---------------- vgvassilev wrote: I think both setups have a flush problem. https://github.com/llvm/llvm-project/pull/166368 From cfe-commits at lists.llvm.org Mon Nov 10 00:50:27 2025 From: cfe-commits at lists.llvm.org (Vassil Vassilev via cfe-commits) Date: Mon, 10 Nov 2025 00:50:27 -0800 (PST) Subject: [clang] [clang-repl] Fix inconsistent flushing between in-process and out-of-process (PR #166368) In-Reply-To: Message-ID: <6911a753.170a0220.3b7fd8.e6db@mx.google.com> ================ @@ -352,6 +352,20 @@ int main(int argc, const char **argv) { Interp = ExitOnErr(clang::Interpreter::create(std::move(CI), Config)); } + if (Config.IsOutOfProcess) { + static const char *const InitUnbufferedStreams = R"( + #include + __attribute__((constructor)) + static void __clang_repl_ioinit(void) { + setvbuf(stdout, NULL, _IONBF, 0); + setvbuf(stderr, NULL, _IONBF, 0); ---------------- vgvassilev wrote: ```suggestion int setvbuf(FILE *restrict stream, char *restrict buf, int type, size_t size); setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); ``` https://github.com/llvm/llvm-project/pull/166368 From cfe-commits at lists.llvm.org Mon Nov 10 00:58:48 2025 From: cfe-commits at lists.llvm.org (Baranov Victor via cfe-commits) Date: Mon, 10 Nov 2025 00:58:48 -0800 (PST) Subject: [clang-tools-extra] [clang-tidy][NFC] Add `.editorconfig` for `.rst` files (PR #167269) In-Reply-To: Message-ID: <6911a948.050a0220.971ca.1c9f@mx.google.com> ================ @@ -0,0 +1,8 @@ +[clang-tidy/checks/**/*.rst] ---------------- vbvictor wrote: Instead of this path, could we just place it in `clang-tool-extra/docs/clang-tidy/checks/`? https://github.com/llvm/llvm-project/pull/167269 From cfe-commits at lists.llvm.org Mon Nov 10 00:58:58 2025 From: cfe-commits at lists.llvm.org (Baranov Victor via cfe-commits) Date: Mon, 10 Nov 2025 00:58:58 -0800 (PST) Subject: [clang-tools-extra] [clang-tidy][NFC] Add `.editorconfig` for `.rst` files (PR #167269) In-Reply-To: Message-ID: <6911a952.050a0220.169e10.7d21@mx.google.com> https://github.com/vbvictor edited https://github.com/llvm/llvm-project/pull/167269 From cfe-commits at lists.llvm.org Mon Nov 10 01:01:54 2025 From: cfe-commits at lists.llvm.org (LLVM Continuous Integration via cfe-commits) Date: Mon, 10 Nov 2025 01:01:54 -0800 (PST) Subject: [clang] [clang][bytecode] Check source pointer for bitcast validity (PR #166907) In-Reply-To: Message-ID: <6911aa02.170a0220.1b951d.e3a8@mx.google.com> llvm-ci wrote: LLVM Buildbot has detected a new failure on builder `ppc64le-flang-rhel-clang` running on `ppc64le-flang-rhel-test` while building `clang` at step 6 "test-build-unified-tree-check-flang". Full details are available at: https://lab.llvm.org/buildbot/#/builders/157/builds/42076
Here is the relevant piece of the build log for the reference ``` Step 6 (test-build-unified-tree-check-flang) failure: 1200 seconds without output running [b'ninja', b'check-flang'], attempting to kill ... PASS: Flang :: Transforms/tbaa-local-alloc-threshold.fir (3969 of 3979) PASS: Flang :: Transforms/stack-arrays.f90 (3970 of 3979) PASS: Flang :: Transforms/stack-arrays-hlfir.f90 (3971 of 3979) PASS: Flang :: Transforms/simplify-fir-operations.fir (3972 of 3979) PASS: Flang :: Transforms/debug-line-table.fir (3973 of 3979) PASS: Flang :: Transforms/debug-dwarf-version.fir (3974 of 3979) PASS: Flang :: Transforms/OpenACC/acc-implicit-data-fortran.F90 (3975 of 3979) PASS: Flang :: Driver/omp-driver-offload.f90 (3976 of 3979) PASS: Flang :: Semantics/modfile03.f90 (3977 of 3979) PASS: Flang :: Intrinsics/math-codegen.fir (3978 of 3979) command timed out: 1200 seconds without output running [b'ninja', b'check-flang'], attempting to kill process killed by signal 9 program finished with exit code -1 elapsedTime=2233.290325 ```
https://github.com/llvm/llvm-project/pull/166907 From cfe-commits at lists.llvm.org Mon Nov 10 01:03:50 2025 From: cfe-commits at lists.llvm.org (Baranov Victor via cfe-commits) Date: Mon, 10 Nov 2025 01:03:50 -0800 (PST) Subject: [clang-tools-extra] [clang-tidy][NFC] Add `.editorconfig` for `.rst` files (PR #167269) In-Reply-To: Message-ID: <6911aa76.170a0220.337f35.ed9e@mx.google.com> ================ @@ -0,0 +1,8 @@ +[clang-tidy/checks/**/*.rst] +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +end_of_line = lf +indent_style = space +indent_size = 2 ---------------- vbvictor wrote: I'd personally want to have `double-`indentation everywhere but a lot of existing options are using `triple-` so we shouldn't enforce `double-` right now. We could in the future after some extensive refactoring but I don't think it's a big priority. https://github.com/llvm/llvm-project/pull/167269 From cfe-commits at lists.llvm.org Mon Nov 10 01:05:50 2025 From: cfe-commits at lists.llvm.org (Yanzuo Liu via cfe-commits) Date: Mon, 10 Nov 2025 01:05:50 -0800 (PST) Subject: [clang] [clang] Support constexpr bitcasts between equal-size vector and integer types (PR #167016) In-Reply-To: Message-ID: <6911aaee.170a0220.2958b3.d6a5@mx.google.com> zwuis wrote: Thank you for your patch! Please [reference](https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/linking-a-pull-request-to-an-issue) the issue fixed by this PR in PR description. > Please let me know if further modifications or additional test coverage are recommended. Tests are required. You might refer to PRs solving sub-issues of #30794 for writing tests. https://github.com/llvm/llvm-project/pull/167016 From cfe-commits at lists.llvm.org Mon Nov 10 01:11:56 2025 From: cfe-commits at lists.llvm.org (Marco Elver via cfe-commits) Date: Mon, 10 Nov 2025 01:11:56 -0800 (PST) Subject: [clang] [Clang] Introduce malloc_span attribute (PR #167010) In-Reply-To: Message-ID: <6911ac5c.170a0220.1b951d.e4b2@mx.google.com> ================ @@ -5247,6 +5247,21 @@ yet implemented in clang. }]; } +def MallocSpanDocs : Documentation { + let Category = DocCatFunction; + let Heading = "malloc_span"; + let Content = [{ +The ``malloc_span`` attribute can be used to mark that a function, which acts +like a system memory allocation function and returns a span-like structure, +returns pointer to memory that does not alias storage from any other object ---------------- melver wrote: ```suggestion where the returned memory range does not alias storage from any other object ``` https://github.com/llvm/llvm-project/pull/167010 From cfe-commits at lists.llvm.org Mon Nov 10 01:11:57 2025 From: cfe-commits at lists.llvm.org (Marco Elver via cfe-commits) Date: Mon, 10 Nov 2025 01:11:57 -0800 (PST) Subject: [clang] [Clang] Introduce malloc_span attribute (PR #167010) In-Reply-To: Message-ID: <6911ac5d.050a0220.25d350.b696@mx.google.com> ================ @@ -1839,6 +1839,39 @@ static void handleRestrictAttr(Sema &S, Decl *D, const ParsedAttr &AL) { RestrictAttr(S.Context, AL, DeallocE, DeallocPtrIdx)); } +static bool isSpanLikeType(const QualType &Ty) { + // Check that the type is a plain record with the first field being a pointer + // type and the second field being an integer. + // This matches the common implementation of std::span or sized_allocation_t + // in P0901R11. + // Note that there may also be numerous cases of pointer+integer structures + // not actually exhibiting a std::span-like semantics, so sometimes ---------------- melver wrote: ```suggestion // not actually exhibiting a span-like semantics, so sometimes ``` https://github.com/llvm/llvm-project/pull/167010 From cfe-commits at lists.llvm.org Mon Nov 10 01:11:57 2025 From: cfe-commits at lists.llvm.org (Marco Elver via cfe-commits) Date: Mon, 10 Nov 2025 01:11:57 -0800 (PST) Subject: [clang] [Clang] Introduce malloc_span attribute (PR #167010) In-Reply-To: Message-ID: <6911ac5d.170a0220.14961c.07f0@mx.google.com> ================ @@ -327,6 +327,10 @@ Attribute Changes in Clang - New format attributes ``gnu_printf``, ``gnu_scanf``, ``gnu_strftime`` and ``gnu_strfmon`` are added as aliases for ``printf``, ``scanf``, ``strftime`` and ``strfmon``. (#GH16219) +- New function attribute `malloc_span` is added. It has the `malloc` semantics, but must be applied ---------------- melver wrote: s/It has the `malloc` semantics/Its semantics are similar to the `malloc` attribute/ The semantics aren't quite identical. https://github.com/llvm/llvm-project/pull/167010 From cfe-commits at lists.llvm.org Mon Nov 10 01:11:56 2025 From: cfe-commits at lists.llvm.org (Marco Elver via cfe-commits) Date: Mon, 10 Nov 2025 01:11:56 -0800 (PST) Subject: [clang] [Clang] Introduce malloc_span attribute (PR #167010) In-Reply-To: Message-ID: <6911ac5c.170a0220.15aa06.1911@mx.google.com> ================ @@ -6642,7 +6642,8 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, CalleeDecl); } if (CalleeDecl->hasAttr() || - CalleeDecl->hasAttr()) { + CalleeDecl->hasAttr() || + CalleeDecl->hasAttr()) { ---------------- melver wrote: Can we do this in a follow-up PR where we also update the test in the same PR? https://github.com/llvm/llvm-project/pull/167010 From cfe-commits at lists.llvm.org Mon Nov 10 01:11:57 2025 From: cfe-commits at lists.llvm.org (Marco Elver via cfe-commits) Date: Mon, 10 Nov 2025 01:11:57 -0800 (PST) Subject: [clang] [Clang] Introduce malloc_span attribute (PR #167010) In-Reply-To: Message-ID: <6911ac5d.170a0220.152201.b9f7@mx.google.com> ================ @@ -5247,6 +5247,21 @@ yet implemented in clang. }]; } +def MallocSpanDocs : Documentation { + let Category = DocCatFunction; + let Heading = "malloc_span"; + let Content = [{ +The ``malloc_span`` attribute can be used to mark that a function, which acts +like a system memory allocation function and returns a span-like structure, +returns pointer to memory that does not alias storage from any other object +accessible to the caller. + +In this context, a span-like structure is assumed to have a pointer to the +allocated memory as its first field and an integer with the size of the ---------------- melver wrote: ```suggestion allocated memory as its first field and any integer type with the size of the ``` https://github.com/llvm/llvm-project/pull/167010 From cfe-commits at lists.llvm.org Mon Nov 10 01:11:57 2025 From: cfe-commits at lists.llvm.org (Marco Elver via cfe-commits) Date: Mon, 10 Nov 2025 01:11:57 -0800 (PST) Subject: [clang] [Clang] Introduce malloc_span attribute (PR #167010) In-Reply-To: Message-ID: <6911ac5d.170a0220.3a6543.f481@mx.google.com> ================ @@ -1839,6 +1839,39 @@ static void handleRestrictAttr(Sema &S, Decl *D, const ParsedAttr &AL) { RestrictAttr(S.Context, AL, DeallocE, DeallocPtrIdx)); } +static bool isSpanLikeType(const QualType &Ty) { + // Check that the type is a plain record with the first field being a pointer + // type and the second field being an integer. + // This matches the common implementation of std::span or sized_allocation_t + // in P0901R11. + // Note that there may also be numerous cases of pointer+integer structures + // not actually exhibiting a std::span-like semantics, so sometimes + // this heuristic expectedly leads to false positive results. + const RecordDecl *RD = Ty->getAsRecordDecl(); + if (!RD || RD->isUnion()) + return false; + const RecordDecl *Def = RD->getDefinition(); + if (!Def) + return false; // This is an incomplete type. + auto FieldsBegin = Def->field_begin(); + if (std::distance(FieldsBegin, Def->field_end()) != 2) + return false; + const FieldDecl *FirstField = *FieldsBegin; + const FieldDecl *SecondField = *std::next(FieldsBegin); + return FirstField->getType()->isAnyPointerType() && ---------------- melver wrote: It would be easy to allow both orderings (ptr+size, size+ptr). For the `malloc` attribute I think we did it for simplicity and not expand the scope too much, but since we're introducing a new attribute entirely, maybe we can permit it right away? Is there any technical reason we should not allow this now? Because I fear in future someone may want this, and then we're stuck again with version checks. https://github.com/llvm/llvm-project/pull/167010 From cfe-commits at lists.llvm.org Mon Nov 10 01:11:56 2025 From: cfe-commits at lists.llvm.org (Marco Elver via cfe-commits) Date: Mon, 10 Nov 2025 01:11:56 -0800 (PST) Subject: [clang] [Clang] Introduce malloc_span attribute (PR #167010) In-Reply-To: Message-ID: <6911ac5c.050a0220.14c4d3.e639@mx.google.com> ================ @@ -1839,6 +1839,39 @@ static void handleRestrictAttr(Sema &S, Decl *D, const ParsedAttr &AL) { RestrictAttr(S.Context, AL, DeallocE, DeallocPtrIdx)); } +static bool isSpanLikeType(const QualType &Ty) { + // Check that the type is a plain record with the first field being a pointer + // type and the second field being an integer. ---------------- melver wrote: ```suggestion // type and the second field being an integer. This matches the ... ``` https://github.com/llvm/llvm-project/pull/167010 From cfe-commits at lists.llvm.org Mon Nov 10 01:22:19 2025 From: cfe-commits at lists.llvm.org (via cfe-commits) Date: Mon, 10 Nov 2025 01:22:19 -0800 (PST) Subject: [clang] [Clang] Add diagnostic reasoning for unsatisfied is_destructible trait (PR #167291) Message-ID: https://github.com/AnushaK6 created https://github.com/llvm/llvm-project/pull/167291 This patch adds diagnostic reasoning for the std::is_destructible type trait in Clang’s Sema diagnostics, in response to issue #141911 It enables detailed “unsatisfied trait” messages when a type fails destructibility checks (e.g., void, function types, deleted/private destructors, incomplete types, etc). Changes: - Added DiagnoseNonDestructibleReason() to SemaTypeTraits.cpp - Integrated UTT_IsDestructible handling in Sema::DiagnoseTypeTraitDetails - Updated diagnostic notes in DiagnosticSemaKinds.td Added new tests to: - clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp - clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp >From e1e0476c4d36b3213ce180d28ba224f69173c86a Mon Sep 17 00:00:00 2001 From: AnushaK6 Date: Mon, 10 Nov 2025 14:30:42 +0530 Subject: [PATCH] Add diagnostic reasoning for unsatisfied is_destructible trait --- .../clang/Basic/DiagnosticSemaKinds.td | 8 +- clang/lib/Sema/SemaTypeTraits.cpp | 64 ++++++++++++++++ .../type-traits-unsatisfied-diags-std.cpp | 76 +++++++++++++++++++ .../SemaCXX/type-traits-unsatisfied-diags.cpp | 49 ++++++++++++ 4 files changed, 193 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 3e864475f22a1..8fb76c2c989f5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1776,7 +1776,8 @@ def note_unsatisfied_trait "%StandardLayout{standard-layout}|" "%Aggregate{aggregate}|" "%Final{final}|" - "%Abstract{abstract}" + "%Abstract{abstract}|" + "%Destructible{destructible}" "}1">; def note_unsatisfied_trait_reason @@ -1808,6 +1809,7 @@ def note_unsatisfied_trait_reason "%NonStandardLayoutMember{has a non-standard-layout member %1 of type %2}|" "%IndirectBaseWithFields{has an indirect base %1 with data members}|" "%DeletedDtr{has a %select{deleted|user-provided}1 destructor}|" + "%InaccessibleDtr{has a %select{private|protected}1 destructor}|" "%UserProvidedCtr{has a user provided %select{copy|move}1 " "constructor}|" "%UserDeclaredCtr{has a user-declared constructor}|" @@ -1823,6 +1825,7 @@ def note_unsatisfied_trait_reason "%FunctionType{is a function type}|" "%CVVoidType{is a cv void type}|" "%IncompleteArrayType{is an incomplete array type}|" + "%IncompleteType{is an incomplete type}|" "%PrivateProtectedDirectDataMember{has a %select{private|protected}1 direct data member}|" "%PrivateProtectedDirectBase{has a %select{private|protected}1 direct base}|" "%NotClassOrUnion{is not a class or union type}|" @@ -12137,9 +12140,6 @@ def err_omp_unexpected_schedule_modifier : Error< "modifier '%0' cannot be used along with modifier '%1'">; def err_omp_schedule_nonmonotonic_static : Error< "'nonmonotonic' modifier can only be specified with 'dynamic' or 'guided' schedule kind">; -def err_omp_incompatible_dyn_groupprivate_modifier - : Error<"modifier '%0' cannot be used along with modifier '%1' in " - "dyn_groupprivate">; def err_omp_simple_clause_incompatible_with_ordered : Error< "'%0' clause with '%1' modifier cannot be specified if an 'ordered' clause is specified">; def err_omp_ordered_simd : Error< diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 38877967af05e..fef47dfc2cc51 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -2028,6 +2028,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { .Case("is_constructible", TypeTrait::TT_IsConstructible) .Case("is_final", TypeTrait::UTT_IsFinal) .Case("is_abstract", TypeTrait::UTT_IsAbstract) + .Case("is_destructible", TypeTrait::UTT_IsDestructible) .Default(std::nullopt); } @@ -2399,6 +2400,66 @@ static void DiagnoseNonConstructibleReason( SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonDestructibleReason(Sema &SemaRef, SourceLocation Loc, + QualType T) { + + QualType CoreT = T.getCanonicalType(); + if (const ArrayType *AT = SemaRef.Context.getAsArrayType(CoreT)) + CoreT = AT->getElementType(); + + SemaRef.Diag(Loc, diag::note_unsatisfied_trait) + << CoreT << diag::TraitName::Destructible; + + if (CoreT->isFunctionType()) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::FunctionType; + return; + } + + if (CoreT->isVoidType()) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::CVVoidType; + return; + } + + if (CoreT->isIncompleteType()) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::IncompleteType; + return; + } + + const CXXRecordDecl *RD = CoreT->getAsCXXRecordDecl(); + if (!RD || RD->isInvalidDecl()) + return; + + const CXXRecordDecl *Def = RD->getDefinition(); + if (!Def) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::IncompleteType; + return; + } + + CXXDestructorDecl *Dtor = Def->getDestructor(); + if (!Dtor) + return; + + if (Dtor->isDeleted()) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::DeletedDtr << 0 + << Dtor->getSourceRange(); + return; + } + + AccessSpecifier AS = Dtor->getAccess(); + if (AS == AS_private || AS == AS_protected) { + unsigned Select = (AS == AS_private) ? 0 : 1; + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::InaccessibleDtr << Select + << Dtor->getSourceRange(); + return; + } +} + static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, SourceLocation Loc, QualType T) { SemaRef.Diag(Loc, diag::note_unsatisfied_trait) @@ -2889,6 +2950,9 @@ void Sema::DiagnoseTypeTraitDetails(const Expr *E) { case TT_IsConstructible: DiagnoseNonConstructibleReason(*this, E->getBeginLoc(), Args); break; + case UTT_IsDestructible: + DiagnoseNonDestructibleReason(*this, E->getBeginLoc(), Args[0]); + break; case UTT_IsAggregate: DiagnoseNonAggregateReason(*this, E->getBeginLoc(), Args[0]); break; diff --git a/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp b/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp index 3e03a79275232..3e02fe8f10f56 100644 --- a/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp +++ b/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp @@ -73,6 +73,15 @@ struct is_abstract { template constexpr bool is_abstract_v = __is_abstract(T); +template +struct is_destructible { + static constexpr bool value = __is_destructible(T); +}; + +template +constexpr bool is_destructible_v = __is_destructible(T); + + #endif #ifdef STD2 @@ -167,6 +176,17 @@ using is_abstract = __details_is_abstract; template constexpr bool is_abstract_v = __is_abstract(T); +template +struct __details_is_destructible { + static constexpr bool value = __is_destructible(T); +}; + +template +using is_destructible = __details_is_destructible; + +template +constexpr bool is_destructible_v = __is_destructible(T); + #endif @@ -252,6 +272,15 @@ using is_abstract = __details_is_abstract; template constexpr bool is_abstract_v = is_abstract::value; +template +struct __details_is_destructible : bool_constant<__is_destructible(T)> {}; + +template +using is_destructible = __details_is_destructible; + +template +constexpr bool is_destructible_v = is_destructible::value; + #endif } @@ -374,6 +403,18 @@ static_assert(std::is_abstract_v); // expected-note at -1 {{because it is a reference type}} \ // expected-note at -1 {{because it is not a struct or class type}} +static_assert(std::is_destructible::value); + +static_assert(std::is_destructible::value); +// expected-error-re at -1 {{static assertion failed due to requirement 'std::{{.*}}is_destructible::value'}} \ +// expected-note at -1 {{'void' is not destructible}} \ +// expected-note at -1 {{because it is a cv void type}} + +static_assert(std::is_destructible_v); +// expected-error at -1 {{static assertion failed due to requirement 'std::is_destructible_v'}} \ +// expected-note at -1 {{'void' is not destructible}} \ +// expected-note at -1 {{because it is a cv void type}} + namespace test_namespace { using namespace std; @@ -473,6 +514,17 @@ namespace test_namespace { // expected-note at -1 {{'int &' is not abstract}} \ // expected-note at -1 {{because it is a reference type}} \ // expected-note at -1 {{because it is not a struct or class type}} + + static_assert(is_destructible::value); + // expected-error-re at -1 {{static assertion failed due to requirement '{{.*}}is_destructible::value'}} \ + // expected-note at -1 {{'void' is not destructible}} \ + // expected-note at -1 {{because it is a cv void type}} + + static_assert(is_destructible_v); + // expected-error at -1 {{static assertion failed due to requirement 'is_destructible_v'}} \ + // expected-note at -1 {{'void' is not destructible}} \ + // expected-note at -1 {{because it is a cv void type}} + } @@ -518,6 +570,15 @@ concept C5 = std::is_aggregate_v; // #concept10 template void g5(); // #cand10 +template +requires std::is_destructible::value void f6(); // #cand11 + +template +concept C6 = std::is_destructible_v; // #concept11 + +template void g6(); // #cand12 + + void test() { f(); // expected-error at -1 {{no matching function for call to 'f'}} \ @@ -589,6 +650,21 @@ void test() { // expected-note@#concept10 {{because 'std::is_aggregate_v' evaluated to false}} \ // expected-note@#concept10 {{'void' is not aggregate}} \ // expected-note@#concept10 {{because it is a cv void type}} + + f6(); + // expected-error at -1 {{no matching function for call to 'f6'}} \ + // expected-note@#cand11 {{candidate template ignored: constraints not satisfied [with T = void]}} \ + // expected-note-re@#cand11 {{because '{{.*}}is_destructible::value' evaluated to false}} \ + // expected-note@#cand11 {{'void' is not destructible}} \ + // expected-note@#cand11 {{because it is a cv void type}} + + g6(); + // expected-error at -1 {{no matching function for call to 'g6'}} \ + // expected-note@#cand12 {{candidate template ignored: constraints not satisfied [with T = void]}} \ + // expected-note@#cand12 {{because 'void' does not satisfy 'C6'}} \ + // expected-note@#concept11 {{because 'std::is_destructible_v' evaluated to false}} \ + // expected-note@#concept11 {{'void' is not destructible}} \ + // expected-note@#concept11 {{because it is a cv void type}} } } diff --git a/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp b/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp index 22740418f09f5..858a5cc24868f 100644 --- a/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp +++ b/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp @@ -1052,3 +1052,52 @@ static_assert(__is_abstract(U)); // expected-note at -1 {{because it is not a struct or class type}} } +namespace destructible { + +struct Incomplete; // expected-note {{forward declaration of 'destructible::Incomplete'}} +static_assert(__is_destructible(Incomplete)); +// expected-error at -1 {{incomplete type 'Incomplete' used in type trait expression}} + +static_assert(__is_destructible(void)); +// expected-error at -1 {{static assertion failed due to requirement '__is_destructible(void)'}} \ +// expected-note at -1 {{'void' is not destructible}} \ +// expected-note at -1 {{because it is a cv void type}} + +using F = void(); +static_assert(__is_destructible(F)); +// expected-error at -1 {{static assertion failed due to requirement '__is_destructible(void ())'}} \ +// expected-note at -1 {{'void ()' is not destructible}} \ +// expected-note at -1 {{because it is a function type}} + +using Ref = int&; +static_assert(__is_destructible(Ref)); // no diagnostics (true) + +struct DeletedDtor { // #d-DeletedDtor + ~DeletedDtor() = delete; +}; +static_assert(__is_destructible(DeletedDtor)); +// expected-error at -1 {{static assertion failed due to requirement '__is_destructible(destructible::DeletedDtor)'}} \ +// expected-note at -1 {{'destructible::DeletedDtor' is not destructible}} \ +// expected-note at -1 {{because it has a deleted destructor}} + +struct PrivateDtor { // #d-PrivateDtor +private: + ~PrivateDtor(); // #d-PrivateDtor-dtor +}; +static_assert(__is_destructible(PrivateDtor)); +// expected-error at -1 {{static assertion failed due to requirement '__is_destructible(destructible::PrivateDtor)'}} \ +// expected-note at -1 {{'destructible::PrivateDtor' is not destructible}} \ +// expected-note at -1 {{because it has a private destructor}} + +struct BaseInaccessible { // #d-BaseInacc +private: + ~BaseInaccessible(); // #d-BaseInacc-dtor +}; + +struct DerivedFromInaccessible : BaseInaccessible {}; // #d-DerivedInacc +static_assert(__is_destructible(DerivedFromInaccessible)); +// expected-error at -1 {{static assertion failed due to requirement '__is_destructible(destructible::DerivedFromInaccessible)'}} \ +// expected-note at -1 {{'destructible::DerivedFromInaccessible' is not destructible}} \ +// expected-note at -1 {{because it has a deleted destructor}} + +} From cfe-commits at lists.llvm.org Mon Nov 10 01:22:40 2025 From: cfe-commits at lists.llvm.org (via cfe-commits) Date: Mon, 10 Nov 2025 01:22:40 -0800 (PST) Subject: [clang] [Clang] Add diagnostic reasoning for unsatisfied is_destructible trait (PR #167291) In-Reply-To: Message-ID: <6911aee0.050a0220.1003b3.0911@mx.google.com> github-actions[bot] wrote: Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using `@` followed by their GitHub username. If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the [LLVM GitHub User Guide](https://llvm.org/docs/GitHub.html). You can also ask questions in a comment on this PR, on the [LLVM Discord](https://discord.com/invite/xS7Z362) or on the [forums](https://discourse.llvm.org/). https://github.com/llvm/llvm-project/pull/167291 From cfe-commits at lists.llvm.org Mon Nov 10 01:23:14 2025 From: cfe-commits at lists.llvm.org (via cfe-commits) Date: Mon, 10 Nov 2025 01:23:14 -0800 (PST) Subject: [clang] [Clang] Add diagnostic reasoning for unsatisfied is_destructible trait (PR #167291) In-Reply-To: Message-ID: <6911af02.a70a0220.1aaf77.2062@mx.google.com> llvmbot wrote: @llvm/pr-subscribers-clang Author: None (AnushaK6)
Changes This patch adds diagnostic reasoning for the std::is_destructible type trait in Clang’s Sema diagnostics, in response to issue #141911 It enables detailed “unsatisfied trait” messages when a type fails destructibility checks (e.g., void, function types, deleted/private destructors, incomplete types, etc). Changes: - Added DiagnoseNonDestructibleReason() to SemaTypeTraits.cpp - Integrated UTT_IsDestructible handling in Sema::DiagnoseTypeTraitDetails - Updated diagnostic notes in DiagnosticSemaKinds.td Added new tests to: - clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp - clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp --- Full diff: https://github.com/llvm/llvm-project/pull/167291.diff 4 Files Affected: - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+4-4) - (modified) clang/lib/Sema/SemaTypeTraits.cpp (+64) - (modified) clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp (+76) - (modified) clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp (+49) ``````````diff diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 3e864475f22a1..8fb76c2c989f5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1776,7 +1776,8 @@ def note_unsatisfied_trait "%StandardLayout{standard-layout}|" "%Aggregate{aggregate}|" "%Final{final}|" - "%Abstract{abstract}" + "%Abstract{abstract}|" + "%Destructible{destructible}" "}1">; def note_unsatisfied_trait_reason @@ -1808,6 +1809,7 @@ def note_unsatisfied_trait_reason "%NonStandardLayoutMember{has a non-standard-layout member %1 of type %2}|" "%IndirectBaseWithFields{has an indirect base %1 with data members}|" "%DeletedDtr{has a %select{deleted|user-provided}1 destructor}|" + "%InaccessibleDtr{has a %select{private|protected}1 destructor}|" "%UserProvidedCtr{has a user provided %select{copy|move}1 " "constructor}|" "%UserDeclaredCtr{has a user-declared constructor}|" @@ -1823,6 +1825,7 @@ def note_unsatisfied_trait_reason "%FunctionType{is a function type}|" "%CVVoidType{is a cv void type}|" "%IncompleteArrayType{is an incomplete array type}|" + "%IncompleteType{is an incomplete type}|" "%PrivateProtectedDirectDataMember{has a %select{private|protected}1 direct data member}|" "%PrivateProtectedDirectBase{has a %select{private|protected}1 direct base}|" "%NotClassOrUnion{is not a class or union type}|" @@ -12137,9 +12140,6 @@ def err_omp_unexpected_schedule_modifier : Error< "modifier '%0' cannot be used along with modifier '%1'">; def err_omp_schedule_nonmonotonic_static : Error< "'nonmonotonic' modifier can only be specified with 'dynamic' or 'guided' schedule kind">; -def err_omp_incompatible_dyn_groupprivate_modifier - : Error<"modifier '%0' cannot be used along with modifier '%1' in " - "dyn_groupprivate">; def err_omp_simple_clause_incompatible_with_ordered : Error< "'%0' clause with '%1' modifier cannot be specified if an 'ordered' clause is specified">; def err_omp_ordered_simd : Error< diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 38877967af05e..fef47dfc2cc51 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -2028,6 +2028,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { .Case("is_constructible", TypeTrait::TT_IsConstructible) .Case("is_final", TypeTrait::UTT_IsFinal) .Case("is_abstract", TypeTrait::UTT_IsAbstract) + .Case("is_destructible", TypeTrait::UTT_IsDestructible) .Default(std::nullopt); } @@ -2399,6 +2400,66 @@ static void DiagnoseNonConstructibleReason( SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonDestructibleReason(Sema &SemaRef, SourceLocation Loc, + QualType T) { + + QualType CoreT = T.getCanonicalType(); + if (const ArrayType *AT = SemaRef.Context.getAsArrayType(CoreT)) + CoreT = AT->getElementType(); + + SemaRef.Diag(Loc, diag::note_unsatisfied_trait) + << CoreT << diag::TraitName::Destructible; + + if (CoreT->isFunctionType()) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::FunctionType; + return; + } + + if (CoreT->isVoidType()) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::CVVoidType; + return; + } + + if (CoreT->isIncompleteType()) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::IncompleteType; + return; + } + + const CXXRecordDecl *RD = CoreT->getAsCXXRecordDecl(); + if (!RD || RD->isInvalidDecl()) + return; + + const CXXRecordDecl *Def = RD->getDefinition(); + if (!Def) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::IncompleteType; + return; + } + + CXXDestructorDecl *Dtor = Def->getDestructor(); + if (!Dtor) + return; + + if (Dtor->isDeleted()) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::DeletedDtr << 0 + << Dtor->getSourceRange(); + return; + } + + AccessSpecifier AS = Dtor->getAccess(); + if (AS == AS_private || AS == AS_protected) { + unsigned Select = (AS == AS_private) ? 0 : 1; + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::InaccessibleDtr << Select + << Dtor->getSourceRange(); + return; + } +} + static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, SourceLocation Loc, QualType T) { SemaRef.Diag(Loc, diag::note_unsatisfied_trait) @@ -2889,6 +2950,9 @@ void Sema::DiagnoseTypeTraitDetails(const Expr *E) { case TT_IsConstructible: DiagnoseNonConstructibleReason(*this, E->getBeginLoc(), Args); break; + case UTT_IsDestructible: + DiagnoseNonDestructibleReason(*this, E->getBeginLoc(), Args[0]); + break; case UTT_IsAggregate: DiagnoseNonAggregateReason(*this, E->getBeginLoc(), Args[0]); break; diff --git a/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp b/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp index 3e03a79275232..3e02fe8f10f56 100644 --- a/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp +++ b/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp @@ -73,6 +73,15 @@ struct is_abstract { template constexpr bool is_abstract_v = __is_abstract(T); +template +struct is_destructible { + static constexpr bool value = __is_destructible(T); +}; + +template +constexpr bool is_destructible_v = __is_destructible(T); + + #endif #ifdef STD2 @@ -167,6 +176,17 @@ using is_abstract = __details_is_abstract; template constexpr bool is_abstract_v = __is_abstract(T); +template +struct __details_is_destructible { + static constexpr bool value = __is_destructible(T); +}; + +template +using is_destructible = __details_is_destructible; + +template +constexpr bool is_destructible_v = __is_destructible(T); + #endif @@ -252,6 +272,15 @@ using is_abstract = __details_is_abstract; template constexpr bool is_abstract_v = is_abstract::value; +template +struct __details_is_destructible : bool_constant<__is_destructible(T)> {}; + +template +using is_destructible = __details_is_destructible; + +template +constexpr bool is_destructible_v = is_destructible::value; + #endif } @@ -374,6 +403,18 @@ static_assert(std::is_abstract_v); // expected-note at -1 {{because it is a reference type}} \ // expected-note at -1 {{because it is not a struct or class type}} +static_assert(std::is_destructible::value); + +static_assert(std::is_destructible::value); +// expected-error-re at -1 {{static assertion failed due to requirement 'std::{{.*}}is_destructible::value'}} \ +// expected-note at -1 {{'void' is not destructible}} \ +// expected-note at -1 {{because it is a cv void type}} + +static_assert(std::is_destructible_v); +// expected-error at -1 {{static assertion failed due to requirement 'std::is_destructible_v'}} \ +// expected-note at -1 {{'void' is not destructible}} \ +// expected-note at -1 {{because it is a cv void type}} + namespace test_namespace { using namespace std; @@ -473,6 +514,17 @@ namespace test_namespace { // expected-note at -1 {{'int &' is not abstract}} \ // expected-note at -1 {{because it is a reference type}} \ // expected-note at -1 {{because it is not a struct or class type}} + + static_assert(is_destructible::value); + // expected-error-re at -1 {{static assertion failed due to requirement '{{.*}}is_destructible::value'}} \ + // expected-note at -1 {{'void' is not destructible}} \ + // expected-note at -1 {{because it is a cv void type}} + + static_assert(is_destructible_v); + // expected-error at -1 {{static assertion failed due to requirement 'is_destructible_v'}} \ + // expected-note at -1 {{'void' is not destructible}} \ + // expected-note at -1 {{because it is a cv void type}} + } @@ -518,6 +570,15 @@ concept C5 = std::is_aggregate_v; // #concept10 template void g5(); // #cand10 +template +requires std::is_destructible::value void f6(); // #cand11 + +template +concept C6 = std::is_destructible_v; // #concept11 + +template void g6(); // #cand12 + + void test() { f(); // expected-error at -1 {{no matching function for call to 'f'}} \ @@ -589,6 +650,21 @@ void test() { // expected-note@#concept10 {{because 'std::is_aggregate_v' evaluated to false}} \ // expected-note@#concept10 {{'void' is not aggregate}} \ // expected-note@#concept10 {{because it is a cv void type}} + + f6(); + // expected-error at -1 {{no matching function for call to 'f6'}} \ + // expected-note@#cand11 {{candidate template ignored: constraints not satisfied [with T = void]}} \ + // expected-note-re@#cand11 {{because '{{.*}}is_destructible::value' evaluated to false}} \ + // expected-note@#cand11 {{'void' is not destructible}} \ + // expected-note@#cand11 {{because it is a cv void type}} + + g6(); + // expected-error at -1 {{no matching function for call to 'g6'}} \ + // expected-note@#cand12 {{candidate template ignored: constraints not satisfied [with T = void]}} \ + // expected-note@#cand12 {{because 'void' does not satisfy 'C6'}} \ + // expected-note@#concept11 {{because 'std::is_destructible_v' evaluated to false}} \ + // expected-note@#concept11 {{'void' is not destructible}} \ + // expected-note@#concept11 {{because it is a cv void type}} } } diff --git a/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp b/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp index 22740418f09f5..858a5cc24868f 100644 --- a/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp +++ b/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp @@ -1052,3 +1052,52 @@ static_assert(__is_abstract(U)); // expected-note at -1 {{because it is not a struct or class type}} } +namespace destructible { + +struct Incomplete; // expected-note {{forward declaration of 'destructible::Incomplete'}} +static_assert(__is_destructible(Incomplete)); +// expected-error at -1 {{incomplete type 'Incomplete' used in type trait expression}} + +static_assert(__is_destructible(void)); +// expected-error at -1 {{static assertion failed due to requirement '__is_destructible(void)'}} \ +// expected-note at -1 {{'void' is not destructible}} \ +// expected-note at -1 {{because it is a cv void type}} + +using F = void(); +static_assert(__is_destructible(F)); +// expected-error at -1 {{static assertion failed due to requirement '__is_destructible(void ())'}} \ +// expected-note at -1 {{'void ()' is not destructible}} \ +// expected-note at -1 {{because it is a function type}} + +using Ref = int&; +static_assert(__is_destructible(Ref)); // no diagnostics (true) + +struct DeletedDtor { // #d-DeletedDtor + ~DeletedDtor() = delete; +}; +static_assert(__is_destructible(DeletedDtor)); +// expected-error at -1 {{static assertion failed due to requirement '__is_destructible(destructible::DeletedDtor)'}} \ +// expected-note at -1 {{'destructible::DeletedDtor' is not destructible}} \ +// expected-note at -1 {{because it has a deleted destructor}} + +struct PrivateDtor { // #d-PrivateDtor +private: + ~PrivateDtor(); // #d-PrivateDtor-dtor +}; +static_assert(__is_destructible(PrivateDtor)); +// expected-error at -1 {{static assertion failed due to requirement '__is_destructible(destructible::PrivateDtor)'}} \ +// expected-note at -1 {{'destructible::PrivateDtor' is not destructible}} \ +// expected-note at -1 {{because it has a private destructor}} + +struct BaseInaccessible { // #d-BaseInacc +private: + ~BaseInaccessible(); // #d-BaseInacc-dtor +}; + +struct DerivedFromInaccessible : BaseInaccessible {}; // #d-DerivedInacc +static_assert(__is_destructible(DerivedFromInaccessible)); +// expected-error at -1 {{static assertion failed due to requirement '__is_destructible(destructible::DerivedFromInaccessible)'}} \ +// expected-note at -1 {{'destructible::DerivedFromInaccessible' is not destructible}} \ +// expected-note at -1 {{because it has a deleted destructor}} + +} ``````````
https://github.com/llvm/llvm-project/pull/167291 From cfe-commits at lists.llvm.org Mon Nov 10 01:26:23 2025 From: cfe-commits at lists.llvm.org (Yanzuo Liu via cfe-commits) Date: Mon, 10 Nov 2025 01:26:23 -0800 (PST) Subject: [clang] [BoundsSafety] build TypeLoc for CountAttributedType (PR #167287) In-Reply-To: Message-ID: <6911afbf.170a0220.36db77.ecf5@mx.google.com> ================ @@ -253,20 +319,36 @@ static void EmitIncompleteCountedByPointeeNotes(Sema &S, << CATy->getPointeeType(); } - // Suggest using __sized_by(_or_null) instead of __counted_by(_or_null) as - // __sized_by(_or_null) doesn't have the complete type restriction. - // - // We use the source range of the expression on the CountAttributedType as an - // approximation for the source range of the attribute. This isn't quite right - // but isn't easy to fix right now. - // - // TODO: Implement logic to find the relevant TypeLoc for the attribute and - // get the SourceRange from that (#113582). - // - // TODO: We should emit a fix-it here. - SourceRange AttrSrcRange = CATy->getCountExpr()->getSourceRange(); + CountAttributedTypeLoc CATL; + if (!TL.isNull()) + CATL = TL.getAs(); + + if (CATL.isNull()) { + // Fall back to pointing to the count expr - not great, but close enough. + // This should happen rarely, if ever. + S.Diag(CATy->getCountExpr()->getExprLoc(), + diag::note_counted_by_consider_using_sized_by) + << CATy->isOrNull(); + return; + } + SourceRange AttrSrcRange = CATL.getAttrNameRange(S); + + StringRef Spelling = CATL.getAttrNameAsWritten(S); + StringRef FixedSpelling; + if (Spelling == "__counted_by") + FixedSpelling = "__sized_by"; + else if (Spelling == "counted_by") + FixedSpelling = "sized_by"; + else if (Spelling == "__counted_by_or_null") + FixedSpelling = "__sized_by_or_null"; + else if (Spelling == "counted_by_or_null") + FixedSpelling = "sized_by_or_null"; ---------------- zwuis wrote: Can we use `llvm::StringSwitch`? https://github.com/llvm/llvm-project/pull/167287 From cfe-commits at lists.llvm.org Mon Nov 10 01:36:37 2025 From: cfe-commits at lists.llvm.org (via cfe-commits) Date: Mon, 10 Nov 2025 01:36:37 -0800 (PST) Subject: [clang] [llvm] [Clang] Add diagnostic reasoning for unsatisfied is_destructible trait (PR #166967) In-Reply-To: Message-ID: <6911b225.050a0220.350bcf.1b2b@mx.google.com> AnushaK6 wrote: Thank you for catching that! I was working on a different issue and accidentally pushed those commits to the same branch. Sincere apologies for the oversight. I've raised a new PR with the correct changes for this issue [here](https://github.com/llvm/llvm-project/pull/167291) https://github.com/llvm/llvm-project/pull/166967 From cfe-commits at lists.llvm.org Mon Nov 10 01:37:34 2025 From: cfe-commits at lists.llvm.org (=?UTF-8?Q?Thorsten_Bla=C3=9F?= via cfe-commits) Date: Mon, 10 Nov 2025 01:37:34 -0800 (PST) Subject: [clang] [AMDGPU][clang] Fix clang driver check for multiple sanitizer arguments (PR #166851) In-Reply-To: Message-ID: <6911b25e.170a0220.2c641b.bc3a@mx.google.com> ThorBl wrote: > Is this supposed to be a warning or an error. Personally I think the user should be able to do stuff like `-Xarch_host -fsanitize=a,b,c -Xarch_device -fsanitize=address` since we only support one. Seems a little unintuitive to just ignore things requested by the user just because we can't handle them. That's a good point. I think if the user applies -fsanitize options generically, a warning is appropriate. This informs them that some sanitizers aren’t supported on the device, but the build can still proceed for the host. However, if the user explicitly targets the device with unsupported sanitizers (e.g., using -Xarch_device), an error would be more appropriate to avoid confusion. A balanced approach would be to warn for implicitly routed unsupported sanitizers, but error out when the user explicitly requests them for the device. https://github.com/llvm/llvm-project/pull/166851 From cfe-commits at lists.llvm.org Mon Nov 10 01:40:48 2025 From: cfe-commits at lists.llvm.org (via cfe-commits) Date: Mon, 10 Nov 2025 01:40:48 -0800 (PST) Subject: [clang-tools-extra] [clang-tidy][NFC] Add `.editorconfig` for `.rst` files (PR #167269) In-Reply-To: Message-ID: <6911b320.050a0220.3648f8.40a3@mx.google.com> ================ @@ -0,0 +1,8 @@ +[clang-tidy/checks/**/*.rst] ---------------- zeyi2 wrote: It will work, I'll move it to that folder :) https://github.com/llvm/llvm-project/pull/167269 From cfe-commits at lists.llvm.org Mon Nov 10 01:49:12 2025 From: cfe-commits at lists.llvm.org (Henrik G. Olsson via cfe-commits) Date: Mon, 10 Nov 2025 01:49:12 -0800 (PST) Subject: [clang] [BoundsSafety] build TypeLoc for CountAttributedType (PR #167287) In-Reply-To: Message-ID: <6911b518.170a0220.7c4e5.f2a2@mx.google.com> https://github.com/hnrklssn updated https://github.com/llvm/llvm-project/pull/167287 >From 8804ce91e34c60bea50c8adaf516204fb8680a00 Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Sun, 9 Nov 2025 19:01:09 -0800 Subject: [PATCH 1/4] [BoundsSafety] build TypeLoc for CountAttributedType This adds attribute SourceRange to CountAttributedTypeLoc and populates it. The following commit will change diagnostics to use this information. Fixes https://github.com/llvm/llvm-project/issues/113582 --- clang/include/clang/AST/TypeLoc.h | 17 +++++++++++------ clang/lib/AST/TypeLoc.cpp | 4 ---- clang/lib/Sema/SemaDeclAttr.cpp | 9 +++++++++ 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h index 2cefaa9611c98..2999c086af3b6 100644 --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -19,6 +19,7 @@ #include "clang/AST/NestedNameSpecifierBase.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TypeBase.h" +#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" @@ -1303,7 +1304,9 @@ class ObjCInterfaceTypeLoc : public ConcreteTypeLoc { @@ -1311,10 +1314,14 @@ class BoundsAttributedTypeLoc TypeLoc getInnerLoc() const { return getInnerTypeLoc(); } QualType getInnerType() const { return getTypePtr()->desugar(); } void initializeLocal(ASTContext &Context, SourceLocation Loc) { - // nothing to do + setAttrRange({Loc, Loc}); + } + void setAttrRange(SourceRange Range) { + getLocalData()->Range = Range; } - // LocalData is empty and TypeLocBuilder doesn't handle DataSize 1. - unsigned getLocalDataSize() const { return 0; } + SourceRange getAttrRange() const { return getLocalData()->Range; } + + unsigned getLocalDataSize() const { return sizeof(BoundsAttributedLocInfo); } }; class CountAttributedTypeLoc final @@ -1325,8 +1332,6 @@ class CountAttributedTypeLoc final Expr *getCountExpr() const { return getTypePtr()->getCountExpr(); } bool isCountInBytes() const { return getTypePtr()->isCountInBytes(); } bool isOrNull() const { return getTypePtr()->isOrNull(); } - - SourceRange getLocalSourceRange() const; }; struct MacroQualifiedLocInfo { diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp index f54ccf0932bc7..66f9e3c67df84 100644 --- a/clang/lib/AST/TypeLoc.cpp +++ b/clang/lib/AST/TypeLoc.cpp @@ -590,10 +590,6 @@ SourceRange AttributedTypeLoc::getLocalSourceRange() const { return getAttr() ? getAttr()->getRange() : SourceRange(); } -SourceRange CountAttributedTypeLoc::getLocalSourceRange() const { - return getCountExpr() ? getCountExpr()->getSourceRange() : SourceRange(); -} - SourceRange BTFTagAttributedTypeLoc::getLocalSourceRange() const { return getAttr() ? getAttr()->getRange() : SourceRange(); } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index a9e7b44ac9d73..1753261822755 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -10,10 +10,12 @@ // //===----------------------------------------------------------------------===// +#include "TypeLocBuilder.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" +#include "clang/AST/Attr.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" @@ -24,6 +26,8 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/Mangle.h" #include "clang/AST/Type.h" +#include "clang/AST/TypeBase.h" +#include "clang/AST/TypeLoc.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/Cuda.h" #include "clang/Basic/DarwinSDKInfo.h" @@ -6580,9 +6584,14 @@ static void handleCountedByAttrField(Sema &S, Decl *D, const ParsedAttr &AL) { if (S.CheckCountedByAttrOnField(FD, CountExpr, CountInBytes, OrNull)) return; + TypeLocBuilder TLB; QualType CAT = S.BuildCountAttributedArrayOrPointerType( FD->getType(), CountExpr, CountInBytes, OrNull); + TLB.pushFullCopy(FD->getTypeSourceInfo()->getTypeLoc()); + CountAttributedTypeLoc CATL = TLB.push(CAT); + CATL.setAttrRange(AL.getRange()); FD->setType(CAT); + FD->setTypeSourceInfo(TLB.getTypeSourceInfo(S.getASTContext(), CAT)); } static void handleFunctionReturnThunksAttr(Sema &S, Decl *D, >From e92dd11798bc3dea17cff61f0ebf185099671d8a Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Sun, 9 Nov 2025 23:32:45 -0800 Subject: [PATCH 2/4] [BoundsSafety] get counted_by spelling from source range This replaces the count expr source location used for note_counted_by_consider_using_sized_by with the actual attribute location fetched from TypeLof, except in the rare case where we couldn't find a TypeLoc. It also attaches a fix-it hint, now that we have the proper source range. Fixes https://github.com/llvm/llvm-project/issues/113585 --- clang/include/clang/AST/TypeLoc.h | 4 + clang/lib/Sema/SemaBoundsSafety.cpp | 121 ++++++++++++++++++++++++---- 2 files changed, 109 insertions(+), 16 deletions(-) diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h index 2999c086af3b6..0cf17c463d6cd 100644 --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -1304,6 +1304,7 @@ class ObjCInterfaceTypeLoc : public ConcreteTypeLocRange; } + StringRef getAttrNameAsWritten(Sema &S) const; + SourceRange getAttrNameRange(Sema &S) const; + unsigned getLocalDataSize() const { return sizeof(BoundsAttributedLocInfo); } }; diff --git a/clang/lib/Sema/SemaBoundsSafety.cpp b/clang/lib/Sema/SemaBoundsSafety.cpp index de9adf8ef5a1b..a699c9d116b15 100644 --- a/clang/lib/Sema/SemaBoundsSafety.cpp +++ b/clang/lib/Sema/SemaBoundsSafety.cpp @@ -11,6 +11,14 @@ /// (e.g. `counted_by`) /// //===----------------------------------------------------------------------===// +#include "clang/AST/Decl.h" +#include "clang/AST/Expr.h" +#include "clang/AST/StmtVisitor.h" +#include "clang/AST/TypeBase.h" +#include "clang/AST/TypeLoc.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" #include "clang/Lex/Lexer.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Sema.h" @@ -231,9 +239,69 @@ bool Sema::CheckCountedByAttrOnField(FieldDecl *FD, Expr *E, bool CountInBytes, return false; } +// FIXME: for some reason diagnostics highlight the end character, while +// getSourceText() does not include the end character. +static SourceRange getAttrNameRangeImpl(Sema &S, SourceLocation Begin, + bool IsForDiagnostics) { + SourceManager &SM = S.getSourceManager(); + SourceLocation TokenStart = Begin; + while (TokenStart.isMacroID()) + TokenStart = SM.getImmediateExpansionRange(TokenStart).getBegin(); + unsigned Offset = IsForDiagnostics ? 1 : 0; + SourceLocation End = S.getLocForEndOfToken(TokenStart, Offset); + return {TokenStart, End}; +} + +StringRef BoundsAttributedTypeLoc::getAttrNameAsWritten(Sema &S) const { + SourceRange Range = getAttrNameRangeImpl(S, getAttrRange().getBegin(), false); + CharSourceRange NameRange = CharSourceRange::getCharRange(Range); + return Lexer::getSourceText(NameRange, S.getSourceManager(), S.getLangOpts()); +} + +SourceRange BoundsAttributedTypeLoc::getAttrNameRange(Sema &S) const { + return getAttrNameRangeImpl(S, getAttrRange().getBegin(), true); +} + +static TypeSourceInfo *getTSI(const Decl *D) { + if (const auto* DD = dyn_cast(D)) { + return DD->getTypeSourceInfo(); + } + return nullptr; +} + +struct TypeLocFinder : public ConstStmtVisitor { + TypeLoc VisitParenExpr(const ParenExpr* E) { + return Visit(E->getSubExpr()); + } + + TypeLoc VisitDeclRefExpr(const DeclRefExpr *E) { + return getTSI(E->getDecl())->getTypeLoc(); + } + + TypeLoc VisitMemberExpr(const MemberExpr *E) { + return getTSI(E->getMemberDecl())->getTypeLoc(); + } + + TypeLoc VisitExplicitCastExpr(const ExplicitCastExpr *E) { + return E->getTypeInfoAsWritten()->getTypeLoc(); + } + + TypeLoc VisitCallExpr(const CallExpr *E) { + if (const auto *D = E->getCalleeDecl()) { + FunctionTypeLoc FTL = getTSI(D)->getTypeLoc().getAs(); + if (FTL.isNull()) { + return FTL; + } + return FTL.getReturnLoc(); + } + return {}; + } +}; + static void EmitIncompleteCountedByPointeeNotes(Sema &S, const CountAttributedType *CATy, - NamedDecl *IncompleteTyDecl) { + NamedDecl *IncompleteTyDecl, + TypeLoc TL) { assert(IncompleteTyDecl == nullptr || isa(IncompleteTyDecl)); if (IncompleteTyDecl) { @@ -253,20 +321,36 @@ static void EmitIncompleteCountedByPointeeNotes(Sema &S, << CATy->getPointeeType(); } - // Suggest using __sized_by(_or_null) instead of __counted_by(_or_null) as - // __sized_by(_or_null) doesn't have the complete type restriction. - // - // We use the source range of the expression on the CountAttributedType as an - // approximation for the source range of the attribute. This isn't quite right - // but isn't easy to fix right now. - // - // TODO: Implement logic to find the relevant TypeLoc for the attribute and - // get the SourceRange from that (#113582). - // - // TODO: We should emit a fix-it here. - SourceRange AttrSrcRange = CATy->getCountExpr()->getSourceRange(); + CountAttributedTypeLoc CATL; + if (!TL.isNull()) + CATL = TL.getAs(); + + if (CATL.isNull()) { + // Fall back to pointing to the count expr - not great, but close enough. + // This should happen rarely, if ever. + S.Diag(CATy->getCountExpr()->getExprLoc(), + diag::note_counted_by_consider_using_sized_by) + << CATy->isOrNull(); + return; + } + SourceRange AttrSrcRange = CATL.getAttrNameRange(S); + + StringRef Spelling = CATL.getAttrNameAsWritten(S); + StringRef FixedSpelling; + if (Spelling == "__counted_by") + FixedSpelling = "__sized_by"; + else if (Spelling == "counted_by") + FixedSpelling = "sized_by"; + else if (Spelling == "__counted_by_or_null") + FixedSpelling = "__sized_by_or_null"; + else if (Spelling == "counted_by_or_null") + FixedSpelling = "sized_by_or_null"; + FixItHint Fix; + if (!FixedSpelling.empty()) + Fix = FixItHint::CreateReplacement(AttrSrcRange, FixedSpelling); + S.Diag(AttrSrcRange.getBegin(), diag::note_counted_by_consider_using_sized_by) - << CATy->isOrNull() << AttrSrcRange; + << CATy->isOrNull() << AttrSrcRange << Fix; } static std::tuple @@ -335,7 +419,11 @@ static bool CheckAssignmentToCountAttrPtrWithIncompletePointeeTy( << CATy->getAttributeName(/*WithMacroPrefix=*/true) << PointeeTy << CATy->isOrNull() << RHSExpr->getSourceRange(); - EmitIncompleteCountedByPointeeNotes(S, CATy, IncompleteTyDecl); + TypeLoc TL; + if (TypeSourceInfo *TSI = getTSI(Assignee)) + TL = TSI->getTypeLoc(); + + EmitIncompleteCountedByPointeeNotes(S, CATy, IncompleteTyDecl, TL); return false; // check failed } @@ -408,7 +496,8 @@ bool Sema::BoundsSafetyCheckUseOfCountAttrPtr(const Expr *E) { << CATy->getAttributeName(/*WithMacroPrefix=*/true) << CATy->isOrNull() << E->getSourceRange(); - EmitIncompleteCountedByPointeeNotes(*this, CATy, IncompleteTyDecl); + TypeLoc TL = TypeLocFinder().Visit(E); + EmitIncompleteCountedByPointeeNotes(*this, CATy, IncompleteTyDecl, TL); return false; } >From f38fc71ea77911e9f227411ebf161e51c34237f8 Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Sun, 9 Nov 2025 23:57:37 -0800 Subject: [PATCH 3/4] format --- clang/include/clang/AST/TypeLoc.h | 4 +--- clang/lib/Sema/SemaBoundsSafety.cpp | 6 ++---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h index 0cf17c463d6cd..24373361f68ca 100644 --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -1317,9 +1317,7 @@ class BoundsAttributedTypeLoc void initializeLocal(ASTContext &Context, SourceLocation Loc) { setAttrRange({Loc, Loc}); } - void setAttrRange(SourceRange Range) { - getLocalData()->Range = Range; - } + void setAttrRange(SourceRange Range) { getLocalData()->Range = Range; } SourceRange getAttrRange() const { return getLocalData()->Range; } StringRef getAttrNameAsWritten(Sema &S) const; diff --git a/clang/lib/Sema/SemaBoundsSafety.cpp b/clang/lib/Sema/SemaBoundsSafety.cpp index a699c9d116b15..befef566f01da 100644 --- a/clang/lib/Sema/SemaBoundsSafety.cpp +++ b/clang/lib/Sema/SemaBoundsSafety.cpp @@ -263,16 +263,14 @@ SourceRange BoundsAttributedTypeLoc::getAttrNameRange(Sema &S) const { } static TypeSourceInfo *getTSI(const Decl *D) { - if (const auto* DD = dyn_cast(D)) { + if (const auto *DD = dyn_cast(D)) { return DD->getTypeSourceInfo(); } return nullptr; } struct TypeLocFinder : public ConstStmtVisitor { - TypeLoc VisitParenExpr(const ParenExpr* E) { - return Visit(E->getSubExpr()); - } + TypeLoc VisitParenExpr(const ParenExpr *E) { return Visit(E->getSubExpr()); } TypeLoc VisitDeclRefExpr(const DeclRefExpr *E) { return getTSI(E->getDecl())->getTypeLoc(); >From aef6bc4e23f3fba898269ad6b4c2a3551a4698ec Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" Date: Mon, 10 Nov 2025 01:44:30 -0800 Subject: [PATCH 4/4] if-else -> StringSwitch --- clang/lib/Sema/SemaBoundsSafety.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/clang/lib/Sema/SemaBoundsSafety.cpp b/clang/lib/Sema/SemaBoundsSafety.cpp index befef566f01da..5d123228b200a 100644 --- a/clang/lib/Sema/SemaBoundsSafety.cpp +++ b/clang/lib/Sema/SemaBoundsSafety.cpp @@ -23,6 +23,8 @@ #include "clang/Sema/Initialization.h" #include "clang/Sema/Sema.h" +#include "llvm/ADT/StringSwitch.h" + namespace clang { static CountAttributedType::DynamicCountPointerKind @@ -334,15 +336,13 @@ static void EmitIncompleteCountedByPointeeNotes(Sema &S, SourceRange AttrSrcRange = CATL.getAttrNameRange(S); StringRef Spelling = CATL.getAttrNameAsWritten(S); - StringRef FixedSpelling; - if (Spelling == "__counted_by") - FixedSpelling = "__sized_by"; - else if (Spelling == "counted_by") - FixedSpelling = "sized_by"; - else if (Spelling == "__counted_by_or_null") - FixedSpelling = "__sized_by_or_null"; - else if (Spelling == "counted_by_or_null") - FixedSpelling = "sized_by_or_null"; + StringRef FixedSpelling = + llvm::StringSwitch(Spelling) + .Case("__counted_by", "__sized_by") + .Case("counted_by", "sized_by") + .Case("__counted_by_or_null", "__sized_by_or_null") + .Case("counted_by_or_null", "sized_by_or_null") + .Default(""); FixItHint Fix; if (!FixedSpelling.empty()) Fix = FixItHint::CreateReplacement(AttrSrcRange, FixedSpelling); From cfe-commits at lists.llvm.org Mon Nov 10 01:49:41 2025 From: cfe-commits at lists.llvm.org (Henrik G. Olsson via cfe-commits) Date: Mon, 10 Nov 2025 01:49:41 -0800 (PST) Subject: [clang] [BoundsSafety] build TypeLoc for CountAttributedType (PR #167287) In-Reply-To: Message-ID: <6911b535.050a0220.5edc1.3136@mx.google.com> ================ @@ -253,20 +319,36 @@ static void EmitIncompleteCountedByPointeeNotes(Sema &S, << CATy->getPointeeType(); } - // Suggest using __sized_by(_or_null) instead of __counted_by(_or_null) as - // __sized_by(_or_null) doesn't have the complete type restriction. - // - // We use the source range of the expression on the CountAttributedType as an - // approximation for the source range of the attribute. This isn't quite right - // but isn't easy to fix right now. - // - // TODO: Implement logic to find the relevant TypeLoc for the attribute and - // get the SourceRange from that (#113582). - // - // TODO: We should emit a fix-it here. - SourceRange AttrSrcRange = CATy->getCountExpr()->getSourceRange(); + CountAttributedTypeLoc CATL; + if (!TL.isNull()) + CATL = TL.getAs(); + + if (CATL.isNull()) { + // Fall back to pointing to the count expr - not great, but close enough. + // This should happen rarely, if ever. + S.Diag(CATy->getCountExpr()->getExprLoc(), + diag::note_counted_by_consider_using_sized_by) + << CATy->isOrNull(); + return; + } + SourceRange AttrSrcRange = CATL.getAttrNameRange(S); + + StringRef Spelling = CATL.getAttrNameAsWritten(S); + StringRef FixedSpelling; + if (Spelling == "__counted_by") + FixedSpelling = "__sized_by"; + else if (Spelling == "counted_by") + FixedSpelling = "sized_by"; + else if (Spelling == "__counted_by_or_null") + FixedSpelling = "__sized_by_or_null"; + else if (Spelling == "counted_by_or_null") + FixedSpelling = "sized_by_or_null"; ---------------- hnrklssn wrote: done! https://github.com/llvm/llvm-project/pull/167287 From cfe-commits at lists.llvm.org Mon Nov 10 01:50:55 2025 From: cfe-commits at lists.llvm.org (Henrik G. Olsson via cfe-commits) Date: Mon, 10 Nov 2025 01:50:55 -0800 (PST) Subject: [clang] [BoundsSafety] build TypeLoc for CountAttributedType (PR #167287) In-Reply-To: Message-ID: <6911b57f.170a0220.2b022f.99df@mx.google.com> hnrklssn wrote: Just found out about `-fdiagnostics-print-source-range-info`. I'll add some test cases for source ranges & fix-its tomorrow. https://github.com/llvm/llvm-project/pull/167287 From cfe-commits at lists.llvm.org Mon Nov 10 01:55:51 2025 From: cfe-commits at lists.llvm.org (via cfe-commits) Date: Mon, 10 Nov 2025 01:55:51 -0800 (PST) Subject: [clang-tools-extra] [clang-tidy][NFC] Add `.editorconfig` for `.rst` files (PR #167269) In-Reply-To: Message-ID: <6911b6a7.170a0220.1df318.8a4f@mx.google.com> ================ @@ -0,0 +1,8 @@ +[clang-tidy/checks/**/*.rst] ---------------- zeyi2 wrote: > Instead of this path, could we just place it in `clang-tool-extra/docs/clang-tidy/checks/`? Will it work like that? Also, should we apply these checks to `list.rst`? The 80 chars limitation may require a lot of refactoring for this file. https://github.com/llvm/llvm-project/pull/167269 From cfe-commits at lists.llvm.org Mon Nov 10 01:56:58 2025 From: cfe-commits at lists.llvm.org (Sergej Salnikov via cfe-commits) Date: Mon, 10 Nov 2025 01:56:58 -0800 (PST) Subject: [clang] [clang][SourceManager] Use `getFileLoc` when computing `getPresumedLoc` (PR #166255) In-Reply-To: Message-ID: <6911b6ea.170a0220.3b8af9.fd4a@mx.google.com> SergejSalnikov wrote: Gentle ping. https://github.com/llvm/llvm-project/pull/166255 From cfe-commits at lists.llvm.org Mon Nov 10 01:57:22 2025 From: cfe-commits at lists.llvm.org (LLVM Continuous Integration via cfe-commits) Date: Mon, 10 Nov 2025 01:57:22 -0800 (PST) Subject: [clang-tools-extra] [clang-tidy] Rename 'cert-err60-cpp' to 'bugprone-exception-copy-constructor-throws' (PR #164061) In-Reply-To: Message-ID: <6911b702.170a0220.2b022f.9aa9@mx.google.com> llvm-ci wrote: LLVM Buildbot has detected a new failure on builder `llvm-clang-x86_64-darwin` running on `doug-worker-3` while building `clang-tools-extra` at step 6 "test-build-unified-tree-check-all". Full details are available at: https://lab.llvm.org/buildbot/#/builders/23/builds/15413
Here is the relevant piece of the build log for the reference ``` Step 6 (test-build-unified-tree-check-all) failure: test (failure) ******************** TEST 'Clang :: Driver/x86-target-features.c' FAILED ******************** Exit Code: 127 Command Output (stdout): -- # RUN: at line 1 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/clang --target=i386 -march=i386 -mx87 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c -### 2>&1 | /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/FileCheck -check-prefix=X87 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c # executed command: /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/clang --target=i386 -march=i386 -mx87 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c '-###' # note: command had no output on stdout or stderr # executed command: /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/FileCheck -check-prefix=X87 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c # note: command had no output on stdout or stderr # RUN: at line 2 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/clang --target=i386 -march=i386 -mno-x87 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c -### 2>&1 | /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/FileCheck -check-prefix=NO-X87 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c # executed command: /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/clang --target=i386 -march=i386 -mno-x87 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c '-###' # note: command had no output on stdout or stderr # executed command: /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/FileCheck -check-prefix=NO-X87 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c # note: command had no output on stdout or stderr # RUN: at line 3 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/clang --target=i386 -march=i386 -m80387 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c -### 2>&1 | /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/FileCheck -check-prefix=X87 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c # executed command: /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/clang --target=i386 -march=i386 -m80387 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c '-###' # note: command had no output on stdout or stderr # executed command: /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/FileCheck -check-prefix=X87 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c # note: command had no output on stdout or stderr # RUN: at line 4 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/clang --target=i386 -march=i386 -mno-80387 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c -### 2>&1 | /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/FileCheck -check-prefix=NO-X87 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c # executed command: /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/clang --target=i386 -march=i386 -mno-80387 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c '-###' # note: command had no output on stdout or stderr # executed command: /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/FileCheck -check-prefix=NO-X87 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c # note: command had no output on stdout or stderr # RUN: at line 5 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/clang --target=i386 -march=i386 -mno-fp-ret-in-387 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c -### 2>&1 | /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/FileCheck -check-prefix=NO-X87 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c # executed command: /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/clang --target=i386 -march=i386 -mno-fp-ret-in-387 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c '-###' # note: command had no output on stdout or stderr # executed command: /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/FileCheck -check-prefix=NO-X87 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c # note: command had no output on stdout or stderr # RUN: at line 9 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/clang --target=i386 -march=i386 -mmmx -m3dnow -m3dnowa /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c -### 2>&1 | /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/FileCheck -check-prefix=MMX /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c # executed command: /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/clang --target=i386 -march=i386 -mmmx -m3dnow -m3dnowa /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c '-###' # note: command had no output on stdout or stderr # executed command: /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/FileCheck -check-prefix=MMX /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c # note: command had no output on stdout or stderr # RUN: at line 10 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/clang --target=i386 -march=i386 -mno-mmx -mno-3dnow -mno-3dnowa /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c -### 2>&1 | /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/FileCheck -check-prefix=NO-MMX /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c # executed command: /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/clang --target=i386 -march=i386 -mno-mmx -mno-3dnow -mno-3dnowa /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c '-###' # note: command had no output on stdout or stderr # executed command: /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/FileCheck -check-prefix=NO-MMX /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c # note: command had no output on stdout or stderr # RUN: at line 19 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/clang --target=i386 -march=i386 -msse -msse2 -msse3 -mssse3 -msse4a -msse4.1 -msse4.2 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c -### 2>&1 | /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/FileCheck -check-prefix=SSE /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c # executed command: /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/bin/clang --target=i386 -march=i386 -msse -msse2 -msse3 -mssse3 -msse4a -msse4.1 -msse4.2 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/llvm-project/clang/test/Driver/x86-target-features.c '-###' ... ```
https://github.com/llvm/llvm-project/pull/164061