aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2000-11-17 10:05:31 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2000-11-17 10:05:31 +0000
commit5cce22b6c2bfebd556b36a9c89d1bdf3eee900ae (patch)
treee34855fe7b427f6d66bd4533fcc51da52d25cfb4 /gcc/cp
parent146c8d603442514a3d8ad791630e87c2cf5169c3 (diff)
downloadgcc-5cce22b6c2bfebd556b36a9c89d1bdf3eee900ae.zip
gcc-5cce22b6c2bfebd556b36a9c89d1bdf3eee900ae.tar.gz
gcc-5cce22b6c2bfebd556b36a9c89d1bdf3eee900ae.tar.bz2
cp-tree.h (PARMLIST_ELLIPSIS_P): New macro.
cp: * 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. From-SVN: r37517
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/decl.c310
-rw-r--r--gcc/cp/semantics.c16
4 files changed, 125 insertions, 216 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f059212..1cbeac8 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 67e4c23..34c9d13 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 192a7cd..a357526 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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;
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 28c0f35..b372fdd 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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;
}