llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clangir Author: Akash Manna (akash-manna-sky) <details> <summary>Changes</summary> Fixes #<!-- -->212106 A file-scope compound literal is always a constant-initialized global, and Sema checks its initializer in a constant context, where `__builtin_constant_p` of something it can't fold just yields 0. CodeGen evaluated the same initializer under whatever context the *caller* was in. When the literal's address is taken by a global that needs dynamic initialization, that context is non-constant, `__builtin_constant_p` refuses to fold, and `tryEmitGlobalCompoundLiteral` asserts. The strict-FP variant of this was fixed in D131555 by propagating the caller's context, which didn't cover this entry point. The literal's constant-ness is a property of the literal, not of whoever asks for its address, so `tryEmitGlobalCompoundLiteral` now sets the constant context itself for any file-scope literal. That covers both callers and keeps the assertion in place. The same two lines are mirrored in CIR, which has the identical check. --- Full diff: https://github.com/llvm/llvm-project/pull/221390.diff 5 Files Affected: - (modified) clang/docs/ReleaseNotes.md (+4) - (modified) clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp (+6) - (modified) clang/lib/CodeGen/CGExprConstant.cpp (+6) - (modified) clang/test/AST/static-compound-literals-crash.cpp (+2-10) - (added) clang/test/CodeGenCXX/GH212106.cpp (+49) ``````````diff diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 042d7112dbe7d..18de7e72abef4 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -652,6 +652,10 @@ features cannot lower the translation-unit ABI level; - Fixed a crash when generating fake uses for parameters of bodyless destructors with `-fextend-variable-liveness`. - Fixed an assertion failure when instantiating a block that captures `this` via a member access through a dependent base class. +- Fixed an assertion failure when the dynamic initializer of a global variable + takes the address of a file-scope compound literal whose initializer is only + constant under constant-evaluation rules, such as `__builtin_constant_p` of a + non-constant expression. (#GH212106) ### OpenACC Specific Changes diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp index 4bebe053f5768..d036d73388100 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp @@ -941,6 +941,12 @@ tryEmitGlobalCompoundLiteral(ConstantEmitter &emitter, if (cir::GlobalOp addr = cgm.getAddrOfConstantCompoundLiteralIfEmitted(e)) return builder.getGlobalViewAttr(addr); + // A file-scope compound literal is a constant-initialized global, so emit + // its initializer under constant-evaluation rules even when reached from a + // non-constant context. + if (e->isFileScope()) + emitter.setInConstantContext(true); + assert(!cir::MissingFeatures::addressSpace()); mlir::Attribute c = emitter.tryEmitForInitializer(e->getInitializer(), e->getType()); diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 48e80910ce577..cf2a4ff18cea6 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1087,6 +1087,12 @@ tryEmitGlobalCompoundLiteral(ConstantEmitter &emitter, CGM.getAddrOfConstantCompoundLiteralIfEmitted(E)) return ConstantAddress(Addr, Addr->getValueType(), Align); + // A file-scope compound literal is a constant-initialized global, so emit + // its initializer under constant-evaluation rules even when reached from a + // non-constant context such as the dynamic initializer of another global. + if (E->isFileScope()) + emitter.setInConstantContext(true); + LangAS addressSpace = E->getType().getAddressSpace(); llvm::Constant *C = emitter.tryEmitForInitializer(E->getInitializer(), addressSpace, E->getType()); diff --git a/clang/test/AST/static-compound-literals-crash.cpp b/clang/test/AST/static-compound-literals-crash.cpp index f9c3bd82fd025..838d67b2f3f17 100644 --- a/clang/test/AST/static-compound-literals-crash.cpp +++ b/clang/test/AST/static-compound-literals-crash.cpp @@ -1,5 +1,5 @@ -// FIXME: These test cases currently crash during codegen, despite initializers -// for CLEs being constant. +// FIXME: This test case currently crashes during codegen, despite the +// initializer for the CLE being constant. // RUN: not --crash %clang_cc1 -verify -std=c++20 -emit-llvm %s -o - // expected-no-diagnostics namespace case1 { @@ -7,11 +7,3 @@ struct RR { int&& r; }; struct Z { RR* x; }; constinit Z z = { (RR[1]){1} }; } - - -namespace case2 { -struct RR { int r; }; -struct Z { int x; const RR* y; int z; }; -inline int f() { return 0; } -Z z2 = { 10, (const RR[1]){__builtin_constant_p(z2.x)}, z2.y->r+f() }; -} diff --git a/clang/test/CodeGenCXX/GH212106.cpp b/clang/test/CodeGenCXX/GH212106.cpp new file mode 100644 index 0000000000000..dfdf5dd96924d --- /dev/null +++ b/clang/test/CodeGenCXX/GH212106.cpp @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -ffp-exception-behavior=strict -emit-llvm -o - %s | FileCheck %s + +// A file-scope compound literal is a constant-initialized global even when its +// address is taken from a non-constant context, so its initializer must be +// emitted under constant-evaluation rules. + +struct RR { int r; }; +struct Z { int x; const RR* y; int z; }; +inline int f() { return 0; } +Z z2 = { 10, (const RR[1]){__builtin_constant_p(z2.x)}, z2.y->r+f() }; + +// CHECK-DAG: @z2 = {{.*}}global %struct.Z zeroinitializer +// CHECK-DAG: [[Z2CL:@.compoundliteral(\.[0-9]+)?]] = internal constant [1 x %struct.RR] zeroinitializer + +namespace reduced { +struct Z { const int* y; int z; }; +int f(); +Z z2 = { (int[1]){__builtin_constant_p(z2.z)}, f() }; +} + +// CHECK-DAG: @_ZN7reduced2z2E = {{.*}}global %"struct.reduced::Z" zeroinitializer +// CHECK-DAG: @.compoundliteral{{(\.[0-9]+)?}} = internal global [1 x i32] zeroinitializer + +struct F { int a; const float *fp; }; +int g(); +F fl = { g(), (float[1]){0.1} }; + +// CHECK-DAG: @fl = {{.*}}global %struct.F zeroinitializer +// CHECK-DAG: @.compoundliteral{{(\.[0-9]+)?}} = internal global [1 x float] [float 1.000000e-01] + +const RR *p = (const RR[1]){__builtin_constant_p(1)}; + +// CHECK-DAG: @.compoundliteral{{(\.[0-9]+)?}} = internal constant [1 x %struct.RR] [%struct.RR { i32 1 }] +// CHECK-DAG: @p = {{.*}}global ptr @.compoundliteral{{(\.[0-9]+)?}} + +// A default member initializer at namespace scope is also a file-scope compound +// literal, reached here from a constructor emitted for a local variable. +extern int n; +struct Q { const int *m = (const int[1]){__builtin_constant_p(n)}; }; +void h() { Q q; } + +// CHECK-DAG: [[QCL:@.compoundliteral(\.[0-9]+)?]] = internal constant [1 x i32] zeroinitializer + +// CHECK-LABEL: define internal void @__cxx_global_var_init() +// CHECK: store ptr [[Z2CL]], ptr getelementptr inbounds{{.*}}(i8, ptr @z2, i64 8) + +// CHECK-LABEL: define {{.*}}void @_ZN1QC2Ev( +// CHECK: store ptr [[QCL]], ptr `````````` </details> https://github.com/llvm/llvm-project/pull/221390 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
