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
This commit is contained in:
parent
146c8d6034
commit
5cce22b6c2
|
@ -1,3 +1,14 @@
|
||||||
|
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>
|
2000-11-17 Nathan Sidwell <nathan@codesourcery.com>
|
||||||
|
|
||||||
* typeck2.c (incomplete_type_error): Reorganise to avoid
|
* typeck2.c (incomplete_type_error): Reorganise to avoid
|
||||||
|
|
|
@ -44,6 +44,7 @@ Boston, MA 02111-1307, USA. */
|
||||||
CTOR_BEGIN_P (in CTOR_STMT)
|
CTOR_BEGIN_P (in CTOR_STMT)
|
||||||
BV_USE_VCALL_INDEX_P (in the BINFO_VIRTUALS TREE_LIST)
|
BV_USE_VCALL_INDEX_P (in the BINFO_VIRTUALS TREE_LIST)
|
||||||
PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF)
|
PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF)
|
||||||
|
PARMLIST_ELLIPSIS_P (in PARMLIST)
|
||||||
1: IDENTIFIER_VIRTUAL_P.
|
1: IDENTIFIER_VIRTUAL_P.
|
||||||
TI_PENDING_TEMPLATE_FLAG.
|
TI_PENDING_TEMPLATE_FLAG.
|
||||||
TEMPLATE_PARMS_FOR_INLINE.
|
TEMPLATE_PARMS_FOR_INLINE.
|
||||||
|
@ -1768,6 +1769,9 @@ struct lang_type
|
||||||
is a list of parameters, as opposed to a list of expressions. */
|
is a list of parameters, as opposed to a list of expressions. */
|
||||||
#define TREE_PARMLIST(NODE) ((NODE)->common.unsigned_flag) /* overloaded! */
|
#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
|
/* 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
|
this type can raise. Each TREE_VALUE is a _TYPE. The TREE_VALUE
|
||||||
will be NULL_TREE to indicate a throw specification of `()', or
|
will be NULL_TREE to indicate a throw specification of `()', or
|
||||||
|
|
200
gcc/cp/decl.c
200
gcc/cp/decl.c
|
@ -100,7 +100,7 @@ extern int (*valid_lang_attribute) PARAMS ((tree, tree, tree, tree));
|
||||||
: "long long unsigned int"))
|
: "long long unsigned int"))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static tree grokparms PARAMS ((tree, int));
|
static tree grokparms PARAMS ((tree));
|
||||||
static const char *redeclaration_error_message PARAMS ((tree, tree));
|
static const char *redeclaration_error_message PARAMS ((tree, tree));
|
||||||
|
|
||||||
static void push_binding_level PARAMS ((struct binding_level *, int,
|
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
|
/* FIXME: This is where default args should be fully
|
||||||
processed. */
|
processed. */
|
||||||
|
|
||||||
arg_types = grokparms (inner_parms, funcdecl_p ? funcdef_flag : 0);
|
arg_types = grokparms (inner_parms);
|
||||||
|
|
||||||
if (declarator && flags == DTOR_FLAG)
|
if (declarator && flags == DTOR_FLAG)
|
||||||
{
|
{
|
||||||
|
@ -11367,11 +11367,6 @@ friend declaration requires class-key, i.e. `friend %#T'",
|
||||||
type = build_pointer_type (type);
|
type = build_pointer_type (type);
|
||||||
else if (TREE_CODE (type) == OFFSET_TYPE)
|
else if (TREE_CODE (type) == OFFSET_TYPE)
|
||||||
type = build_pointer_type (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))
|
for (; parms; parms = TREE_CHAIN (parms))
|
||||||
{
|
{
|
||||||
tree type = TREE_TYPE (parms);
|
if (VOID_TYPE_P (TREE_TYPE (parms)))
|
||||||
|
/* grokparms will have already issued an error */
|
||||||
/* 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;
|
TREE_TYPE (parms) = error_mark_node;
|
||||||
}
|
else if (complete_type_or_else (TREE_TYPE (parms), parms))
|
||||||
else
|
|
||||||
layout_decl (parms, 0);
|
layout_decl (parms, 0);
|
||||||
|
else
|
||||||
|
TREE_TYPE (parms) = error_mark_node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11986,68 +11969,23 @@ check_default_argument (decl, arg)
|
||||||
Given the list of things declared inside the parens,
|
Given the list of things declared inside the parens,
|
||||||
return a list of types.
|
return a list of types.
|
||||||
|
|
||||||
The list we receive can have three kinds of elements:
|
We determine whether ellipsis parms are used by PARMLIST_ELLIPSIS_P
|
||||||
an IDENTIFIER_NODE for names given without types,
|
flag. If unset, we append void_list_node. A parmlist declared
|
||||||
a TREE_LIST node for arguments given as typespecs or names with typespecs,
|
as `(void)' is accepted as the empty parmlist.
|
||||||
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
|
Also set last_function_parms to the chain of PARM_DECLs. */
|
||||||
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. */
|
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
grokparms (first_parm, funcdef_flag)
|
grokparms (first_parm)
|
||||||
tree first_parm;
|
tree first_parm;
|
||||||
int funcdef_flag;
|
|
||||||
{
|
{
|
||||||
tree result = NULL_TREE;
|
tree result = NULL_TREE;
|
||||||
tree decls = 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
|
my_friendly_assert (!first_parm || TREE_PARMLIST (first_parm), 20001115);
|
||||||
&& 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
|
|
||||||
{
|
|
||||||
/* 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;
|
|
||||||
|
|
||||||
if (first_parm != NULL_TREE)
|
|
||||||
{
|
|
||||||
tree last_result = NULL_TREE;
|
|
||||||
tree last_decl = NULL_TREE;
|
|
||||||
|
|
||||||
for (parm = first_parm; parm != NULL_TREE; parm = chain)
|
for (parm = first_parm; parm != NULL_TREE; parm = chain)
|
||||||
{
|
{
|
||||||
|
@ -12068,40 +12006,36 @@ grokparms (first_parm, funcdef_flag)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TREE_CODE (decl) != VOID_TYPE)
|
if (parm == void_list_node)
|
||||||
{
|
break;
|
||||||
decl = grokdeclarator (TREE_VALUE (decl),
|
|
||||||
TREE_PURPOSE (decl),
|
decl = grokdeclarator (TREE_VALUE (decl), TREE_PURPOSE (decl),
|
||||||
PARM, init != NULL_TREE,
|
PARM, init != NULL_TREE, NULL_TREE);
|
||||||
NULL_TREE);
|
|
||||||
if (! decl || TREE_TYPE (decl) == error_mark_node)
|
if (! decl || TREE_TYPE (decl) == error_mark_node)
|
||||||
continue;
|
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
|
/* Top-level qualifiers on the parameters are
|
||||||
ignored for function types. */
|
ignored for function types. */
|
||||||
type = TYPE_MAIN_VARIANT (TREE_TYPE (decl));
|
type = TYPE_MAIN_VARIANT (type);
|
||||||
|
if (TREE_CODE (type) == METHOD_TYPE)
|
||||||
if (TREE_CODE (type) == VOID_TYPE)
|
|
||||||
decl = void_type_node;
|
|
||||||
else if (TREE_CODE (type) == METHOD_TYPE)
|
|
||||||
{
|
{
|
||||||
if (DECL_NAME (decl))
|
cp_error ("parameter `%D' invalidly declared method type", 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);
|
type = build_pointer_type (type);
|
||||||
TREE_TYPE (decl) = type;
|
TREE_TYPE (decl) = type;
|
||||||
}
|
}
|
||||||
else if (TREE_CODE (type) == OFFSET_TYPE)
|
else if (TREE_CODE (type) == OFFSET_TYPE)
|
||||||
{
|
{
|
||||||
if (DECL_NAME (decl))
|
cp_error ("parameter `%D' invalidly declared offset type", decl);
|
||||||
cp_error ("parameter `%D' invalidly declared offset type",
|
|
||||||
DECL_NAME (decl));
|
|
||||||
else
|
|
||||||
error ("parameter invalidly declared offset type");
|
|
||||||
type = build_pointer_type (type);
|
type = build_pointer_type (type);
|
||||||
TREE_TYPE (decl) = type;
|
TREE_TYPE (decl) = type;
|
||||||
}
|
}
|
||||||
|
@ -12109,37 +12043,19 @@ grokparms (first_parm, funcdef_flag)
|
||||||
any_error = 1; /* Seems like a good idea. */
|
any_error = 1; /* Seems like a good idea. */
|
||||||
else if (POINTER_TYPE_P (type))
|
else if (POINTER_TYPE_P (type))
|
||||||
{
|
{
|
||||||
|
/* [dcl.fct]/6, parameter types cannot contain pointers (references)
|
||||||
|
to arrays of unknown bound. */
|
||||||
tree t = type;
|
tree t = type;
|
||||||
|
|
||||||
while (POINTER_TYPE_P (t)
|
while (POINTER_TYPE_P (t)
|
||||||
|| (TREE_CODE (t) == ARRAY_TYPE
|
|| (TREE_CODE (t) == ARRAY_TYPE
|
||||||
&& TYPE_DOMAIN (t) != NULL_TREE))
|
&& TYPE_DOMAIN (t) != NULL_TREE))
|
||||||
t = TREE_TYPE (t);
|
t = TREE_TYPE (t);
|
||||||
if (TREE_CODE (t) == ARRAY_TYPE)
|
if (TREE_CODE (t) == ARRAY_TYPE)
|
||||||
cp_error ("parameter type `%T' includes %s to array of unknown bound",
|
cp_error ("parameter `%D' includes %s to array of unknown bound `%T'",
|
||||||
type,
|
decl, TYPE_PTR_P (type) ? "pointer" : "reference", t);
|
||||||
TYPE_PTR_P (type) ? "pointer" : "reference");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Since there is a prototype, args are passed in their own types. */
|
|
||||||
DECL_ARG_TYPE (decl) = TREE_TYPE (decl);
|
DECL_ARG_TYPE (decl) = TREE_TYPE (decl);
|
||||||
if (PROMOTE_PROTOTYPES
|
if (PROMOTE_PROTOTYPES
|
||||||
&& (TREE_CODE (type) == INTEGER_TYPE
|
&& (TREE_CODE (type) == INTEGER_TYPE
|
||||||
|
@ -12147,44 +12063,20 @@ grokparms (first_parm, funcdef_flag)
|
||||||
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
|
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
|
||||||
DECL_ARG_TYPE (decl) = integer_type_node;
|
DECL_ARG_TYPE (decl) = integer_type_node;
|
||||||
if (!any_error && init)
|
if (!any_error && init)
|
||||||
{
|
|
||||||
any_init++;
|
|
||||||
init = check_default_argument (decl, init);
|
init = check_default_argument (decl, init);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
init = NULL_TREE;
|
init = NULL_TREE;
|
||||||
|
|
||||||
if (decls == NULL_TREE)
|
TREE_CHAIN (decl) = decls;
|
||||||
{
|
|
||||||
decls = decl;
|
decls = decl;
|
||||||
last_decl = decls;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TREE_CHAIN (last_decl) = decl;
|
|
||||||
last_decl = decl;
|
|
||||||
}
|
|
||||||
list_node = tree_cons (init, type, NULL_TREE);
|
list_node = tree_cons (init, type, NULL_TREE);
|
||||||
if (result == NULL_TREE)
|
TREE_CHAIN (list_node) = result;
|
||||||
{
|
|
||||||
result = list_node;
|
result = list_node;
|
||||||
last_result = result;
|
|
||||||
}
|
}
|
||||||
else
|
decls = nreverse (decls);
|
||||||
{
|
result = nreverse (result);
|
||||||
TREE_CHAIN (last_result) = list_node;
|
if (!ellipsis)
|
||||||
last_result = list_node;
|
result = chainon (result, void_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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
last_function_parms = decls;
|
last_function_parms = decls;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -1695,13 +1695,15 @@ finish_parmlist (parms, ellipsis)
|
||||||
tree parms;
|
tree parms;
|
||||||
int ellipsis;
|
int ellipsis;
|
||||||
{
|
{
|
||||||
if (!ellipsis)
|
if (parms)
|
||||||
chainon (parms, void_list_node);
|
{
|
||||||
/* We mark the PARMS as a parmlist so that declarator processing can
|
/* We mark the PARMS as a parmlist so that declarator processing can
|
||||||
disambiguate certain constructs. */
|
disambiguate certain constructs. */
|
||||||
if (parms != NULL_TREE)
|
|
||||||
TREE_PARMLIST (parms) = 1;
|
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;
|
return parms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>
|
2000-11-16 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
* gcc.c-torture/execute/nestfunc-2.c: New test.
|
* gcc.c-torture/execute/nestfunc-2.c: New test.
|
||||||
|
|
|
@ -1,5 +1,16 @@
|
||||||
// Build don't link:
|
// 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.
|
||||||
|
|
||||||
|
struct S; // ERROR - forward ref
|
||||||
|
|
||||||
|
void f(S); // ok
|
||||||
void f(S s) {} // ERROR - incomplete type
|
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
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
template <class T>
|
template <class T>
|
||||||
void f(T) {} // ERROR - parameter has incomplete type
|
void f(T) {} // ERROR - parameter has incomplete type
|
||||||
|
|
||||||
class C;
|
class C; // ERROR - forward declaration
|
||||||
|
|
||||||
void g(const C& c)
|
void g(const C& c)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue