aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/decl.c32
-rw-r--r--gcc/testsuite/g++.target/i386/pr102295.C12
2 files changed, 44 insertions, 0 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 930531a..1a2925b 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6124,6 +6124,38 @@ layout_var_decl (tree decl)
error_at (DECL_SOURCE_LOCATION (decl),
"storage size of %qD isn%'t constant", decl);
TREE_TYPE (decl) = error_mark_node;
+ type = error_mark_node;
+ }
+ }
+
+ /* If the final element initializes a flexible array field, add the size of
+ that initializer to DECL's size. */
+ if (type != error_mark_node
+ && DECL_INITIAL (decl)
+ && TREE_CODE (DECL_INITIAL (decl)) == CONSTRUCTOR
+ && !vec_safe_is_empty (CONSTRUCTOR_ELTS (DECL_INITIAL (decl)))
+ && DECL_SIZE (decl) != NULL_TREE
+ && TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST
+ && TYPE_SIZE (type) != NULL_TREE
+ && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
+ && tree_int_cst_equal (DECL_SIZE (decl), TYPE_SIZE (type)))
+ {
+ constructor_elt &elt = CONSTRUCTOR_ELTS (DECL_INITIAL (decl))->last ();
+ if (elt.index)
+ {
+ tree itype = TREE_TYPE (elt.index);
+ tree vtype = TREE_TYPE (elt.value);
+ if (TREE_CODE (itype) == ARRAY_TYPE
+ && TYPE_DOMAIN (itype) == NULL
+ && TREE_CODE (vtype) == ARRAY_TYPE
+ && COMPLETE_TYPE_P (vtype))
+ {
+ DECL_SIZE (decl)
+ = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (vtype));
+ DECL_SIZE_UNIT (decl)
+ = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
+ TYPE_SIZE_UNIT (vtype));
+ }
}
}
}
diff --git a/gcc/testsuite/g++.target/i386/pr102295.C b/gcc/testsuite/g++.target/i386/pr102295.C
new file mode 100644
index 0000000..09efc3c
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/pr102295.C
@@ -0,0 +1,12 @@
+// PR c++/102295
+// { dg-do compile { target *-*-linux* } }
+// { dg-options "-Wno-pedantic" }
+
+struct S {
+ int a;
+ int b[];
+} S;
+
+struct S s = { 1, { 2, 3 } };
+
+/* { dg-final { scan-assembler ".size\[\t \]*s, 12" } } */