re PR c++/27102 (ICE with invalid class name in function template)
authorMark Mitchell <mark@codesourcery.com>
Wed, 19 Apr 2006 16:58:23 +0000 (16:58 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Wed, 19 Apr 2006 16:58:23 +0000 (16:58 +0000)
PR c++/27102
* class.c (currently_open_class): Tidy.
* decl.c (grokdeclarator): If we encounter an erroneous
declarator, assume that we have already issued an error message
and return.  Return error_mark_node instead of NULL_TREE in more
places.  Issue errors about function definitions that do not have
a function declarator.  Check for complete types for all function
definitions.
* cp-tree.h (cp_error_declarator): Remove.
(currently_open_class): Change return type.
* parser.c (cp_parser_id_expression): Add optional_p parameter.
(cp_parser_parse_diagnose_invalid_type_name): Adjust calls.
(cp_parser_id_expression): Likewise.
(cp_parser_unqualified_id): If the name is optional, return
NULL_TREE.
(cp_parser_postfix_dot_deref_expression): Adjust calls.
(cp_parser_type_parameter): Likewise.
(cp_parser_unqualified_id): Likewise.
(cp_parser_direct_declarator): Likewise.
(cp_parser_declarator_id): Add optional_p parameter.
(cp_parser_function_definition_from_specifiers_and_declarator):
Assume that start_function indicates failure only if it has issued
an error.
(cp_parser_omp_var_list_no_open): Adjust calls.

PR c++/27102
* g++.dg/template/crash35.C: Tweak error markers.
* g++.dg/template/crash46.C: New test.
* g++.old-deja/g++.brendan/friend4.C: Tweak error markers.
* g++.old-deja/g++.pt/incomplete1.C: Likewise.

From-SVN: r113081

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/crash35.C
gcc/testsuite/g++.dg/template/crash46.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.brendan/friend4.C
gcc/testsuite/g++.old-deja/g++.pt/incomplete1.C

index 78525726ecb935d6b3190097bf470dc1cdd516f1..2d80e524bd619fc74fa2f449ac6e4e1813451c36 100644 (file)
@@ -1,3 +1,30 @@
+2006-04-19  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/27102
+       * class.c (currently_open_class): Tidy.
+       * decl.c (grokdeclarator): If we encounter an erroneous
+       declarator, assume that we have already issued an error message
+       and return.  Return error_mark_node instead of NULL_TREE in more
+       places.  Issue errors about function definitions that do not have
+       a function declarator.  Check for complete types for all function
+       definitions. 
+       * cp-tree.h (cp_error_declarator): Remove.
+       (currently_open_class): Change return type.
+       * parser.c (cp_parser_id_expression): Add optional_p parameter.
+       (cp_parser_parse_diagnose_invalid_type_name): Adjust calls.
+       (cp_parser_id_expression): Likewise.
+       (cp_parser_unqualified_id): If the name is optional, return
+       NULL_TREE.
+       (cp_parser_postfix_dot_deref_expression): Adjust calls.
+       (cp_parser_type_parameter): Likewise.
+       (cp_parser_unqualified_id): Likewise.
+       (cp_parser_direct_declarator): Likewise.
+       (cp_parser_declarator_id): Add optional_p parameter.
+       (cp_parser_function_definition_from_specifiers_and_declarator):
+       Assume that start_function indicates failure only if it has issued
+       an error.
+       (cp_parser_omp_var_list_no_open): Adjust calls.
+       
 2006-04-17  Janis Johnson  <janis187@us.ibm.com>
 
        PR c++/26114, c++/26115
index 0edade8863124c85823ab9310ed151aea30dd741..cc26cb8f56c55d2e5219136cbe6b08a77491983d 100644 (file)
@@ -5496,25 +5496,33 @@ pop_class_stack (void)
     --current_class_stack[current_class_depth - 1].hidden;
 }
 
-/* Returns 1 if current_class_type is either T or a nested type of T.
-   We start looking from 1 because entry 0 is from global scope, and has
-   no type.  */
+/* Returns 1 if the class type currently being defined is either T or
+   a nested type of T.  */
 
