OSDN Git Service

cp:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 17 Nov 2000 10:05:31 +0000 (10:05 +0000)
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 17 Nov 2000 10:05:31 +0000 (10:05 +0000)
* cp-tree.h (PARMLIST_ELLIPSIS_P): New macro.
* decl.c (grokdeclarator): Don't reject void parms here.
(require_complete_types_for_parms): Simplify, use
complete_type_or_else.
(grokparms): Remove bitrot. Remove funcdef parm.
Deal with ellipsis parm lists here.
* semantics.c (finish_parmlist): Don't append void_list_node
here. Set PARMLIST_ELLIPSIS_P.

testsuite:
* g++.old-deja/g++.other/incomplete.C: Add more tests.
* g++.old-deja/g++.pt/crash9.C: Mark new expected error.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@37517 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.old-deja/g++.other/incomplete.C
gcc/testsuite/g++.old-deja/g++.pt/crash9.C

index f059212..1cbeac8 100644 (file)
@@ -1,5 +1,16 @@
 2000-11-17  Nathan Sidwell  <nathan@codesourcery.com>
 
+       * cp-tree.h (PARMLIST_ELLIPSIS_P): New macro.
+       * decl.c (grokdeclarator): Don't reject void parms here.
+       (require_complete_types_for_parms): Simplify, use
+       complete_type_or_else.
+       (grokparms): Remove bitrot. Remove funcdef parm.
+       Deal with ellipsis parm lists here.
+       * semantics.c (finish_parmlist): Don't append void_list_node
+       here. Set PARMLIST_ELLIPSIS_P.
+
+2000-11-17  Nathan Sidwell  <nathan@codesourcery.com>
+
        * typeck2.c (incomplete_type_error): Reorganise to avoid
        excessive diagnostics.
 
index 67e4c23..34c9d13 100644 (file)
@@ -44,6 +44,7 @@ Boston, MA 02111-1307, USA.  */
       CTOR_BEGIN_P (in CTOR_STMT)
       BV_USE_VCALL_INDEX_P (in the BINFO_VIRTUALS TREE_LIST)
       PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF)
+      PARMLIST_ELLIPSIS_P (in PARMLIST)
    1: IDENTIFIER_VIRTUAL_P.
       TI_PENDING_TEMPLATE_FLAG.
       TEMPLATE_PARMS_FOR_INLINE.
@@ -1768,6 +1769,9 @@ struct lang_type
    is a list of parameters, as opposed to a list of expressions.  */
 #define TREE_PARMLIST(NODE) ((NODE)->common.unsigned_flag) /* overloaded! */
 
+/* Nonzero for a parmlist means that this parmlist ended in ...  */
+#define PARMLIST_ELLIPSIS_P(NODE) TREE_LANG_FLAG_0 (NODE)
+
 /* For FUNCTION_TYPE or METHOD_TYPE, a list of the exceptions that
    this type can raise.  Each TREE_VALUE is a _TYPE.  The TREE_VALUE
    will be NULL_TREE to indicate a throw specification of `()', or
index 192a7cd..a357526 100644 (file)
@@ -100,7 +100,7 @@ extern int (*valid_lang_attribute) PARAMS ((tree, tree, tree, tree));
                        : "long long unsigned int"))
 #endif
 
-static tree grokparms                          PARAMS ((tree, int));
+static tree grokparms                          PARAMS ((tree));
 static const char *redeclaration_error_message PARAMS ((tree, tree));
 
 static void push_binding_level PARAMS ((struct binding_level *, int,
@@ -10738,7 +10738,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
            /* FIXME: This is where default args should be fully
               processed.  */
 
