[clang] Nameof operator (PR #104777)

Urvi Rav via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 19 06:26:45 PDT 2024


https://github.com/ravurvi20 created https://github.com/llvm/llvm-project/pull/104777

This Pull Request introduces the `__nameof` operator, enabling users to obtain the symbolic name of any enumerator value. When the `__nameof` operator is used, the compiler will return the fully qualified name of the enum constant, enhancing readability and debugging capabilities.
*Problem Statement:*
C++ enum classes allow developers to define enumerator values, which can simplify code and improve readability. However, there are times when understanding or logging the actual names of these enumerator values is necessary, especially in complex codebases or during debugging. Developers need a straightforward way to retrieve the symbolic names of enum constants to better understand and manage their code.
*Proposed Solution:*
The proposed solution is to implement a compiler feature that allows the use of a `__nameof` operator to retrieve the symbolic names of enumerator values. This operator will construct and return the fully qualified name of the enum constant, providing clarity and aiding in debugging.
Implementation:
*1. EnumNameVisitor Class:*
Introduced the `EnumNameVisitor` class to handle the `__nameof` operator.
Implemented logic to construct the fully qualified name of the enum constant in the format `EnumName::EnumConstant`.
  Added methods to traverse the expression tree, identify `DeclRefExpr` nodes, and fetch the name from the node.
*2. Parser Modifications:*
Updated the parser to recognize and parse the `__nameof` operator.
Integrated the handling of the `__nameof` operator into the semantic analysis phase to ensure accurate name retrieval.
 
*3. Test Case:*
```
#include<iostream>
using namespace std;
// Define an enumeration
enum Day {
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
};
enum Month{
    January,
    February,
    March,
    April,
    May,
    June,
    July,
    August,
    September,
    October,
    November,
    December
};
int main() {
   cout<<"Symbolic Name for "<<Day::Tuesday<<" is: "<<__nameof(Day::Tuesday)<<endl;
   cout<<"Symbolic Name for "<<Month::August<<" is: "<<__nameof(Month::August)<<endl;
   
}
```
*Output:*
Symbolic Name for 1 is: Day::Tuesday
Symbolic Name for 7 is: Month::August

 
*Benefits to the Community:*
Improved Code Comprehension: Developers can easily see the fully qualified names of enum constants, which enhances their understanding of the code.
Enhanced Debugging: During debugging, knowing the exact names of enum constants can help diagnose issues more efficiently.
Consistency: Ensures that enum names are retrieved consistently and accurately across the codebase.

>From 59053c0666a54c120ca86a3a6d5960af668f2e16 Mon Sep 17 00:00:00 2001
From: Urvi Rav <urvi.rav at hpe.com>
Date: Wed, 19 Jun 2024 01:41:50 -0500
Subject: [PATCH 1/3] Add __nameof operator to extract symbolic names of enum
 values

---
 .../clang/Basic/DiagnosticSemaKinds.td        |  2 +
 clang/include/clang/Basic/TokenKinds.def      |  1 +
 clang/include/clang/Sema/Sema.h               |  1 +
 clang/lib/Parse/ParseExpr.cpp                 |  6 ++-
 clang/lib/Sema/SemaDecl.cpp                   |  1 +
 clang/lib/Sema/SemaExpr.cpp                   | 54 ++++++++++++++++++-
 clang/test/Sema/nameof_operator.cpp           | 38 +++++++++++++
 7 files changed, 101 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/Sema/nameof_operator.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 8f85371df3b85b..34ae6da86459ae 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -103,6 +103,8 @@ def note_ice_conversion_here : Note<
 def err_ice_ambiguous_conversion : Error<
   "ambiguous conversion from type %0 to an integral or unscoped "
   "enumeration type">;
+def err_invalid_enum_decl : Error<"unsupported declaration type. "
+                                      "Only enum constants are supported">;
 def err_ice_too_large : Error<
   "integer constant expression evaluates to value %0 that cannot be "
   "represented in a %1-bit %select{signed|unsigned}2 integer type">;
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 9c4b17465e18a1..5d7daa076cad26 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -311,6 +311,7 @@ KEYWORD(register                    , KEYALL)
 KEYWORD(return                      , KEYALL)
 KEYWORD(short                       , KEYALL)
 KEYWORD(signed                      , KEYALL)
+UNARY_EXPR_OR_TYPE_TRAIT(__nameof, nameof, KEYALL)
 UNARY_EXPR_OR_TYPE_TRAIT(sizeof, SizeOf, KEYALL)
 UNARY_EXPR_OR_TYPE_TRAIT(__datasizeof, DataSizeOf, KEYCXX)
 KEYWORD(static                      , KEYALL)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 174b9dbc6d980c..4f5b152fa96f6b 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -244,6 +244,7 @@ class PossiblyUnreachableDiag;
 class RISCVIntrinsicManager;
 class SemaPPCallbacks;
 class TemplateDeductionInfo;
+static std::vector<std::string> enumvector;
 } // namespace sema
 
 namespace threadSafety {
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index eb7447fa038e47..08ed45457027d2 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1491,6 +1491,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
   // unary-expression: '__datasizeof' unary-expression
   // unary-expression: '__datasizeof' '(' type-name ')'
   case tok::kw___datasizeof:
+  case tok::kw___nameof:
   case tok::kw_vec_step:   // unary-expression: OpenCL 'vec_step' expression
   // unary-expression: '__builtin_omp_required_simd_align' '(' type-name ')'
   case tok::kw___builtin_omp_required_simd_align:
@@ -2521,7 +2522,7 @@ ExprResult Parser::ParseSYCLUniqueStableNameExpression() {
 /// [C++11] 'alignof' '(' type-id ')'
 /// \endverbatim
 ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
-  assert(Tok.isOneOf(tok::kw_sizeof, tok::kw___datasizeof, tok::kw___alignof,
+  assert(Tok.isOneOf(tok::kw_sizeof, tok::kw___datasizeof, tok::kw___nameof, tok::kw___alignof,
                      tok::kw_alignof, tok::kw__Alignof, tok::kw_vec_step,
                      tok::kw___builtin_omp_required_simd_align,
                      tok::kw___builtin_vectorelements) &&
@@ -2612,6 +2613,9 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
   case tok::kw___datasizeof:
     ExprKind = UETT_DataSizeOf;
     break;
+  case tok::kw___nameof:
+    ExprKind = UETT_nameof;
+    break;
   case tok::kw___builtin_vectorelements:
     ExprKind = UETT_VectorElements;
     break;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 34a1654be134f9..4cebb8eedd992f 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -20149,6 +20149,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
 
     const llvm::APSInt &InitVal = ECD->getInitVal();
 
+    enumvector.push_back(ECD->getName().str());
     // Keep track of the size of positive and negative values.
     if (InitVal.isUnsigned() || InitVal.isNonNegative()) {
       // If the enumerator is zero that should still be counted as a positive
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index acaff304be193f..45cd58fbbc4bef 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -67,7 +67,46 @@
 
 using namespace clang;
 using namespace sema;
+class EnumNameVisitor {
+private:
+  std::string EnumName;
+
+public:
+ Sema &S;
+
+  EnumNameVisitor(Sema &S) : S(S) {}
+  void VisitDeclRefExpr(DeclRefExpr *Node) {
+    const Decl *D = Node->getDecl();
+    // Check if the declaration referenced is an enum constant
+    if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
+      if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) {
+        // Construct the fully qualified name
+        EnumName = ED->getName().str() + "::" + ECD->getName().str();
+        return; // No error for valid enum constants
+      }
+    }
+  }
+  void VisitExpr(Expr *Ex) {
+     if (!Ex->children().empty()) {
+      // Recursively visit child expressions
+      for (auto *Child : Ex->children()) {
+        if (auto *ChildExpr = dyn_cast<Expr>(Child)) {
+
+          VisitExpr(ChildExpr);
+        }
+      }
+    }
+    // Now handle the current expression node
+    if (auto *DRE = dyn_cast<DeclRefExpr>(Ex)) {
+      VisitDeclRefExpr(DRE); // If it's a DeclRefExpr, visit it
+      return;
+    }
+  }
 
+  // Method to retrieve the last fetched string
+  StringRef getEnumName() const { 
+    return StringRef(EnumName); }
+};
 /// Determine whether the use of this declaration is valid, without
 /// emitting diagnostics.
 bool Sema::CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid) {
@@ -4682,6 +4721,9 @@ ExprResult Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
 ExprResult
 Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
                                      UnaryExprOrTypeTrait ExprKind) {
+  EnumNameVisitor obj(*this);
+  obj.VisitExpr(E);
+  StringRef EnumName = obj.getEnumName();
   ExprResult PE = CheckPlaceholderExpr(E);
   if (PE.isInvalid())
     return ExprError();
@@ -4716,7 +4758,17 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
     if (PE.isInvalid()) return ExprError();
     E = PE.get();
   }
-
+  QualType StrTy =
+      Context.getStringLiteralArrayType(Context.CharTy, EnumName.size());
+  if (ExprKind == UETT_nameof) {
+    StringLiteral *EnumStr =
+        StringLiteral::Create(Context, EnumName, StringLiteralKind::Ordinary,
+                              /*Pascal*/ false, StrTy, OpLoc);
+    if (EnumStr->getString() == "") {
+      Diag(E->getExprLoc(), diag::err_invalid_enum_decl);
+    }
+    return EnumStr;
+  }
   // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
   return new (Context) UnaryExprOrTypeTraitExpr(
       ExprKind, E, Context.getSizeType(), OpLoc, E->getSourceRange().getEnd());
diff --git a/clang/test/Sema/nameof_operator.cpp b/clang/test/Sema/nameof_operator.cpp
new file mode 100644
index 00000000000000..4d129d4aa2dac1
--- /dev/null
+++ b/clang/test/Sema/nameof_operator.cpp
@@ -0,0 +1,38 @@
+// RUN: %clangxx -std=c++11 -fsyntax-only -Xclang -verify %s 
+#include <iostream>
+using namespace std;
+// Define an enumeration
+enum Day {
+    Monday,
+    Tuesday,
+    Wednesday,
+    Thursday,
+    Friday,
+    Saturday,
+    Sunday
+};
+
+enum Month {
+    January,
+    February,
+    March,
+    April,
+    May,
+    June,
+    July,
+    August,
+    September,
+    October,
+    November,
+    December
+};
+
+int main() {
+    // Check valid usage
+    cout<<"Symbolic Name for "<<Day::Tuesday<<" is: "<<__nameof(Day::Tuesday)<<endl; // expected-output {{Symbolic Name for 1 is: Day::Tuesday}}
+    cout<<"Symbolic Name for "<<Month::August<<" is: "<<__nameof(Month::August)<<endl; // expected-output {{Symbolic Name for 7 is: Month::August}}
+    // Check invalid usage
+    cout<<"Symbolic Name: "<<__nameof(1)<<endl;  // expected-error {{unsupported declaration type. Only enum constants are supported}}
+    cout<<"Symbolic Name: "<<__nameof("")<<endl;  // expected-error {{unsupported declaration type. Only enum constants are supported}}
+    return 0;
+}
\ No newline at end of file

>From ed034596a13b2f28d08178286ecc4171be1cc0ce Mon Sep 17 00:00:00 2001
From: Urvi Rav <urvi.rav20 at gmail.com>
Date: Mon, 19 Aug 2024 07:52:16 -0500
Subject: [PATCH 2/3] Modified EnumNameVisitor and LIT test case

---
 clang/include/clang/Basic/TokenKinds.def |  2 +-
 clang/include/clang/Sema/Sema.h          |  2 +-
 clang/lib/Parse/ParseExpr.cpp            |  3 +-
 clang/lib/Sema/SemaDecl.cpp              |  1 -
 clang/lib/Sema/SemaExpr.cpp              | 43 +++++++++---------------
 clang/test/Sema/nameof_operator.c        | 39 +++++++++++++++++++++
 clang/test/Sema/nameof_operator.cpp      | 38 ---------------------
 7 files changed, 58 insertions(+), 70 deletions(-)
 create mode 100644 clang/test/Sema/nameof_operator.c
 delete mode 100644 clang/test/Sema/nameof_operator.cpp

diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 5d7daa076cad26..965784ef3d2dc3 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -311,7 +311,7 @@ KEYWORD(register                    , KEYALL)
 KEYWORD(return                      , KEYALL)
 KEYWORD(short                       , KEYALL)
 KEYWORD(signed                      , KEYALL)
-UNARY_EXPR_OR_TYPE_TRAIT(__nameof, nameof, KEYALL)
+UNARY_EXPR_OR_TYPE_TRAIT(__nameof, NameOf, KEYALL)
 UNARY_EXPR_OR_TYPE_TRAIT(sizeof, SizeOf, KEYALL)
 UNARY_EXPR_OR_TYPE_TRAIT(__datasizeof, DataSizeOf, KEYCXX)
 KEYWORD(static                      , KEYALL)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 4f5b152fa96f6b..2aa9488a5c56ea 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -244,7 +244,7 @@ class PossiblyUnreachableDiag;
 class RISCVIntrinsicManager;
 class SemaPPCallbacks;
 class TemplateDeductionInfo;
-static std::vector<std::string> enumvector;
+class EnumNameVector{ static std::vector<std::string> enumvector; };
 } // namespace sema
 
 namespace threadSafety {
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 08ed45457027d2..30990f024b3273 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1491,6 +1491,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
   // unary-expression: '__datasizeof' unary-expression
   // unary-expression: '__datasizeof' '(' type-name ')'
   case tok::kw___datasizeof:
+  //unary-experssion: The `nameof` operator takes an enum value as input and returns the fully qualified name of the enum and its value.
   case tok::kw___nameof:
   case tok::kw_vec_step:   // unary-expression: OpenCL 'vec_step' expression
   // unary-expression: '__builtin_omp_required_simd_align' '(' type-name ')'
@@ -2614,7 +2615,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
     ExprKind = UETT_DataSizeOf;
     break;
   case tok::kw___nameof:
-    ExprKind = UETT_nameof;
+    ExprKind = UETT_NameOf;
     break;
   case tok::kw___builtin_vectorelements:
     ExprKind = UETT_VectorElements;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 4cebb8eedd992f..34a1654be134f9 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -20149,7 +20149,6 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
 
     const llvm::APSInt &InitVal = ECD->getInitVal();
 
-    enumvector.push_back(ECD->getName().str());
     // Keep track of the size of positive and negative values.
     if (InitVal.isUnsigned() || InitVal.isNonNegative()) {
       // If the enumerator is zero that should still be counted as a positive
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 45cd58fbbc4bef..65044fe995ab91 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -67,14 +67,10 @@
 
 using namespace clang;
 using namespace sema;
-class EnumNameVisitor {
+class EnumNameVisitor : public RecursiveASTVisitor<EnumNameVisitor> {
 private:
   std::string EnumName;
-
 public:
- Sema &S;
-
-  EnumNameVisitor(Sema &S) : S(S) {}
   void VisitDeclRefExpr(DeclRefExpr *Node) {
     const Decl *D = Node->getDecl();
     // Check if the declaration referenced is an enum constant
@@ -82,30 +78,21 @@ class EnumNameVisitor {
       if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) {
         // Construct the fully qualified name
         EnumName = ED->getName().str() + "::" + ECD->getName().str();
-        return; // No error for valid enum constants
       }
     }
   }
-  void VisitExpr(Expr *Ex) {
-     if (!Ex->children().empty()) {
-      // Recursively visit child expressions
-      for (auto *Child : Ex->children()) {
-        if (auto *ChildExpr = dyn_cast<Expr>(Child)) {
-
-          VisitExpr(ChildExpr);
-        }
+  bool VisitExpr(Expr *Ex) {
+    for (auto *Child : Ex->children()) {
+      if (auto *DRE = dyn_cast<DeclRefExpr>(Child)) {
+        VisitDeclRefExpr(DRE);
       }
+      // Recursively visit the child nodes
+      RecursiveASTVisitor<EnumNameVisitor>::VisitStmt(Child);
     }
-    // Now handle the current expression node
-    if (auto *DRE = dyn_cast<DeclRefExpr>(Ex)) {
-      VisitDeclRefExpr(DRE); // If it's a DeclRefExpr, visit it
-      return;
-    }
+    return true; // Continue traversal
   }
-
   // Method to retrieve the last fetched string
-  StringRef getEnumName() const { 
-    return StringRef(EnumName); }
+  StringRef getEnumName() const { return StringRef(EnumName); }
 };
 /// Determine whether the use of this declaration is valid, without
 /// emitting diagnostics.
@@ -4721,9 +4708,6 @@ ExprResult Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
 ExprResult
 Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
                                      UnaryExprOrTypeTrait ExprKind) {
-  EnumNameVisitor obj(*this);
-  obj.VisitExpr(E);
-  StringRef EnumName = obj.getEnumName();
   ExprResult PE = CheckPlaceholderExpr(E);
   if (PE.isInvalid())
     return ExprError();
@@ -4758,13 +4742,16 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
     if (PE.isInvalid()) return ExprError();
     E = PE.get();
   }
-  QualType StrTy =
+  if (ExprKind == UETT_NameOf) {
+    EnumNameVisitor obj;
+    obj.VisitExpr(E);
+    StringRef EnumName = obj.getEnumName();
+    QualType StrTy =
       Context.getStringLiteralArrayType(Context.CharTy, EnumName.size());
-  if (ExprKind == UETT_nameof) {
     StringLiteral *EnumStr =
         StringLiteral::Create(Context, EnumName, StringLiteralKind::Ordinary,
                               /*Pascal*/ false, StrTy, OpLoc);
-    if (EnumStr->getString() == "") {
+    if (EnumStr->getString().empty()) {
       Diag(E->getExprLoc(), diag::err_invalid_enum_decl);
     }
     return EnumStr;
diff --git a/clang/test/Sema/nameof_operator.c b/clang/test/Sema/nameof_operator.c
new file mode 100644
index 00000000000000..dd58f08209d53a
--- /dev/null
+++ b/clang/test/Sema/nameof_operator.c
@@ -0,0 +1,39 @@
+// RUN: %clangxx -std=c++11 -fsyntax-only -Xclang -verify %s
+
+int printf(const char *restrict, ...);
+
+// Define an enumeration
+enum Day {
+    Monday,
+    Tuesday,
+    Wednesday,
+    Thursday,
+    Friday,
+    Saturday,
+    Sunday
+};
+
+enum Month {
+    January,
+    February,
+    March,
+    April,
+    May,
+    June,
+    July,
+    August,
+    September,
+    October,
+    November,
+    December
+};
+
+void test_enum_nameof() {
+    // Check valid usage
+    printf("Symbolic Name for %d is: %s ", Day::Tuesday, __nameof(Day::Tuesday)); // expected-output {{Symbolic Name for 1 is: Day::Tuesday}}
+    printf("Symbolic Name for %d is: %s ", Month::August, __nameof(Month::August)); // expected-output {{Symbolic Name for 7 is: Month::August}}
+    
+    // Check invalid usage
+    printf("Symbolic Name: %s ", __nameof(1));  // expected-error {{unsupported declaration type. Only enum constants are supported}}
+    printf("Symbolic Name: %s ", __nameof(""));  // expected-error {{unsupported declaration type. Only enum constants are supported}}
+}
\ No newline at end of file
diff --git a/clang/test/Sema/nameof_operator.cpp b/clang/test/Sema/nameof_operator.cpp
deleted file mode 100644
index 4d129d4aa2dac1..00000000000000
--- a/clang/test/Sema/nameof_operator.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-// RUN: %clangxx -std=c++11 -fsyntax-only -Xclang -verify %s 
-#include <iostream>
-using namespace std;
-// Define an enumeration
-enum Day {
-    Monday,
-    Tuesday,
-    Wednesday,
-    Thursday,
-    Friday,
-    Saturday,
-    Sunday
-};
-
-enum Month {
-    January,
-    February,
-    March,
-    April,
-    May,
-    June,
-    July,
-    August,
-    September,
-    October,
-    November,
-    December
-};
-
-int main() {
-    // Check valid usage
-    cout<<"Symbolic Name for "<<Day::Tuesday<<" is: "<<__nameof(Day::Tuesday)<<endl; // expected-output {{Symbolic Name for 1 is: Day::Tuesday}}
-    cout<<"Symbolic Name for "<<Month::August<<" is: "<<__nameof(Month::August)<<endl; // expected-output {{Symbolic Name for 7 is: Month::August}}
-    // Check invalid usage
-    cout<<"Symbolic Name: "<<__nameof(1)<<endl;  // expected-error {{unsupported declaration type. Only enum constants are supported}}
-    cout<<"Symbolic Name: "<<__nameof("")<<endl;  // expected-error {{unsupported declaration type. Only enum constants are supported}}
-    return 0;
-}
\ No newline at end of file

>From da4f6ded986402a233065efb0cf4e667cad5fa74 Mon Sep 17 00:00:00 2001
From: Urvi Rav <urvi.rav20 at gmail.com>
Date: Mon, 19 Aug 2024 08:00:55 -0500
Subject: [PATCH 3/3] Changes in Error Message

---
 clang/include/clang/Basic/DiagnosticSemaKinds.td | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 34ae6da86459ae..4d1bd3a51d0231 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -103,8 +103,9 @@ def note_ice_conversion_here : Note<
 def err_ice_ambiguous_conversion : Error<
   "ambiguous conversion from type %0 to an integral or unscoped "
   "enumeration type">;
-def err_invalid_enum_decl : Error<"unsupported declaration type. "
-                                      "Only enum constants are supported">;
+def err_invalid_enum_decl : Error<
+  "unsupported declaration type. "
+  "Only enum constants are supported">;
 def err_ice_too_large : Error<
   "integer constant expression evaluates to value %0 that cannot be "
   "represented in a %1-bit %select{signed|unsigned}2 integer type">;



More information about the cfe-commits mailing list