-int
+bool
 currently_open_class (tree t)
 {
   int i;
-  if (current_class_type && same_type_p (t, current_class_type))
-    return 1;
-  for (i = current_class_depth - 1; i > 0; --i)
+
+  /* We start looking from 1 because entry 0 is from global scope,
+     and has no type.  */
+  for (i = current_class_depth; i > 0; --i)
     {
-      if (current_class_stack[i].hidden)
-       break;
-      if (current_class_stack[i].type
-         && same_type_p (current_class_stack [i].type, t))
-       return 1;
+      tree c;
+      if (i == current_class_depth)
+       c = current_class_type;
+      else
+       {
+         if (current_class_stack[i].hidden)
+           break;
+         c = current_class_stack[i].type;
+       }
+      if (!c)
+       continue;
+      if (same_type_p (c, t))
+       return true;
     }
-  return 0;
+  return false;
 }
 
 /* If either current_class_type or one of its enclosing classes are derived
index b488be62789104ab8d5888231869106e18b1d9d9..f82ab32f8d23613642eaeee3ca28cd3e7f344bc6 100644 (file)
@@ -3691,9 +3691,6 @@ struct cp_declarator {
   } u;
 };
 
-/* An erroneous declarator.  */
-extern cp_declarator *cp_error_declarator;
-
 /* A parameter list indicating for a function with no parameters,
    e.g  "int f(void)".  */
 extern cp_parameter_declarator *no_parameters;
@@ -3750,7 +3747,7 @@ extern tree get_vtable_decl                       (tree, int);
 extern void resort_type_method_vec             (void *, void *,
                                                 gt_pointer_operator, void *);
 extern bool add_method                         (tree, tree, tree);
-extern int currently_open_class                        (tree);
+extern bool currently_open_class               (tree);
 extern tree currently_open_derived_class       (tree);
 extern tree finish_struct                      (tree, tree);
 extern void finish_struct_1                    (tree);
index 3d8c2f84ba34e2f4ff8d7c886b619f526a706c45..9e101c15eab84a125383a885f91bce0dd1df5eb6 100644 (file)
@@ -6956,7 +6956,7 @@ grokdeclarator (const cp_declarator *declarator,
            break;
 
          case cdk_error:
-           break;
+           return error_mark_node;
 
          default:
            gcc_unreachable ();
@@ -6966,11 +6966,15 @@ grokdeclarator (const cp_declarator *declarator,
        break;
     }
 
-  /* A function definition's declarator must have the form of
-     a function declarator.  */
-
+  /* [dcl.fct.edf]
+     
+     The declarator in a function-definition shall have the form
+     D1 ( parameter-declaration-clause) ...  */
   if (funcdef_flag && innermost_code != cdk_function)
-    return NULL_TREE;
+    {
+      error ("function definition does not declare parameters");
+      return error_mark_node;
+    }
 
   if (((dname && IDENTIFIER_OPNAME_P (dname)) || flags == TYPENAME_FLAG)
       && innermost_code != cdk_function
@@ -7711,6 +7715,20 @@ grokdeclarator (const cp_declarator *declarator,
            pedwarn ("extra qualification %<%T::%> on member %qs",
                     ctype, name);
        }
+      else if (/* If the qualifying type is already complete, then we
+                 can skip the following checks.  */
+              !COMPLETE_TYPE_P (ctype)
+              /* If a function is being defined, then the qualifing
+                 type must be complete.  The qualifing type may be
+                 incomplete for a declaration only if the qualitying
+                 type is one of the classes presently being defined,
+                 or if it is a dependent type.  */
+              && (funcdef_flag 
+                  || !(dependent_type_p (ctype)
+                       || currently_open_class (ctype)))
+              /* Check that the qualifing type is complete.  */
+              && !complete_type_or_else (ctype, NULL_TREE))
+       return error_mark_node;
       else if (TREE_CODE (type) == FUNCTION_TYPE)
        {
          tree sname = declarator->u.id.unqualified_name;
@@ -7736,23 +7754,10 @@ grokdeclarator (const cp_declarator *declarator,
                                               TYPE_ARG_TYPES (type));
        }
       else if (declspecs->specs[(int)ds_typedef]
-              || COMPLETE_TYPE_P (complete_type (ctype)))
-       {
-         /* Have to move this code elsewhere in this function.
-            this code is used for i.e., typedef int A::M; M *pm;
-
-            It is?  How? jason 10/2/94 */
-
-         if (current_class_type)
-           {
-             error ("cannot declare member %<%T::%s%> within %qT",
-                    ctype, name, current_class_type);
-             return void_type_node;
-           }
-       }
-      else
+              && current_class_type)
        {
-         cxx_incomplete_type_error (NULL_TREE, ctype);
+         error ("cannot declare member %<%T::%s%> within %qT",
+                ctype, name, current_class_type);
          return error_mark_node;
        }
     }