-           arg_types = grokparms (inner_parms, funcdecl_p ? funcdef_flag : 0);
+           arg_types = grokparms (inner_parms);
 
            if (declarator && flags == DTOR_FLAG)
              {
@@ -11367,11 +11367,6 @@ friend declaration requires class-key, i.e. `friend %#T'",
        type = build_pointer_type (type);
       else if (TREE_CODE (type) == OFFSET_TYPE)
        type = build_pointer_type (type);
-      else if (TREE_CODE (type) == VOID_TYPE && declarator)
-       {
-         error ("declaration of `%s' as void", name);
-         return NULL_TREE;
-       }
     }
 
   {
@@ -11837,25 +11832,13 @@ require_complete_types_for_parms (parms)
 {
   for (; parms; parms = TREE_CHAIN (parms))
     {
-      tree type = TREE_TYPE (parms);
-
-      /* Try to complete the TYPE.  */
-      type = complete_type (type);
-
-      if (type == error_mark_node)
-       continue;
-
-      if (!COMPLETE_TYPE_P (type))
-       {
-         if (DECL_NAME (parms))
-           error ("parameter `%s' has incomplete type",
-                  IDENTIFIER_POINTER (DECL_NAME (parms)));
-         else
-           error ("parameter has incomplete type");
-         TREE_TYPE (parms) = error_mark_node;
-       }
-      else
+      if (VOID_TYPE_P (TREE_TYPE (parms)))
+        /* grokparms will have already issued an error */
+        TREE_TYPE (parms) = error_mark_node;
+      else if (complete_type_or_else (TREE_TYPE (parms), parms))
        layout_decl (parms, 0);
+      else
+        TREE_TYPE (parms) = error_mark_node;
     }
 }
 
@@ -11986,205 +11969,114 @@ check_default_argument (decl, arg)
    Given the list of things declared inside the parens,
    return a list of types.
 
-   The list we receive can have three kinds of elements:
-   an IDENTIFIER_NODE for names given without types,
-   a TREE_LIST node for arguments given as typespecs or names with typespecs,
-   or void_type_node, to mark the end of an argument list
-   when additional arguments are not permitted (... was not used).
-
-   FUNCDEF_FLAG is nonzero for a function definition, 0 for
-   a mere declaration.  A nonempty identifier-list gets an error message
-   when FUNCDEF_FLAG is zero.
-   If FUNCDEF_FLAG is 1, then parameter types must be complete.
-   If FUNCDEF_FLAG is -1, then parameter types may be incomplete.
-
-   If all elements of the input list contain types,
-   we return a list of the types.
-   If all elements contain no type (except perhaps a void_type_node
-   at the end), we return a null list.
-   If some have types and some do not, it is an error, and we
-   return a null list.
-
-   Also set last_function_parms to either
-   a list of names (IDENTIFIER_NODEs) or a chain of PARM_DECLs.
-   A list of names is converted to a chain of PARM_DECLs
-   by store_parm_decls so that ultimately it is always a chain of decls.
-
-   Note that in C++, parameters can take default values.  These default
-   values are in the TREE_PURPOSE field of the TREE_LIST.  It is
-   an error to specify default values which are followed by parameters
-   that have no default values, or an ELLIPSES.  For simplicities sake,
-   only parameters which are specified with their types can take on
-   default values.  */
+   We determine whether ellipsis parms are used by PARMLIST_ELLIPSIS_P
+   flag. If unset, we append void_list_node. A parmlist declared
+   as `(void)' is accepted as the empty parmlist.
+
+   Also set last_function_parms to the chain of PARM_DECLs.  */
 
 static tree
-grokparms (first_parm, funcdef_flag)
+grokparms (first_parm)
      tree first_parm;
-     int funcdef_flag;
 {
   tree result = NULL_TREE;
   tree decls = NULL_TREE;
+  int ellipsis = !first_parm || PARMLIST_ELLIPSIS_P (first_parm);
+  tree parm, chain;
+  int any_error = 0;
 
-  if (first_parm != NULL_TREE
-      && TREE_CODE (TREE_VALUE (first_parm)) == IDENTIFIER_NODE)
-    {
-      if (! funcdef_flag)
-       pedwarn ("parameter names (without types) in function declaration");
-      last_function_parms = first_parm;
-      return NULL_TREE;
-    }
-  else if (first_parm != NULL_TREE
-          && TREE_CODE (TREE_VALUE (first_parm)) != TREE_LIST
-          && TREE_CODE (TREE_VALUE (first_parm)) != VOID_TYPE)
-    my_friendly_abort (145);
-  else
+  my_friendly_assert (!first_parm || TREE_PARMLIST (first_parm), 20001115);
+
+  for (parm = first_parm; parm != NULL_TREE; parm = chain)
     {
-      /* Types were specified.  This is a list of declarators
-        each represented as a TREE_LIST node.  */
-      register tree parm, chain;
-      int any_init = 0, any_error = 0;
+      tree type = NULL_TREE, list_node = parm;
+      register tree decl = TREE_VALUE (parm);
+      tree init = TREE_PURPOSE (parm);
 
-      if (first_parm != NULL_TREE)
+      chain = TREE_CHAIN (parm);
+      /* @@ weak defense against parse errors.  */
+      if (TREE_CODE (decl) != VOID_TYPE
+         && TREE_CODE (decl) != TREE_LIST)
        {
-         tree last_result = NULL_TREE;
-         tree last_decl = NULL_TREE;
-
-         for (parm = first_parm; parm != NULL_TREE; parm = chain)
-           {
-             tree type = NULL_TREE, list_node = parm;
-             register tree decl = TREE_VALUE (parm);
-             tree init = TREE_PURPOSE (parm);
-
-             chain = TREE_CHAIN (parm);
-             /* @@ weak defense against parse errors.  */
-             if (TREE_CODE (decl) != VOID_TYPE
-                 && TREE_CODE (decl) != TREE_LIST)
-               {
-                 /* Give various messages as the need arises.  */
-                 if (TREE_CODE (decl) == STRING_CST)
-                   cp_error ("invalid string constant `%E'", decl);
-                 else if (TREE_CODE (decl) == INTEGER_CST)
-                   error ("invalid integer constant in parameter list, did you forget to give parameter name?");
-                 continue;
-               }
+         /* Give various messages as the need arises.  */
+         if (TREE_CODE (decl) == STRING_CST)
+           cp_error ("invalid string constant `%E'", decl);
+         else if (TREE_CODE (decl) == INTEGER_CST)
+           error ("invalid integer constant in parameter list, did you forget to give parameter name?");
+         continue;
+       }
 
