@@ -4791,6 +4791,12 @@ finish_decl (tree decl, location_t init_loc, tree init,
TREE_TYPE (decl) = error_mark_node;
}
+ if ((RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))
+ || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
+ && DECL_SIZE (decl) == NULL_TREE
+ && TREE_STATIC (decl))
+ incomplete_record_decls.safe_push (decl);
+
if (is_global_var (decl) && DECL_SIZE (decl) != 0)
{
if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
@@ -59,6 +59,15 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-expr.h"
#include "context.h"
+/* We need to walk over decls with incomplete struct/union/enum types
+ after parsing the whole translation unit.
+ In finish_decl(), if the decl is static, has incomplete
+ struct/union/enum type, it is appened to incomplete_record_decls.
+ In c_parser_translation_unit(), we iterate over incomplete_record_decls
+ and report error if any of the decls are still incomplete. */
+
+vec<tree> incomplete_record_decls = vNULL;
+
void
set_c_expr_source_range (c_expr *expr,
location_t start, location_t finish)
@@ -1421,6 +1430,16 @@ c_parser_translation_unit (c_parser *parser)
}
while (c_parser_next_token_is_not (parser, CPP_EOF));
}
+
+ for (unsigned i = 0; i < incomplete_record_decls.length (); ++i)
+ {
+ tree decl = incomplete_record_decls[i];
+ if (DECL_SIZE (decl) == NULL_TREE && TREE_TYPE (decl) != error_mark_node)
+ {
+ error ("storage size of %q+D isn%'t known", decl);
+ TREE_TYPE (decl) = error_mark_node;
+ }
+ }
}
/* Parse an external declaration (C90 6.7, C99 6.9).
@@ -731,4 +731,6 @@ set_c_expr_source_range (c_expr *expr,
/* In c-fold.c */
extern tree decl_constant_value_for_optimization (tree);
+extern vec<tree> incomplete_record_decls;
+
#endif /* ! GCC_C_TREE_H */
@@ -33,6 +33,7 @@ enum e3
__typeof__ (struct s5 { int i; }) v5; /* { dg-warning "invalid in C\[+\]\[+\]" } */
__typeof__ (struct t5) w5; /* { dg-bogus "invalid in C\[+\]\[+\]" } */
+ /* { dg-error "storage size of 'w5' isn't known" "" { target *-*-* } 35 } */
int
f1 (struct s1 *p)
@@ -64,4 +65,4 @@ f5 ()
return &((struct t8) { }); /* { dg-warning "invalid in C\[+\]\[+\]" } */
}
-/* { dg-error "invalid use of undefined type" "" { target *-*-* } 64 } */
+/* { dg-error "invalid use of undefined type" "" { target *-*-* } 65 } */
@@ -9,13 +9,15 @@ typedef int t;
/* These should all be diagnosed, but only once, not for every
identifier declared. */
struct s0 int x0, /* { dg-error "two or more data types" } */
-x1;
+/* { dg-error "storage size of 'x0' isn't known" "" { target *-*-* } 11 } */
+x1; /* { dg-error "storage size of 'x1' isn't known" } */
char union u0 x2, /* { dg-error "two or more data types" } */
x3;
enum e0 struct s1 x4, /* { dg-error "two or more data types" } */
-x5;
+ /* { dg-error "storage size of 'x4' isn't known" "" { target *-*-* } 18 } */
+x5; /* { dg-error "storage size of 'x5' isn't known" } */
short short x6, /* { dg-error "duplicate" } */
x7;
new file mode 100644
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-fsyntax-only" } */
+
+static struct foo x; /* { dg-error "storage size of 'x' isn't known" } */
+static union bar y; /* { dg-error "storage size of 'y' isn't known" } */
+
+typedef struct P p;
+static p p_obj; /* { dg-error "storage size of 'p_obj' isn't known" } */
+
+static enum e e_var; /* { dg-error "storage size of 'e_var' isn't known" } */
+
+extern struct undefined_object object;
@@ -2,6 +2,6 @@
/* { dg-do compile } */
/* { dg-options "" } */
-enum E e;
+enum E e; /* { dg-error "storage size of 'e' isn't known" } */
int a[10];
int i = a[e]; /* { dg-error "has an incomplete type" } */