This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH for crash with incomplete types
- To: egcs-patches at cygnus dot com
- Subject: PATCH for crash with incomplete types
- From: Mark Mitchell <mark at markmitchell dot com>
- Date: Sun, 7 Jun 1998 19:45:11 -0700
- Cc: Jason Merrill <jason at cygnus dot com>
- Reply-to: mark at markmitchell dot com
Here's a patch for the crash on the enclosed testcase. Jason, OK?
--
Mark Mitchell mark@markmitchell.com
Mark Mitchell Consulting http://www.markmitchell.com
1998-06-07 Mark Mitchell <mark@markmitchell.com>
* cp-tree.h (ICS_USER_FLAG): Move here from call.c
(ICS_ELLIPSIS_FLAG): Likewise.
(ICS_THIS_FLAG): Likewise.
(ICS_BAD_FLAG): Likewise.
(convert_like): Declare.
(convert_arguments): Change interface.
* typeck.c (build_function_call_real): Use new interface to
convert_arguments.
(convert_arguments): Merge in code from build_over_call.
* call.c (convert_default_arg): Remove.
(convert_like): Make global, not static.
(ICS_USER_FLAG): Remove.
(ICS_ELLIPSIS_FLAG): Likewise.
(ICS_THIS_FLAG): Likewise.
(ICS_BAD_FLAG): Likewise.
(build_over_call): Use convert_arguments rather than duplicating
inline.
Index: testsuite/g++.old-deja/g++.pt/crash9.C
===================================================================
RCS file: crash9.C
diff -N crash9.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- crash9.C Sun Jun 7 19:15:02 1998
***************
*** 0 ****
--- 1,11 ----
+ // Build don't link:
+
+ template <class T>
+ void f(T) {} // ERROR - parameter has incomplete type
+
+ class C;
+
+ void g(const C& c)
+ {
+ f(c); // ERROR - invalid use of undefined type
+ }
Index: cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.79
diff -c -p -r1.79 cp-tree.h
*** cp-tree.h 1998/06/05 02:26:44 1.79
--- cp-tree.h 1998/06/08 02:15:47
*************** Boston, MA 02111-1307, USA. */
*** 34,39 ****
--- 34,40 ----
LOOKUP_EXPR_GLOBAL (in LOOKUP_EXPR).
TREE_NEGATED_INT (in INTEGER_CST).
(TREE_MANGLED) (in IDENTIFIER_NODE) (commented-out).
+ ICS_USER_FLAG (in a _CONV).
1: IDENTIFIER_VIRTUAL_P.
TI_PENDING_TEMPLATE_FLAG.
TI_PENDING_SPECIALIZATION_FLAG.
*************** Boston, MA 02111-1307, USA. */
*** 42,54 ****
--- 43,58 ----
(TREE_CALLS_NEW) (in _EXPR or _REF) (commented-out).
TYPE_USES_COMPLEX_INHERITANCE (in _TYPE).
C_DECLARED_LABEL_FLAG.
+ ICS_ELLIPSIS_FLAG (in a _CONV).
2: IDENTIFIER_OPNAME_P.
BINFO_FIELDS_MARKED.
TYPE_VIRTUAL_P.
PARM_DECL_EXPR (in SAVE_EXPR).
+ ICS_BAD_FLAG (in a _CONV).
3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE).
BINFO_VTABLE_PATH_MARKED.
(TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
+ ICS_BAD_FLAG (in a _CONV).
4: BINFO_NEW_VTABLE_MARKED.
TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
or FIELD_DECL).
*************** extern tree current_class_type; /* _TYPE
*** 2194,2199 ****
--- 2198,2214 ----
#define CONV_C_CAST (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \
| CONV_REINTERPRET | CONV_PRIVATE | CONV_FORCE_TEMP)
+ /* These flags are used by the conversion code.
+ ICS_USER_FLAG : A user-defined conversion.
+ ICS_ELLIPSIS_FLAG : An ellipsis conversion.
+ ICS_THIS_FLAG : A conversion of `this'.
+ ICS_BAD_FLAG : An invalid conversion. */
+
+ #define ICS_USER_FLAG(NODE) TREE_LANG_FLAG_0 (NODE)
+ #define ICS_ELLIPSIS_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
+ #define ICS_THIS_FLAG(NODE) TREE_LANG_FLAG_2 (NODE)
+ #define ICS_BAD_FLAG(NODE) TREE_LANG_FLAG_3 (NODE)
+
/* Used by build_expr_type_conversion to indicate which types are
acceptable as arguments to the expression under consideration. */
*************** extern tree build_op_delete_call PROTO(
*** 2252,2257 ****
--- 2267,2273 ----
extern int can_convert PROTO((tree, tree));
extern int can_convert_arg PROTO((tree, tree, tree));
extern void enforce_access PROTO((tree, tree));
+ extern tree convert_like PROTO((tree, tree));
/* in class.c */
extern tree build_vbase_path PROTO((enum tree_code, tree, tree, tree, int));
*************** extern tree get_member_function_from_ptr
*** 2921,2927 ****
extern tree build_function_call_real PROTO((tree, tree, int, int));
extern tree build_function_call PROTO((tree, tree));
extern tree build_function_call_maybe PROTO((tree, tree));
! extern tree convert_arguments PROTO((tree, tree, tree, tree, int));
extern tree build_x_binary_op PROTO((enum tree_code, tree, tree));
extern tree build_binary_op PROTO((enum tree_code, tree, tree, int));
extern tree build_binary_op_nodefault PROTO((enum tree_code, tree, tree, enum tree_code));
--- 2937,2943 ----
extern tree build_function_call_real PROTO((tree, tree, int, int));
extern tree build_function_call PROTO((tree, tree));
extern tree build_function_call_maybe PROTO((tree, tree));
! extern tree convert_arguments PROTO((tree, tree, tree, tree, int, tree, int));
extern tree build_x_binary_op PROTO((enum tree_code, tree, tree));
extern tree build_binary_op PROTO((enum tree_code, tree, tree, int));
extern tree build_binary_op_nodefault PROTO((enum tree_code, tree, tree, enum tree_code));
Index: cp/typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck.c,v
retrieving revision 1.76
diff -c -p -r1.76 typeck.c
*** typeck.c 1998/06/07 12:13:52 1.76
--- typeck.c 1998/06/08 02:15:25
*************** build_function_call_real (function, para
*** 2803,2812 ****
if (flags & LOOKUP_COMPLAIN)
coerced_params = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
! params, fndecl, LOOKUP_NORMAL);
else
coerced_params = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
! params, fndecl, 0);
if (coerced_params == error_mark_node)
{
--- 2803,2813 ----
if (flags & LOOKUP_COMPLAIN)
coerced_params = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
! params, fndecl, LOOKUP_NORMAL,
! NULL_TREE, 0);
else
coerced_params = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
! params, fndecl, 0, NULL_TREE, 0);
if (coerced_params == error_mark_node)
{
*************** build_function_call (function, params)
*** 2877,2884 ****
value directly. If we are not eliding constructors, then we set this
to NULL_TREE to avoid this avoidance.
! NAME is an IDENTIFIER_NODE or 0. It is used only for error messages.
This is also where warnings about wrong number of args are generated.
Return a list of expressions for the parameters as converted.
--- 2878,2891 ----
value directly. If we are not eliding constructors, then we set this
to NULL_TREE to avoid this avoidance.
! FNDECL is the function being called.
+ The CONVS, if non-NULL, are a vector of conversions computed during
+ overload resolution, and used to direct the conversion of the
+ arguments.
+
+ I is the index of the first argument, starting from zero.
+
This is also where warnings about wrong number of args are generated.
Return a list of expressions for the parameters as converted.
*************** build_function_call (function, params)
*** 2890,2903 ****
default arguments, if such were specified. Do so here. */
tree
! convert_arguments (return_loc, typelist, values, fndecl, flags)
tree return_loc, typelist, values, fndecl;
int flags;
{
register tree typetail, valtail;
register tree result = NULL_TREE;
char *called_thing = 0;
! int i = 0;
if (! flag_elide_constructors)
return_loc = 0;
--- 2897,2912 ----
default arguments, if such were specified. Do so here. */
tree
! convert_arguments (return_loc, typelist, values, fndecl, flags, convs, i)
tree return_loc, typelist, values, fndecl;
int flags;
+ tree convs;
+ int i;
{
register tree typetail, valtail;
register tree result = NULL_TREE;
char *called_thing = 0;
! int is_method = 0;
if (! flag_elide_constructors)
return_loc = 0;
*************** convert_arguments (return_loc, typelist,
*** 2912,2919 ****
if (DECL_NAME (fndecl) == NULL_TREE
|| IDENTIFIER_HAS_TYPE_VALUE (DECL_NAME (fndecl)))
called_thing = "constructor";
! else
! called_thing = "member function";
}
else
called_thing = "function";
--- 2921,2931 ----
if (DECL_NAME (fndecl) == NULL_TREE
|| IDENTIFIER_HAS_TYPE_VALUE (DECL_NAME (fndecl)))
called_thing = "constructor";
! else
! {
! called_thing = "member function";
! is_method = 1;
! }
}
else
called_thing = "function";
*************** convert_arguments (return_loc, typelist,
*** 3000,3013 ****
if (TYPE_SIZE (complete_type (type)) == 0)
{
! error ("parameter type of called function is incomplete");
parmval = val;
}
else
{
! parmval = convert_for_initialization
! (return_loc, type, val, flags,
! "argument passing", fndecl, i);
#ifdef PROMOTE_PROTOTYPES
if ((TREE_CODE (type) == INTEGER_TYPE
|| TREE_CODE (type) == ENUMERAL_TYPE)
--- 3012,3051 ----
if (TYPE_SIZE (complete_type (type)) == 0)
{
! if (fndecl)
! cp_error ("parameter type `%T' of called %s `%D' is incomplete",
! type, called_thing, fndecl);
! else
! cp_error ("parameter type `%T' of called function is incomplete",
! type);
parmval = val;
}
else
{
! tree conv = convs ? TREE_VEC_ELT (convs, i) : NULL_TREE;
!
! if (!conv || ICS_BAD_FLAG (conv))
! {
! tree t = conv;
!
! for (; t; t = TREE_OPERAND (t, 0))
! {
! if (TREE_CODE (t) == USER_CONV
! || TREE_CODE (t) == AMBIG_CONV)
! {
! parmval = convert_like (t, val);
! break;
! }
! else if (TREE_CODE (t) == IDENTITY_CONV)
! break;
! }
! parmval = convert_for_initialization
! (return_loc, type, val, flags,
! "argument passing", fndecl, i - is_method);
! }
! else
! parmval = convert_like (conv, val);
!
#ifdef PROMOTE_PROTOTYPES
if ((TREE_CODE (type) == INTEGER_TYPE
|| TREE_CODE (type) == ENUMERAL_TYPE)
*************** convert_arguments (return_loc, typelist,
*** 3056,3067 ****
/* See if there are default arguments that can be used */
if (TREE_PURPOSE (typetail))
{
! for (; typetail != void_list_node; ++i)
{
tree type = TREE_VALUE (typetail);
! tree val = break_out_target_exprs (TREE_PURPOSE (typetail));
tree parmval;
if (val == NULL_TREE)
parmval = error_mark_node;
else if (TREE_CODE (val) == CONSTRUCTOR)
--- 3094,3131 ----
/* See if there are default arguments that can be used */
if (TREE_PURPOSE (typetail))
{
! for (; typetail && typetail != void_list_node;
! typetail = TREE_CHAIN (typetail), ++i)
{
tree type = TREE_VALUE (typetail);
! tree val = TREE_PURPOSE (typetail);
tree parmval;
+ if (fndecl && DECL_TEMPLATE_INFO (fndecl))
+ {
+ /* This came from a template. Instantiate the
+ default arg here, not in tsubst. In the case of
+ something like:
+
+ template <class T>
+ struct S {
+ static T t();
+ void f(T = t());
+ };
+
+ we must be careful to do name lookup in the scope of
+ S<T>, rather than in the current class. */
+ if (DECL_CLASS_SCOPE_P (fndecl))
+ pushclass (DECL_REAL_CONTEXT (fndecl), 2);
+
+ val = tsubst_expr (val, DECL_TI_ARGS (fndecl), NULL_TREE);
+
+ if (DECL_CLASS_SCOPE_P (fndecl))
+ popclass (0);
+ }
+
+ val = break_out_target_exprs (val);
+
if (val == NULL_TREE)
parmval = error_mark_node;
else if (TREE_CODE (val) == CONSTRUCTOR)
*************** convert_arguments (return_loc, typelist,
*** 3069,3075 ****
parmval = digest_init (type, val, (tree *)0);
parmval = convert_for_initialization (return_loc, type,
parmval, flags,
! "default constructor",
fndecl, i);
}
else
--- 3133,3139 ----
parmval = digest_init (type, val, (tree *)0);
parmval = convert_for_initialization (return_loc, type,
parmval, flags,
! "default argument",
fndecl, i);
}
else
*************** convert_arguments (return_loc, typelist,
*** 3090,3104 ****
parmval = default_conversion (parmval);
#endif
}
-
- if (parmval == error_mark_node)
- return error_mark_node;
! result = expr_tree_cons (0, parmval, result);
! typetail = TREE_CHAIN (typetail);
! /* ends with `...'. */
! if (typetail == NULL_TREE)
! break;
}
}
else
--- 3154,3161 ----
parmval = default_conversion (parmval);
#endif
}
! result = expr_tree_cons (NULL_TREE, parmval, result);
}
}
else
Index: cp/call.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/call.c,v
retrieving revision 1.85
diff -c -p -r1.85 call.c
*** call.c 1998/06/05 23:03:33 1.85
--- call.c 1998/06/08 02:15:36
*************** static struct z_candidate * tourney PROT
*** 47,54 ****
static int joust PROTO((struct z_candidate *, struct z_candidate *, int));
static int compare_ics PROTO((tree, tree));
static tree build_over_call PROTO((struct z_candidate *, tree, int));
- static tree convert_default_arg PROTO((tree, tree));
- static tree convert_like PROTO((tree, tree));
static void op_error PROTO((enum tree_code, enum tree_code, tree, tree,
tree, char *));
static tree build_object_call PROTO((tree, tree));
--- 47,52 ----
*************** struct z_candidate {
*** 719,729 ****
#define ICS_STD_RANK(NODE) TREE_COMPLEXITY (NODE)
- #define ICS_USER_FLAG(NODE) TREE_LANG_FLAG_0 (NODE)
- #define ICS_ELLIPSIS_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
- #define ICS_THIS_FLAG(NODE) TREE_LANG_FLAG_2 (NODE)
- #define ICS_BAD_FLAG(NODE) TREE_LANG_FLAG_3 (NODE)
-
#define USER_CONV_CAND(NODE) \
((struct z_candidate *)WRAPPER_PTR (TREE_OPERAND (NODE, 1)))
#define USER_CONV_FN(NODE) (USER_CONV_CAND (NODE)->fn)
--- 717,722 ----
*************** enforce_access (basetype_path, decl)
*** 3069,3075 ****
/* Perform the conversions in CONVS on the expression EXPR. */
! static tree
convert_like (convs, expr)
tree convs, expr;
{
--- 3062,3068 ----
/* Perform the conversions in CONVS on the expression EXPR. */
! tree
convert_like (convs, expr)
tree convs, expr;
{
*************** convert_like (convs, expr)
*** 3169,3205 ****
}
static tree
- convert_default_arg (type, arg)
- tree type, arg;
- {
- arg = break_out_target_exprs (arg);
-
- if (TREE_CODE (arg) == CONSTRUCTOR)
- {
- arg = digest_init (type, arg, 0);
- arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
- "default argument", 0, 0);
- }
- else
- {
- /* This could get clobbered by the following call. */
- if (TREE_HAS_CONSTRUCTOR (arg))
- arg = copy_node (arg);
-
- arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
- "default argument", 0, 0);
- #ifdef PROMOTE_PROTOTYPES
- if ((TREE_CODE (type) == INTEGER_TYPE
- || TREE_CODE (type) == ENUMERAL_TYPE)
- && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
- arg = default_conversion (arg);
- #endif
- }
-
- return arg;
- }
-
- static tree
build_over_call (cand, args, flags)
struct z_candidate *cand;
tree args;
--- 3162,3167 ----
*************** build_over_call (cand, args, flags)
*** 3209,3217 ****
tree convs = cand->convs;
tree converted_args = NULL_TREE;
tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
! tree conv, arg, val;
int i = 0;
- int is_method = 0;
/* Give any warnings we noticed during overload resolution. */
if (cand->warnings)
--- 3171,3178 ----
tree convs = cand->convs;
tree converted_args = NULL_TREE;
tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
! tree arg, val;
int i = 0;
/* Give any warnings we noticed during overload resolution. */
if (cand->warnings)
*************** build_over_call (cand, args, flags)
*** 3263,3362 ****
parm = TREE_CHAIN (parm);
arg = TREE_CHAIN (arg);
++i;
- is_method = 1;
- }
-
- for (; arg && parm;
- parm = TREE_CHAIN (parm), arg = TREE_CHAIN (arg), ++i)
- {
- tree type = TREE_VALUE (parm);
-
- conv = TREE_VEC_ELT (convs, i);
- if (ICS_BAD_FLAG (conv))
- {
- tree t = conv;
- val = TREE_VALUE (arg);
-
- for (; t; t = TREE_OPERAND (t, 0))
- {
- if (TREE_CODE (t) == USER_CONV
- || TREE_CODE (t) == AMBIG_CONV)
- {
- val = convert_like (t, val);
- break;
- }
- else if (TREE_CODE (t) == IDENTITY_CONV)
- break;
- }
- val = convert_for_initialization
- (NULL_TREE, type, val, LOOKUP_NORMAL,
- "argument passing", fn, i - is_method);
- }
- else
- val = convert_like (conv, TREE_VALUE (arg));
-
- #ifdef PROMOTE_PROTOTYPES
- if ((TREE_CODE (type) == INTEGER_TYPE
- || TREE_CODE (type) == ENUMERAL_TYPE)
- && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
- val = default_conversion (val);
- #endif
- converted_args = expr_tree_cons (NULL_TREE, val, converted_args);
- }
-
- /* Default arguments */
- for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm))
- {
- tree arg = TREE_PURPOSE (parm);
-
- if (DECL_TEMPLATE_INFO (fn))
- {
- /* This came from a template. Instantiate the default arg here,
- not in tsubst. In the case of something like:
-
- template <class T>
- struct S {
- static T t();
- void f(T = t());
- };
-
- we must be careful to do name lookup in the scope of
- S<T>, rather than in the current class. */
- if (DECL_CLASS_SCOPE_P (fn))
- pushclass (DECL_REAL_CONTEXT (fn), 2);
-
- arg = tsubst_expr (arg, DECL_TI_ARGS (fn), NULL_TREE);
-
- if (DECL_CLASS_SCOPE_P (fn))
- popclass (0);
- }
- converted_args = expr_tree_cons
- (NULL_TREE, convert_default_arg (TREE_VALUE (parm), arg),
- converted_args);
- }
-
- /* Ellipsis */
- for (; arg; arg = TREE_CHAIN (arg))
- {
- val = TREE_VALUE (arg);
-
- if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE
- && (TYPE_PRECISION (TREE_TYPE (val))
- < TYPE_PRECISION (double_type_node)))
- /* Convert `float' to `double'. */
- val = cp_convert (double_type_node, val);
- else if (IS_AGGR_TYPE (TREE_TYPE (val))
- && ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (val)))
- cp_warning ("cannot pass objects of type `%T' through `...'",
- TREE_TYPE (val));
- else
- /* Convert `short' and `char' to full-size `int'. */
- val = default_conversion (val);
-
- converted_args = expr_tree_cons (NULL_TREE, val, converted_args);
}
! converted_args = nreverse (converted_args);
/* Avoid actually calling copy constructors and copy assignment operators,
if possible. */
--- 3224,3235 ----
parm = TREE_CHAIN (parm);
arg = TREE_CHAIN (arg);
++i;
}
! converted_args =
! chainon (nreverse (converted_args),
! convert_arguments (NULL_TREE, parm, arg, fn,
! LOOKUP_NORMAL, convs, i));
/* Avoid actually calling copy constructors and copy assignment operators,
if possible. */