re PR c/20385 (Lame parse error message for undefined type)
authorPaolo Bonzini <bonzini@gnu.org>
Fri, 17 Dec 2010 21:23:36 +0000 (21:23 +0000)
committerPaolo Bonzini <bonzini@gcc.gnu.org>
Fri, 17 Dec 2010 21:23:36 +0000 (21:23 +0000)
gcc:
2010-12-17  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 another 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.

testsuite:
2010-12-17  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-18.c: New test.

From-SVN: r167999

gcc/ChangeLog
gcc/c-decl.c
gcc/c-parser.c
gcc/function.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/declspec-18.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/noncompile/920923-1.c
gcc/testsuite/gcc.dg/noncompile/pr44517.c
gcc/testsuite/objc.dg/tls/init-2.m

index f0a0882586ffb1c14c3c2fdc816f00fed1d9623b..944f8069d72423f4271b44231e0b09edcd37ffc7 100644 (file)
@@ -1,3 +1,29 @@
+2010-12-17  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 another 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.
+
 2010-12-17  Joseph Myers  <joseph@codesourcery.com>
 
        * config/i386/netware.h (ASM_SPEC, SIZE_TYPE, PTRDIFF_TYPE):
index 06e01ad194757011fdf727923ca6419941ccec08..f9672a0975ff2930bb997e64a159bec2bfe086a7 100644 (file)
@@ -4865,6 +4865,8 @@ grokdeclarator (const struct c_declarator *declarator,
   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)
@@ -9315,9 +9317,9 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
       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)
@@ -9332,11 +9334,6 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
        }
       specs->type = type;
     }
-  else
-    {
-      /* Set a dummy type here to avoid warning about implicit 'int'.  */
-      specs->type = integer_type_node;
-    }
 
   return specs;
 }
@@ -9452,6 +9449,10 @@ finish_declspecs (struct c_declspecs *specs)
       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 8238506b540606e6bea01a3517df0a37ba496446..261ea3da56e94d72b0ebd8f9fb6da9fc1d5ab2b5 100644 (file)
@@ -433,6 +433,22 @@ c_parser_next_token_is_keyword (c_parser *parser, enum rid keyword)
   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 *token)
     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 (c_parser *parser)
   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_fndef (c_parser *, bool, bool, bool,
 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, enum c_lookahead_kind);
 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 *parser, bool fndef_ok,
       fndef_ok = !nested;
     }
 
-  c_parser_declspecs (parser, specs, true, true, start_attr_ok);
+  c_parser_declspecs (parser, specs, true, true, start_attr_ok, cla_nonabstract_decl);
   if (parser->error)
     {
       c_parser_skip_to_end_of_block_or_statement (parser);
@@ -1922,12 +1945,16 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
 
 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,
+                   enum c_lookahead_kind la)
 {
   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)
