This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] PR c/20385: more detection of unknown type names


This fixes the remaining part of PR 20385 by detecting unknown type
names within declspecs, typeof/sizeof/alignof, casts, etc.  Since these
are implemented with (conservative) heuristics, in some cases the new
error is disabled: for example in typeof(X) it is better to diagnose an
undeclared identifier than an unknown type name.

There is in some cases suboptimal error recovery, that leads the parser
to emit a bogus error message about a missing closing parenthesis.
This however happens only in complex cases such as casts to function
pointer types with an unknown typename in the arguments.

Another suboptimal case is that sizeof(X*) is not handled correctly
because the current parser code would require a three-token lookahead.
I believe this can be fixed, anyway it is minor compared to the overall
improvement.

Bootstrapped/regtested x86_64-pc-linux-gnu, ok?

Paolo

2010-11-20  Paolo Bonzini  <bonzini@gnu.org>

        PR c/20385
        * function.c (used_types_insert): Handle ERROR_MARK.
        * c-decl.c (grokdeclarator): Handle ERROR_MARK.
        (declspecs_add_type): Leave error_mark_node in specs->type.
        (finish_declspecs): Change it to integer_type_node here.
        * c-parser.c (c_parser_peek_2nd_token): Move earlier.
        (enum c_lookahead_kind): New.
        (c_parser_next_token_starts_typename): New name of
        c_parser_next_tokens_start_typename.  Accept lookahead enum
        and handle it here instead of...
        (c_parser_next_tokens_start_declaration): ... here.  Call it.
        (c_parser_declspecs): Accept bool argument.  Do not exit
        on C_ID_ID if it is guessed to be an unknown typename.
        (c_parser_parms_declarator): Use 2nd token to distinguish a K&R
        declaration from an ANSI declaration starting with an unknown
        typename.
        (c_parser_struct_declaration, c_parser_objc_type_name,
        c_parser_typeof_specifier, c_parser_declarator,
        c_parser_direct_declarator_inner): Adjust calls.
        (c_parser_parameter_declaration): Likewise.
        (c_parser_type_name): Pass back an error_mark_node to the caller.
        (c_parser_postfix_expression): Do error recovery when 
        c_parser_type_name returns NULL for the first offsetof argument.

2010-11-20  Paolo Bonzini  <bonzini@gnu.org>

        PR c/20385
        * objc.dg/tls/init-2.m: Adjust.
        * gcc.dg/noncompile/920923-1.c: Adjust.
        * gcc.dg/noncompile/pr44517.c: Adjust.
        * gcc.dg/declspec.c: New test.

Index: gcc/function.c
===================================================================
--- gcc/function.c	(branch diag-2)
+++ gcc/function.c	(working copy)
@@ -5704,6 +5704,8 @@ used_types_insert (tree t)
       break;
     else
       t = TREE_TYPE (t);