-             if (TREE_CODE (decl) != VOID_TYPE)
-               {
-                 decl = grokdeclarator (TREE_VALUE (decl),
-                                        TREE_PURPOSE (decl),
-                                        PARM, init != NULL_TREE,
-                                        NULL_TREE);
-                 if (! decl || TREE_TYPE (decl) == error_mark_node)
-                   continue;
-
-                 /* Top-level qualifiers on the parameters are
-                    ignored for function types.  */
-                 type = TYPE_MAIN_VARIANT (TREE_TYPE (decl));
-
-                 if (TREE_CODE (type) == VOID_TYPE)
-                   decl = void_type_node;
-                 else if (TREE_CODE (type) == METHOD_TYPE)
-                   {
-                     if (DECL_NAME (decl))
-                       /* Cannot use the decl here because
-                          we don't have DECL_CONTEXT set up yet.  */
-                       cp_error ("parameter `%D' invalidly declared method type",
-                                 DECL_NAME (decl));
-                     else
-                       error ("parameter invalidly declared method type");
-                     type = build_pointer_type (type);
-                     TREE_TYPE (decl) = type;
-                   }
-                 else if (TREE_CODE (type) == OFFSET_TYPE)
-                   {
-                     if (DECL_NAME (decl))
-                       cp_error ("parameter `%D' invalidly declared offset type",
-                                 DECL_NAME (decl));
-                     else
-                       error ("parameter invalidly declared offset type");
-                     type = build_pointer_type (type);
-                     TREE_TYPE (decl) = type;
-                   }
-                  else if (abstract_virtuals_error (decl, type))
-                   any_error = 1;  /* Seems like a good idea. */
-                 else if (POINTER_TYPE_P (type))
-                   {
-                     tree t = type;
-                     while (POINTER_TYPE_P (t)
-                            || (TREE_CODE (t) == ARRAY_TYPE
-                                && TYPE_DOMAIN (t) != NULL_TREE))
-                       t = TREE_TYPE (t);
-                     if (TREE_CODE (t) == ARRAY_TYPE)
-                       cp_error ("parameter type `%T' includes %s to array of unknown bound",
-                                 type,
-                                 TYPE_PTR_P (type) ? "pointer" : "reference");
-                   }
-               }
+      if (parm == void_list_node)
+        break;
 
-             if (TREE_CODE (decl) == VOID_TYPE)
-               {
-                 if (result == NULL_TREE)
-                   {
-                     result = void_list_node;
-                     last_result = result;
-                   }
-                 else
-                   {
-                     TREE_CHAIN (last_result) = void_list_node;
-                     last_result = void_list_node;
-                   }
-                 if (chain
-                     && (chain != void_list_node || TREE_CHAIN (chain)))
-                   error ("`void' in parameter list must be entire list");
-                 break;
-               }
+      decl = grokdeclarator (TREE_VALUE (decl), TREE_PURPOSE (decl),
+                            PARM, init != NULL_TREE, NULL_TREE);
+      if (! decl || TREE_TYPE (decl) == error_mark_node)
+        continue;
+    
+      type = TREE_TYPE (decl);
+      if (VOID_TYPE_P (type))
+        {
+          if (same_type_p (type, void_type_node)
+              && !DECL_NAME (decl) && !result && !chain && !ellipsis)
+            /* this is a parmlist of `(void)', which is ok.  */
+            break;
+          incomplete_type_error (decl, type);
+        }
+      
+      /* Top-level qualifiers on the parameters are
+         ignored for function types.  */
+      type = TYPE_MAIN_VARIANT (type);
+      if (TREE_CODE (type) == METHOD_TYPE)
+        {
+          cp_error ("parameter `%D' invalidly declared method type", decl);
+          type = build_pointer_type (type);
+          TREE_TYPE (decl) = type;
+        }
+      else if (TREE_CODE (type) == OFFSET_TYPE)
+        {
+          cp_error ("parameter `%D' invalidly declared offset type", decl);
+          type = build_pointer_type (type);
+          TREE_TYPE (decl) = type;
+        }
+      else if (abstract_virtuals_error (decl, type))
+        any_error = 1;  /* Seems like a good idea. */
+      else if (POINTER_TYPE_P (type))
+        {
+          /* [dcl.fct]/6, parameter types cannot contain pointers (references)
+             to arrays of unknown bound.  */
+          tree t = type;
+          
+          while (POINTER_TYPE_P (t)
+                 || (TREE_CODE (t) == ARRAY_TYPE
+                     && TYPE_DOMAIN (t) != NULL_TREE))
+           t = TREE_TYPE (t);
+          if (TREE_CODE (t) == ARRAY_TYPE)
+           cp_error ("parameter `%D' includes %s to array of unknown bound `%T'",
+                     decl, TYPE_PTR_P (type) ? "pointer" : "reference", t);
+        }
 
-             /* Since there is a prototype, args are passed in their own types.  */
-             DECL_ARG_TYPE (decl) = TREE_TYPE (decl);
-             if (PROMOTE_PROTOTYPES
-                 && (TREE_CODE (type) == INTEGER_TYPE
-                     || TREE_CODE (type) == ENUMERAL_TYPE)
-                 && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
-               DECL_ARG_TYPE (decl) = integer_type_node;
-             if (!any_error && init)
-               {
-                 any_init++;
-                 init = check_default_argument (decl, init);
-               }
-             else
-               init = NULL_TREE;
+      DECL_ARG_TYPE (decl) = TREE_TYPE (decl);
+      if (PROMOTE_PROTOTYPES
+         && (TREE_CODE (type) == INTEGER_TYPE
+             || TREE_CODE (type) == ENUMERAL_TYPE)
+         && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+       DECL_ARG_TYPE (decl) = integer_type_node;
+      if (!any_error && init)
+        init = check_default_argument (decl, init);
+      else
+       init = NULL_TREE;
 
-             if (decls == NULL_TREE)
-               {
-                 decls = decl;
-                 last_decl = decls;
-               }
-             else
-               {
-                 TREE_CHAIN (last_decl) = decl;
-                 last_decl = decl;
-               }
-             list_node = tree_cons (init, type, NULL_TREE);
-             if (result == NULL_TREE)
-               {
-                 result = list_node;
-                 last_result = result;
-               }
-             else
-               {
-                 TREE_CHAIN (last_result) = list_node;
-                 last_result = list_node;
-               }
-           }
-         if (last_result)
-           TREE_CHAIN (last_result) = NULL_TREE;
-         /* If there are no parameters, and the function does not end
-            with `...', then last_decl will be NULL_TREE.  */
-         if (last_decl != NULL_TREE)
-           TREE_CHAIN (last_decl) = NULL_TREE;
-       }
+      TREE_CHAIN (decl) = decls;
+      decls = decl;
+      list_node = tree_cons (init, type, NULL_TREE);
+      TREE_CHAIN (list_node) = result;
+      result = list_node;
     }
-
+  decls = nreverse (decls);
+  result = nreverse (result);
+  if (!ellipsis)
+    result = chainon (result, void_list_node);
   last_function_parms = decls;
 
   return result;
index 28c0f35..b372fdd 100644 (file)
@@ -1695,13 +1695,15 @@ finish_parmlist (parms, ellipsis)
      tree parms;
      int ellipsis;
 {
-  if (!ellipsis)
-    chainon (parms, void_list_node);
-  /* We mark the PARMS as a parmlist so that declarator processing can
-     disambiguate certain constructs.  */
-  if (parms != NULL_TREE)
-    TREE_PARMLIST (parms) = 1;
-
+  if (parms)
+    {
+      /* We mark the PARMS as a parmlist so that declarator processing can
+         disambiguate certain constructs.  */
+      TREE_PARMLIST (parms) = 1;
+      /* We do not append void_list_node here, but leave it to grokparms
+         to do that.  */
+      PARMLIST_ELLIPSIS_P (parms) = ellipsis;
+    }
   return parms;
 }
 
index d0c3dbf..b6acd13 100644 (file)
@@ -1,3 +1,8 @@
+2000-11-17  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * g++.old-deja/g++.other/incomplete.C: Add more tests.
+       * g++.old-deja/g++.pt/crash9.C: Mark new expected error.
+
 2000-11-16  Nick Clifton  <nickc@redhat.com>
 
        * gcc.c-torture/execute/nestfunc-2.c: New test.
index 0c230c1..f5e9a58 100644 (file)
@@ -1,5 +1,16 @@
 // Build don't link:
 
-struct S;
+// gcc represents non-ellipsis parmlists by terminating them with
+// a void parm. We need to distinguish between a parmlist of (void), and
+// some ill-formed ones.
 
-void f(S s) {} // ERROR - incomplete type
+struct S; // ERROR - forward ref
+
+void f(S);            // ok
+void f(S s) {}        // ERROR - incomplete type
+void j (int){};       // ok
+void k (){};          // ok
+void q (void){}       // ok
+void t (void t);      // ERROR - incomplete
+void r (void, ...);   // ERROR - incomplete
+void s (void const);  // ERROR - incomplete
index 297b8ac..d72699d 100644 (file)
@@ -3,7 +3,7 @@
 template <class T>
 void f(T) {} // ERROR - parameter has incomplete type
 
-class C;
+class C;    // ERROR - forward declaration
 
 void g(const C& c)
 {