diff mbox

reject decl with incomplete struct/union type in check_global_declaration()

Message ID CAAgBjM=RSwqZhWLbgD2=-D0M1kq_kGGWyP8dAKB+FxszyiRsUA@mail.gmail.com
State New
Headers show

Commit Message

Prathamesh Kulkarni Jan. 20, 2016, 1:22 p.m. UTC
On 19 January 2016 at 16:49, Marek Polacek <polacek@redhat.com> wrote:
> Sorry for speaking up late, but I think we could do better with formatting

> in this patch:

>

> On Sat, Jan 16, 2016 at 03:45:22PM +0530, Prathamesh Kulkarni wrote:

>> diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c

>> index 915376d..d36fc67 100644

>> --- a/gcc/c/c-decl.c

>> +++ b/gcc/c/c-decl.c

>> @@ -4791,6 +4791,13 @@ 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) == 0 && TREE_STATIC (decl))

>

> DECL_SIZE yields a tree, so I'd rather see NULL_TREE instead of 0 here (yeah,

> the enclosing code uses 0s :().  The "&& TREE_STATIC..." should be on its own

> line.

>

>> +     {

>> +       incomplete_record_decls.safe_push (decl);

>> +     }

>> +

>

> Redundant braces.

>

>> diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c

>> index a0e0052..3c8a496 100644

>> --- a/gcc/c/c-parser.c

>> +++ b/gcc/c/c-parser.c

>> @@ -59,6 +59,8 @@ along with GCC; see the file COPYING3.  If not see

>>  #include "gimple-expr.h"

>>  #include "context.h"

>>

>> +vec<tree> incomplete_record_decls = vNULL;

>

> This could use a comment.

>

>> +

>> +  for (unsigned i = 0; i < incomplete_record_decls.length (); ++i)

>> +    {

>> +      tree decl = incomplete_record_decls[i];

>> +      if (DECL_SIZE (decl) == 0 && TREE_TYPE (decl) != error_mark_node)

>

> I'd s/0/NULL_TREE/.

Thanks for the review, I have done the suggested changes in this
version of the patch.
Ok for trunk ?

Thanks,
Prathamesh
>

>         Marek
diff mbox

Patch

diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 5830e22..1ec6042 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -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)
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 919680a..1d3b9e1 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -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).
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 81a3d58..cf79ba7 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -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 */
diff --git a/gcc/testsuite/gcc.dg/Wcxx-compat-8.c b/gcc/testsuite/gcc.dg/Wcxx-compat-8.c
index f7e8c55..4e9ddc1 100644
--- a/gcc/testsuite/gcc.dg/Wcxx-compat-8.c
+++ b/gcc/testsuite/gcc.dg/Wcxx-compat-8.c
@@ -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 } */
diff --git a/gcc/testsuite/gcc.dg/declspec-1.c b/gcc/testsuite/gcc.dg/declspec-1.c
index c19f107..b024601 100644
--- a/gcc/testsuite/gcc.dg/declspec-1.c
+++ b/gcc/testsuite/gcc.dg/declspec-1.c
@@ -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;
diff --git a/gcc/testsuite/gcc.dg/pr24293.c b/gcc/testsuite/gcc.dg/pr24293.c
new file mode 100644
index 0000000..5bf7ad17
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr24293.c
@@ -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;
diff --git a/gcc/testsuite/gcc.dg/pr63549.c b/gcc/testsuite/gcc.dg/pr63549.c
index c9b1718..bd0b706 100644
--- a/gcc/testsuite/gcc.dg/pr63549.c
+++ b/gcc/testsuite/gcc.dg/pr63549.c
@@ -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" } */