https://github.com/memehdi14 updated 
https://github.com/llvm/llvm-project/pull/228212

>From 2e2accca8d8df05aaeddb01ec6f0377c07f753b7 Mon Sep 17 00:00:00 2001
From: MeMehdi14 <[email protected]>
Date: Thu, 1 Oct 2026 19:26:45 +0000
Subject: [PATCH 1/2] [Clang][Sema] Diagnose type mismatch on redeclaration
 after redefinition error

When a variable redefinition error occurs, the rejected declaration
is marked invalid. In Sema::MergeVarDecl, this invalid declaration was
passed to MergeVarDeclTypes, which returns early when either declaration
is invalid. As a result, subsequent redeclarations with conflicting
types were never diagnosed.

Later, constant evaluation of expressions reading the variable would walk
the redeclaration chain and locate the original initializer with a
mismatched type, causing an assertion failure in IntExprEvaluator::Success.

Fix this by merging types against the most recent valid declaration in the
redeclaration chain, ensuring type incompatibility errors are emitted
and invalid declarations do not bypass semantic type checking.

Also verified that related issue #114174 does not crash.

Fixes #227733
---
 clang/docs/ReleaseNotes.md                     |  3 +++
 clang/lib/Sema/SemaDecl.cpp                    | 18 +++++++++++++++---
 .../Sema/redefinition-then-different-type.c    | 10 ++++++++++
 3 files changed, 28 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/Sema/redefinition-then-different-type.c

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 32116077622b5..0b0d6503fe99a 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -618,6 +618,9 @@ features cannot lower the translation-unit ABI level;
 
 ### Bug Fixes in This Version
 
+- Fixed an assertion failure in the constant evaluator after a variable 
redefinition
+  error followed by a redeclaration with a different type. (#227733)
+
 - Fixed incorrect handling of C++ import preprocessing token when a digraph 
character after import. (#GH190693)
 - Fixed a crash when emitting RTTI for a `dllexport` class, or the fundamental 
type descriptors for `__cxxabiv1::__fundamental_type_info`, under 
`-fvisibility=hidden`. (#GH207963)
 - Fixed an assertion failure when passing a wide string literal to 
`__builtin_nan`. (#GH212108)
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 1459b71326375..c744c69aeb999 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -4814,15 +4814,27 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult 
&Previous) {
     }
 
   // Merge the types.
-  VarDecl *MostRecent = Old->getMostRecentDecl();
-  if (MostRecent != Old) {
+  VarDecl *TypeOld = Old;
+  if (TypeOld->isInvalidDecl()) {
+    for (VarDecl *Prev = Old->getPreviousDecl(); Prev;
+         Prev = Prev->getPreviousDecl()) {
+      if (!Prev->isInvalidDecl()) {
+        TypeOld = Prev;
+        break;
+      }
+    }
+  }
+
+  VarDecl *MostRecent = TypeOld->getMostRecentDecl();
+  if (MostRecent != TypeOld) {
     MergeVarDeclTypes(New, MostRecent,
                       mergeTypeWithPrevious(*this, New, MostRecent, Previous));
     if (New->isInvalidDecl())
       return;
   }
 
-  MergeVarDeclTypes(New, Old, mergeTypeWithPrevious(*this, New, Old, 
Previous));
+  MergeVarDeclTypes(New, TypeOld,
+                    mergeTypeWithPrevious(*this, New, TypeOld, Previous));
   if (New->isInvalidDecl())
     return;
 
diff --git a/clang/test/Sema/redefinition-then-different-type.c 
b/clang/test/Sema/redefinition-then-different-type.c
new file mode 100644
index 0000000000000..f859ad69aa6e8
--- /dev/null
+++ b/clang/test/Sema/redefinition-then-different-type.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -x c++ %s
+
+// Previously crashed with an assertion in IntExprEvaluator::Success.
+// https://github.com/llvm/llvm-project/issues/227733
+
+const char e = 1; // expected-note 2 {{previous definition is here}}
+const char e = 1; // expected-error {{redefinition of 'e'}}
+const unsigned e; // expected-error {{redefinition of 'e' with a different 
type: 'const unsigned int' vs 'const char'}}
+int x = e;

>From 08f1d84310e2253ba798018753ceb929fbfded2b Mon Sep 17 00:00:00 2001
From: MeMehdi14 <[email protected]>
Date: Mon, 12 Oct 2026 18:03:02 +0000
Subject: [PATCH 2/2] [Clang][Sema] Fix #227733: handle all-invalid decl chains
 and mismatched initializer types

Address reviewer feedback on PR #228212:

1. SemaDecl.cpp (MergeVarDecl): If the entire redeclaration chain is
   invalid (i.e. no valid previous declaration exists), propagate
   invalidity to the new declaration via setInvalidDecl().  Previously,
   the loop fell through and TypeOld remained invalid, causing
   MergeVarDeclTypes to silently skip type-checking and leave the new
   declaration in an inconsistent valid state.  Also guard MostRecent
   from being used when it is itself invalid.

2. ExprConstant.cpp (evaluateVarDeclInit): After getAnyInitializer()
   walks the redeclaration chain and returns an initializer attached to
   InitDecl (which may differ from VD), verify two things before
   proceeding:
   - InitDecl is not invalid.
   - InitDecl->getType() and VD->getType() are the same or compatible
     (canonical, unqualified).  A mismatch means the initializer was
     written for a declaration with a different type (e.g. the original
     const char, while VD is const unsigned), and using it would produce
     an APSInt with the wrong signedness/width, triggering the
     assertion in IntExprEvaluator::Success.
   Return false cleanly in both cases so the evaluator treats the
   variable as non-constant rather than crashing.

3. ByteCode/Compiler.cpp (visitDeclRef): Bail out with emitError() if
   the resolved VarDecl is invalid, preventing the new constant
   interpreter from attempting to evaluate references to declarations
   that are in an invalid state.

4. Test updates (redefinition-then-different-type.c):
   - Add -fexperimental-new-constant-interpreter RUN lines (C and C++).
   - Add coverage for the all-invalid-chain case (two bad-type
     declarations followed by a valid one).

Fixes #227733
---
 clang/lib/AST/ByteCode/Compiler.cpp             |  2 +-
 clang/lib/AST/ExprConstant.cpp                  | 17 ++++++++++++++++-
 clang/lib/Sema/SemaDecl.cpp                     |  5 ++++-
 .../Sema/redefinition-then-different-type.c     |  8 ++++++++
 4 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/clang/lib/AST/ByteCode/Compiler.cpp 
b/clang/lib/AST/ByteCode/Compiler.cpp
index e0f2a29860d09..7b695b65ccfca 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -8567,7 +8567,7 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, 
const Expr *E) {
   // Try to lazily visit (or emit dummy pointers for) declarations
   // we haven't seen yet.
   const auto *VD = dyn_cast<VarDecl>(D);
-  if (!VD)
+  if (!VD || VD->isInvalidDecl())
     return this->emitError(E);
 
   // For C.
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index d5b8d0ed889d1..e0fbacb58a4b5 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -3560,7 +3560,8 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const 
Expr *E,
   // Dig out the initializer, and use the declaration which it's attached to.
   // FIXME: We should eventually check whether the variable has a reachable
   // initializing declaration.
-  const Expr *Init = VD->getAnyInitializer(VD);
+  const VarDecl *InitDecl = VD;
+  const Expr *Init = VD->getAnyInitializer(InitDecl);
   // P2280R4 struck the restriction that variable of reference type should have
   // a preceding initialization.
   // Used to be C++20 [expr.const]p5.12:
@@ -3576,6 +3577,20 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const 
Expr *E,
     return false;
   }
 
+  if (Init) {
+    if (InitDecl->isInvalidDecl())
+      return false;
+
+    QualType InitType =
+        Info.Ctx.getCanonicalType(InitDecl->getType()).getUnqualifiedType();
+    QualType VDType =
+        Info.Ctx.getCanonicalType(VD->getType()).getUnqualifiedType();
+    if (InitType != VDType && !Info.Ctx.typesAreCompatible(InitType, VDType))
+      return false;
+
+    VD = InitDecl;
+  }
+
   // P2280R4 struck the initialization requirement for variables of reference
   // type so we can no longer assume we have an Init.
   // Used to be C++20 [expr.const]p5.12:
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index c744c69aeb999..71248a73ac93c 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -4825,8 +4825,11 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult 
&Previous) {
     }
   }
 