+  if (TREE_CODE (t) == ERROR_MARK)
+    return;
   if (TYPE_NAME (t) == NULL_TREE
       || TYPE_NAME (t) == TYPE_NAME (TYPE_MAIN_VARIANT (t)))
     t = TYPE_MAIN_VARIANT (t);
Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c	(branch diag-2)
+++ gcc/c-decl.c	(working copy)
@@ -4864,6 +4864,8 @@ grokdeclarator (const struct c_declarato
   tree expr_dummy;
   bool expr_const_operands_dummy;
 
+  if (TREE_CODE (type) == ERROR_MARK)
+    return error_mark_node;
   if (expr == NULL)
     expr = &expr_dummy;
   if (expr_const_operands == NULL)
@@ -9307,9 +9309,9 @@ declspecs_add_type (location_t loc, stru
       else
 	specs->type = TREE_TYPE (t);
     }
-  else if (TREE_CODE (type) != ERROR_MARK)
+  else
     {
-      if (spec.kind == ctsk_typeof)
+      if (TREE_CODE (type) != ERROR_MARK && spec.kind == ctsk_typeof)
 	{
 	  specs->typedef_p = true;
 	  if (spec.expr)
@@ -9324,11 +9326,6 @@ declspecs_add_type (location_t loc, stru
 	}
       specs->type = type;
     }
-  else
-    {
-      /* Set a dummy type here to avoid warning about implicit 'int'.  */
-      specs->type = integer_type_node;
-    }
 
   return specs;
 }
@@ -9444,6 +9441,10 @@ finish_declspecs (struct c_declspecs *sp
       gcc_assert (!specs->long_p && !specs->long_long_p && !specs->short_p
 		  && !specs->signed_p && !specs->unsigned_p
 		  && !specs->complex_p);
+
+      /* Set a dummy type.  */
+      if (TREE_CODE (specs->type) == ERROR_MARK)
+        specs->type = integer_type_node;
       return specs;
     }
 
Index: gcc/c-parser.c
===================================================================
--- gcc/c-parser.c	(branch diag-2)
+++ gcc/c-parser.c	(working copy)
@@ -433,6 +433,22 @@ c_parser_next_token_is_keyword (c_parser
   return c_parser_peek_token (parser)->keyword == keyword;
 }
 
+/* Return a pointer to the next-but-one token from PARSER, reading it
+   in if necessary.  The next token is already read in.  */
+
+static c_token *
+c_parser_peek_2nd_token (c_parser *parser)
+{
+  if (parser->tokens_avail >= 2)
+    return &parser->tokens[1];
+  gcc_assert (parser->tokens_avail == 1);
+  gcc_assert (parser->tokens[0].type != CPP_EOF);
+  gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL);
+  c_lex_one_token (parser, &parser->tokens[1]);
+  parser->tokens_avail = 2;
+  return &parser->tokens[1];
+}
+
 /* Return true if TOKEN can start a type name,
    false otherwise.  */
 static bool
@@ -497,13 +513,46 @@ c_token_starts_typename (c_token *token)
     }
 }
 
+enum c_lookahead_kind {
+  /* Always treat unknown identifiers as typenames.  */
+  cla_prefer_type,
+
+  /* Could be parsing a nonabstract declarator.  Only treat an identifier
+     as a typename if followed by another identifier or a star.  */
+  cla_nonabstract_decl,
+
+  /* Never treat identifiers as typenames.  */
+  cla_prefer_id
+};
+
 /* Return true if the next token from PARSER can start a type name,
-   false otherwise.  */
+   false otherwise.  LA specifies how to do lookahead in order to
+   detect unknown type names.  If unsure, pick CLA_PREFER_ID.  */
+
 static inline bool
