[clang] [compiler-rt] [ubsan] Improve scoped enum diagnostic printer (PR #216460)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Aug 16 18:56:38 PDT 2026
https://github.com/zebullax updated https://github.com/llvm/llvm-project/pull/216460
>From 59284200a3e2e65ec041fba72aaf0339e374c755 Mon Sep 17 00:00:00 2001
From: zebullax <zebullax at gmail.com>
Date: Sat, 15 Aug 2026 16:02:54 +0900
Subject: [PATCH 1/3] Improve scoped enum printer
---
clang/lib/CodeGen/CGExpr.cpp | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 9201e40bc13a1..c8ac2fd53fc82 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -3959,18 +3959,27 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) {
uint16_t TypeInfo = 0;
bool IsBitInt = false;
- if (T->isIntegerType()) {
+ // isIntegerType() never holds for scoped enums, and getAs<BitIntType> can't
+ // see through the EnumType node to a __BitInt underlying type even for
+ // unscoped enums.
+ QualType ValueTy = T;
+ if (const EnumType *ET = T->getAs<EnumType>()) {
+ if (ET->getDecl()->isComplete())
+ ValueTy = ET->getDecl()->getIntegerType();
+ }
+
+ if (ValueTy->isIntegerType()) {
TypeKind = TK_Integer;
- TypeInfo = (llvm::Log2_32(getContext().getTypeSize(T)) << 1) |
- (T->isSignedIntegerType() ? 1 : 0);
+ TypeInfo = (llvm::Log2_32(getContext().getTypeSize(ValueTy)) << 1) |
+ (ValueTy->isSignedIntegerType() ? 1 : 0);
// Follow suggestion from discussion of issue 64100.
// So we can write the exact amount of bits in TypeName after '\0'
// making it <diagnostic-like type name>.'\0'.<32-bit width>.
- if (T->isSignedIntegerType() && T->getAs<BitIntType>()) {
+ if (ValueTy->isSignedIntegerType() && ValueTy->getAs<BitIntType>()) {
// Do a sanity checks as we are using 32-bit type to store bit length.
- assert(getContext().getTypeSize(T) > 0 &&
+ assert(getContext().getTypeSize(ValueTy) > 0 &&
" non positive amount of bits in __BitInt type");
- assert(getContext().getTypeSize(T) <= 0xFFFFFFFF &&
+ assert(getContext().getTypeSize(ValueTy) <= 0xFFFFFFFF &&
" too many bits in __BitInt type");
// Redefine TypeKind with the actual __BitInt type if we have signed
@@ -3994,7 +4003,7 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) {
// The Structure is: 0 to end the string, 32 bit unsigned integer in target
// endianness, zero.
char S[6] = {'\0', '\0', '\0', '\0', '\0', '\0'};
- const auto *EIT = T->castAs<BitIntType>();
+ const auto *EIT = ValueTy->castAs<BitIntType>();
uint32_t Bits = EIT->getNumBits();
llvm::support::endian::write32(S + 1, Bits,
getTarget().isBigEndian()
>From 50fd4cfd4f816d1c0b8a162fe47ab7100775cde1 Mon Sep 17 00:00:00 2001
From: zebullax <zebullax at gmail.com>
Date: Sat, 15 Aug 2026 16:04:42 +0900
Subject: [PATCH 2/3] Update error message for enum value check
---
compiler-rt/test/ubsan/TestCases/Misc/enum.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/compiler-rt/test/ubsan/TestCases/Misc/enum.cpp b/compiler-rt/test/ubsan/TestCases/Misc/enum.cpp
index 2684029c2960b..b51347f07c050 100644
--- a/compiler-rt/test/ubsan/TestCases/Misc/enum.cpp
+++ b/compiler-rt/test/ubsan/TestCases/Misc/enum.cpp
@@ -25,7 +25,7 @@ int main(int argc, char **argv) {
return ((int)e1 != -1) & ((int)e2 != -1) &
// CHECK: error: load of value 4294967295, which is not a valid value for type 'E'
((int)e3 != -1) & ((int)e4 == 1) &
- // CHECK: error: load of value <unknown>, which is not a valid value for type 'enum EBool'
+ // CHECK: error: load of value 255, which is not a valid value for type 'enum EBool'
((int)e5 == 2) & ((int)e6 == 1) &
// CHECK: error: load of value 2, which is not a valid value for type 'EEmpty'
((int)e7 == 2);
>From e1276090dd75b3a2192c6cdd6523c4253cf6cd30 Mon Sep 17 00:00:00 2001
From: acassagnes <acassagnes at bloomberg.net>
Date: Mon, 17 Aug 2026 10:52:27 +0900
Subject: [PATCH 3/3] Use original T as much as possible
Signed-off-by: acassagnes <acassagnes at bloomberg.net>
---
clang/lib/CodeGen/CGExpr.cpp | 27 +++++++++++++--------------
1 file changed, 13 insertions(+), 14 deletions(-)
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index c8ac2fd53fc82..d7cf52d24474f 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -3962,24 +3962,23 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) {
// isIntegerType() never holds for scoped enums, and getAs<BitIntType> can't
// see through the EnumType node to a __BitInt underlying type even for
// unscoped enums.
- QualType ValueTy = T;
- if (const EnumType *ET = T->getAs<EnumType>()) {
+ QualType BackupT = T;
+ if (const EnumType *ET = T->getAs<EnumType>())
if (ET->getDecl()->isComplete())
- ValueTy = ET->getDecl()->getIntegerType();
- }
+ T = ET->getDecl()->getIntegerType();
- if (ValueTy->isIntegerType()) {
+ if (T->isIntegerType()) {
TypeKind = TK_Integer;
- TypeInfo = (llvm::Log2_32(getContext().getTypeSize(ValueTy)) << 1) |
- (ValueTy->isSignedIntegerType() ? 1 : 0);
+ TypeInfo = (llvm::Log2_32(getContext().getTypeSize(T)) << 1) |
+ (T->isSignedIntegerType() ? 1 : 0);
// Follow suggestion from discussion of issue 64100.
// So we can write the exact amount of bits in TypeName after '\0'
// making it <diagnostic-like type name>.'\0'.<32-bit width>.
- if (ValueTy->isSignedIntegerType() && ValueTy->getAs<BitIntType>()) {
+ if (T->isSignedIntegerType() && T->getAs<BitIntType>()) {
// Do a sanity checks as we are using 32-bit type to store bit length.
- assert(getContext().getTypeSize(ValueTy) > 0 &&
+ assert(getContext().getTypeSize(T) > 0 &&
" non positive amount of bits in __BitInt type");
- assert(getContext().getTypeSize(ValueTy) <= 0xFFFFFFFF &&
+ assert(getContext().getTypeSize(T) <= 0xFFFFFFFF &&
" too many bits in __BitInt type");
// Redefine TypeKind with the actual __BitInt type if we have signed
@@ -3996,14 +3995,14 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) {
// optionally an 'aka'.
SmallString<32> Buffer;
CGM.getDiags().ConvertArgToString(DiagnosticsEngine::ak_qualtype,
- (intptr_t)T.getAsOpaquePtr(), StringRef(),
- StringRef(), {}, Buffer, {});
+ (intptr_t)BackupT.getAsOpaquePtr(),
+ StringRef(), StringRef(), {}, Buffer, {});
if (IsBitInt) {
// The Structure is: 0 to end the string, 32 bit unsigned integer in target
// endianness, zero.
char S[6] = {'\0', '\0', '\0', '\0', '\0', '\0'};
- const auto *EIT = ValueTy->castAs<BitIntType>();
+ const auto *EIT = T->castAs<BitIntType>();
uint32_t Bits = EIT->getNumBits();
llvm::support::endian::write32(S + 1, Bits,
getTarget().isBigEndian()
@@ -4026,7 +4025,7 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) {
CGM.getSanitizerMetadata()->disableSanitizerForGlobal(GV);
// Remember the descriptor for this type.
- CGM.setTypeDescriptorInMap(T, GV);
+ CGM.setTypeDescriptorInMap(BackupT, GV);
return GV;
}
More information about the cfe-commits
mailing list