https://github.com/Fznamznon created https://github.com/llvm/llvm-project/pull/156933
Do not wait until the body of the function is met. This helps with initializing static variables in conseval functions. Fixes https://github.com/llvm/llvm-project/issues/82994 >From 3885133c5a2bafb8654f7b60e016c058705a21ee Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" <mariya.podchishcha...@intel.com> Date: Thu, 4 Sep 2025 10:17:23 -0700 Subject: [PATCH] [clang] Emit static const/constexpr variables once they're met Do not wait until the body of the function is met. This helps with initializing static variables in conseval functions. Fixes https://github.com/llvm/llvm-project/issues/82994 --- clang/lib/CodeGen/CGDecl.cpp | 21 +++++- clang/test/CodeGenCXX/pr47636.cpp | 2 +- clang/test/CodeGenCXX/reference-init.cpp | 2 +- .../static-constexpr-in-consteval.cpp | 73 +++++++++++++++++++ 4 files changed, 92 insertions(+), 6 deletions(-) create mode 100644 clang/test/CodeGenCXX/static-constexpr-in-consteval.cpp diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 29193e0c541b9..da030f4c73779 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -275,18 +275,31 @@ llvm::Constant *CodeGenModule::getOrCreateStaticVarDecl( LangAS AS = GetGlobalVarAddressSpace(&D); unsigned TargetAS = getContext().getTargetAddressSpace(AS); + Expr::EvalResult EvalResult; + llvm::Constant *Init = nullptr; + std::optional<ConstantEmitter> Emitter; // OpenCL variables in local address space and CUDA shared // variables cannot have an initializer. - llvm::Constant *Init = nullptr; if (Ty.getAddressSpace() == LangAS::opencl_local || - D.hasAttr<CUDASharedAttr>() || D.hasAttr<LoaderUninitializedAttr>()) + D.hasAttr<CUDASharedAttr>() || D.hasAttr<LoaderUninitializedAttr>()) { Init = llvm::UndefValue::get(LTy); - else + } else if (D.isUsableInConstantExpressions(getContext())) { + const Expr *InitExpr = D.getInit(); + assert(InitExpr && "Usable in constant expressions without initializer?"); + Emitter.emplace(*this); + llvm::Constant *Initializer = Emitter->tryEmitForInitializer(D); + Init = Initializer; + } else { Init = EmitNullConstant(Ty); + } llvm::GlobalVariable *GV = new llvm::GlobalVariable( - getModule(), LTy, Ty.isConstant(getContext()), Linkage, Init, Name, + getModule(), Init->getType(), Ty.isConstant(getContext()), Linkage, Init, Name, nullptr, llvm::GlobalVariable::NotThreadLocal, TargetAS); + + if (Emitter) + Emitter->finalize(GV); + GV->setAlignment(getContext().getDeclAlign(&D).getAsAlign()); if (supportsCOMDAT() && GV->isWeakForLinker()) diff --git a/clang/test/CodeGenCXX/pr47636.cpp b/clang/test/CodeGenCXX/pr47636.cpp index 597e94695ca5f..022e085e28845 100644 --- a/clang/test/CodeGenCXX/pr47636.cpp +++ b/clang/test/CodeGenCXX/pr47636.cpp @@ -5,8 +5,8 @@ int(&&intu_rvref)[] {1,2,3,4}; void foo() { static const int(&&intu_rvref)[] {1,2,3,4}; - // CHECK: @_ZZ3foovE10intu_rvref = internal constant ptr @_ZGRZ3foovE10intu_rvref_ // CHECK: @_ZGRZ3foovE10intu_rvref_ = internal constant [4 x i32] [i32 1, i32 2, i32 3, i32 4] + // CHECK: @_ZZ3foovE10intu_rvref = internal constant ptr @_ZGRZ3foovE10intu_rvref_ } // Example given on review, ensure this doesn't crash as well. diff --git a/clang/test/CodeGenCXX/reference-init.cpp b/clang/test/CodeGenCXX/reference-init.cpp index a98d400eb17a2..67a901dfe6fa3 100644 --- a/clang/test/CodeGenCXX/reference-init.cpp +++ b/clang/test/CodeGenCXX/reference-init.cpp @@ -4,8 +4,8 @@ // expected-no-diagnostics #if __cplusplus >= 201103L -// CHECK-CXX11: @_ZZ15InitRefWithListvE1r = internal constant ptr @_ZGRZ15InitRefWithListvE1r_ // CHECK-CXX11: @_ZGRZ15InitRefWithListvE1r_ = internal constant i32 123 +// CHECK-CXX11: @_ZZ15InitRefWithListvE1r = internal constant ptr @_ZGRZ15InitRefWithListvE1r_ int InitRefWithList() { static const int &r = {123}; return r; } #endif diff --git a/clang/test/CodeGenCXX/static-constexpr-in-consteval.cpp b/clang/test/CodeGenCXX/static-constexpr-in-consteval.cpp new file mode 100644 index 0000000000000..d818f9725f196 --- /dev/null +++ b/clang/test/CodeGenCXX/static-constexpr-in-consteval.cpp @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++23 %s -emit-llvm -o - | FileCheck %s + +consteval const int* a() { + static constexpr int b = 3; + return &b; +} + +consteval const int returns42() { + static constexpr long c = 42; + return c; +} + +struct S { + int a; + constexpr S(int _a) : a(_a){}; +}; + +consteval auto returns48viastruct() { + static constexpr S s{ 48 }; + return s; +} + +consteval int why() { + static constexpr int a = 10; + { + static constexpr int a = 20; + return a; + } + +} + +consteval const int* returnsarray() { + static constexpr int a[] = {10, 20, 30}; + return a; +} + +// CHECK: @_ZZ1avE1b = linkonce_odr constant i32 3, comdat, align 4 +// CHECK: @_ZZ12returnsarrayvE1a = linkonce_odr constant [3 x i32] [i32 10, i32 20, i32 30], comdat, align 4 + +// CHECK: define dso_local noundef i32 @_Z1cv() +// CHECK-NEXT: entry: +// CHECK-NEXT: %0 = load i32, ptr @_ZZ1avE1b, align 4 +// CHECK-NEXT: ret i32 %0 +// CHECK-NEXT: } +int c() { return *a(); } + +// CHECK: define dso_local noundef i32 @_Z1dv() +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 42 +// CHECK-NEXT: } +int d() { return returns42(); } + +int e() { return returns48viastruct().a; } +// CHECK: define dso_local noundef i32 @_Z1ev() +// CHECK-NEXT: entry: +// CHECK-NEXT: %ref.tmp = alloca %struct.S, align 4 +// CHECK-NEXT: %0 = getelementptr inbounds nuw %struct.S, ptr %ref.tmp, i32 0, i32 0 +// CHECK-NEXT: store i32 48, ptr %0, align 4 +// CHECK-NEXT: ret i32 48 +// CHECK-NEXT: } + +int f() { return why(); } +// CHECK: define dso_local noundef i32 @_Z1fv() +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 20 +// CHECK-NEXT: } + +int g() { return returnsarray()[2]; } +// CHECK: define dso_local noundef i32 @_Z1gv() +// CHECK-NEXT: entry: +// CHECK-NEXT: %0 = load i32, ptr getelementptr inbounds (i32, ptr @_ZZ12returnsarrayvE1a, i64 2), align 4 +// CHECK-NEXT: ret i32 %0 +// CHECK-NEXT: } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits