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
