https://github.com/Tsche created 
https://github.com/llvm/llvm-project/pull/204682

This patch makes clang attempt printing enumerator names rather than C-style 
cast expressions in more diagnostics (notably static_assert) iff the value 
matches an enumerator exactly.

For example, consider a static assertion `static_assert(E == TestEnum::B);` 
where `E` is a constant template argument. Assuming `(TestEnum)1 == 
TestEnum::A`, this changes emitted diagnostics as follows:
```
// old
static assertion failed due to requirement '(TestEnum)1 == TestEnum::B'

// new
static assertion failed due to requirement 'TestEnum::A == TestEnum::B'
```

>From b3c82970bebe87c557f17fbd23e4d177a16f0fcc Mon Sep 17 00:00:00 2001
From: Matthias Wippich <[email protected]>
Date: Thu, 18 Jun 2026 22:57:28 +0200
Subject: [PATCH] [clang] improve diagnostics for enums

---
 clang/docs/ReleaseNotes.rst                    |  3 +++
 clang/lib/AST/StmtPrinter.cpp                  | 15 +++++++++++++++
 .../test/Misc/diag-template-diffing-cxx11.cpp  |  2 +-
 clang/test/SemaCXX/static-assert.cpp           | 18 ++++++++++++++++++
 4 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7828135a6edbc..0d824f47764ca 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -646,6 +646,9 @@ Improvements to Clang's diagnostics
 - Diagnostics for the C++11 range-based for statement now report the correct
   iterator type in notes for invalid iterator types.
 
+- Clang now attempts to print enumerator names rather than C-style cast 
expressions
+  in more diagnostics.
+
 Improvements to Clang's time-trace
 ----------------------------------
 
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 6c3294573e9d4..889592c47e962 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -1843,6 +1843,21 @@ void 
StmtPrinter::VisitMatrixElementExpr(MatrixElementExpr *Node) {
 }
 
 void StmtPrinter::VisitCStyleCastExpr(CStyleCastExpr *Node) {
+  // special case enums to avoid producing cast expressions when naming
+  // an enumerator would suffice
+  if (QualType T = Node->getType(); T->isEnumeralType()) {
+    const auto *IL = dyn_cast<IntegerLiteral>(Node->getSubExpr());
+    const auto *ED = T->getAsEnumDecl();
+    if (IL && ED) {
+      llvm::APInt Val = IL->getValue();
+      for (const EnumConstantDecl *ECD : ED->enumerators()) {
+        if (llvm::APInt::isSameValue(ECD->getInitVal(), Val)) {
+          ECD->printQualifiedName(OS, Policy);
+          return;
+        }
+      }
+    }
+  }
   OS << '(';
   Node->getTypeAsWritten().print(OS, Policy);
   OS << ')';
diff --git a/clang/test/Misc/diag-template-diffing-cxx11.cpp 
b/clang/test/Misc/diag-template-diffing-cxx11.cpp
index 0b145475fe191..e543a3a132489 100644
--- a/clang/test/Misc/diag-template-diffing-cxx11.cpp
+++ b/clang/test/Misc/diag-template-diffing-cxx11.cpp
@@ -1451,7 +1451,7 @@ void run() {
   D<X::X1>(VectorType<X::X2>());
 }
 // CHECK-ELIDE-NOTREE: error: no matching function for call to 'D'
-// CHECK-ELIDE-NOTREE: note: candidate function template not viable: no known 
conversion from 'VectorType<X::X2>' to 'const VectorType<(X)0>' for 1st argument
+// CHECK-ELIDE-NOTREE: note: candidate function template not viable: no known 
conversion from 'VectorType<X::X2>' to 'const VectorType<TypeAlias::X::X1>' for 
1st argument
 }
 
 namespace TypeAlias2 {
diff --git a/clang/test/SemaCXX/static-assert.cpp 
b/clang/test/SemaCXX/static-assert.cpp
index 354016db36432..5ea42d4c99489 100644
--- a/clang/test/SemaCXX/static-assert.cpp
+++ b/clang/test/SemaCXX/static-assert.cpp
@@ -363,4 +363,22 @@ namespace Diagnostics {
                                  // expected-note {{evaluates to '1 == 2'}}
   static_assert(1 << 3 != 8, ""); // expected-error {{failed}} \
                                  // expected-note {{evaluates to '8 != 8'}}
+  enum class TestEnum {
+    A = 0,
+    B = 1
+  };
+
+  template<TestEnum E> struct EnumTemplate {
+    static_assert(E == TestEnum::B, ""); // #enum-assert
+  };
+
+  EnumTemplate<TestEnum::A> test1;
+  // expected-error@#enum-assert {{static assertion failed due to requirement 
'Diagnostics::TestEnum::A == Diagnostics::TestEnum::B': }} \
+  // expected-note@-1 {{in instantiation of template class 
'Diagnostics::EnumTemplate<Diagnostics::TestEnum::A>' requested here}} \
+  // expected-note@#enum-assert {{evaluates to '0 == 1'}}
+
+  EnumTemplate<TestEnum(42)> test2;
+  // expected-error@#enum-assert {{static assertion failed due to requirement 
'(Diagnostics::TestEnum)42 == Diagnostics::TestEnum::B': }} \
+  // expected-note@-1 {{in instantiation of template class 
'Diagnostics::EnumTemplate<42>' requested here}} \
+  // expected-note@#enum-assert {{evaluates to '42 == 1'}}
 }

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to