https://github.com/AhmedKamel10 updated 
https://github.com/llvm/llvm-project/pull/219358

>From c0d58fd3b0c899031a5cca0b20422232de7de37b Mon Sep 17 00:00:00 2001
From: ahmedkamel10 <[email protected]>
Date: Fri, 28 Aug 2026 06:33:09 +0300
Subject: [PATCH 1/2] [Clang][ConstExpr] Reject member function calls before
 base initialization

This patch diagnoses undefined behavior during constant evaluation when a
member function is called for an object under construction before all
base classes have been initialized, per C++20 [class.base.init]/16.

Fixes #211286
---
 clang/lib/AST/ExprConstant.cpp                |  6 ++++++
 .../SemaCXX/constant-expression-cxx2a.cpp     | 19 ++++++++++++++++++
 test.cpp                                      | 20 +++++++++++++++++++
 3 files changed, 45 insertions(+)
 create mode 100644 test.cpp

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 9702105951b7b..34c1cb39dd8b1 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -6625,6 +6625,12 @@ static bool
 checkNonVirtualMemberCallThisPointer(EvalInfo &Info, const Expr *E,
                                      const LValue &This,
                                      const CXXMethodDecl *NamedMember) {
+  ConstructionPhase Phase =
+      Info.isEvaluatingCtorDtor(This.getLValueBase(), This.Designator.Entries);
+  if (Phase == ConstructionPhase::Bases) {
+    Info.FFDiag(E);
+    return false;
+  }                                                       
   return checkDynamicType(
       Info, E, This,
       isa<CXXDestructorDecl>(NamedMember) ? AK_Destroy : AK_MemberCall, false);
diff --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp 
b/clang/test/SemaCXX/constant-expression-cxx2a.cpp
index 870865646a61e..88b4808a4671e 100644
--- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp
@@ -1544,3 +1544,22 @@ namespace GH197403 {
   }
   static_assert(test() == 0);
 }
+
+namespace GH211286 {
+  struct A {
+    constexpr A(int x) : val(x) {}
+    int val;
+  };
+
+  struct B : A {
+    constexpr int f() const { return 42; }
+    constexpr B() : A(f()) {} // expected-note 2{{subexpression not valid in a 
constant expression}}
+  };
+
+  constexpr int foo() {
+    constexpr B b{}; // expected-error {{constexpr variable 'b' must be 
initialized by a constant expression}} expected-note 2{{in call to 'B()'}}
+    return b.val;
+  }
+
+  constexpr auto x = foo(); // expected-error {{constexpr variable 'x' must be 
initialized by a constant expression}} expected-note {{in call to 'foo()'}}
+}
\ No newline at end of file
diff --git a/test.cpp b/test.cpp
new file mode 100644
index 0000000000000..a57b905cc317b
--- /dev/null
+++ b/test.cpp
@@ -0,0 +1,20 @@
+struct A {
+    constexpr A(int x) : val(x) {}
+    int val;
+};
+
+struct B : A {
+    constexpr int f() const { return 42; }
+
+    constexpr B() : A(f()) {}
+};
+
+constexpr int foo() {
+    constexpr B b{};
+    return b.val;
+}
+
+int main() {
+    constexpr auto x = foo();
+    return 0;
+}

>From 9dfc0a974c0cd457abfbe78de4590dd588e534b3 Mon Sep 17 00:00:00 2001
From: ahmedkamel10 <[email protected]>
Date: Fri, 28 Aug 2026 07:16:45 +0300
Subject: [PATCH 2/2] Remove test.cpp

---
 clang/lib/AST/ExprConstant.cpp                |  2 +-
 .../SemaCXX/constant-expression-cxx2a.cpp     |  9 +++------
 test.cpp                                      | 20 -------------------
 3 files changed, 4 insertions(+), 27 deletions(-)
 delete mode 100644 test.cpp

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 34c1cb39dd8b1..5c67eee6fcb1d 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -6630,7 +6630,7 @@ checkNonVirtualMemberCallThisPointer(EvalInfo &Info, 
const Expr *E,
   if (Phase == ConstructionPhase::Bases) {
     Info.FFDiag(E);
     return false;
-  }                                                       
+  }                                                     
   return checkDynamicType(
       Info, E, This,
       isa<CXXDestructorDecl>(NamedMember) ? AK_Destroy : AK_MemberCall, false);
diff --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp 
b/clang/test/SemaCXX/constant-expression-cxx2a.cpp
index 88b4808a4671e..7b62ecca1b4c7 100644
--- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp
@@ -1550,16 +1550,13 @@ namespace GH211286 {
     constexpr A(int x) : val(x) {}
     int val;
   };
-
   struct B : A {
     constexpr int f() const { return 42; }
-    constexpr B() : A(f()) {} // expected-note 2{{subexpression not valid in a 
constant expression}}
+    constexpr B() : A(f()) {} 
   };
-
   constexpr int foo() {
-    constexpr B b{}; // expected-error {{constexpr variable 'b' must be 
initialized by a constant expression}} expected-note 2{{in call to 'B()'}}
+    constexpr B b{}; 
     return b.val;
   }
-
-  constexpr auto x = foo(); // expected-error {{constexpr variable 'x' must be 
initialized by a constant expression}} expected-note {{in call to 'foo()'}}
+  constexpr auto x = foo(); 
 }
\ No newline at end of file
diff --git a/test.cpp b/test.cpp
deleted file mode 100644
index a57b905cc317b..0000000000000
--- a/test.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-struct A {
-    constexpr A(int x) : val(x) {}
-    int val;
-};
-
-struct B : A {
-    constexpr int f() const { return 42; }
-
-    constexpr B() : A(f()) {}
-};
-
-constexpr int foo() {
-    constexpr B b{};
-    return b.val;
-}
-
-int main() {
-    constexpr auto x = foo();
-    return 0;
-}

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

Reply via email to