https://github.com/PrabbyDD updated https://github.com/llvm/llvm-project/pull/195945
>From 36ce4b83c0c674cdc6439f49a90c59ee5bdc613a Mon Sep 17 00:00:00 2001 From: PrabbyDD <[email protected]> Date: Tue, 5 May 2026 14:16:55 -0700 Subject: [PATCH 1/5] Fix crash by checking for the type signage before entering getCorrespondingSignedType() --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/SemaExpr.cpp | 18 +++++++++++------- clang/test/Sema/va_arg_enum_underlying.cpp | 15 +++++++++++++++ 3 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 clang/test/Sema/va_arg_enum_underlying.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index ec64c2008d89b..f01a73739d8e0 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -519,6 +519,7 @@ Bug Fixes in This Version - Clang now emits an error for friend declarations of lambda members. (#GH26540) - Fixed a crash caused by lambda capture handling in delayed default arguments. (#GH176534) - Fixed a crash when parsing invalid ``static_assert`` declarations with string-literal messages (#GH187690). +- Fixed an assert/crash in ``__builtin_va_arg`` when the argument type is an enum without a correspoding signed type (#GH191698). Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index c494669420282..2712acb0d0936 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -17314,13 +17314,17 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, if (!PromoteType.isNull() && !UnderlyingType->isBooleanType() && PromoteType->isUnsignedIntegerType() != UnderlyingType->isUnsignedIntegerType()) { - UnderlyingType = - UnderlyingType->isUnsignedIntegerType() - ? Context.getCorrespondingSignedType(UnderlyingType) - : Context.getCorrespondingUnsignedType(UnderlyingType); - if (Context.typesAreCompatible(PromoteType, UnderlyingType, - /*CompareUnqualified*/ true)) - PromoteType = QualType(); + + if (!UnderlyingType->isUnsignedIntegerType() || + UnderlyingType->hasSignedIntegerRepresentation()) { + UnderlyingType = + UnderlyingType->isUnsignedIntegerType() + ? Context.getCorrespondingSignedType(UnderlyingType) + : Context.getCorrespondingUnsignedType(UnderlyingType); + if (Context.typesAreCompatible(PromoteType, UnderlyingType, + /*CompareUnqualified*/ true)) + PromoteType = QualType(); + } } } if (TInfo->getType()->isSpecificBuiltinType(BuiltinType::Float)) diff --git a/clang/test/Sema/va_arg_enum_underlying.cpp b/clang/test/Sema/va_arg_enum_underlying.cpp new file mode 100644 index 0000000000000..e4962f4e1326e --- /dev/null +++ b/clang/test/Sema/va_arg_enum_underlying.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +__builtin_va_list ap; + +void foo() { + enum E1 : char16_t {}; + enum E2 : char32_t {}; + enum E3 : unsigned char {}; + enum E4 : wchar_t {}; + + (void)__builtin_va_arg(ap, E1); // expected-warning {{second argument to 'va_arg' is of promotable type}} + (void)__builtin_va_arg(ap, E2); // expected-warning {{second argument to 'va_arg' is of promotable type}} + (void)__builtin_va_arg(ap, E3); // expected-warning {{second argument to 'va_arg' is of promotable type}} + (void)__builtin_va_arg(ap, E4); // expected-warning {{second argument to 'va_arg' is of promotable type}} +} >From 14b664ec4a3b1251679b71c93f3eca3e37168d8f Mon Sep 17 00:00:00 2001 From: PrabbyDD <[email protected]> Date: Tue, 5 May 2026 14:46:42 -0700 Subject: [PATCH 2/5] adding an expected warning to varargs test since we now emit that --- clang/test/SemaCXX/varargs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/SemaCXX/varargs.cpp b/clang/test/SemaCXX/varargs.cpp index 1e5920a8728d3..c84d765296e88 100644 --- a/clang/test/SemaCXX/varargs.cpp +++ b/clang/test/SemaCXX/varargs.cpp @@ -31,7 +31,7 @@ void record_context(int a, ...) { // Ensure the correct behavior for promotable type UB checking. void promotable(int a, ...) { enum Unscoped1 { One = 0x7FFFFFFF }; - (void)__builtin_va_arg(ap, Unscoped1); // ok + (void)__builtin_va_arg(ap, Unscoped1); // expected-warning {{second argument to 'va_arg' is of promotable type}} enum Unscoped2 { Two = 0xFFFFFFFF }; (void)__builtin_va_arg(ap, Unscoped2); // ok >From f7d982d99aca247f7bb5cb0f9d58cde25d82a985 Mon Sep 17 00:00:00 2001 From: PrabbyDD <[email protected]> Date: Wed, 6 May 2026 14:20:16 -0700 Subject: [PATCH 3/5] hard guarding against the problematic types...and reverting expected warning in varargs test. --- clang/lib/Sema/SemaExpr.cpp | 58 +++++++++++++++++++--------------- clang/test/SemaCXX/varargs.cpp | 2 +- 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 2712acb0d0936..ac60fe19afb58 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -12521,28 +12521,6 @@ static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc, AlwaysEqual, // std::strong_ordering::equal from operator<=> }; - // C++1a [array.comp]: - // Equality and relational comparisons ([expr.eq], [expr.rel]) between two - // operands of array type. - // C++2a [depr.array.comp]: - // Equality and relational comparisons ([expr.eq], [expr.rel]) between two - // operands of array type are deprecated. - if (S.getLangOpts().CPlusPlus && LHSStripped->getType()->isArrayType() && - RHSStripped->getType()->isArrayType()) { - auto IsDeprArrayComparionIgnored = - S.getDiagnostics().isIgnored(diag::warn_depr_array_comparison, Loc); - auto DiagID = S.getLangOpts().CPlusPlus26 - ? diag::warn_array_comparison_cxx26 - : !S.getLangOpts().CPlusPlus20 || IsDeprArrayComparionIgnored - ? diag::warn_array_comparison - : diag::warn_depr_array_comparison; - S.Diag(Loc, DiagID) << LHS->getSourceRange() << RHS->getSourceRange() - << LHSStripped->getType() << RHSStripped->getType(); - // Carry on to produce the tautological comparison warning, if this - // expression is potentially-evaluated, we can resolve the array to a - // non-weak declaration, and so on. - } - if (!LHS->getBeginLoc().isMacroID() && !RHS->getBeginLoc().isMacroID()) { if (Expr::isSameComparisonOperand(LHS, RHS)) { unsigned Result; @@ -12860,6 +12838,31 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, return Ty->isPointerType() || Ty->isMemberPointerType(); }; + // C++1a [array.comp]: + // Equality and relational comparisons ([expr.eq], [expr.rel]) between two + // operands of array type. + // C++2a [depr.array.comp]: + // Equality and relational comparisons ([expr.eq], [expr.rel]) between two + // operands of array type are deprecated. + Expr *LHSStripped = LHS.get()->IgnoreParenImpCasts(); + Expr *RHSStripped = RHS.get()->IgnoreParenImpCasts(); + if (getLangOpts().CPlusPlus && LHSStripped->getType()->isArrayType() && + RHSStripped->getType()->isArrayType()) { + + auto IsDeprArrayComparionIgnored = + getDiagnostics().isIgnored(diag::warn_depr_array_comparison, Loc); + auto DiagID = getLangOpts().CPlusPlus26 ? diag::warn_array_comparison_cxx26 + : !getLangOpts().CPlusPlus20 || IsDeprArrayComparionIgnored + ? diag::warn_array_comparison + : diag::warn_depr_array_comparison; + Diag(Loc, DiagID) << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange() << LHSStripped->getType() + << RHSStripped->getType(); + if (getLangOpts().CPlusPlus26) { + return QualType(); + } + } + // C++2a [expr.spaceship]p6: If at least one of the operands is of pointer // type, array-to-pointer, ..., conversions are performed on both operands to // bring them to their composite type. @@ -17315,14 +17318,17 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, PromoteType->isUnsignedIntegerType() != UnderlyingType->isUnsignedIntegerType()) { - if (!UnderlyingType->isUnsignedIntegerType() || - UnderlyingType->hasSignedIntegerRepresentation()) { + // Because char16_t and char32_t have no corresponding signed type, + // calling getCorrespondingSignedType on them would assert. Guard + // against this. + const auto *BT = UnderlyingType->getAs<BuiltinType>(); + if (!BT || (BT->getKind() != BuiltinType::Char16 && + BT->getKind() != BuiltinType::Char32)) { UnderlyingType = UnderlyingType->isUnsignedIntegerType() ? Context.getCorrespondingSignedType(UnderlyingType) : Context.getCorrespondingUnsignedType(UnderlyingType); - if (Context.typesAreCompatible(PromoteType, UnderlyingType, - /*CompareUnqualified*/ true)) + if (Context.typesAreCompatible(PromoteType, UnderlyingType, true)) PromoteType = QualType(); } } diff --git a/clang/test/SemaCXX/varargs.cpp b/clang/test/SemaCXX/varargs.cpp index c84d765296e88..1e5920a8728d3 100644 --- a/clang/test/SemaCXX/varargs.cpp +++ b/clang/test/SemaCXX/varargs.cpp @@ -31,7 +31,7 @@ void record_context(int a, ...) { // Ensure the correct behavior for promotable type UB checking. void promotable(int a, ...) { enum Unscoped1 { One = 0x7FFFFFFF }; - (void)__builtin_va_arg(ap, Unscoped1); // expected-warning {{second argument to 'va_arg' is of promotable type}} + (void)__builtin_va_arg(ap, Unscoped1); // ok enum Unscoped2 { Two = 0xFFFFFFFF }; (void)__builtin_va_arg(ap, Unscoped2); // ok >From 45dd8500072c93a4ca6651b78954e000bab7489f Mon Sep 17 00:00:00 2001 From: PrabbyDD <[email protected]> Date: Wed, 6 May 2026 14:42:40 -0700 Subject: [PATCH 4/5] not sure why my PRs got mixed up --- clang/lib/Sema/SemaExpr.cpp | 48 +++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index ac60fe19afb58..4e0b7387dc008 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -12521,6 +12521,28 @@ static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc, AlwaysEqual, // std::strong_ordering::equal from operator<=> }; + // C++1a [array.comp]: + // Equality and relational comparisons ([expr.eq], [expr.rel]) between two + // operands of array type. + // C++2a [depr.array.comp]: + // Equality and relational comparisons ([expr.eq], [expr.rel]) between two + // operands of array type are deprecated. + if (S.getLangOpts().CPlusPlus && LHSStripped->getType()->isArrayType() && + RHSStripped->getType()->isArrayType()) { + auto IsDeprArrayComparionIgnored = + S.getDiagnostics().isIgnored(diag::warn_depr_array_comparison, Loc); + auto DiagID = S.getLangOpts().CPlusPlus26 + ? diag::warn_array_comparison_cxx26 + : !S.getLangOpts().CPlusPlus20 || IsDeprArrayComparionIgnored + ? diag::warn_array_comparison + : diag::warn_depr_array_comparison; + S.Diag(Loc, DiagID) << LHS->getSourceRange() << RHS->getSourceRange() + << LHSStripped->getType() << RHSStripped->getType(); + // Carry on to produce the tautological comparison warning, if this + // expression is potentially-evaluated, we can resolve the array to a + // non-weak declaration, and so on. + } + if (!LHS->getBeginLoc().isMacroID() && !RHS->getBeginLoc().isMacroID()) { if (Expr::isSameComparisonOperand(LHS, RHS)) { unsigned Result; @@ -12838,31 +12860,6 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, return Ty->isPointerType() || Ty->isMemberPointerType(); }; - // C++1a [array.comp]: - // Equality and relational comparisons ([expr.eq], [expr.rel]) between two - // operands of array type. - // C++2a [depr.array.comp]: - // Equality and relational comparisons ([expr.eq], [expr.rel]) between two - // operands of array type are deprecated. - Expr *LHSStripped = LHS.get()->IgnoreParenImpCasts(); - Expr *RHSStripped = RHS.get()->IgnoreParenImpCasts(); - if (getLangOpts().CPlusPlus && LHSStripped->getType()->isArrayType() && - RHSStripped->getType()->isArrayType()) { - - auto IsDeprArrayComparionIgnored = - getDiagnostics().isIgnored(diag::warn_depr_array_comparison, Loc); - auto DiagID = getLangOpts().CPlusPlus26 ? diag::warn_array_comparison_cxx26 - : !getLangOpts().CPlusPlus20 || IsDeprArrayComparionIgnored - ? diag::warn_array_comparison - : diag::warn_depr_array_comparison; - Diag(Loc, DiagID) << LHS.get()->getSourceRange() - << RHS.get()->getSourceRange() << LHSStripped->getType() - << RHSStripped->getType(); - if (getLangOpts().CPlusPlus26) { - return QualType(); - } - } - // C++2a [expr.spaceship]p6: If at least one of the operands is of pointer // type, array-to-pointer, ..., conversions are performed on both operands to // bring them to their composite type. @@ -17332,7 +17329,6 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, PromoteType = QualType(); } } - } if (TInfo->getType()->isSpecificBuiltinType(BuiltinType::Float)) PromoteType = Context.DoubleTy; if (!PromoteType.isNull()) >From 20d332f7a6aea2c8470ca23526f5f02765a7f724 Mon Sep 17 00:00:00 2001 From: PrabbyDD <[email protected]> Date: Wed, 6 May 2026 14:51:26 -0700 Subject: [PATCH 5/5] always remember to re run the tests locally so you dont forget the curly brace --- clang/lib/Sema/SemaExpr.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 4e0b7387dc008..51aa19f830ae3 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -17329,6 +17329,7 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, PromoteType = QualType(); } } + } if (TInfo->getType()->isSpecificBuiltinType(BuiltinType::Float)) PromoteType = Context.DoubleTy; if (!PromoteType.isNull()) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
