[clang] [Clang][Sema] Fix type of enumerators in incomplete enumerations (PR #84068)

via cfe-commits cfe-commits at lists.llvm.org
Mon Mar 11 11:14:05 PDT 2024


https://github.com/Kupa-Martin updated https://github.com/llvm/llvm-project/pull/84068

>From cc6a1329761a8fa5ae0b9f51ef8b7f839d5edff2 Mon Sep 17 00:00:00 2001
From: 44-2-Kupa-Martin <kupamartinclassroom at gmail.com>
Date: Tue, 5 Mar 2024 17:21:02 -0300
Subject: [PATCH] [Clang][Sema] Fix type of enumerators in incomplete
 enumerations Enumerators dont have the type of their enumeration before the
 closing brace. In these cases Expr::getEnumCoercedType() incorrectly returned
 the enumeration type.

Introduced in PR #81418
Fixes #84712
---
 clang/lib/AST/Expr.cpp                             | 13 ++++++++-----
 clang/test/Sema/enum-constant-type.cpp             | 12 ++++++++++++
 clang/test/Sema/warn-compare-enum-types-mismatch.c | 11 ++++++++++-
 3 files changed, 30 insertions(+), 6 deletions(-)
 create mode 100644 clang/test/Sema/enum-constant-type.cpp

diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index b4de2155adcebd..f5ad402e3bd73e 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -264,11 +264,14 @@ namespace {
 }
 
 QualType Expr::getEnumCoercedType(const ASTContext &Ctx) const {
-  if (isa<EnumType>(this->getType()))
-    return this->getType();
-  else if (const auto *ECD = this->getEnumConstantDecl())
-    return Ctx.getTypeDeclType(cast<EnumDecl>(ECD->getDeclContext()));
-  return this->getType();
+  if (isa<EnumType>(getType()))
+    return getType();
+  if (const auto *ECD = getEnumConstantDecl()) {
+    const auto *ED = cast<EnumDecl>(ECD->getDeclContext());
+    if (ED->isCompleteDefinition())
+      return Ctx.getTypeDeclType(ED);
+  }
+  return getType();
 }
 
 SourceLocation Expr::getExprLoc() const {
diff --git a/clang/test/Sema/enum-constant-type.cpp b/clang/test/Sema/enum-constant-type.cpp
new file mode 100644
index 00000000000000..5db3a859a39599
--- /dev/null
+++ b/clang/test/Sema/enum-constant-type.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -x c++ -fsyntax-only -verify %s -Wenum-compare
+// expected-no-diagnostics
+
+enum E1 {
+  E11 = 0
+};
+
+enum E2 {
+  E21 = 0,
+  E22 = E11,
+  E23 = E21 + E22
+};
diff --git a/clang/test/Sema/warn-compare-enum-types-mismatch.c b/clang/test/Sema/warn-compare-enum-types-mismatch.c
index 2b72aae16b977a..47dd592488e6dc 100644
--- a/clang/test/Sema/warn-compare-enum-types-mismatch.c
+++ b/clang/test/Sema/warn-compare-enum-types-mismatch.c
@@ -1,12 +1,21 @@
 // RUN: %clang_cc1 -x c -fsyntax-only -verify -Wenum-compare -Wno-unused-comparison %s
 // RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wenum-compare -Wno-unused-comparison %s
 
+// In C enumerators (i.e enumeration constants) have type int (until C23). In
+// order to support diagnostics such as -Wenum-compare we pretend they have the
+// type of their enumeration.
+
 typedef enum EnumA {
   A
 } EnumA;
 
 enum EnumB {
-  B
+  B,
+  B1 = 1,
+  // In C++ this comparison doesnt warn as enumerators dont have the type of
+  // their enumeration before the closing brace. We mantain the same behavior
+  // in C.
+  B2 = A == B1
 };
 
 enum {



More information about the cfe-commits mailing list