index fede4df9bcf5c0b5228e7a36f6372b7376e902ab..13c73627e1c3baead7e37162bf89a5d3eb3c4c27 100644 (file)
@@ -780,7 +780,8 @@ static cp_parameter_declarator *make_parameter_declarator
 static cp_declarator *make_ptrmem_declarator
   (cp_cv_quals, tree, cp_declarator *);
 
-cp_declarator *cp_error_declarator;
+/* An erroneous declarator.  */
+static cp_declarator *cp_error_declarator;
 
 /* The obstack on which declarators and related data structures are
    allocated.  */
@@ -1389,9 +1390,9 @@ static bool cp_parser_translation_unit
 static tree cp_parser_primary_expression
   (cp_parser *, bool, bool, bool, cp_id_kind *);
 static tree cp_parser_id_expression
-  (cp_parser *, bool, bool, bool *, bool);
+  (cp_parser *, bool, bool, bool *, bool, bool);
 static tree cp_parser_unqualified_id
-  (cp_parser *, bool, bool, bool);
+  (cp_parser *, bool, bool, bool, bool);
 static tree cp_parser_nested_name_specifier_opt
   (cp_parser *, bool, bool, bool, bool);
 static tree cp_parser_nested_name_specifier
@@ -1536,7 +1537,7 @@ static enum tree_code cp_parser_ptr_operator
 static cp_cv_quals cp_parser_cv_qualifier_seq_opt
   (cp_parser *);
 static tree cp_parser_declarator_id
-  (cp_parser *);
+  (cp_parser *, bool);
 static tree cp_parser_type_id
   (cp_parser *);
 static void cp_parser_type_specifier_seq
@@ -2142,7 +2143,8 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
                                /*template_keyword_p=*/false,
                                /*check_dependency_p=*/true,
                                /*template_p=*/NULL,
-                               /*declarator_p=*/true);
+                               /*declarator_p=*/true,
+                               /*optional_p=*/false);
   /* After the id-expression, there should be a plain identifier,
      otherwise this is not a simple variable declaration. Also, if
      the scope is dependent, we cannot do much.  */
@@ -3021,7 +3023,8 @@ cp_parser_primary_expression (cp_parser *parser,
                                     /*template_keyword_p=*/false,
                                     /*check_dependency_p=*/true,
                                     &template_p,
-                                    /*declarator_p=*/false);
+                                    /*declarator_p=*/false,
+                                    /*optional_p=*/false);
        if (id_expression == error_mark_node)
          return error_mark_node;
        token = cp_lexer_peek_token (parser->lexer);
