https://github.com/aalmkainzi updated 
https://github.com/llvm/llvm-project/pull/232825

>From 7dd89682672c9b8a30e4a589171942b04465aaf6 Mon Sep 17 00:00:00 2001
From: Abdulmalek Almkainzi <[email protected]>
Date: Fri, 16 Oct 2026 19:18:19 +0300
Subject: [PATCH 1/3] file scope compound literal initializers are not
 converted to constexpr

---
 clang/lib/Sema/SemaExpr.cpp | 10 ++++------
 clang/test/Sema/constexpr.c |  4 ++++
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index e29caaab8e3f3..f191f59164b73 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7667,12 +7667,12 @@ Sema::BuildCompoundLiteralExpr(SourceLocation 
LParenLoc, TypeSourceInfo *TInfo,
     // constant context.
     auto CheckElement = [&](Expr *Init) -> Expr * {
       if (Init->isTypeDependent() || Init->isValueDependent())
-        return ConstantExpr::Create(Context, Init);
+        return Init;
       if (DeferImmediate) {
         ImmediateCallVisitor V(Context);
         V.TraverseStmt(Init);
         if (V.HasImmediateCalls)
-          return ConstantExpr::Create(Context, Init);
+          return Init;
       }
       Expr::EvalResult Eval;
       if (!Init->EvaluateAsConstantExpr(Eval, Context,
@@ -7681,10 +7681,8 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, 
TypeSourceInfo *TInfo,
             << Init->getSourceBitField();
         return nullptr;
       }
-      // An immediate invocation already is a ConstantExpr.
-      if (isa<ConstantExpr>(Init))
-        return Init;
-      return ConstantExpr::Create(Context, Init, Eval.Val);
+
+      return Init;
     };
     if (auto *ILE = dyn_cast<InitListExpr>(LiteralExpr)) {
       for (unsigned i = 0, j = ILE->getNumInits(); i != j; i++) {
diff --git a/clang/test/Sema/constexpr.c b/clang/test/Sema/constexpr.c
index 3bb8cffe16ab2..ed95fdd3592d6 100644
--- a/clang/test/Sema/constexpr.c
+++ b/clang/test/Sema/constexpr.c
@@ -473,3 +473,7 @@ static_assert(s2[0].L[2] == 'x');// expected-warning 
{{folding it to a constant
 
 x y; // expected-error{{unknown type name 'x'}}
 constexpr int *p = (int*){y};
+
+const int g1 = 1;
+constexpr int g2 = g1; // expected-error{{constexpr variable 'g2' must be 
initialized by a constant expression}}
+constexpr int g3 = (int){g1}; // expected-error{{constexpr variable 'g3' must 
be initialized by a constant expression}}

>From e7e3f6d8a8e42866a927c68029ed1dd8288c43c1 Mon Sep 17 00:00:00 2001
From: Abdulmalek Almkainzi <[email protected]>
Date: Fri, 16 Oct 2026 20:48:01 +0300
Subject: [PATCH 2/3] only in C

---
 clang/lib/Sema/SemaExpr.cpp | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index f191f59164b73..a5fb2bbed7083 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7667,12 +7667,12 @@ Sema::BuildCompoundLiteralExpr(SourceLocation 
LParenLoc, TypeSourceInfo *TInfo,
     // constant context.
     auto CheckElement = [&](Expr *Init) -> Expr * {
       if (Init->isTypeDependent() || Init->isValueDependent())
-        return Init;
+        return ConstantExpr::Create(Context, Init);
       if (DeferImmediate) {
         ImmediateCallVisitor V(Context);
         V.TraverseStmt(Init);
         if (V.HasImmediateCalls)
-          return Init;
+          return ConstantExpr::Create(Context, Init);
       }
       Expr::EvalResult Eval;
       if (!Init->EvaluateAsConstantExpr(Eval, Context,
@@ -7681,8 +7681,10 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, 
TypeSourceInfo *TInfo,
             << Init->getSourceBitField();
         return nullptr;
       }
-
-      return Init;
+      // An immediate invocation already is a ConstantExpr.
+      if (!getLangOpts().CPlusPlus || isa<ConstantExpr>(Init))
+        return Init;
+      return ConstantExpr::Create(Context, Init, Eval.Val);
     };
     if (auto *ILE = dyn_cast<InitListExpr>(LiteralExpr)) {
       for (unsigned i = 0, j = ILE->getNumInits(); i != j; i++) {

>From 51ad40f687d1960323d46dfeff036fe4c932c61e Mon Sep 17 00:00:00 2001
From: Abdulmalek Almkainzi <[email protected]>
Date: Wed, 21 Oct 2026 02:52:30 +0300
Subject: [PATCH 3/3] dont attempt to read non constexpr object if
 InConstantContext and in initializer

---
 clang/lib/AST/ExprConstant.cpp |  7 ++-----
 clang/lib/Sema/SemaExpr.cpp    |  2 +-
 clang/test/Sema/constexpr.c    | 28 +++++++++++++++++++++++++++-
 3 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 6d390032e2c71..d86cb3934c80f 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -4815,10 +4815,6 @@ static CompleteObject findCompleteObject(EvalInfo &Info, 
const Expr *E,
     }
 
     bool IsConstant = BaseType.isConstant(Info.Ctx);
-    bool ConstexprVar = false;
-    if (const auto *VD = dyn_cast_if_present<VarDecl>(
-            Info.EvaluatingDecl.dyn_cast<const ValueDecl *>()))
-      ConstexprVar = VD->isConstexpr();
 
     // Unless we're looking at a local variable or argument in a constexpr 
call,
     // the variable we're reading must be const (unless we are binding to a
@@ -4839,7 +4835,8 @@ static CompleteObject findCompleteObject(EvalInfo &Info, 
const Expr *E,
         return CompleteObject();
       } else if (VD->isConstexpr()) {
         // OK, we can read this variable.
-      } else if (Info.getLangOpts().C23 && ConstexprVar) {
+      } else if (Info.getLangOpts().C23 && Info.InConstantContext &&
+                 Info.EvaluatingDecl) {
         Info.FFDiag(E);
         return CompleteObject();
       } else if (VD->isCXXForRangeImplicitVar()) {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index a5fb2bbed7083..e29caaab8e3f3 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7682,7 +7682,7 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, 
TypeSourceInfo *TInfo,
         return nullptr;
       }
       // An immediate invocation already is a ConstantExpr.
-      if (!getLangOpts().CPlusPlus || isa<ConstantExpr>(Init))
+      if (isa<ConstantExpr>(Init))
         return Init;
       return ConstantExpr::Create(Context, Init, Eval.Val);
     };
diff --git a/clang/test/Sema/constexpr.c b/clang/test/Sema/constexpr.c
index ed95fdd3592d6..71ad72e1808bc 100644
--- a/clang/test/Sema/constexpr.c
+++ b/clang/test/Sema/constexpr.c
@@ -476,4 +476,30 @@ constexpr int *p = (int*){y};
 
 const int g1 = 1;
 constexpr int g2 = g1; // expected-error{{constexpr variable 'g2' must be 
initialized by a constant expression}}
-constexpr int g3 = (int){g1}; // expected-error{{constexpr variable 'g3' must 
be initialized by a constant expression}}
+constexpr int g3 = (int){g1}; // expected-error{{initializer element is not a 
compile-time constant}}
+
+// gh121694
+const int a = 0;
+struct C { const int *p; };
+constexpr struct C c1 = {&a}; // expected-error{{constexpr pointer initializer 
is not null}}
+constexpr struct C c2 = (struct C){&a}; // expected-error{{constexpr variable 
'c2' must be initialized by a constant expression}}
+constexpr struct C c3 = (struct C){nullptr};
+
+union U { const int *p; int x; };
+constexpr union U u1 = {.p = &a}; // expected-error{{constexpr pointer 
initializer is not null}}
+constexpr union U u2 = (union U){.p = &a}; // expected-error{{constexpr 
variable 'u2' must be initialized by a constant expression}}
+constexpr union U u3 = {.x = 1};
+constexpr union U u4 = (union U){.x = 1};
+
+void f() {
+  constexpr int *p2 = &a; // expected-error{{constexpr pointer initializer is 
not null}}
+}
+
+typedef typeof(nullptr) nullptr_t;
+
+constexpr nullptr_t woo1 = nullptr;
+constexpr struct C c4 = { woo1 };
+
+const nullptr_t woo2 = nullptr;
+constexpr struct C c5 = { woo2 };
+

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

Reply via email to