673 lines
26 KiB
Diff
673 lines
26 KiB
Diff
From 0a34bb6b18cdf34cb9d4f34b1697e1bcfcff139b Mon Sep 17 00:00:00 2001
|
|
From: Joseph Myers <joseph@codesourcery.com>
|
|
Date: Thu, 25 Aug 2022 21:02:57 +0000
|
|
Subject: [PATCH 135/157] [Backport][SME] c: Support C2x empty initializer
|
|
braces
|
|
|
|
Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=14cfa01755a66afbae2539f8b5796c960ddcecc6
|
|
|
|
ISO C2x standardizes empty initializer braces {}. Implement this
|
|
feature accordingly. The basic case was already supported and so just
|
|
needed diagnostic adjustments. However, the standard feature also
|
|
includes two cases that were not previously supported: empty
|
|
initializer braces for scalars, and empty initializer braces for
|
|
VLAs. Thus, add support for those features as well, updating existing
|
|
tests that expected them to be diagnosed.
|
|
|
|
There was already some gimplifier support for converting
|
|
variable-sized initializations with empty CONSTRUCTORs to memset.
|
|
However, it didn't apply here; code earlier in gimplify_modify_expr
|
|
ended up calling gimplify_init_constructor via
|
|
gimplify_modify_expr_rhs, which ended up handling the CONSTRUCTOR in a
|
|
way that generated an ICE later. Add a check for this case earlier in
|
|
gimplify_modify_expr to avoid that issue.
|
|
|
|
Bootstrapped with no regressions for x86_64-pc-linux-gnu.
|
|
|
|
gcc/
|
|
* gimplify.cc (gimplify_modify_expr): Convert initialization from
|
|
a variable-size CONSTRUCTOR to memset before call to
|
|
gimplify_modify_expr_rhs.
|
|
|
|
gcc/c/
|
|
* c-decl.cc (start_decl): Do not diagnose initialization of
|
|
variable-sized objects here.
|
|
* c-parser.cc (c_parser_braced_init): Add argument DECL. All
|
|
callers changed.
|
|
(c_parser_initializer): Diagnose initialization of variable-sized
|
|
objects other than with braced initializer.
|
|
(c_parser_braced_init): Use pedwarn_c11 for empty initializer
|
|
braces and update diagnostic text. Diagnose initialization of
|
|
variable-sized objects with nonempty braces.
|
|
* c-typeck.cc (digest_init): Update diagnostic for initialization
|
|
of variable-sized objects.
|
|
(really_start_incremental_init, set_designator)
|
|
(process_init_element): Update comments.
|
|
(pop_init_level): Allow scalar empty initializers.
|
|
|
|
gcc/testsuite/
|
|
* gcc.dg/c11-empty-init-1.c, gcc.dg/c11-empty-init-2.c,
|
|
gcc.dg/c11-empty-init-3.c, gcc.dg/c2x-empty-init-1.c,
|
|
gcc.dg/c2x-empty-init-2.c, gcc.dg/c2x-empty-init-3.c,
|
|
gcc.dg/gnu2x-empty-init-1.c, gcc.dg/gnu2x-empty-init-2.c: New
|
|
tests.
|
|
* gcc.dg/torture/dfp-default-init-1.c: Also test empty
|
|
initializers.
|
|
* gcc.dg/init-bad-1.c, gcc.dg/noncompile/pr71583.c,
|
|
gcc.dg/pr61096-1.c, gcc.dg/vla-init-2.c, gcc.dg/vla-init-3.c,
|
|
gcc.target/i386/sse2-bfloat16-scalar-typecheck.c: Update expected
|
|
diagnostics.
|
|
* gcc.dg/ubsan/c-shift-1.c: Use nonempty initializers for VLA
|
|
initializations expected to be diagnosed.
|
|
---
|
|
gcc/c/c-decl.cc | 20 +-----
|
|
gcc/c/c-parser.cc | 24 +++++--
|
|
gcc/c/c-typeck.cc | 23 ++++---
|
|
gcc/gimplify.cc | 15 +++++
|
|
gcc/testsuite/gcc.dg/c11-empty-init-1.c | 25 +++++++
|
|
gcc/testsuite/gcc.dg/c11-empty-init-2.c | 25 +++++++
|
|
gcc/testsuite/gcc.dg/c11-empty-init-3.c | 25 +++++++
|
|
gcc/testsuite/gcc.dg/c2x-empty-init-1.c | 80 +++++++++++++++++++++++
|
|
gcc/testsuite/gcc.dg/c2x-empty-init-2.c | 18 +++++
|
|
gcc/testsuite/gcc.dg/c2x-empty-init-3.c | 25 +++++++
|
|
gcc/testsuite/gcc.dg/gnu2x-empty-init-1.c | 29 ++++++++
|
|
gcc/testsuite/gcc.dg/gnu2x-empty-init-2.c | 16 +++++
|
|
gcc/testsuite/gcc.dg/init-bad-1.c | 3 +-
|
|
gcc/testsuite/gcc.dg/noncompile/pr71583.c | 2 +-
|
|
gcc/testsuite/gcc.dg/pr61096-1.c | 2 +-
|
|
gcc/testsuite/gcc.dg/ubsan/c-shift-1.c | 12 ++--
|
|
gcc/testsuite/gcc.dg/vla-init-2.c | 1 -
|
|
gcc/testsuite/gcc.dg/vla-init-3.c | 1 -
|
|
18 files changed, 301 insertions(+), 45 deletions(-)
|
|
create mode 100644 gcc/testsuite/gcc.dg/c11-empty-init-1.c
|
|
create mode 100644 gcc/testsuite/gcc.dg/c11-empty-init-2.c
|
|
create mode 100644 gcc/testsuite/gcc.dg/c11-empty-init-3.c
|
|
create mode 100644 gcc/testsuite/gcc.dg/c2x-empty-init-1.c
|
|
create mode 100644 gcc/testsuite/gcc.dg/c2x-empty-init-2.c
|
|
create mode 100644 gcc/testsuite/gcc.dg/c2x-empty-init-3.c
|
|
create mode 100644 gcc/testsuite/gcc.dg/gnu2x-empty-init-1.c
|
|
create mode 100644 gcc/testsuite/gcc.dg/gnu2x-empty-init-2.c
|
|
|
|
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
|
|
index 9d87a8cdb..685bb1757 100644
|
|
--- a/gcc/c/c-decl.cc
|
|
+++ b/gcc/c/c-decl.cc
|
|
@@ -5166,29 +5166,15 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
|
|
initialized = false;
|
|
else if (COMPLETE_TYPE_P (TREE_TYPE (decl)))
|
|
{
|
|
- /* A complete type is ok if size is fixed. */
|
|
-
|
|
- if (!poly_int_tree_p (TYPE_SIZE (TREE_TYPE (decl)))
|
|
- || C_DECL_VARIABLE_SIZE (decl))
|
|
- {
|
|
- error ("variable-sized object may not be initialized");
|
|
- initialized = false;
|
|
- }
|
|
+ /* A complete type is ok if size is fixed. If the size is
|
|
+ variable, an empty initializer is OK and nonempty
|
|
+ initializers will be diagnosed in the parser. */
|
|
}
|
|
else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
|
|
{
|
|
error ("variable %qD has initializer but incomplete type", decl);
|
|
initialized = false;
|
|
}
|
|
- else if (C_DECL_VARIABLE_SIZE (decl))
|
|
- {
|
|
- /* Although C99 is unclear about whether incomplete arrays
|
|
- of VLAs themselves count as VLAs, it does not make
|
|
- sense to permit them to be initialized given that
|
|
- ordinary VLAs may not be initialized. */
|
|
- error ("variable-sized object may not be initialized");
|
|
- initialized = false;
|
|
- }
|
|
}
|
|
|
|
if (initialized)
|
|
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
|
|
index 486f46e1c..6db535d11 100644
|
|
--- a/gcc/c/c-parser.cc
|
|
+++ b/gcc/c/c-parser.cc
|
|
@@ -1515,7 +1515,7 @@ static tree c_parser_simple_asm_expr (c_parser *);
|
|
static tree c_parser_gnu_attributes (c_parser *);
|
|
static struct c_expr c_parser_initializer (c_parser *, tree);
|
|
static struct c_expr c_parser_braced_init (c_parser *, tree, bool,
|
|
- struct obstack *);
|
|
+ struct obstack *, tree);
|
|
static void c_parser_initelt (c_parser *, struct obstack *);
|
|
static void c_parser_initval (c_parser *, struct c_expr *,
|
|
struct obstack *);
|
|
@@ -5247,11 +5247,15 @@ static struct c_expr
|
|
c_parser_initializer (c_parser *parser, tree decl)
|
|
{
|
|
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
|
|
- return c_parser_braced_init (parser, NULL_TREE, false, NULL);
|
|
+ return c_parser_braced_init (parser, NULL_TREE, false, NULL, decl);
|
|
else
|
|
{
|
|
struct c_expr ret;
|
|
location_t loc = c_parser_peek_token (parser)->location;
|
|
+ if (decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl))
|
|
+ error_at (loc,
|
|
+ "variable-sized object may not be initialized except "
|
|
+ "with an empty initializer");
|
|
ret = c_parser_expr_no_commas (parser, NULL);
|
|
/* This is handled mostly by gimplify.cc, but we have to deal with
|
|
not warning about int x = x; as it is a GCC extension to turn off
|
|
@@ -5278,11 +5282,12 @@ location_t last_init_list_comma;
|
|
compound literal, and NULL_TREE for other initializers and for
|
|
nested braced lists. NESTED_P is true for nested braced lists,
|
|
false for the list of a compound literal or the list that is the
|
|
- top-level initializer in a declaration. */
|
|
+ top-level initializer in a declaration. DECL is the declaration for
|
|
+ the top-level initializer for a declaration, otherwise NULL_TREE. */
|
|
|
|
static struct c_expr
|
|
c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
|
|
- struct obstack *outer_obstack)
|
|
+ struct obstack *outer_obstack, tree decl)
|
|
{
|
|
struct c_expr ret;
|
|
struct obstack braced_init_obstack;
|
|
@@ -5300,10 +5305,15 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
|
|
really_start_incremental_init (type);
|
|
if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
|
|
{
|
|
- pedwarn (brace_loc, OPT_Wpedantic, "ISO C forbids empty initializer braces");
|
|
+ pedwarn_c11 (brace_loc, OPT_Wpedantic,
|
|
+ "ISO C forbids empty initializer braces before C2X");
|
|
}
|
|
else
|
|
{
|
|
+ if (decl && decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl))
|
|
+ error_at (brace_loc,
|
|
+ "variable-sized object may not be initialized except "
|
|
+ "with an empty initializer");
|
|
/* Parse a non-empty initializer list, possibly with a trailing
|
|
comma. */
|
|
while (true)
|
|
@@ -5559,7 +5569,7 @@ c_parser_initval (c_parser *parser, struct c_expr *after,
|
|
|
|
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after)
|
|
init = c_parser_braced_init (parser, NULL_TREE, true,
|
|
- braced_init_obstack);
|
|
+ braced_init_obstack, NULL_TREE);
|
|
else
|
|
{
|
|
init = c_parser_expr_no_commas (parser, after);
|
|
@@ -10312,7 +10322,7 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
|
|
error_at (type_loc, "compound literal has variable size");
|
|
type = error_mark_node;
|
|
}
|
|
- init = c_parser_braced_init (parser, type, false, NULL);
|
|
+ init = c_parser_braced_init (parser, type, false, NULL, NULL_TREE);
|
|
finish_init ();
|
|
maybe_warn_string_init (type_loc, type, init);
|
|
|
|
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
|
|
index 603b03fe1..0889dd4cb 100644
|
|
--- a/gcc/c/c-typeck.cc
|
|
+++ b/gcc/c/c-typeck.cc
|
|
@@ -8267,7 +8267,9 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
|
|
|
|
if (COMPLETE_TYPE_P (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
|
|
{
|
|
- error_init (init_loc, "variable-sized object may not be initialized");
|
|
+ error_init (init_loc,
|
|
+ "variable-sized object may not be initialized except "
|
|
+ "with an empty initializer");
|
|
return error_mark_node;
|
|
}
|
|
|
|
@@ -8617,8 +8619,9 @@ really_start_incremental_init (tree type)
|
|
constructor_max_index = integer_minus_one_node;
|
|
|
|
/* constructor_max_index needs to be an INTEGER_CST. Attempts
|
|
- to initialize VLAs will cause a proper error; avoid tree
|
|
- checking errors as well by setting a safe value. */
|
|
+ to initialize VLAs with a nonempty initializer will cause a
|
|
+ proper error; avoid tree checking errors as well by setting a
|
|
+ safe value. */
|
|
if (constructor_max_index
|
|
&& TREE_CODE (constructor_max_index) != INTEGER_CST)
|
|
constructor_max_index = integer_minus_one_node;
|
|
@@ -9000,12 +9003,14 @@ pop_init_level (location_t loc, int implicit,
|
|
&& !gnu_vector_type_p (constructor_type))
|
|
{
|
|
/* A nonincremental scalar initializer--just return
|
|
- the element, after verifying there is just one. */
|
|
+ the element, after verifying there is just one.
|
|
+ Empty scalar initializers are supported in C2X. */
|
|
if (vec_safe_is_empty (constructor_elements))
|
|
{
|
|
- if (!constructor_erroneous && constructor_type != error_mark_node)
|
|
- error_init (loc, "empty scalar initializer");
|
|
- ret.value = error_mark_node;
|
|
+ if (constructor_erroneous || constructor_type == error_mark_node)
|
|
+ ret.value = error_mark_node;
|
|
+ else
|
|
+ ret.value = build_zero_cst (constructor_type);
|
|
}
|
|
else if (vec_safe_length (constructor_elements) != 1)
|
|
{
|
|
@@ -9090,7 +9095,7 @@ set_designator (location_t loc, bool array,
|
|
return true;
|
|
|
|
/* Likewise for an initializer for a variable-size type. Those are
|
|
- diagnosed in digest_init. */
|
|
+ diagnosed in the parser, except for empty initializer braces. */
|
|
if (COMPLETE_TYPE_P (constructor_type)
|
|
&& TREE_CODE (TYPE_SIZE (constructor_type)) != INTEGER_CST)
|
|
return true;
|
|
@@ -10251,7 +10256,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
|
|
return;
|
|
|
|
/* Ignore elements of an initializer for a variable-size type.
|
|
- Those are diagnosed in digest_init. */
|
|
+ Those are diagnosed in the parser (empty initializer braces are OK). */
|
|
if (COMPLETE_TYPE_P (constructor_type)
|
|
&& !poly_int_tree_p (TYPE_SIZE (constructor_type)))
|
|
return;
|
|
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
|
|
index a551c574a..91500e2fb 100644
|
|
--- a/gcc/gimplify.cc
|
|
+++ b/gcc/gimplify.cc
|
|
@@ -6026,6 +6026,21 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
|
|
return GS_ALL_DONE;
|
|
}
|
|
|
|
+ /* Convert initialization from an empty variable-size CONSTRUCTOR to
|
|
+ memset. */
|
|
+ if (TREE_TYPE (*from_p) != error_mark_node
|
|
+ && TYPE_SIZE_UNIT (TREE_TYPE (*from_p))
|
|
+ && !poly_int_tree_p (TYPE_SIZE_UNIT (TREE_TYPE (*from_p)))
|
|
+ && TREE_CODE (*from_p) == CONSTRUCTOR
|
|
+ && CONSTRUCTOR_NELTS (*from_p) == 0)
|
|
+ {
|
|
+ maybe_with_size_expr (from_p);
|
|
+ gcc_assert (TREE_CODE (*from_p) == WITH_SIZE_EXPR);
|
|
+ return gimplify_modify_expr_to_memset (expr_p,
|
|
+ TREE_OPERAND (*from_p, 1),
|
|
+ want_value, pre_p);
|
|
+ }
|
|
+
|
|
/* Insert pointer conversions required by the middle-end that are not
|
|
required by the frontend. This fixes middle-end type checking for
|
|
for example gcc.dg/redecl-6.c. */
|
|
diff --git a/gcc/testsuite/gcc.dg/c11-empty-init-1.c b/gcc/testsuite/gcc.dg/c11-empty-init-1.c
|
|
new file mode 100644
|
|
index 000000000..120c28225
|
|
--- /dev/null
|
|
+++ b/gcc/testsuite/gcc.dg/c11-empty-init-1.c
|
|
@@ -0,0 +1,25 @@
|
|
+/* Test C11 does not support empty initializers. */
|
|
+/* { dg-do compile } */
|
|
+/* { dg-options "-std=c11 -pedantic-errors" } */
|
|
+
|
|
+struct s { int a; };
|
|
+struct s s = {}; /* { dg-error "empty initializer" } */
|
|
+int x = {}; /* { dg-error "empty initializer" } */
|
|
+float y = {}; /* { dg-error "empty initializer" } */
|
|
+void *p = {}; /* { dg-error "empty initializer" } */
|
|
+union u { int a; long b; };
|
|
+union u z = {}; /* { dg-error "empty initializer" } */
|
|
+int aa[2] = {}; /* { dg-error "empty initializer" } */
|
|
+
|
|
+void
|
|
+f (int a)
|
|
+{
|
|
+ int vla[a] = {}; /* { dg-error "empty initializer" } */
|
|
+ struct s as = {}; /* { dg-error "empty initializer" } */
|
|
+ int ax = {}; /* { dg-error "empty initializer" } */
|
|
+ float ay = {}; /* { dg-error "empty initializer" } */
|
|
+ void *ap = {}; /* { dg-error "empty initializer" } */
|
|
+ union u az = {}; /* { dg-error "empty initializer" } */
|
|
+ int aaa[2] = {}; /* { dg-error "empty initializer" } */
|
|
+ int t = (int) {}; /* { dg-error "empty initializer" } */
|
|
+}
|
|
diff --git a/gcc/testsuite/gcc.dg/c11-empty-init-2.c b/gcc/testsuite/gcc.dg/c11-empty-init-2.c
|
|
new file mode 100644
|
|
index 000000000..3ec7c512a
|
|
--- /dev/null
|
|
+++ b/gcc/testsuite/gcc.dg/c11-empty-init-2.c
|
|
@@ -0,0 +1,25 @@
|
|
+/* Test C11 does not support empty initializers. */
|
|
+/* { dg-do compile } */
|
|
+/* { dg-options "-std=c11 -pedantic" } */
|
|
+
|
|
+struct s { int a; };
|
|
+struct s s = {}; /* { dg-warning "empty initializer" } */
|
|
+int x = {}; /* { dg-warning "empty initializer" } */
|
|
+float y = {}; /* { dg-warning "empty initializer" } */
|
|
+void *p = {}; /* { dg-warning "empty initializer" } */
|
|
+union u { int a; long b; };
|
|
+union u z = {}; /* { dg-warning "empty initializer" } */
|
|
+int aa[2] = {}; /* { dg-warning "empty initializer" } */
|
|
+
|
|
+void
|
|
+f (int a)
|
|
+{
|
|
+ int vla[a] = {}; /* { dg-warning "empty initializer" } */
|
|
+ struct s as = {}; /* { dg-warning "empty initializer" } */
|
|
+ int ax = {}; /* { dg-warning "empty initializer" } */
|
|
+ float ay = {}; /* { dg-warning "empty initializer" } */
|
|
+ void *ap = {}; /* { dg-warning "empty initializer" } */
|
|
+ union u az = {}; /* { dg-warning "empty initializer" } */
|
|
+ int aaa[2] = {}; /* { dg-warning "empty initializer" } */
|
|
+ int t = (int) {}; /* { dg-warning "empty initializer" } */
|
|
+}
|
|
diff --git a/gcc/testsuite/gcc.dg/c11-empty-init-3.c b/gcc/testsuite/gcc.dg/c11-empty-init-3.c
|
|
new file mode 100644
|
|
index 000000000..fd43fa789
|
|
--- /dev/null
|
|
+++ b/gcc/testsuite/gcc.dg/c11-empty-init-3.c
|
|
@@ -0,0 +1,25 @@
|
|
+/* Test C11 does not support empty initializers. */
|
|
+/* { dg-do compile } */
|
|
+/* { dg-options "-std=c11 -Wc11-c2x-compat" } */
|
|
+
|
|
+struct s { int a; };
|
|
+struct s s = {}; /* { dg-warning "empty initializer" } */
|
|
+int x = {}; /* { dg-warning "empty initializer" } */
|
|
+float y = {}; /* { dg-warning "empty initializer" } */
|
|
+void *p = {}; /* { dg-warning "empty initializer" } */
|
|
+union u { int a; long b; };
|
|
+union u z = {}; /* { dg-warning "empty initializer" } */
|
|
+int aa[2] = {}; /* { dg-warning "empty initializer" } */
|
|
+
|
|
+void
|
|
+f (int a)
|
|
+{
|
|
+ int vla[a] = {}; /* { dg-warning "empty initializer" } */
|
|
+ struct s as = {}; /* { dg-warning "empty initializer" } */
|
|
+ int ax = {}; /* { dg-warning "empty initializer" } */
|
|
+ float ay = {}; /* { dg-warning "empty initializer" } */
|
|
+ void *ap = {}; /* { dg-warning "empty initializer" } */
|
|
+ union u az = {}; /* { dg-warning "empty initializer" } */
|
|
+ int aaa[2] = {}; /* { dg-warning "empty initializer" } */
|
|
+ int t = (int) {}; /* { dg-warning "empty initializer" } */
|
|
+}
|
|
diff --git a/gcc/testsuite/gcc.dg/c2x-empty-init-1.c b/gcc/testsuite/gcc.dg/c2x-empty-init-1.c
|
|
new file mode 100644
|
|
index 000000000..1487a2b23
|
|
--- /dev/null
|
|
+++ b/gcc/testsuite/gcc.dg/c2x-empty-init-1.c
|
|
@@ -0,0 +1,80 @@
|
|
+/* Test C2X support for empty initializers: valid use cases. */
|
|
+/* { dg-do run } */
|
|
+/* { dg-options "-std=c2x -pedantic-errors" } */
|
|
+
|
|
+extern void exit (int);
|
|
+extern void abort (void);
|
|
+
|
|
+struct s { int a; };
|
|
+struct s s = {};
|
|
+int x = {};
|
|
+float y = {};
|
|
+void *p = {};
|
|
+union u { int a; long b; };
|
|
+union u z = {};
|
|
+int aa[2] = {};
|
|
+
|
|
+void
|
|
+f (int a)
|
|
+{
|
|
+ volatile int vla[a] = {};
|
|
+ struct s as = {};
|
|
+ int ax = {};
|
|
+ float ay = {};
|
|
+ void *ap = {};
|
|
+ union u az = {};
|
|
+ int aaa[2] = {};
|
|
+ for (int i = 0; i < a; i++)
|
|
+ if (vla[i] != 0)
|
|
+ abort ();
|
|
+ if (as.a != 0)
|
|
+ abort ();
|
|
+ if (ax != 0)
|
|
+ abort ();
|
|
+ if (ay != 0)
|
|
+ abort ();
|
|
+ if (ap != 0)
|
|
+ abort ();
|
|
+ if (az.a != 0)
|
|
+ abort ();
|
|
+ if (aaa[0] != 0)
|
|
+ abort ();
|
|
+ if (aaa[1] != 0)
|
|
+ abort ();
|
|
+ if ((int) {} != 0)
|
|
+ abort ();
|
|
+ if ((float) {} != 0)
|
|
+ abort ();
|
|
+ if ((struct s) {}.a != 0)
|
|
+ abort ();
|
|
+ if ((union u) {}.a != 0)
|
|
+ abort ();
|
|
+ if ((int [5]) {}[2] != 0)
|
|
+ abort ();
|
|
+ /* Overwrite contents of vla before second call to make it more likely stack
|
|
+ contents are nonzero if proper initialization did not occur. */
|
|
+ for (int i = 0; i < a; i++)
|
|
+ vla[i] = -1;
|
|
+}
|
|
+
|
|
+int
|
|
+main (void)
|
|
+{
|
|
+ f (100);
|
|
+ f (100);
|
|
+ if (s.a != 0)
|
|
+ abort ();
|
|
+ if (x != 0)
|
|
+ abort ();
|
|
+ if (y != 0)
|
|
+ abort ();
|
|
+ if (p != 0)
|
|
+ abort ();
|
|
+ if (z.a != 0)
|
|
+ abort ();
|
|
+ if (aa[0] != 0)
|
|
+ abort ();
|
|
+ if (aa[1] != 0)
|
|
+ abort ();
|
|
+ exit (0);
|
|
+}
|
|
diff --git a/gcc/testsuite/gcc.dg/c2x-empty-init-2.c b/gcc/testsuite/gcc.dg/c2x-empty-init-2.c
|
|
new file mode 100644
|
|
index 000000000..0dc81ce5b
|
|
--- /dev/null
|
|
+++ b/gcc/testsuite/gcc.dg/c2x-empty-init-2.c
|
|
@@ -0,0 +1,18 @@
|
|
+/* Test C2X support for empty initializers: invalid use cases. */
|
|
+/* { dg-do compile } */
|
|
+/* { dg-options "-std=c2x -pedantic-errors" } */
|
|
+
|
|
+/* Empty initialization is invalid for arrays of unknown size. This is
|
|
+ diagnosed via the diagnostic for zero-size arrays. */
|
|
+int x[] = {}; /* { dg-error "zero or negative size array" } */
|
|
+
|
|
+void
|
|
+f (int a)
|
|
+{
|
|
+ int x1[] = {}; /* { dg-error "zero or negative size array" } */
|
|
+ int x2[][a] = {}; /* { dg-error "zero or negative size array" } */
|
|
+ /* Nonempty VLA initializers are still invalid. */
|
|
+ int x3[a] = { 0 }; /* { dg-error "variable-sized object may not be initialized except with an empty initializer" } */
|
|
+ /* Variable-size compound literals are still invalid. */
|
|
+ (void) (int [a]) {}; /* { dg-error "compound literal has variable size" } */
|
|
+}
|
|
diff --git a/gcc/testsuite/gcc.dg/c2x-empty-init-3.c b/gcc/testsuite/gcc.dg/c2x-empty-init-3.c
|
|
new file mode 100644
|
|
index 000000000..472f8169c
|
|
--- /dev/null
|
|
+++ b/gcc/testsuite/gcc.dg/c2x-empty-init-3.c
|
|
@@ -0,0 +1,25 @@
|
|
+/* Test empty initializers diagnosed in C2X mode with -Wc11-c2x-compat. */
|
|
+/* { dg-do compile } */
|
|
+/* { dg-options "-std=c2x -Wc11-c2x-compat" } */
|
|
+
|
|
+struct s { int a; };
|
|
+struct s s = {}; /* { dg-warning "empty initializer" } */
|
|
+int x = {}; /* { dg-warning "empty initializer" } */
|
|
+float y = {}; /* { dg-warning "empty initializer" } */
|
|
+void *p = {}; /* { dg-warning "empty initializer" } */
|
|
+union u { int a; long b; };
|
|
+union u z = {}; /* { dg-warning "empty initializer" } */
|
|
+int aa[2] = {}; /* { dg-warning "empty initializer" } */
|
|
+
|
|
+void
|
|
+f (int a)
|
|
+{
|
|
+ int vla[a] = {}; /* { dg-warning "empty initializer" } */
|
|
+ struct s as = {}; /* { dg-warning "empty initializer" } */
|
|
+ int ax = {}; /* { dg-warning "empty initializer" } */
|
|
+ float ay = {}; /* { dg-warning "empty initializer" } */
|
|
+ void *ap = {}; /* { dg-warning "empty initializer" } */
|
|
+ union u az = {}; /* { dg-warning "empty initializer" } */
|
|
+ int aaa[2] = {}; /* { dg-warning "empty initializer" } */
|
|
+ int t = (int) {}; /* { dg-warning "empty initializer" } */
|
|
+}
|
|
diff --git a/gcc/testsuite/gcc.dg/gnu2x-empty-init-1.c b/gcc/testsuite/gcc.dg/gnu2x-empty-init-1.c
|
|
new file mode 100644
|
|
index 000000000..e7dc9dfde
|
|
--- /dev/null
|
|
+++ b/gcc/testsuite/gcc.dg/gnu2x-empty-init-1.c
|
|
@@ -0,0 +1,29 @@
|
|
+/* Test C2X support for empty initializers: valid use cases with GNU
|
|
+ extensions. */
|
|
+/* { dg-do run } */
|
|
+/* { dg-options "-std=gnu2x" } */
|
|
+
|
|
+extern void exit (int);
|
|
+extern void abort (void);
|
|
+
|
|
+void
|
|
+f (int a)
|
|
+{
|
|
+ struct s { volatile int x[a]; };
|
|
+ struct s b = {};
|
|
+ for (int i = 0; i < a; i++)
|
|
+ if (b.x[i] != 0)
|
|
+ abort ();
|
|
+ /* Overwrite contents of b.x before second call to make it more likely stack
|
|
+ contents are nonzero if proper initialization did not occur. */
|
|
+ for (int i = 0; i < a; i++)
|
|
+ b.x[i] = -1;
|
|
+}
|
|
+
|
|
+int
|
|
+main (void)
|
|
+{
|
|
+ f (100);
|
|
+ f (100);
|
|
+ exit (0);
|
|
+}
|
|
diff --git a/gcc/testsuite/gcc.dg/gnu2x-empty-init-2.c b/gcc/testsuite/gcc.dg/gnu2x-empty-init-2.c
|
|
new file mode 100644
|
|
index 000000000..69ee4e36b
|
|
--- /dev/null
|
|
+++ b/gcc/testsuite/gcc.dg/gnu2x-empty-init-2.c
|
|
@@ -0,0 +1,16 @@
|
|
+/* Test C2X support for empty initializers: invalid use cases with GNU
|
|
+ extensions. */
|
|
+/* { dg-do compile } */
|
|
+/* { dg-options "-std=gnu2x" } */
|
|
+
|
|
+void
|
|
+f (int a)
|
|
+{
|
|
+ /* Make sure a non-braced initializer for a VLA-in-struct is still not
|
|
+ allowed. */
|
|
+ struct s { int x[a]; };
|
|
+ struct s b;
|
|
+ for (int i = 0; i < a; i++)
|
|
+ b.x[i] = 0;
|
|
+ struct s c = b; /* { dg-error "variable-sized object may not be initialized except with an empty initializer" } */
|
|
+}
|
|
diff --git a/gcc/testsuite/gcc.dg/init-bad-1.c b/gcc/testsuite/gcc.dg/init-bad-1.c
|
|
index 61734045f..0da10c315 100644
|
|
--- a/gcc/testsuite/gcc.dg/init-bad-1.c
|
|
+++ b/gcc/testsuite/gcc.dg/init-bad-1.c
|
|
@@ -21,8 +21,7 @@ char t1[1] = { "xy" }; /* { dg-warning "initializer-string for array of 'char' i
|
|
char u[1] = { "x", "x" }; /* { dg-error "excess elements in 'char' array initializer" } */
|
|
/* { dg-message "near init" "near" { target *-*-* } .-1 } */
|
|
|
|
-int i = { }; /* { dg-error "empty scalar initializer" } */
|
|
-/* { dg-message "near init" "near" { target *-*-* } .-1 } */
|
|
+int i = { };
|
|
|
|
int j = { 1 };
|
|
|
|
diff --git a/gcc/testsuite/gcc.dg/noncompile/pr71583.c b/gcc/testsuite/gcc.dg/noncompile/pr71583.c
|
|
index 5045b88b6..fe6e556ad 100644
|
|
--- a/gcc/testsuite/gcc.dg/noncompile/pr71583.c
|
|
+++ b/gcc/testsuite/gcc.dg/noncompile/pr71583.c
|
|
@@ -5,7 +5,7 @@ void
|
|
f (int i)
|
|
{
|
|
(int (*)[++i]) { int }; /* { dg-error "expected" } */
|
|
- (int (*)[++i]) { }; /* { dg-error "empty" } */
|
|
+ (int (*)[++i]) { };
|
|
(int (*)[++i]) { , }; /* { dg-error "expected" } */
|
|
(int (*)[++i]) { f () }; /* { dg-error "too few" } */
|
|
}
|
|
diff --git a/gcc/testsuite/gcc.dg/pr61096-1.c b/gcc/testsuite/gcc.dg/pr61096-1.c
|
|
index e707904c0..f41789c5f 100644
|
|
--- a/gcc/testsuite/gcc.dg/pr61096-1.c
|
|
+++ b/gcc/testsuite/gcc.dg/pr61096-1.c
|
|
@@ -36,7 +36,7 @@ struct S s = { { 1 }, { 3 } }; /* { dg-error "23:extra brace group at end of ini
|
|
struct g g1 = { {0, { 1 } } }; /* { dg-error "21:initialization of flexible array member in a nested context" } */
|
|
struct g g2 = { .f[0] = 1 }; /* { dg-error "20:array index in non-array initializer" } */
|
|
|
|
-__extension__ int a8 = { }; /* { dg-error "24:empty scalar initializer" } */
|
|
+__extension__ int a8 = { };
|
|
int a9[10] = {[1.2] = 2 }; /* { dg-error "16:array index in initializer not of integer type" } */
|
|
int a10[10] = {[e] = 2 }; /* { dg-error "17:nonconstant array index in initializer" } */
|
|
__extension__ int a11[10] = {[1 ... e] = 1 }; /* { dg-error "31:nonconstant array index in initializer" } */
|
|
diff --git a/gcc/testsuite/gcc.dg/ubsan/c-shift-1.c b/gcc/testsuite/gcc.dg/ubsan/c-shift-1.c
|
|
index 9d561016f..f88ee2de3 100644
|
|
--- a/gcc/testsuite/gcc.dg/ubsan/c-shift-1.c
|
|
+++ b/gcc/testsuite/gcc.dg/ubsan/c-shift-1.c
|
|
@@ -7,12 +7,12 @@ int
|
|
main (void)
|
|
{
|
|
/* None of the following should pass. */
|
|
- int A[1 >> -1] = {}; /* { dg-error "variable-sized object may not be initialized" } */
|
|
- int B[-1 >> -1] = {}; /* { dg-error "variable-sized object may not be initialized" } */
|
|
- int D[1 << -1] = {}; /* { dg-error "variable-sized object may not be initialized" } */
|
|
- int E[-1 << -1] = {}; /* { dg-error "variable-sized object may not be initialized" } */
|
|
- int F[-1 >> 200] = {}; /* { dg-error "variable-sized object may not be initialized" } */
|
|
- int G[1 << 200] = {}; /* { dg-error "variable-sized object may not be initialized" } */
|
|
+ int A[1 >> -1] = { 0 }; /* { dg-error "variable-sized object may not be initialized" } */
|
|
+ int B[-1 >> -1] = { 0 }; /* { dg-error "variable-sized object may not be initialized" } */
|
|
+ int D[1 << -1] = { 0 }; /* { dg-error "variable-sized object may not be initialized" } */
|
|
+ int E[-1 << -1] = { 0 }; /* { dg-error "variable-sized object may not be initialized" } */
|
|
+ int F[-1 >> 200] = { 0 }; /* { dg-error "variable-sized object may not be initialized" } */
|
|
+ int G[1 << 200] = { 0 }; /* { dg-error "variable-sized object may not be initialized" } */
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/gcc/testsuite/gcc.dg/vla-init-2.c b/gcc/testsuite/gcc.dg/vla-init-2.c
|
|
index 19fbffc26..f23630a36 100644
|
|
--- a/gcc/testsuite/gcc.dg/vla-init-2.c
|
|
+++ b/gcc/testsuite/gcc.dg/vla-init-2.c
|
|
@@ -7,4 +7,3 @@
|
|
|
|
const int i = 1;
|
|
void foo() { char a[][i] = {""}; } /* { dg-error "variable-sized object may not be initialized" } */
|
|
-/* { dg-error "array size missing in 'a'" "extra error" { target *-*-* } .-1 } */
|
|
diff --git a/gcc/testsuite/gcc.dg/vla-init-3.c b/gcc/testsuite/gcc.dg/vla-init-3.c
|
|
index 55e1de69c..a854f1268 100644
|
|
--- a/gcc/testsuite/gcc.dg/vla-init-3.c
|
|
+++ b/gcc/testsuite/gcc.dg/vla-init-3.c
|
|
@@ -6,4 +6,3 @@
|
|
/* { dg-options "" } */
|
|
|
|
void foo(int i) { char a[][i] = {""}; } /* { dg-error "variable-sized object may not be initialized" } */
|
|
-/* { dg-error "array size missing in 'a'" "extra error" { target *-*-* } .-1 } */
|
|
--
|
|
2.33.0
|
|
|