Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions clang/lib/CodeGen/CGDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGenCXX/pr47636.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGenCXX/reference-init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
73 changes: 73 additions & 0 deletions clang/test/CodeGenCXX/static-constexpr-in-consteval.cpp
Original file line number Diff line number Diff line change
@@ -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: }
Loading