[clang] [clang] Fix for Assertion `(T->hasSignedIntegerRepresentation() || T->isSignedFixedPointType()) && "Unexpected signed integer or fixed point type"' failed. (PR #195945)
via cfe-commits
cfe-commits at lists.llvm.org
Wed May 6 14:51:44 PDT 2026
https://github.com/PrabbyDD updated https://github.com/llvm/llvm-project/pull/195945
>From 36ce4b83c0c674cdc6439f49a90c59ee5bdc613a Mon Sep 17 00:00:00 2001
From: PrabbyDD <dhaliprabh at gmail.com>
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 <dhaliprabh at gmail.com>
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 <dhaliprabh at gmail.com>
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 <dhaliprabh at gmail.com>
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 <dhaliprabh at gmail.com>
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())
More information about the cfe-commits
mailing list