wanders created this revision.
wanders added reviewers: cor3ntin, rsmith.
wanders added a project: clang.
Herald added a project: All.
wanders requested review of this revision.
Herald added a subscriber: cfe-commits.

The commit 683e83c5 
<https://reviews.llvm.org/rG683e83c56f98df6fe42d506a04dda44309ca758f>

  [Clang][C++2b] P2242R3: Non-literal variables [...] in constexpr

fixed a code generation bug when using (C-extension) statement
expressions inside initializer expressions.

Before that commit a nested static initializer inside the statement
expression would not be emitted, causing it to be zero initialized.

It is a bit surprising (at least to me) that a commit implementing a new
C++ feature would fix this code generation bug. Zooming in it is the
change done in ExprConstant.cpp that helps. That changes so that
"ESR_Failed" is returned in more cases, causing the expression to not be
deemed constant. This fixes the code generation as instead the compiler
has to resort to generating a dynamic initializer.

That commit also meant that some statement expressions (in particular
the ones using static variables) that previously were accepted now are
errors due to not being constant (matching GCC behavior).

Given how a seemingly unrelated change caused this behavior to change,
it is probably a good thing to add at least some rudimentary tests for
these kind expressions.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D127201

Files:
  clang/test/CodeGen/stmtexpr-init.c
  clang/test/Sema/stmtexpr-init.c


Index: clang/test/Sema/stmtexpr-init.c
===================================================================
--- /dev/null
+++ clang/test/Sema/stmtexpr-init.c
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -verify -fsyntax-only -std=gnu11 %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}}
+}
Index: clang/test/CodeGen/stmtexpr-init.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/stmtexpr-init.c
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -O -std=gnu11 %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);
+}


Index: clang/test/Sema/stmtexpr-init.c
===================================================================
--- /dev/null
+++ clang/test/Sema/stmtexpr-init.c
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -verify -fsyntax-only -std=gnu11 %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}}
+}
Index: clang/test/CodeGen/stmtexpr-init.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/stmtexpr-init.c
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -O -std=gnu11 %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);
+}
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to