-c_parser_next_token_starts_typename (c_parser *parser)
+c_parser_next_tokens_start_typename (c_parser *parser, enum c_lookahead_kind la)
 {
   c_token *token = c_parser_peek_token (parser);
-  return c_token_starts_typename (token);
+  if (c_token_starts_typename (token))
+    return true;
+
+  /* Try a bit harder to detect an unknown typename.  */
+  if (la != cla_prefer_id
+      && token->type == CPP_NAME
+      && token->id_kind == C_ID_ID
+
+      /* Do not try too hard when we could have "object in array".  */
+      && !parser->objc_could_be_foreach_context
+
+      && (la == cla_prefer_type
+          || c_parser_peek_2nd_token (parser)->type == CPP_NAME
+          || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
+
+      /* Only unknown identifiers.  */
+      && !lookup_name (token->value))
+    return true;
+
+  return false;
 }
 
 /* Return true if TOKEN is a type qualifier, false otherwise.  */
@@ -631,8 +680,6 @@ c_token_starts_declaration (c_token *tok
     return false;
 }
 
-static c_token *c_parser_peek_2nd_token (c_parser *parser);
-
 /* Return true if the next token from PARSER can start declaration
    specifiers, false otherwise.  */
 static inline bool
@@ -677,36 +724,12 @@ c_parser_next_tokens_start_declaration (
   if (c_token_starts_declaration (token))
     return true;
 
-  /* Try a bit harder to detect an unknown typename.  */
-  if (token->type == CPP_NAME
-      && token->id_kind == C_ID_ID
-      && (c_parser_peek_2nd_token (parser)->type == CPP_NAME
-          || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
-      && !lookup_name (token->value)
-
-      /* Do not try too hard when we could have "object in array".  */
-      && !parser->objc_could_be_foreach_context)
+  if (c_parser_next_tokens_start_typename (parser, cla_nonabstract_decl))
     return true;
 
   return false;
 }
 
-/* Return a pointer to the next-but-one token from PARSER, reading it
-   in if necessary.  The next token is already read in.  */
-
-static c_token *
-c_parser_peek_2nd_token (c_parser *parser)
-{
-  if (parser->tokens_avail >= 2)
-    return &parser->tokens[1];
-  gcc_assert (parser->tokens_avail == 1);
-  gcc_assert (parser->tokens[0].type != CPP_EOF);
-  gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL);
-  c_lex_one_token (parser, &parser->tokens[1]);
-  parser->tokens_avail = 2;
-  return &parser->tokens[1];
-}
-
 /* Consume the next token from PARSER.  */
 
 static void
@@ -1076,7 +1099,7 @@ static void c_parser_declaration_or_fnde
 static void c_parser_static_assert_declaration_no_semi (c_parser *);
 static void c_parser_static_assert_declaration (c_parser *);
 static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
-				bool);
+				bool, bool);
 static struct c_typespec c_parser_enum_specifier (c_parser *);
 static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
 static tree c_parser_struct_declaration (c_parser *);
@@ -1425,7 +1448,7 @@ c_parser_declaration_or_fndef (c_parser 
       fndef_ok = !nested;
     }
 