@@ -3154,7 +3157,8 @@ cp_parser_id_expression (cp_parser *parser,
                         bool template_keyword_p,
                         bool check_dependency_p,
                         bool *template_p,
-                        bool declarator_p)
+                        bool declarator_p,
+                        bool optional_p)
 {
   bool global_scope_p;
   bool nested_name_specifier_p;
@@ -3197,7 +3201,8 @@ cp_parser_id_expression (cp_parser *parser,
       /* Process the final unqualified-id.  */
       unqualified_id = cp_parser_unqualified_id (parser, *template_p,
                                                 check_dependency_p,
-                                                declarator_p);
+                                                declarator_p,
+                                                /*optional_p=*/false);
       /* Restore the SAVED_SCOPE for our caller.  */
       parser->scope = saved_scope;
       parser->object_scope = saved_object_scope;
@@ -3255,7 +3260,8 @@ cp_parser_id_expression (cp_parser *parser,
   else
     return cp_parser_unqualified_id (parser, template_keyword_p,
                                     /*check_dependency_p=*/true,
-                                    declarator_p);
+                                    declarator_p,
+                                    optional_p);
 }
 
 /* Parse an unqualified-id.
@@ -3284,7 +3290,8 @@ static tree
 cp_parser_unqualified_id (cp_parser* parser,
                          bool template_keyword_p,
                          bool check_dependency_p,
-                         bool declarator_p)
+                         bool declarator_p, 
+                         bool optional_p)
 {
   cp_token *token;
 
@@ -3505,6 +3512,8 @@ cp_parser_unqualified_id (cp_parser* parser,
       /* Fall through.  */
 
     default:
+      if (optional_p)
+       return NULL_TREE;
       cp_parser_error (parser, "expected unqualified-id");
       return error_mark_node;
     }
@@ -4501,7 +4510,8 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
               cp_parser_optional_template_keyword (parser),
               /*check_dependency_p=*/true,
               &template_p,
-              /*declarator_p=*/false));
+              /*declarator_p=*/false,
+              /*optional_p=*/false));
       /* In general, build a SCOPE_REF if the member name is qualified.
         However, if the name was not dependent and has already been
         resolved; there is no need to build the SCOPE_REF.  For example;
@@ -8623,7 +8633,8 @@ cp_parser_type_parameter (cp_parser* parser)
                                         /*template_keyword_p=*/false,
                                         /*check_dependency_p=*/true,
                                         /*template_p=*/&is_template,
-                                        /*declarator_p=*/false);
+                                        /*declarator_p=*/false,
+                                        /*optional_p=*/false);
            if (TREE_CODE (default_argument) == TYPE_DECL)
              /* If the id-expression was a template-id that refers to
                 a template-class, we already have the declaration here,
@@ -9177,7 +9188,8 @@ cp_parser_template_argument (cp_parser* parser)
                                      /*template_keyword_p=*/false,
                                      /*check_dependency_p=*/true,
                                      &template_p,
-                                     /*declarator_p=*/false);
+                                     /*declarator_p=*/false,
+                                     /*optional_p=*/false);
   /* If the next token isn't a `,' or a `>', then this argument wasn't
      really finished.  */
   if (!cp_parser_next_token_ends_template_argument_p (parser))
@@ -10624,7 +10636,8 @@ cp_parser_using_declaration (cp_parser* parser)
   identifier = cp_parser_unqualified_id (parser,
                                         /*template_keyword_p=*/false,
                                         /*check_dependency_p=*/true,
-                                        /*declarator_p=*/true);
+                                        /*declarator_p=*/true,
+                                        /*optional_p=*/false);
 
   /* The function we call to handle a using-declaration is different
      depending on what scope we are in.  */
@@ -11515,25 +11528,31 @@ cp_parser_direct_declarator (cp_parser* parser,
          tree qualifying_scope;
          tree unqualified_name;
          special_function_kind sfk;
+         bool abstract_ok;
 
          /* Parse a declarator-id */
-         if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
+         abstract_ok = (dcl_kind == CP_PARSER_DECLARATOR_EITHER);
+         if (abstract_ok)
            cp_parser_parse_tentatively (parser);
-         unqualified_name = cp_parser_declarator_id (parser);
+         unqualified_name 
+           = cp_parser_declarator_id (parser, /*optional_p=*/abstract_ok);
          qualifying_scope = parser->scope;
-         if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
+         if (abstract_ok)
            {
              if (!cp_parser_parse_definitely (parser))
                unqualified_name = error_mark_node;
-             else if (qualifying_scope
-                      || (TREE_CODE (unqualified_name)
-                          != IDENTIFIER_NODE))
+             else if (unqualified_name
+                      && (qualifying_scope
+                          || (TREE_CODE (unqualified_name)
+                              != IDENTIFIER_NODE)))
                {
                  cp_parser_error (parser, "expected unqualified-id");
                  unqualified_name = error_mark_node;
                }
            }
 
+         if (!unqualified_name)
+           return NULL;
          if (unqualified_name == error_mark_node)
            {
              declarator = cp_error_declarator;
@@ -11853,7 +11872,7 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
    unqualified-id.  */
 
 static tree
-cp_parser_declarator_id (cp_parser* parser)
+cp_parser_declarator_id (cp_parser* parser, bool optional_p)
 {
   tree id;
   /* The expression must be an id-expression.  Assume that qualified
@@ -11874,8 +11893,9 @@ cp_parser_declarator_id (cp_parser* parser)
                                /*template_keyword_p=*/false,
                                /*check_dependency_p=*/false,
                                /*template_p=*/NULL,
-                               /*declarator_p=*/true);
-  if (BASELINK_P (id))
+                               /*declarator_p=*/true,
+                               optional_p);
+  if (id && BASELINK_P (id))
     id = BASELINK_FUNCTIONS (id);
   return id;
 }
