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