+
+  if (!typespec_ok)
+    gcc_assert (la == cla_prefer_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)))
     {
@@ -1935,21 +1962,14 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
       tree attrs;
       location_t loc = c_parser_peek_token (parser)->location;
 
-      if (!c_parser_next_token_is_qualifier (parser))
-        {
-         /* Exit for TYPENAMEs after any type 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;
-        }
+      /* If we cannot accept a type, exit if the next token must start
+        one.  Also, if we already have seen a tagged definition,
+        a typename would be an error anyway and likely the user
+        has simply forgotten a semicolon, so we exit.  */
+      if ((!typespec_ok || specs->typespec_kind == ctsk_tagdef)
+         && c_parser_next_tokens_start_typename (parser, la)
+         && !c_parser_next_token_is_qualifier (parser))
+       break;
 
       if (c_parser_next_token_is (parser, CPP_NAME))
        {
@@ -1966,20 +1986,34 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
              continue;
            }
 
-         /* Now at a C_ID_TYPENAME or C_ID_CLASSNAME.  */
+         gcc_assert (!c_parser_next_token_is_qualifier (parser));
+
+         /* 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 (seen_type || !c_parser_next_tokens_start_typename (parser, la))
+           break;
+
+         /* 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 +2023,9 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
              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 +2532,7 @@ c_parser_struct_declaration (c_parser *parser)
     }
   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, cla_nonabstract_decl);
   if (parser->error)
     return NULL_TREE;
   if (!specs->declspecs_seen_p)
@@ -2644,7 +2678,7 @@ c_parser_typeof_specifier (c_parser *parser)
       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--;
@@ -2765,7 +2799,7 @@ c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
       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, cla_prefer_id);
       inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
       if (inner == NULL)
        return NULL;
@@ -2917,12 +2951,12 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
       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, cla_prefer_id);
       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, cla_prefer_id);
       if (!quals_attrs->declspecs_seen_p)
        quals_attrs = NULL;
       /* If "static" is present, there must be an array dimension.
@@ -3010,7 +3044,13 @@ c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs)
   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)
@@ -3173,9 +3213,7 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
       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;
@@ -3194,7 +3232,7 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
       declspecs_add_attrs (specs, attrs);
       attrs = NULL_TREE;
     }
-  c_parser_declspecs (parser, specs, true, true, true);
+  c_parser_declspecs (parser, specs, true, true, true, cla_nonabstract_decl);
   finish_declspecs (specs);
   pending_xref_error ();
   prefix_attrs = specs->attrs;
@@ -3484,14 +3522,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, cla_prefer_type);
   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);
@@ -5619,7 +5660,8 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
   /* 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)))
     {
@@ -6181,16 +6223,16 @@ c_parser_postfix_expression (c_parser *parser)
            }
          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;
@@ -7436,7 +7478,7 @@ c_parser_objc_type_name (c_parser *parser)
       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 c69a5c55554ef741418afd2194d216deca1e865a..7fa3b0c0aac6970265e09f20807394b797aaacc7 100644 (file)
@@ -5712,6 +5712,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 95ede64a181d5c7ba1ea38c079e37bb10b119b21..7db98fc0a440fbef6a4e075f10b194a72d7e3ef8 100644 (file)
@@ -1,3 +1,11 @@
+2010-12-17  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-18.c: New test.
+
 2010-12-17  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
 
        * gcc.dg/titype-1.c: Enable TImode on __SPU__.
diff --git a/gcc/testsuite/gcc.dg/declspec-18.c b/gcc/testsuite/gcc.dg/declspec-18.c
new file mode 100644 (file)
index 0000000..d29ff13
--- /dev/null
@@ -0,0 +1,100 @@
+/* { 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 (t12 *) 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 t13);   /* { dg-error "unknown type name 't13'" } */
+int s3 = sizeof (t14 *);       /* { dg-error "unknown type name 't14'" "" { 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 t15);   /* { dg-error "unknown type name 't15'" } */
+int a3 = __alignof__ (t16 *);       /* { dg-error "unknown type name 't16'" "" { 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 t17) "abc";       /* { dg-error "unknown type name 't17'" } */
+/* { dg-bogus "expected" "" { target *-*-* } 63 } */
+}
+
+const char *f2()
+{
+  return (const t18 *) "abc";     /* { dg-error "unknown type name 't18'" } */
+/* { 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 *(*)(t19)) f3);       /* { dg-error "unknown type name 't19'" } */
+/* { dg-bogus "expected" "" { xfail *-*-* } 79 } */
+}
+
+const void *f4()
+{
+  return &((const t20){1});       /* { dg-error "unknown type name 't20'" } */
+/* { dg-bogus "return discards 'const'" "" { target *-*-* } 85 } */
+/* { dg-bogus "expected" "" { target *-*-* } 85 } */
+}
+
+int f5(__builtin_va_list ap)
+{
+  int x = __builtin_va_arg (ap, t21);       /* { dg-error "unknown type name 't21'" } */
+  int y = __builtin_va_arg (ap, const t22); /* { dg-error "unknown type name 't22'" } */
+}
+
+int f6(void)
+{
+  return __builtin_offsetof (t23, field); /* { dg-error "unknown type name 't23'" } */
+/* { dg-bogus "request for member" "" { target *-*-* } 98 } */
+}
index f586a7c0d0433d34fd67129d4329851e3870bfe2..ccd1dc3a7829ea3f11bf9712419199cd2dab9907 100644 (file)
@@ -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 5977d68fef82c1d938f60b5fb632d3151601ce9f..3a5148af83f83c0ac2d2319d510d00e69f55a736 100644 (file)
@@ -12,7 +12,7 @@ int f2(int x, lon y, long z, ...){ /* { dg-error "unknown type name 'lon'" } */
 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'" } */
index 69733cc3c1c81973a89693b301a339691c68c7ad..882e5f809950b3e334d58ec6518e789279b22ec3 100644 (file)
@@ -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" } */