-  c_parser_declspecs (parser, specs, true, true, start_attr_ok);
+  c_parser_declspecs (parser, specs, true, true, start_attr_ok, true);
   if (parser->error)
     {
       c_parser_skip_to_end_of_block_or_statement (parser);
@@ -1922,12 +1945,12 @@ c_parser_static_assert_declaration_no_se
 
 static void
 c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
-		    bool scspec_ok, bool typespec_ok, bool start_attr_ok)
+		    bool scspec_ok, bool typespec_ok, bool start_attr_ok,
+		    bool nonabstract_decl)
 {
   bool attrs_ok = start_attr_ok;
   bool seen_type = specs->typespec_kind != ctsk_none;
-  while ((c_parser_next_token_is (parser, CPP_NAME)
-	  && c_parser_peek_token (parser)->id_kind != C_ID_ID)
+  while (c_parser_next_token_is (parser, CPP_NAME)
 	 || c_parser_next_token_is (parser, CPP_KEYWORD)
 	 || (c_dialect_objc () && c_parser_next_token_is (parser, CPP_LESS)))
     {
@@ -1937,18 +1960,30 @@ c_parser_declspecs (c_parser *parser, st
 
       if (!c_parser_next_token_is_qualifier (parser))
         {
-	  /* Exit for TYPENAMEs after any type because they can appear as a
+          enum c_lookahead_kind la;
+
+	  /* After any type, exit even for TYPENAMEs, because they can appear as a
 	     field name.  */
           if (seen_type && c_parser_next_token_is (parser, CPP_NAME))
             break;
 
-          /* If we cannot accept a type, and the next token must start one,
-	     exit.  Do the same if we already have seen a tagged definition,
-	     since it would be an error anyway and likely the user has simply
-	     forgotten a semicolon.  */
-          if ((!typespec_ok || specs->typespec_kind == ctsk_tagdef)
-	      && c_parser_next_token_starts_typename (parser))
-            break;
+          la = nonabstract_decl ? cla_nonabstract_decl : cla_prefer_type;
+          if (c_parser_next_tokens_start_typename (parser, la))
+            {
+              /* We cannot accept a type, and the next token must start one;
+                 exit.  Do the same if we already have seen a tagged definition,
+                 since it would be an error anyway and likely the user has simply
+                 forgotten a semicolon.  */
+              if (!typespec_ok || specs->typespec_kind == ctsk_tagdef)
+                break;
+            }
+          else
+            {
+              /* If the next token is an identifier, and it is not guessed
+                 to be an unknown typename, exit.  */
+              if (c_parser_next_token_is (parser, CPP_NAME))
+                break;
+            }
         }
 
       if (c_parser_next_token_is (parser, CPP_NAME))
@@ -1966,20 +2001,25 @@ c_parser_declspecs (c_parser *parser, st
 	      continue;
 	    }
 
-	  /* Now at a C_ID_TYPENAME or C_ID_CLASSNAME.  */
+	  /* Now at an unknown typename (C_ID_ID), a C_ID_TYPENAME or
+	     a C_ID_CLASSNAME.  */
 	  c_parser_consume_token (parser);
 	  seen_type = true;
 	  attrs_ok = true;
-	  if (kind == C_ID_TYPENAME
-	      && (!c_dialect_objc ()
-		  || c_parser_next_token_is_not (parser, CPP_LESS)))
+          if (kind == C_ID_ID)
+            {
+              error ("unknown type name %qE", value);
+              t.kind = ctsk_typedef;
+              t.spec = error_mark_node;
+            }
+          else if (kind == C_ID_TYPENAME
+                   && (!c_dialect_objc ()
+                       || c_parser_next_token_is_not (parser, CPP_LESS)))
 	    {
 	      t.kind = ctsk_typedef;
 	      /* For a typedef name, record the meaning, not the name.
 		 In case of 'foo foo, bar;'.  */
 	      t.spec = lookup_name (value);
-	      t.expr = NULL_TREE;
-	      t.expr_const_operands = true;
 	    }
 	  else
 	    {
@@ -1989,9 +2029,9 @@ c_parser_declspecs (c_parser *parser, st
 	      if (c_parser_next_token_is (parser, CPP_LESS))
 		proto = c_parser_objc_protocol_refs (parser);
 	      t.spec = objc_get_protocol_qualified_type (value, proto);
-	      t.expr = NULL_TREE;
-	      t.expr_const_operands = true;
 	    }
+          t.expr = NULL_TREE;
+          t.expr_const_operands = true;
 	  declspecs_add_type (loc, specs, t);
 	  continue;
 	}
@@ -2498,7 +2538,7 @@ c_parser_struct_declaration (c_parser *p
     }
   specs = build_null_declspecs ();
   decl_loc = c_parser_peek_token (parser)->location;
-  c_parser_declspecs (parser, specs, false, true, true);
+  c_parser_declspecs (parser, specs, false, true, true, true);
   if (parser->error)
     return NULL_TREE;
   if (!specs->declspecs_seen_p)
@@ -2644,7 +2684,7 @@ c_parser_typeof_specifier (c_parser *par
       in_typeof--;
       return ret;
     }
-  if (c_parser_next_token_starts_typename (parser))
+  if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
     {
       struct c_type_name *type = c_parser_type_name (parser);
       c_inhibit_evaluation_warnings--;
@@ -2770,7 +2810,8 @@ c_parser_declarator (c_parser *parser, b
       struct c_declspecs *quals_attrs = build_null_declspecs ();
       struct c_declarator *inner;
       c_parser_consume_token (parser);
-      c_parser_declspecs (parser, quals_attrs, false, false, true);
+      c_parser_declspecs (parser, quals_attrs, false, false, true,
+			  kind != C_DTR_ABSTRACT);
       inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
       if (inner == NULL)
 	return NULL;
@@ -2922,12 +2963,12 @@ c_parser_direct_declarator_inner (c_pars
       bool star_seen;
       tree dimen;
       c_parser_consume_token (parser);
-      c_parser_declspecs (parser, quals_attrs, false, false, true);
+      c_parser_declspecs (parser, quals_attrs, false, false, true, true);
       static_seen = c_parser_next_token_is_keyword (parser, RID_STATIC);
       if (static_seen)
 	c_parser_consume_token (parser);
       if (static_seen && !quals_attrs->declspecs_seen_p)
-	c_parser_declspecs (parser, quals_attrs, false, false, true);
+	c_parser_declspecs (parser, quals_attrs, false, false, true, true);
       if (!quals_attrs->declspecs_seen_p)
 	quals_attrs = NULL;
       /* If "static" is present, there must be an array dimension.
@@ -3015,7 +3056,13 @@ c_parser_parms_declarator (c_parser *par
   if (id_list_ok
       && !attrs
       && c_parser_next_token_is (parser, CPP_NAME)
-      && c_parser_peek_token (parser)->id_kind == C_ID_ID)
+      && c_parser_peek_token (parser)->id_kind == C_ID_ID
+      
+      /* Look ahead to detect typos in type names.  */
+      && c_parser_peek_2nd_token (parser)->type != CPP_NAME
+      && c_parser_peek_2nd_token (parser)->type != CPP_MULT
+      && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
+      && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_SQUARE)
     {
       tree list = NULL_TREE, *nextp = &list;
       while (c_parser_next_token_is (parser, CPP_NAME)
@@ -3178,9 +3225,7 @@ c_parser_parameter_declaration (c_parser
       if (parser->error)
 	return NULL;
       c_parser_set_source_position_from_token (token);
-      if (token->type == CPP_NAME
-	  && c_parser_peek_2nd_token (parser)->type != CPP_COMMA
-	  && c_parser_peek_2nd_token (parser)->type != CPP_CLOSE_PAREN)
+      if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
 	{
 	  error ("unknown type name %qE", token->value);
 	  parser->error = true;
@@ -3199,7 +3244,7 @@ c_parser_parameter_declaration (c_parser
       declspecs_add_attrs (specs, attrs);
       attrs = NULL_TREE;
     }
-  c_parser_declspecs (parser, specs, true, true, true);
+  c_parser_declspecs (parser, specs, true, true, true, true);
   finish_declspecs (specs);
   pending_xref_error ();
   prefix_attrs = specs->attrs;
@@ -3489,14 +3534,17 @@ c_parser_type_name (c_parser *parser)
   struct c_declarator *declarator;
   struct c_type_name *ret;
   bool dummy = false;
-  c_parser_declspecs (parser, specs, false, true, true);
+  c_parser_declspecs (parser, specs, false, true, true, false);
   if (!specs->declspecs_seen_p)
     {
       c_parser_error (parser, "expected specifier-qualifier-list");
       return NULL;
     }
-  pending_xref_error ();
-  finish_declspecs (specs);
+  if (specs->type != error_mark_node)
+    {
+      pending_xref_error ();
+      finish_declspecs (specs);
+    }
   declarator = c_parser_declarator (parser,
 				    specs->typespec_kind != ctsk_none,
 				    C_DTR_ABSTRACT, &dummy);
@@ -5624,7 +5672,8 @@ c_parser_cast_expression (c_parser *pars
   /* If the expression begins with a parenthesized type name, it may
      be either a cast or a compound literal; we need to see whether
      the next character is '{' to tell the difference.  If not, it is
-     an unary expression.  */
+     an unary expression.  Full detection of unknown typenames here
+     would require a 3-token lookahead.  */
   if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
       && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
     {
@@ -6186,16 +6235,16 @@ c_parser_postfix_expression (c_parser *p
 	    }
 	  t1 = c_parser_type_name (parser);
 	  if (t1 == NULL)
-	    {
-	      expr.value = error_mark_node;
-	      break;
-	    }
+	    parser->error = true;
 	  if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
+            gcc_assert (parser->error);
+	  if (parser->error)
 	    {
 	      c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
 	      expr.value = error_mark_node;
 	      break;
 	    }
+
 	  {
 	    tree type = groktypename (t1, NULL, NULL);
 	    tree offsetof_ref;
@@ -7427,7 +7476,7 @@ c_parser_objc_type_name (c_parser *parse
       else
 	break;
     }
-  if (c_parser_next_token_starts_typename (parser))
+  if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
     type_name = c_parser_type_name (parser);
   if (type_name)
     type = groktypename (type_name, NULL, NULL);
Index: gcc/testsuite/objc.dg/tls/init-2.m
===================================================================
--- gcc/testsuite/objc.dg/tls/init-2.m	(branch diag-2)
+++ gcc/testsuite/objc.dg/tls/init-2.m	(working copy)
@@ -11,4 +11,4 @@ struct S
 {
   S(); 			/* { dg-error "expected specifier-qualifier-list before 'S'" } */
 };
-__thread S s;		/* { dg-error "expected" } two errors here */
+__thread S s;		/* { dg-error "unknown type name" } */
Index: gcc/testsuite/gcc.dg/noncompile/920923-1.c
===================================================================
--- gcc/testsuite/gcc.dg/noncompile/920923-1.c	(branch diag-2)
+++ gcc/testsuite/gcc.dg/noncompile/920923-1.c	(working copy)
@@ -2,13 +2,13 @@
 typedef BYTE unsigned char;	/* { dg-error "expected" } */
 typedef int item_n;
 typedef int perm_set;
-struct PENT { caddr_t v_addr; };/* { dg-error "expected" } */
+struct PENT { caddr_t v_addr; };/* { dg-error "unknown type name" } */
 typedef struct PENT prec;
 typedef struct PENT *prec_t;
 prec_t mem_hash;
 BYTE *mem_base;			/* { dg-error "unknown type name" } */
 struct PTE {
-     BYTE *p_page;		/* { dg-error "expected" } */
+     BYTE *p_page;		/* { dg-error "unknown type name" } */
      perm_set p_perms;
 };
 typedef struct PTE pte;
@@ -56,7 +56,7 @@ int va_op;
 caddr_t v_addr;			/* { dg-error "unknown type name" } */
 {
      register prec_t bucket;
-     register caddr_t p_addr;	/* { dg-error "expected|undeclared" } */
+     register caddr_t p_addr;	/* { dg-error "unknown type name" } */
      bucket = mem_hash+((((v_addr)>>ITEMBITS))&hash_mask);  /* { dg-error "undeclared" } */
      do {
 	  if (bucket->v_addr == ((v_addr)>>ITEMBITS) {	/* { dg-error "expected|undeclared|no member" } */
Index: gcc/testsuite/gcc.dg/noncompile/pr44517.c
===================================================================
--- gcc/testsuite/gcc.dg/noncompile/pr44517.c	(branch diag-2)
+++ gcc/testsuite/gcc.dg/noncompile/pr44517.c	(working copy)
@@ -12,7 +12,7 @@ int f2(int x, lon y, long z, ...){ /* { 
 void f3(int n, int a[n], pid_t x); /* { dg-error "unknown type name 'pid_t'" } */
 void f4() {}
 void f5(int a, *b); /* { dg-error "expected declaration specifiers or" } */
-void f6(int a, b);  /* { dg-error "expected declaration specifiers or" } */
+void f6(int a, b);  /* { dg-error "unknown type name 'b'" } */
 void f7(int a, goto b); /* { dg-error "expected declaration specifiers or" } */
 void f8(int a, in goto); /* { dg-error "unknown type name 'in'" } */
 void f9(int a, in 1); /* { dg-error "unknown type name 'in'" } */



/* { dg-do compile } */
/* { dg-options "-std=gnu89" } */

static t1 *a;           /* { dg-error "unknown type name 't1'" } */

int z;                  /* { dg-message "previous declaration of 'z'" } */
typedef t2 *z;          /* { dg-error "unknown type name 't2'" } */
/* { dg-error "'z' redeclared " "" { target *-*-* } 7 } */

extern t3 p1(void);     /* { dg-error "unknown type name 't3'" } */
int p2(const t4 x);     /* { dg-error "unknown type name 't4'" } */
int p3(const t1 x);     /* { dg-error "unknown type name 't1'" } */ /* dup??? */
int p4(t5 (*x)(void));  /* { dg-error "unknown type name 't5'" } */
int p5(t6 *);           /* { dg-error "unknown type name 't6'" } */
int p6(t7 x);           /* { dg-error "unknown type name 't7'" } */
int p7(t8[]);           /* { dg-error "unknown type name 't8'" } */
int p8(int, t9);        /* { dg-error "unknown type name 't9'" } */

struct s {
  const t1 a;           /* { dg-error "unknown type name 't1'" } */ /* dup??? */
  const t10 b;          /* { dg-error "unknown type name 't10'" } */
  int b;                /* { dg-error "duplicate member" } */
};

typeof (z) c1;
typeof (x1) c2;         /* { dg-error "undeclared" } */
typeof (const t11) c3;  /* { dg-error "unknown type name 't11'" } */
typeof (t11 *) c3;      /* { dg-error "unknown type name 't12'" "" { xfail *-*-* } } */
/* { dg-bogus "unknown type name 'x1'" "" { target *-*-* } 26 } */
/* { dg-bogus "undeclared" "" { xfail *-*-* } 28 } */
/* { dg-bogus "expected expression before" "" { xfail *-*-* } 28 } */

int recover1;

int s0 = sizeof (z);
int s1 = sizeof (x2);          /* { dg-error "undeclared" } */
int s2 = sizeof (const t12);   /* { dg-error "unknown type name 't12'" } */
int s3 = sizeof (t13 *);       /* { dg-error "unknown type name 't13'" "" { xfail *-*-* } } */

int recover2;

/* { dg-bogus "unknown type name 'x2'" "" { target *-*-* } 36 } */
/* { dg-bogus "undeclared" "" { xfail *-*-* } 38 } */
/* { dg-bogus "expected expression before" "" { xfail *-*-* } 38 } */

int a0 = __alignof__ (z);
int a1 = __alignof__ (x3);          /* { dg-error "undeclared" } */
int a2 = __alignof__ (const t14);   /* { dg-error "unknown type name 't14'" } */
int a3 = __alignof__ (t15 *);       /* { dg-error "unknown type name 't15'" "" { xfail *-*-* } } */

int recover3;

/* { dg-bogus "unknown type name 'x3'" "" { target *-*-* } 47 } */
/* { dg-bogus "undeclared" "" { xfail *-*-* } 49 } */
/* { dg-bogus "expected expression before" "" { xfail *-*-* } 49 } */


/* Cannot detect (undefd_type *) or (undefd_type (*) because it would
   require 3 tokens of lookahead (same as above).  */

const char *f1()
{
  return (const t16) "abc";       /* { dg-error "unknown type name 't16'" } */
/* { dg-bogus "expected" "" { target *-*-* } 63 } */
}

const char *f2()
{
  return (const t17 *) "abc";     /* { dg-error "unknown type name 't17'" } */
/* { dg-bogus "expected" "" { target *-*-* } 69 } */
}


/* The parser has problems distinguishing semantic and syntactic errors,
   so it emits a wrong "expected ')'" error here.  */

void *f3(int x)
{
  return (void *) ((void *(*)(t18)) f3);       /* { dg-error "unknown type name 't18'" } */
/* { dg-bogus "expected" "" { xfail *-*-* } 79 } */
}

const void *f4()
{
  return &((const t19){1});       /* { dg-error "unknown type name 't19'" } */
/* { dg-bogus "return discards 'const'" "" { target *-*-* } 85 } */
/* { dg-bogus "expected" "" { target *-*-* } 85 } */
}

int f5(__builtin_va_list ap)
{
  int x = __builtin_va_arg (ap, t20);       /* { dg-error "unknown type name 't20'" } */
  int y = __builtin_va_arg (ap, const t21); /* { dg-error "unknown type name 't21'" } */
}

int f6(void)
{
  return __builtin_offsetof (t22, field); /* { dg-error "unknown type name 't22'" } */
/* { dg-bogus "request for member" "" { target *-*-* } 98 } */
}







Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]