diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -170,6 +170,11 @@ fixes `Issue 48230 `_. - Fixed memory leak due to ``VarTemplateSpecializationDecl`` using ``TemplateArgumentListInfo`` instead of ``ASTTemplateArgumentListInfo``. +- An initializer for a static variable declaration, which is nested + inside a statement expression in an aggregate initializer, is now + emitted as a dynamic initializer. Previously the variable would + incorrectly be zero-initialized. In contexts where a dynamic + initializer is not allowed this is now diagnosed as an error. Improvements to Clang's diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/test/CodeGen/stmtexpr-init.c b/clang/test/CodeGen/stmtexpr-init.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/stmtexpr-init.c @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s + +void escape(const void *); + +// CHECK-DAG: internal global i8 99 + +void T1(void) { + const char *x[1] = {({static char _x = 99; &_x; })}; + escape(x); +} + +struct sized_array { + int count; + int entries[]; +}; + +#define N_ARGS(...) (sizeof((int[]){__VA_ARGS__}) / sizeof(int)) + +#define ARRAY_PTR(...) ({ \ + static const struct sized_array _a = {N_ARGS(__VA_ARGS__), {__VA_ARGS__}}; \ + &_a; \ +}) + +struct outer { + const struct sized_array *a; +}; + +void T2(void) { + // CHECK-DAG: internal constant { i32, [2 x i32] } { i32 2, [2 x i32] [i32 50, i32 60] } + const struct sized_array *A = ARRAY_PTR(50, 60); + + // CHECK-DAG: internal constant { i32, [3 x i32] } { i32 3, [3 x i32] [i32 10, i32 20, i32 30] } + struct outer X = {ARRAY_PTR(10, 20, 30)}; + + escape(A); + escape(&X); +} diff --git a/clang/test/Sema/stmtexpr-init.c b/clang/test/Sema/stmtexpr-init.c new file mode 100644 --- /dev/null +++ b/clang/test/Sema/stmtexpr-init.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -verify -fsyntax-only %s + +static int *z[1] = {({ static int _x = 70; &_x; })}; // expected-error {{statement expression not allowed at file scope}} + +void T1(void) { + int *x[1] = {({ static int _x = 10; &_x; })}; // expected-no-error + + /* Before commit + 683e83c5 [Clang][C++2b] P2242R3: Non-literal variables [...] in constexpr + (i.e in clang-14 and earlier) + this was silently accepted, but generated incorrect code. + */ + static int *y[1] = {({ static int _x = 20; &_x; })}; // expected-error {{initializer element is not a compile-time constant}} +}