[clang] [clang] Fixed inconsistent diagnostics when initializing a constexpr variable with a compound literal (PR #232825)

Abdulmalek Almkainzi via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 16 10:48:17 PDT 2026


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 <aalmkainzi at gmail.com>
Date: Fri, 16 Oct 2026 19:18:19 +0300
Subject: [PATCH 1/2] 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 e29caaab8e3f30..f191f59164b731 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 3bb8cffe16ab21..ed95fdd3592d6c 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 <aalmkainzi at gmail.com>
Date: Fri, 16 Oct 2026 20:48:01 +0300
Subject: [PATCH 2/2] 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 f191f59164b731..a5fb2bbed7083a 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++) {



More information about the cfe-commits mailing list