@@ -15298,7 +15318,6 @@ cp_parser_function_definition_from_specifiers_and_declarator
   if (!success_p)
     {
       /* Skip the entire function.  */
-      error ("invalid function declaration");
       cp_parser_skip_to_end_of_block_or_statement (parser);
       fn = error_mark_node;
     }
@@ -17786,7 +17805,8 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
       name = cp_parser_id_expression (parser, /*template_p=*/false,
                                      /*check_dependency_p=*/true,
                                      /*template_p=*/NULL,
-                                     /*declarator_p=*/false);
+                                     /*declarator_p=*/false,
+                                     /*optional_p=*/false);
       if (name == error_mark_node)
        goto skip_comma;
 
index 44a9b9f87da17acbc2e3ee52140bd095d2ee0f72..f3783b449da34e4cf50b149e2d7a1847c1414866 100644 (file)
@@ -1,3 +1,11 @@
+2006-04-19  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/27102
+       * g++.dg/template/crash35.C: Tweak error markers.
+       * g++.dg/template/crash46.C: New test.
+       * g++.old-deja/g++.brendan/friend4.C: Tweak error markers.
+       * g++.old-deja/g++.pt/incomplete1.C: Likewise.
+
 2006-04-19  Andreas Krebbel  <krebbel1@de.ibm.com>
 
        PR rtl-optimization/14261
index dd8aa2f0906a95f33b715a88c95dd1d91c99a9c9..348d91d0cafa2be887f008bc9ce0accbf1856b5f 100644 (file)
@@ -5,5 +5,5 @@ template <typename T> struct C; // { dg-error "declaration" }
 
 template <typename T> void C<T>::f() // { dg-error "invalid|template" }
 {
-  const foo bar; // { dg-error "name a type" }
+  const foo bar;
 }
diff --git a/gcc/testsuite/g++.dg/template/crash46.C b/gcc/testsuite/g++.dg/template/crash46.C
new file mode 100644 (file)
index 0000000..6fbda7c
--- /dev/null
@@ -0,0 +1,5 @@
+// PR c++/27102
+
+template <class T>
+void T::foo() {} // { dg-error "invalid" }
+
index af33199a14e509bdc8aa401a9769b747acfb9bf6..4d436e5c9c6772f8aefeb1761e9d764b4321967a 100644 (file)
@@ -2,5 +2,5 @@
 // GROUPS passed friends
 // do_friend should complain that foo was declared as a friend of
 // A before A was defined
-struct A;
+struct A; // { dg-error "forward" } 
 struct B { friend A::foo (); };// { dg-error "" } .*
index 37c30a44805aa54df24bc54317d64e1b1c8aaa1a..9189df2227687eee3de65424dcc57c652257c9f2 100644 (file)
@@ -6,6 +6,6 @@
 // Inspired by by 756. We'd ICE when trying to define a member of an
 // incomplete template type.
 
-template<class X> struct ObjCount;  // { dg-error "" } forward decl
+template<class X> struct ObjCount;
 
 template<class X> int ObjCount<X>::m; // { dg-error "" } undefined type