+  if (TypeOld->isInvalidDecl())
+    return New->setInvalidDecl();
+
   VarDecl *MostRecent = TypeOld->getMostRecentDecl();
-  if (MostRecent != TypeOld) {
+  if (MostRecent != TypeOld && !MostRecent->isInvalidDecl()) {
     MergeVarDeclTypes(New, MostRecent,
                       mergeTypeWithPrevious(*this, New, MostRecent, Previous));
     if (New->isInvalidDecl())
diff --git a/clang/test/Sema/redefinition-then-different-type.c 
b/clang/test/Sema/redefinition-then-different-type.c
index f859ad69aa6e8..d6d2f99b2d22c 100644
--- a/clang/test/Sema/redefinition-then-different-type.c
+++ b/clang/test/Sema/redefinition-then-different-type.c
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 // RUN: %clang_cc1 -fsyntax-only -verify -x c++ %s
+// RUN: %clang_cc1 -fsyntax-only -verify 
-fexperimental-new-constant-interpreter %s
+// RUN: %clang_cc1 -fsyntax-only -verify 
-fexperimental-new-constant-interpreter -x c++ %s
 
 // Previously crashed with an assertion in IntExprEvaluator::Success.
 // https://github.com/llvm/llvm-project/issues/227733
@@ -8,3 +10,9 @@ const char e = 1; // expected-note 2 {{previous definition is 
here}}
 const char e = 1; // expected-error {{redefinition of 'e'}}
 const unsigned e; // expected-error {{redefinition of 'e' with a different 
type: 'const unsigned int' vs 'const char'}}
 int x = e;
+
+// Test when all previous declarations in the redeclaration chain are invalid.
+invalid_type_1 a; // expected-error {{unknown type name 'invalid_type_1'}}
+invalid_type_2 a; // expected-error {{unknown type name 'invalid_type_2'}}
+int a;
+int y = a;

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

Reply via email to