call.c, [...]: Remove support for -fno-ansi-overloading and overloading METHOD_CALL_EXPR.
* call.c, class.c, cp-tree.h, cvt.c, decl.c, init.c, lex.c, method.c, pt.c, ptree.c, typeck.c: Remove support for -fno-ansi-overloading and overloading METHOD_CALL_EXPR. * class.h: Remove. * Makefile.in: Adjust. From-SVN: r18384
This commit is contained in:
parent
4943217104
commit
277294d73b
15 changed files with 61 additions and 3675 deletions
|
@ -1,5 +1,11 @@
|
|||
Tue Mar 3 01:38:17 1998 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* call.c, class.c, cp-tree.h, cvt.c, decl.c, init.c, lex.c,
|
||||
method.c, pt.c, ptree.c, typeck.c: Remove support for
|
||||
-fno-ansi-overloading and overloading METHOD_CALL_EXPR.
|
||||
* class.h: Remove.
|
||||
* Makefile.in: Adjust.
|
||||
|
||||
* pt.c (unify): Don't allow reduced cv-quals when strict.
|
||||
|
||||
* call.c, class.c, pt.c, cp-tree.h: Remove nsubsts parm from
|
||||
|
|
|
@ -240,12 +240,12 @@ typeck2.o : typeck2.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h
|
|||
typeck.o : typeck.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H) \
|
||||
$(srcdir)/../expr.h ../insn-codes.h
|
||||
class.o : class.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h
|
||||
call.o : call.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h class.h
|
||||
call.o : call.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h
|
||||
friend.o : friend.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H)
|
||||
init.o : init.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H) \
|
||||
$(srcdir)/../expr.h ../insn-codes.h
|
||||
method.o : method.c $(CONFIG_H) $(CXX_TREE_H) class.h
|
||||
cvt.o : cvt.c $(CONFIG_H) $(CXX_TREE_H) class.h
|
||||
method.o : method.c $(CONFIG_H) $(CXX_TREE_H)
|
||||
cvt.o : cvt.c $(CONFIG_H) $(CXX_TREE_H)
|
||||
search.o : search.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../stack.h $(srcdir)/../flags.h
|
||||
tree.o : tree.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h
|
||||
ptree.o : ptree.c $(CONFIG_H) $(CXX_TREE_H)
|
||||
|
|
2362
gcc/cp/call.c
2362
gcc/cp/call.c
File diff suppressed because it is too large
Load diff
|
@ -3229,7 +3229,7 @@ finish_struct_1 (t, warn_anon)
|
|||
|
||||
if (IS_SIGNATURE (t))
|
||||
all_virtual = 0;
|
||||
else if (flag_all_virtual == 1 && TYPE_OVERLOADS_METHOD_CALL_EXPR (t))
|
||||
else if (flag_all_virtual == 1)
|
||||
all_virtual = 1;
|
||||
else
|
||||
all_virtual = 0;
|
||||
|
|
117
gcc/cp/class.h
117
gcc/cp/class.h
|
@ -1,117 +0,0 @@
|
|||
/* Variables and structures for overloading rules.
|
||||
Copyright (C) 1993 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU CC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* The following structure is used when comparing various alternatives
|
||||
for overloading. The unsigned quantity `strikes.i' is used
|
||||
for fast comparison of two possibilities. This number is an
|
||||
aggregate of four constituents:
|
||||
|
||||
EVIL: if this is non-zero, then the candidate should not be considered
|
||||
ELLIPSIS: if this is non-zero, then some actual argument has been matched
|
||||
against an ellipsis
|
||||
USER: if this is non-zero, then a user-defined type conversion is needed
|
||||
B_OR_D: if this is non-zero, then use a base pointer instead of the
|
||||
type of the pointer we started with.
|
||||
EASY: if this is non-zero, then we have a builtin conversion
|
||||
(such as int to long, int to float, etc) to do.
|
||||
|
||||
If two candidates require user-defined type conversions, and the
|
||||
type conversions are not identical, then an ambiguity error
|
||||
is reported.
|
||||
|
||||
If two candidates agree on user-defined type conversions,
|
||||
and one uses pointers of strictly higher type (derived where
|
||||
another uses base), then that alternative is silently chosen.
|
||||
|
||||
Note that this technique really only works for 255 arguments. Perhaps
|
||||
this is not enough. */
|
||||
|
||||
/* These macros and harshness_code are used by the NEW METHOD. */
|
||||
#define EVIL_CODE (1<<7)
|
||||
#define CONST_CODE (1<<6)
|
||||
#define ELLIPSIS_CODE (1<<5)
|
||||
#define USER_CODE (1<<4)
|
||||
#define STD_CODE (1<<3)
|
||||
#define PROMO_CODE (1<<2)
|
||||
#define QUAL_CODE (1<<1)
|
||||
#define TRIVIAL_CODE (1<<0)
|
||||
|
||||
struct harshness_code
|
||||
{
|
||||
/* What kind of conversion is involved. */
|
||||
unsigned short code;
|
||||
|
||||
/* The inheritance distance. */
|
||||
short distance;
|
||||
|
||||
/* For a PROMO_CODE, Any special penalties involved in integral conversions.
|
||||
This exists because $4.1 of the ARM states that something like
|
||||
`short unsigned int' should promote to `int', not `unsigned int'.
|
||||
If, for example, it tries to match two fns, f(int) and f(unsigned),
|
||||
f(int) should be a better match than f(unsigned) by this rule. Without
|
||||
this extra metric, they both only appear as "integral promotions", which
|
||||
will lead to an ambiguity.
|
||||
For a TRIVIAL_CODE, This is also used by build_overload_call_real and
|
||||
convert_harshness to keep track of other information we need. */
|
||||
unsigned short int_penalty;
|
||||
};
|
||||
|
||||
struct candidate
|
||||
{
|
||||
struct harshness_code h; /* Used for single-argument conversions. */
|
||||
|
||||
int h_len; /* The length of the harshness vector. */
|
||||
|
||||
tree function; /* A FUNCTION_DECL */
|
||||
tree basetypes; /* The path to function. */
|
||||
tree arg; /* first parm to function. */
|
||||
|
||||
/* Indexed by argument number, encodes evil, user, d_to_b, and easy
|
||||
strikes for that argument. At end of array, we store the index+1
|
||||
of where we started using default parameters, or 0 if there are
|
||||
none. */
|
||||
struct harshness_code *harshness;
|
||||
|
||||
union
|
||||
{
|
||||
tree field; /* If no evil strikes, the FUNCTION_DECL of
|
||||
the function (if a member function). */
|
||||
int bad_arg; /* the index of the first bad argument:
|
||||
0 if no bad arguments
|
||||
> 0 is first bad argument
|
||||
-1 if extra actual arguments
|
||||
-2 if too few actual arguments.
|
||||
-3 if const/non const method mismatch.
|
||||
-4 if type unification failed.
|
||||
-5 if contravariance violation. */
|
||||
} u;
|
||||
};
|
||||
int rank_for_overload PROTO ((struct candidate *, struct candidate *));
|
||||
|
||||
/* Variables shared between class.c and call.c. */
|
||||
|
||||
extern int n_vtables;
|
||||
extern int n_vtable_entries;
|
||||
extern int n_vtable_searches;
|
||||
extern int n_vtable_elems;
|
||||
extern int n_convert_harshness;
|
||||
extern int n_compute_conversion_costs;
|
||||
extern int n_build_method_call;
|
||||
extern int n_inner_fields_searched;
|
|
@ -327,11 +327,6 @@ extern int flag_elide_constructors;
|
|||
|
||||
extern int flag_ansi;
|
||||
|
||||
/* Nonzero means do argument matching for overloading according to the
|
||||
ANSI rules, rather than what g++ used to believe to be correct. */
|
||||
|
||||
extern int flag_ansi_overloading;
|
||||
|
||||
/* Nonzero means recognize and handle signature language constructs. */
|
||||
|
||||
extern int flag_handle_signatures;
|
||||
|
@ -620,10 +615,6 @@ struct lang_type
|
|||
convenient, don't reprocess any methods that appear in its redefinition. */
|
||||
#define TYPE_REDEFINED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.redefined)
|
||||
|
||||
/* Nonzero means that this _CLASSTYPE node overloads the method call
|
||||
operator. In this case, all method calls go through `operator->()(...). */
|
||||
#define TYPE_OVERLOADS_METHOD_CALL_EXPR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_method_call_overloaded)
|
||||
|
||||
/* Nonzero means that this type is a signature. */
|
||||
# define IS_SIGNATURE(NODE) (TYPE_LANG_SPECIFIC(NODE)?TYPE_LANG_SPECIFIC(NODE)->type_flags.is_signature:0)
|
||||
# define SET_SIGNATURE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.is_signature=1)
|
||||
|
@ -2039,19 +2030,14 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
|
|||
extern char **opname_tab, **assignop_tab;
|
||||
|
||||
/* in call.c */
|
||||
extern struct candidate *ansi_c_filler;
|
||||
extern int get_arglist_len_in_bytes PROTO((tree));
|
||||
|
||||
extern int rank_for_overload PROTO((struct candidate *, struct candidate *));
|
||||
extern void compute_conversion_costs PROTO((tree, tree, struct candidate *, int));
|
||||
extern tree build_vfield_ref PROTO((tree, tree));
|
||||
extern tree resolve_scope_to_name PROTO((tree, tree));
|
||||
extern tree build_scoped_method_call PROTO((tree, tree, tree, tree));
|
||||
extern tree build_addr_func PROTO((tree));
|
||||
extern tree build_call PROTO((tree, tree, tree));
|
||||
extern tree build_method_call PROTO((tree, tree, tree, tree, int));
|
||||
extern tree build_overload_call_real PROTO((tree, tree, int, struct candidate *, int));
|
||||
extern tree build_overload_call PROTO((tree, tree, int));
|
||||
extern int null_ptr_cst_p PROTO((tree));
|
||||
extern tree type_decays_to PROTO((tree));
|
||||
extern tree build_user_type_conversion PROTO((tree, tree, int));
|
||||
|
@ -2090,7 +2076,6 @@ extern void warn_hidden PROTO((tree));
|
|||
/* in cvt.c */
|
||||
extern tree convert_to_reference PROTO((tree, tree, int, int, tree));
|
||||
extern tree convert_from_reference PROTO((tree));
|
||||
extern tree convert_to_aggr PROTO((tree, tree, char **, int));
|
||||
extern tree convert_pointer_to_real PROTO((tree, tree));
|
||||
extern tree convert_pointer_to PROTO((tree, tree));
|
||||
extern tree ocp_convert PROTO((tree, tree, int, int));
|
||||
|
@ -2399,7 +2384,6 @@ extern void yyhook PROTO((int));
|
|||
/* in method.c */
|
||||
extern void init_method PROTO((void));
|
||||
extern void do_inline_function_hair PROTO((tree, tree));
|
||||
extern void report_type_mismatch PROTO((struct candidate *, tree, char *));
|
||||
extern char *build_overload_name PROTO((tree, int, int));
|
||||
extern tree build_static_name PROTO((tree, tree));
|
||||
extern tree build_decl_overload PROTO((tree, tree, int));
|
||||
|
|
412
gcc/cp/cvt.c
412
gcc/cp/cvt.c
|
@ -30,7 +30,6 @@ Boston, MA 02111-1307, USA. */
|
|||
#include "tree.h"
|
||||
#include "flags.h"
|
||||
#include "cp-tree.h"
|
||||
#include "class.h"
|
||||
#include "convert.h"
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
|
@ -482,11 +481,8 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
|
|||
{
|
||||
/* Look for a user-defined conversion to lvalue that we can use. */
|
||||
|
||||
if (flag_ansi_overloading)
|
||||
rval_as_conversion
|
||||
= build_type_conversion (CONVERT_EXPR, reftype, expr, 1);
|
||||
else
|
||||
rval_as_conversion = build_type_conversion (CONVERT_EXPR, type, expr, 1);
|
||||
rval_as_conversion
|
||||
= build_type_conversion (CONVERT_EXPR, reftype, expr, 1);
|
||||
|
||||
if (rval_as_conversion && rval_as_conversion != error_mark_node
|
||||
&& real_lvalue_p (rval_as_conversion))
|
||||
|
@ -556,7 +552,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
|
|||
if (rval != error_mark_node)
|
||||
rval = build1 (NOP_EXPR, reftype, rval);
|
||||
}
|
||||
else if (flag_ansi_overloading)
|
||||
else
|
||||
{
|
||||
rval = convert_for_initialization (NULL_TREE, type, expr, flags,
|
||||
"converting", 0, 0);
|
||||
|
@ -568,89 +564,6 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
|
|||
cp_pedwarn ("initializing non-const `%T' with `%T' will use a temporary",
|
||||
reftype, intype);
|
||||
}
|
||||
else
|
||||
{
|
||||
tree rval_as_ctor = NULL_TREE;
|
||||
|
||||
if (rval_as_conversion)
|
||||
{
|
||||
if (rval_as_conversion == error_mark_node)
|
||||
{
|
||||
cp_error ("conversion from `%T' to `%T' is ambiguous",
|
||||
intype, reftype);
|
||||
return error_mark_node;
|
||||
}
|
||||
rval_as_conversion = build_up_reference (reftype, rval_as_conversion,
|
||||
flags, 1);
|
||||
}
|
||||
|
||||
/* Definitely need to go through a constructor here. */
|
||||
if (TYPE_HAS_CONSTRUCTOR (type)
|
||||
&& ! CLASSTYPE_ABSTRACT_VIRTUALS (type)
|
||||
&& (rval = build_method_call
|
||||
(NULL_TREE, ctor_identifier,
|
||||
build_expr_list (NULL_TREE, expr), TYPE_BINFO (type),
|
||||
LOOKUP_NO_CONVERSION|LOOKUP_SPECULATIVELY
|
||||
| LOOKUP_ONLYCONVERTING)))
|
||||
{
|
||||
tree init;
|
||||
|
||||
if (toplevel_bindings_p ())
|
||||
{
|
||||
tree t = get_temp_name (type, toplevel_bindings_p ());
|
||||
init = build_method_call (t, ctor_identifier,
|
||||
build_expr_list (NULL_TREE, expr),
|
||||
TYPE_BINFO (type),
|
||||
LOOKUP_NORMAL|LOOKUP_NO_CONVERSION
|
||||
| LOOKUP_ONLYCONVERTING);
|
||||
|
||||
if (init == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
make_decl_rtl (t, NULL_PTR, 1);
|
||||
static_aggregates = perm_tree_cons (expr, t, static_aggregates);
|
||||
rval = build_unary_op (ADDR_EXPR, t, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
init = build_method_call (NULL_TREE, ctor_identifier,
|
||||
build_expr_list (NULL_TREE, expr),
|
||||
TYPE_BINFO (type),
|
||||
LOOKUP_NORMAL|LOOKUP_NO_CONVERSION
|
||||
|LOOKUP_ONLYCONVERTING);
|
||||
|
||||
if (init == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
rval = build_cplus_new (type, init);
|
||||
rval = build_up_reference (reftype, rval, flags, 1);
|
||||
}
|
||||
rval_as_ctor = rval;
|
||||
}
|
||||
|
||||
if (rval_as_ctor && rval_as_conversion)
|
||||
{
|
||||
cp_error ("ambiguous conversion from `%T' to `%T'; both user-defined conversion and constructor apply",
|
||||
intype, reftype);
|
||||
return error_mark_node;
|
||||
}
|
||||
else if (rval_as_ctor)
|
||||
rval = rval_as_ctor;
|
||||
else if (rval_as_conversion)
|
||||
rval = rval_as_conversion;
|
||||
else if (! IS_AGGR_TYPE (type) && ! IS_AGGR_TYPE (intype))
|
||||
{
|
||||
rval = cp_convert (type, expr);
|
||||
if (rval == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
rval = build_up_reference (reftype, rval, flags, 1);
|
||||
}
|
||||
|
||||
if (rval && ! TYPE_READONLY (TREE_TYPE (reftype)))
|
||||
cp_pedwarn ("initializing non-const `%T' with `%T' will use a temporary",
|
||||
reftype, intype);
|
||||
}
|
||||
|
||||
if (rval)
|
||||
{
|
||||
|
@ -685,190 +598,6 @@ convert_from_reference (val)
|
|||
return val;
|
||||
}
|
||||
|
||||
/* See if there is a constructor of type TYPE which will convert
|
||||
EXPR. The reference manual seems to suggest (8.5.6) that we need
|
||||
not worry about finding constructors for base classes, then converting
|
||||
to the derived class.
|
||||
|
||||
MSGP is a pointer to a message that would be an appropriate error
|
||||
string. If MSGP is NULL, then we are not interested in reporting
|
||||
errors. */
|
||||
|
||||
tree
|
||||
convert_to_aggr (type, expr, msgp, protect)
|
||||
tree type, expr;
|
||||
char **msgp;
|
||||
int protect;
|
||||
{
|
||||
tree basetype = type;
|
||||
tree name = TYPE_IDENTIFIER (basetype);
|
||||
tree function, fndecl, fntype, parmtypes, parmlist, result;
|
||||
#if 0
|
||||
/* See code below that used this. */
|
||||
tree method_name;
|
||||
#endif
|
||||
tree access;
|
||||
int can_be_private, can_be_protected;
|
||||
|
||||
if (! TYPE_HAS_CONSTRUCTOR (basetype))
|
||||
{
|
||||
if (msgp)
|
||||
*msgp = "type `%s' does not have a constructor";
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
access = access_public_node;
|
||||
can_be_private = 0;
|
||||
can_be_protected = IDENTIFIER_CLASS_VALUE (name) || name == current_class_name;
|
||||
|
||||
parmlist = build_expr_list (NULL_TREE, expr);
|
||||
parmtypes = scratch_tree_cons (NULL_TREE, TREE_TYPE (expr), void_list_node);
|
||||
|
||||
if (TYPE_USES_VIRTUAL_BASECLASSES (basetype))
|
||||
{
|
||||
parmtypes = expr_tree_cons (NULL_TREE, integer_type_node, parmtypes);
|
||||
parmlist = scratch_tree_cons (NULL_TREE, integer_one_node, parmlist);
|
||||
}
|
||||
|
||||
/* The type of the first argument will be filled in inside the loop. */
|
||||
parmlist = expr_tree_cons (NULL_TREE, integer_zero_node, parmlist);
|
||||
parmtypes = scratch_tree_cons (NULL_TREE, build_pointer_type (basetype), parmtypes);
|
||||
|
||||
/* No exact conversion was found. See if an approximate
|
||||
one will do. */
|
||||
fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0);
|
||||
|
||||
{
|
||||
int saw_private = 0;
|
||||
int saw_protected = 0;
|
||||
struct candidate *candidates
|
||||
= (struct candidate *) alloca ((decl_list_length (fndecl)+1) * sizeof (struct candidate));
|
||||
struct candidate *cp = candidates;
|
||||
|
||||
while (fndecl)
|
||||
{
|
||||
function = fndecl;
|
||||
cp->h_len = 2;
|
||||
cp->harshness = (struct harshness_code *)
|
||||
alloca (3 * sizeof (struct harshness_code));
|
||||
|
||||
compute_conversion_costs (fndecl, parmlist, cp, 2);
|
||||
if ((cp->h.code & EVIL_CODE) == 0)
|
||||
{
|
||||
cp->u.field = fndecl;
|
||||
if (protect)
|
||||
{
|
||||
if (TREE_PRIVATE (fndecl))
|
||||
access = access_private_node;
|
||||
else if (TREE_PROTECTED (fndecl))
|
||||
access = access_protected_node;
|
||||
else
|
||||
access = access_public_node;
|
||||
}
|
||||
else
|
||||
access = access_public_node;
|
||||
|
||||
if (access == access_private_node
|
||||
? (basetype == current_class_type
|
||||
|| is_friend (basetype, cp->function)
|
||||
|| purpose_member (basetype, DECL_ACCESS (fndecl)))
|
||||
: access == access_protected_node
|
||||
? (can_be_protected
|
||||
|| purpose_member (basetype, DECL_ACCESS (fndecl)))
|
||||
: 1)
|
||||
{
|
||||
if (cp->h.code <= TRIVIAL_CODE)
|
||||
goto found_and_ok;
|
||||
cp++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (access == access_private_node)
|
||||
saw_private = 1;
|
||||
else
|
||||
saw_protected = 1;
|
||||
}
|
||||
}
|
||||
fndecl = DECL_CHAIN (fndecl);
|
||||
}
|
||||
if (cp - candidates)
|
||||
{
|
||||
/* Rank from worst to best. Then cp will point to best one.
|
||||
Private fields have their bits flipped. For unsigned
|
||||
numbers, this should make them look very large.
|
||||
If the best alternate has a (signed) negative value,
|
||||
then all we ever saw were private members. */
|
||||
if (cp - candidates > 1)
|
||||
qsort (candidates, /* char *base */
|
||||
cp - candidates, /* int nel */
|
||||
sizeof (struct candidate), /* int width */
|
||||
(int (*) PROTO((const void *, const void *))) rank_for_overload); /* int (*compar)() */
|
||||
|
||||
--cp;
|
||||
if (cp->h.code & EVIL_CODE)
|
||||
{
|
||||
if (msgp)
|
||||
*msgp = "ambiguous type conversion possible for `%s'";
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
function = cp->function;
|
||||
fndecl = cp->u.field;
|
||||
goto found_and_ok;
|
||||
}
|
||||
else if (msgp)
|
||||
{
|
||||
if (saw_private)
|
||||
{
|
||||
if (saw_protected)
|
||||
*msgp = "only private and protected conversions apply";
|
||||
else
|
||||
*msgp = "only private conversions apply";
|
||||
}
|
||||
else if (saw_protected)
|
||||
*msgp = "only protected conversions apply";
|
||||
else
|
||||
*msgp = "no appropriate conversion to type `%s'";
|
||||
}
|
||||
return error_mark_node;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
|
||||
found:
|
||||
if (access == access_private_node)
|
||||
if (! can_be_private)
|
||||
{
|
||||
if (msgp)
|
||||
*msgp = TREE_PRIVATE (fndecl)
|
||||
? "conversion to type `%s' is private"
|
||||
: "conversion to type `%s' is from private base class";
|
||||
return error_mark_node;
|
||||
}
|
||||
if (access == access_protected_node)
|
||||
if (! can_be_protected)
|
||||
{
|
||||
if (msgp)
|
||||
*msgp = TREE_PRIVATE (fndecl)
|
||||
? "conversion to type `%s' is protected"
|
||||
: "conversion to type `%s' is from protected base class";
|
||||
return error_mark_node;
|
||||
}
|
||||
function = fndecl;
|
||||
found_and_ok:
|
||||
|
||||
/* It will convert, but we don't do anything about it yet. */
|
||||
if (msgp == 0)
|
||||
return NULL_TREE;
|
||||
|
||||
fntype = TREE_TYPE (function);
|
||||
|
||||
parmlist = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
|
||||
parmlist, NULL_TREE, LOOKUP_NORMAL);
|
||||
|
||||
result = build_call (function, TREE_TYPE (fntype), parmlist);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Call this when we know (for any reason) that expr is not, in fact,
|
||||
zero. This routine is like convert_pointer_to, but it pays
|
||||
attention to which specific instance of what type we want to
|
||||
|
@ -1119,71 +848,20 @@ ocp_convert (type, expr, convtype, flags)
|
|||
There may be some ambiguity between using a constructor
|
||||
vs. using a type conversion operator when both apply. */
|
||||
|
||||
if (flag_ansi_overloading)
|
||||
ctor = e;
|
||||
|
||||
if ((flags & LOOKUP_ONLYCONVERTING)
|
||||
&& ! (IS_AGGR_TYPE (dtype) && DERIVED_FROM_P (type, dtype)))
|
||||
{
|
||||
ctor = e;
|
||||
|
||||
if ((flags & LOOKUP_ONLYCONVERTING)
|
||||
&& ! (IS_AGGR_TYPE (dtype) && DERIVED_FROM_P (type, dtype)))
|
||||
{
|
||||
ctor = build_user_type_conversion (type, ctor, flags);
|
||||
flags |= LOOKUP_NO_CONVERSION;
|
||||
}
|
||||
if (ctor)
|
||||
ctor = build_method_call (NULL_TREE, ctor_identifier,
|
||||
build_expr_list (NULL_TREE, ctor),
|
||||
TYPE_BINFO (type), flags);
|
||||
if (ctor)
|
||||
return build_cplus_new (type, ctor);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IS_AGGR_TYPE (dtype) && ! DERIVED_FROM_P (type, dtype)
|
||||
&& TYPE_HAS_CONVERSION (dtype))
|
||||
conversion = build_type_conversion (CONVERT_EXPR, type, e, 1);
|
||||
|
||||
if (conversion == error_mark_node)
|
||||
{
|
||||
if (flags & LOOKUP_COMPLAIN)
|
||||
error ("ambiguous pointer conversion");
|
||||
return conversion;
|
||||
}
|
||||
|
||||
if (TYPE_HAS_CONSTRUCTOR (complete_type (type)))
|
||||
ctor = build_method_call (NULL_TREE, ctor_identifier,
|
||||
build_expr_list (NULL_TREE, e),
|
||||
TYPE_BINFO (type),
|
||||
(flags & LOOKUP_NORMAL)
|
||||
| LOOKUP_SPECULATIVELY
|
||||
| (flags & LOOKUP_ONLYCONVERTING)
|
||||
| (flags & LOOKUP_NO_CONVERSION)
|
||||
| (conversion ? LOOKUP_NO_CONVERSION : 0));
|
||||
|
||||
if (ctor == error_mark_node)
|
||||
{
|
||||
if (flags & LOOKUP_COMPLAIN)
|
||||
cp_error ("in conversion to type `%T'", type);
|
||||
if (flags & LOOKUP_SPECULATIVELY)
|
||||
return NULL_TREE;
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
if (conversion && ctor)
|
||||
{
|
||||
if (flags & LOOKUP_COMPLAIN)
|
||||
error ("both constructor and type conversion operator apply");
|
||||
if (flags & LOOKUP_SPECULATIVELY)
|
||||
return NULL_TREE;
|
||||
return error_mark_node;
|
||||
}
|
||||
else if (conversion)
|
||||
return conversion;
|
||||
else if (ctor)
|
||||
{
|
||||
ctor = build_cplus_new (type, ctor);
|
||||
return ctor;
|
||||
}
|
||||
ctor = build_user_type_conversion (type, ctor, flags);
|
||||
flags |= LOOKUP_NO_CONVERSION;
|
||||
}
|
||||
if (ctor)
|
||||
ctor = build_method_call (NULL_TREE, ctor_identifier,
|
||||
build_expr_list (NULL_TREE, ctor),
|
||||
TYPE_BINFO (type), flags);
|
||||
if (ctor)
|
||||
return build_cplus_new (type, ctor);
|
||||
}
|
||||
|
||||
/* If TYPE or TREE_TYPE (E) is not on the permanent_obstack,
|
||||
|
@ -1339,64 +1017,8 @@ build_type_conversion (code, xtype, expr, for_sure)
|
|||
{
|
||||
/* C++: check to see if we can convert this aggregate type
|
||||
into the required type. */
|
||||
tree basetype;
|
||||
tree conv;
|
||||
tree winner = NULL_TREE;
|
||||
|
||||
if (flag_ansi_overloading)
|
||||
return build_user_type_conversion
|
||||
(xtype, expr, for_sure ? LOOKUP_NORMAL : 0);
|
||||
|
||||
if (expr == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
basetype = TREE_TYPE (expr);
|
||||
if (TREE_CODE (basetype) == REFERENCE_TYPE)
|
||||
basetype = TREE_TYPE (basetype);
|
||||
|
||||
basetype = TYPE_MAIN_VARIANT (basetype);
|
||||
if (! TYPE_LANG_SPECIFIC (basetype) || ! TYPE_HAS_CONVERSION (basetype))
|
||||
return NULL_TREE;
|
||||
|
||||
/* Do we have an exact match? */
|
||||
{
|
||||
tree typename = build_typename_overload (xtype);
|
||||
if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
|
||||
return build_type_conversion_1 (xtype, basetype, expr, typename,
|
||||
for_sure);
|
||||
}
|
||||
|
||||
/* Nope; try looking for others. */
|
||||
for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv))
|
||||
{
|
||||
tree cand = TREE_VALUE (conv);
|
||||
|
||||
if (winner && winner == cand)
|
||||
continue;
|
||||
|
||||
if (can_convert (xtype, TREE_TYPE (TREE_TYPE (cand))))
|
||||
{
|
||||
if (winner)
|
||||
{
|
||||
if (for_sure)
|
||||
{
|
||||
cp_error ("ambiguous conversion from `%T' to `%T'", basetype,
|
||||
xtype);
|
||||
cp_error (" candidate conversions include `%D' and `%D'",
|
||||
winner, cand);
|
||||
}
|
||||
return NULL_TREE;
|
||||
}
|
||||
else
|
||||
winner = cand;
|
||||
}
|
||||
}
|
||||
|
||||
if (winner)
|
||||
return build_type_conversion_1 (xtype, basetype, expr,
|
||||
DECL_NAME (winner), for_sure);
|
||||
|
||||
return NULL_TREE;
|
||||
return build_user_type_conversion
|
||||
(xtype, expr, for_sure ? LOOKUP_NORMAL : 0);
|
||||
}
|
||||
|
||||
/* Convert the given EXPR to one of a group of types suitable for use in an
|
||||
|
|
|
@ -10760,8 +10760,7 @@ grok_op_properties (decl, virtualp, friendp)
|
|||
}
|
||||
}
|
||||
|
||||
if (name == ansi_opname[(int) CALL_EXPR]
|
||||
|| name == ansi_opname[(int) METHOD_CALL_EXPR])
|
||||
if (name == ansi_opname[(int) CALL_EXPR])
|
||||
return; /* no restrictions on args */
|
||||
|
||||
if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl))
|
||||
|
@ -11245,7 +11244,6 @@ xref_basetypes (code_type_node, name, ref, binfo)
|
|||
TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
|
||||
}
|
||||
|
||||
TYPE_OVERLOADS_METHOD_CALL_EXPR (ref) |= TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype);
|
||||
TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype);
|
||||
TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
|
||||
CLASSTYPE_LOCAL_TYPEDECLS (ref) |= CLASSTYPE_LOCAL_TYPEDECLS (basetype);
|
||||
|
|
|
@ -143,11 +143,6 @@ int flag_no_ident;
|
|||
|
||||
int flag_ansi;
|
||||
|
||||
/* Nonzero means do argument matching for overloading according to the
|
||||
ANSI rules, rather than what g++ used to believe to be correct. */
|
||||
|
||||
int flag_ansi_overloading = 1;
|
||||
|
||||
/* Nonzero means do emit exported implementations of functions even if
|
||||
they can be inlined. */
|
||||
|
||||
|
@ -470,7 +465,6 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
|
|||
{"implement-inlines", &flag_implement_inlines, 1},
|
||||
{"external-templates", &flag_external_templates, 1},
|
||||
{"implicit-templates", &flag_implicit_templates, 1},
|
||||
{"ansi-overloading", &flag_ansi_overloading, 1},
|
||||
{"huge-objects", &flag_huge_objects, 1},
|
||||
{"conserve-space", &flag_conserve_space, 1},
|
||||
{"vtable-thunks", &flag_vtable_thunks, 1},
|
||||
|
@ -565,6 +559,13 @@ lang_decode_option (p)
|
|||
flag_guiding_decls = 0;
|
||||
found = 1;
|
||||
}
|
||||
else if (!strcmp (p, "ansi-overloading"))
|
||||
found = 1;
|
||||
else if (!strcmp (p, "no-ansi-overloading"))
|
||||
{
|
||||
error ("-fno-ansi-overloading is no longer supported");
|
||||
found = 1;
|
||||
}
|
||||
else if (!strncmp (p, "template-depth-", 15))
|
||||
{
|
||||
char *endp = p + 15;
|
||||
|
|
225
gcc/cp/init.c
225
gcc/cp/init.c
|
@ -1249,7 +1249,7 @@ expand_default_init (binfo, true_exp, exp, init, alias_this, flags)
|
|||
tree rval;
|
||||
tree parms;
|
||||
|
||||
if (flag_ansi_overloading && init && TREE_CODE (init) != TREE_LIST
|
||||
if (init && TREE_CODE (init) != TREE_LIST
|
||||
&& (flags & LOOKUP_ONLYCONVERTING))
|
||||
{
|
||||
/* Base subobjects should only get direct-initialization. */
|
||||
|
@ -1287,15 +1287,6 @@ expand_default_init (binfo, true_exp, exp, init, alias_this, flags)
|
|||
if (parms)
|
||||
init = TREE_VALUE (parms);
|
||||
}
|
||||
else if (! flag_ansi_overloading
|
||||
&& TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init)
|
||||
&& TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (init)))
|
||||
{
|
||||
rval = convert_for_initialization (exp, type, init, 0, 0, 0, 0);
|
||||
TREE_USED (rval) = 1;
|
||||
expand_expr_stmt (rval);
|
||||
return;
|
||||
}
|
||||
else
|
||||
parms = build_expr_list (NULL_TREE, init);
|
||||
|
||||
|
@ -1308,52 +1299,9 @@ expand_default_init (binfo, true_exp, exp, init, alias_this, flags)
|
|||
flags |= LOOKUP_HAS_IN_CHARGE;
|
||||
}
|
||||
|
||||
if (flag_ansi_overloading)
|
||||
{
|
||||
rval = build_method_call (exp, ctor_identifier,
|
||||
parms, binfo, flags);
|
||||
expand_expr_stmt (rval);
|
||||
return;
|
||||
}
|
||||
|
||||
if (init && TREE_CHAIN (parms) == NULL_TREE
|
||||
&& TYPE_HAS_TRIVIAL_INIT_REF (type)
|
||||
&& TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (init)))
|
||||
{
|
||||
rval = build (INIT_EXPR, type, exp, init);
|
||||
TREE_SIDE_EFFECTS (rval) = 1;
|
||||
expand_expr_stmt (rval);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flags & LOOKUP_ONLYCONVERTING)
|
||||
flags |= LOOKUP_NO_CONVERSION;
|
||||
rval = build_method_call (exp, ctor_identifier,
|
||||
parms, binfo, flags);
|
||||
|
||||
/* Private, protected, or otherwise unavailable. */
|
||||
if (rval == error_mark_node)
|
||||
{
|
||||
if (flags & LOOKUP_COMPLAIN)
|
||||
cp_error ("in base initialization for %sclass `%T'",
|
||||
TREE_VIA_VIRTUAL (binfo) ? "virtual base " : "",
|
||||
binfo);
|
||||
}
|
||||
else if (rval == NULL_TREE)
|
||||
my_friendly_abort (361);
|
||||
else
|
||||
{
|
||||
/* p. 222: if the base class assigns to `this', then that
|
||||
value is used in the derived class. */
|
||||
if ((flag_this_is_variable & 1) && alias_this)
|
||||
{
|
||||
TREE_TYPE (rval) = TREE_TYPE (current_class_ptr);
|
||||
expand_assignment (current_class_ptr, rval, 0, 0);
|
||||
}
|
||||
else
|
||||
expand_expr_stmt (rval);
|
||||
}
|
||||
}
|
||||
rval = build_method_call (exp, ctor_identifier,
|
||||
parms, binfo, flags);
|
||||
expand_expr_stmt (rval);
|
||||
}
|
||||
|
||||
/* This function is responsible for initializing EXP with INIT
|
||||
|
@ -1413,171 +1361,6 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
|
|||
return;
|
||||
}
|
||||
|
||||
if (init && ! flag_ansi_overloading)
|
||||
{
|
||||
tree init_list = NULL_TREE;
|
||||
|
||||
if (TREE_CODE (init) == TREE_LIST)
|
||||
{
|
||||
init_list = init;
|
||||
if (TREE_CHAIN (init) == NULL_TREE)
|
||||
init = TREE_VALUE (init);
|
||||
}
|
||||
|
||||
init_type = TREE_TYPE (init);
|
||||
|
||||
if (TREE_CODE (init) != TREE_LIST)
|
||||
{
|
||||
if (init_type == error_mark_node)
|
||||
return;
|
||||
|
||||
/* This happens when we use C++'s functional cast notation.
|
||||
If the types match, then just use the TARGET_EXPR
|
||||
directly. Otherwise, we need to create the initializer
|
||||
separately from the object being initialized. */
|
||||
if (TREE_CODE (init) == TARGET_EXPR)
|
||||
{
|
||||
if (TYPE_MAIN_VARIANT (init_type) == TYPE_MAIN_VARIANT (type))
|
||||
{
|
||||
if (TREE_CODE (exp) == VAR_DECL
|
||||
|| TREE_CODE (exp) == RESULT_DECL)
|
||||
/* Unify the initialization targets. */
|
||||
DECL_RTL (TREE_OPERAND (init, 0)) = DECL_RTL (exp);
|
||||
else
|
||||
DECL_RTL (TREE_OPERAND (init, 0)) = expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL);
|
||||
|
||||
expand_expr_stmt (init);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (init_type == type && TREE_CODE (init) == CALL_EXPR)
|
||||
{
|
||||
/* A CALL_EXPR is a legitimate form of initialization, so
|
||||
we should not print this warning message. */
|
||||
|
||||
expand_assignment (exp, init, 0, 0);
|
||||
if (exp == DECL_RESULT (current_function_decl))
|
||||
{
|
||||
/* Failing this assertion means that the return value
|
||||
from receives multiple initializations. */
|
||||
my_friendly_assert (DECL_INITIAL (exp) == NULL_TREE
|
||||
|| DECL_INITIAL (exp) == error_mark_node,
|
||||
212);
|
||||
DECL_INITIAL (exp) = init;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (init_type == type
|
||||
&& TREE_CODE (init) == COND_EXPR)
|
||||
{
|
||||
/* Push value to be initialized into the cond, where possible.
|
||||
Avoid spurious warning messages when initializing the
|
||||
result of this function. */
|
||||
TREE_OPERAND (init, 1)
|
||||
= build_modify_expr (exp, INIT_EXPR, TREE_OPERAND (init, 1));
|
||||
if (exp == DECL_RESULT (current_function_decl))
|
||||
DECL_INITIAL (exp) = NULL_TREE;
|
||||
TREE_OPERAND (init, 2)
|
||||
= build_modify_expr (exp, INIT_EXPR, TREE_OPERAND (init, 2));
|
||||
if (exp == DECL_RESULT (current_function_decl))
|
||||
DECL_INITIAL (exp) = init;
|
||||
TREE_SIDE_EFFECTS (init) = 1;
|
||||
expand_expr (init, const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||
free_temp_slots ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* We did not know what we were initializing before. Now we do. */
|
||||
if (TREE_CODE (init) == TARGET_EXPR)
|
||||
{
|
||||
tree tmp = TREE_OPERAND (TREE_OPERAND (init, 1), 1);
|
||||
|
||||
if (tmp && TREE_CODE (TREE_VALUE (tmp)) == NOP_EXPR
|
||||
&& TREE_OPERAND (TREE_VALUE (tmp), 0) == integer_zero_node)
|
||||
{
|
||||
/* In order for this to work for RESULT_DECLs, if their
|
||||
type has a constructor, then they must be BLKmode
|
||||
so that they will be meaningfully addressable. */
|
||||
tree arg = build_unary_op (ADDR_EXPR, exp, 0);
|
||||
init = TREE_OPERAND (init, 1);
|
||||
init = build (CALL_EXPR, build_pointer_type (TREE_TYPE (init)),
|
||||
TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), NULL_TREE);
|
||||
TREE_SIDE_EFFECTS (init) = 1;
|
||||
TREE_VALUE (TREE_OPERAND (init, 1))
|
||||
= convert_pointer_to (TREE_TYPE (TREE_TYPE (TREE_VALUE (tmp))), arg);
|
||||
|
||||
if (alias_this)
|
||||
{
|
||||
expand_assignment (current_function_decl, init, 0, 0);
|
||||
return;
|
||||
}
|
||||
if (exp == DECL_RESULT (current_function_decl))
|
||||
{
|
||||
if (DECL_INITIAL (DECL_RESULT (current_function_decl)))
|
||||
fatal ("return value from function receives multiple initializations");
|
||||
DECL_INITIAL (exp) = init;
|
||||
}
|
||||
expand_expr_stmt (init);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle this case: when calling a constructor: xyzzy foo(bar);
|
||||
which really means: xyzzy foo = bar; Ugh!
|
||||
|
||||
More useful for this case: xyzzy *foo = new xyzzy (bar); */
|
||||
|
||||
if (! TYPE_NEEDS_CONSTRUCTING (type) && ! IS_AGGR_TYPE (type))
|
||||
{
|
||||
if (init_list && TREE_CHAIN (init_list))
|
||||
{
|
||||
warning ("initializer list being treated as compound expression");
|
||||
init = cp_convert (type, build_compound_expr (init_list));
|
||||
if (init == error_mark_node)
|
||||
return;
|
||||
}
|
||||
|
||||
expand_assignment (exp, init, 0, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* If this is copy-initialization, see whether we can go through a
|
||||
type conversion operator. */
|
||||
if (TREE_CODE (init) != TREE_LIST && (flags & LOOKUP_ONLYCONVERTING))
|
||||
{
|
||||
tree ttype = TREE_CODE (init_type) == REFERENCE_TYPE
|
||||
? TREE_TYPE (init_type) : init_type;
|
||||
|
||||
if (ttype != type && IS_AGGR_TYPE (ttype))
|
||||
{
|
||||
tree rval = build_type_conversion (CONVERT_EXPR, type, init, 1);
|
||||
|
||||
if (rval)
|
||||
{
|
||||
/* See if there is a constructor for``type'' that takes a
|
||||
``ttype''-typed object. */
|
||||
tree parms = build_expr_list (NULL_TREE, init);
|
||||
tree as_cons = NULL_TREE;
|
||||
if (TYPE_HAS_CONSTRUCTOR (type))
|
||||
as_cons = build_method_call (exp, ctor_identifier,
|
||||
parms, binfo,
|
||||
LOOKUP_SPECULATIVELY|LOOKUP_NO_CONVERSION);
|
||||
if (as_cons != NULL_TREE && as_cons != error_mark_node)
|
||||
/* ANSI C++ June 5 1992 WP 12.3.2.6.1 */
|
||||
cp_error ("ambiguity between conversion to `%T' and constructor",
|
||||
type);
|
||||
else
|
||||
if (rval != error_mark_node)
|
||||
expand_aggr_init_1 (binfo, true_exp, exp, rval, alias_this, flags);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We know that expand_default_init can handle everything we want
|
||||
at this point. */
|
||||
expand_default_init (binfo, true_exp, exp, init, alias_this, flags);
|
||||
|
|
|
@ -615,8 +615,6 @@ init_lex ()
|
|||
IDENTIFIER_OPNAME_P (ansi_opname[(int) MAX_EXPR]) = 1;
|
||||
ansi_opname[(int) COND_EXPR] = get_identifier ("__cn");
|
||||
IDENTIFIER_OPNAME_P (ansi_opname[(int) COND_EXPR]) = 1;
|
||||
ansi_opname[(int) METHOD_CALL_EXPR] = get_identifier ("__wr");
|
||||
IDENTIFIER_OPNAME_P (ansi_opname[(int) METHOD_CALL_EXPR]) = 1;
|
||||
|
||||
init_method ();
|
||||
init_error ();
|
||||
|
@ -747,7 +745,6 @@ init_lex ()
|
|||
|
||||
opname_tab[(int) COMPONENT_REF] = "->";
|
||||
opname_tab[(int) MEMBER_REF] = "->*";
|
||||
opname_tab[(int) METHOD_CALL_EXPR] = "->()";
|
||||
opname_tab[(int) INDIRECT_REF] = "*";
|
||||
opname_tab[(int) ARRAY_REF] = "[]";
|
||||
opname_tab[(int) MODIFY_EXPR] = "=";
|
||||
|
|
393
gcc/cp/method.c
393
gcc/cp/method.c
|
@ -34,7 +34,6 @@ Boston, MA 02111-1307, USA. */
|
|||
#include <stdio.h>
|
||||
#include "tree.h"
|
||||
#include "cp-tree.h"
|
||||
#include "class.h"
|
||||
#include "obstack.h"
|
||||
#include <ctype.h>
|
||||
#include "rtl.h"
|
||||
|
@ -175,92 +174,6 @@ do_inline_function_hair (type, friend_list)
|
|||
}
|
||||
}
|
||||
|
||||
/* Report an argument type mismatch between the best declared function
|
||||
we could find and the current argument list that we have. */
|
||||
|
||||
void
|
||||
report_type_mismatch (cp, parmtypes, name_kind)
|
||||
struct candidate *cp;
|
||||
tree parmtypes;
|
||||
char *name_kind;
|
||||
{
|
||||
int i = cp->u.bad_arg;
|
||||
tree ttf, tta;
|
||||
char *tmp_firstobj;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case -4:
|
||||
my_friendly_assert (TREE_CODE (cp->function) == TEMPLATE_DECL, 240);
|
||||
cp_error ("type unification failed for function template `%#D'",
|
||||
cp->function);
|
||||
return;
|
||||
|
||||
case -2:
|
||||
cp_error ("too few arguments for %s `%#D'", name_kind, cp->function);
|
||||
return;
|
||||
case -1:
|
||||
cp_error ("too many arguments for %s `%#D'", name_kind, cp->function);
|
||||
return;
|
||||
case 0:
|
||||
if (TREE_CODE (TREE_TYPE (cp->function)) != METHOD_TYPE)
|
||||
break;
|
||||
case -3:
|
||||
/* Happens when the implicit object parameter is rejected. */
|
||||
my_friendly_assert (! TYPE_READONLY (TREE_TYPE (TREE_VALUE (parmtypes))),
|
||||
241);
|
||||
if (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (TREE_VALUE (parmtypes))))
|
||||
&& ! TYPE_VOLATILE (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (cp->function))))))
|
||||
cp_error ("call to non-volatile %s `%#D' with volatile object",
|
||||
name_kind, cp->function);
|
||||
else
|
||||
cp_error ("call to non-const %s `%#D' with const object",
|
||||
name_kind, cp->function);
|
||||
return;
|
||||
}
|
||||
|
||||
ttf = TYPE_ARG_TYPES (TREE_TYPE (cp->function));
|
||||
tta = parmtypes;
|
||||
|
||||
while (i-- > 0)
|
||||
{
|
||||
ttf = TREE_CHAIN (ttf);
|
||||
tta = TREE_CHAIN (tta);
|
||||
}
|
||||
|
||||
OB_INIT ();
|
||||
OB_PUTS ("bad argument ");
|
||||
sprintf (digit_buffer, "%d", cp->u.bad_arg
|
||||
- (TREE_CODE (TREE_TYPE (cp->function)) == METHOD_TYPE)
|
||||
+ 1);
|
||||
OB_PUTCP (digit_buffer);
|
||||
|
||||
OB_PUTS (" for function `");
|
||||
OB_PUTCP (decl_as_string (cp->function, 1));
|
||||
OB_PUTS ("' (type was ");
|
||||
|
||||
/* Reset `i' so that type printing routines do the right thing. */
|
||||
if (tta)
|
||||
{
|
||||
enum tree_code code = TREE_CODE (TREE_TYPE (TREE_VALUE (tta)));
|
||||
if (code == ERROR_MARK)
|
||||
OB_PUTS ("(failed type instantiation)");
|
||||
else
|
||||
{
|
||||
i = (code == FUNCTION_TYPE || code == METHOD_TYPE);
|
||||
OB_PUTCP (type_as_string (TREE_TYPE (TREE_VALUE (tta)), 1));
|
||||
}
|
||||
}
|
||||
else OB_PUTS ("void");
|
||||
OB_PUTC (')');
|
||||
OB_FINISH ();
|
||||
|
||||
tmp_firstobj = (char *)alloca (obstack_object_size (&scratch_obstack));
|
||||
bcopy (obstack_base (&scratch_obstack), tmp_firstobj,
|
||||
obstack_object_size (&scratch_obstack));
|
||||
error (tmp_firstobj);
|
||||
}
|
||||
|
||||
/* Here is where overload code starts. */
|
||||
|
||||
/* type tables for K and B type compression */
|
||||
|
@ -1733,311 +1646,7 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
|
|||
int flags;
|
||||
tree xarg1, xarg2, arg3;
|
||||
{
|
||||
tree rval = 0;
|
||||
tree arg1, arg2;
|
||||
tree type1, type2, fnname;
|
||||
tree fields1 = 0, parms = 0;
|
||||
tree global_fn;
|
||||
int try_second;
|
||||
int binary_is_unary;
|
||||
|
||||
if (flag_ansi_overloading)
|
||||
return build_new_op (code, flags, xarg1, xarg2, arg3);
|
||||
|
||||
if (xarg1 == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
if (code == COND_EXPR)
|
||||
{
|
||||
if (xarg2 == error_mark_node
|
||||
|| arg3 == error_mark_node)
|
||||
return error_mark_node;
|
||||
}
|
||||
if (code == COMPONENT_REF)
|
||||
if (TREE_CODE (TREE_TYPE (xarg1)) == POINTER_TYPE)
|
||||
return rval;
|
||||
|
||||
/* First, see if we can work with the first argument */
|
||||
type1 = TREE_TYPE (xarg1);
|
||||
|
||||
/* Some tree codes have length > 1, but we really only want to
|
||||
overload them if their first argument has a user defined type. */
|
||||
switch (code)
|
||||
{
|
||||
case PREINCREMENT_EXPR:
|
||||
case PREDECREMENT_EXPR:
|
||||
case POSTINCREMENT_EXPR:
|
||||
case POSTDECREMENT_EXPR:
|
||||
case COMPONENT_REF:
|
||||
binary_is_unary = 1;
|
||||
try_second = 0;
|
||||
break;
|
||||
|
||||
/* ARRAY_REFs and CALL_EXPRs must overload successfully.
|
||||
If they do not, return error_mark_node instead of NULL_TREE. */
|
||||
case ARRAY_REF:
|
||||
if (xarg2 == error_mark_node)
|
||||
return error_mark_node;
|
||||
case CALL_EXPR:
|
||||
rval = error_mark_node;
|
||||
binary_is_unary = 0;
|
||||
try_second = 0;
|
||||
break;
|
||||
|
||||
case VEC_NEW_EXPR:
|
||||
case NEW_EXPR:
|
||||
{
|
||||
tree args = expr_tree_cons (NULL_TREE, xarg2, arg3);
|
||||
fnname = ansi_opname[(int) code];
|
||||
if (flags & LOOKUP_GLOBAL)
|
||||
return build_overload_call (fnname, args, flags & LOOKUP_COMPLAIN);
|
||||
|
||||
rval = build_method_call
|
||||
(build_indirect_ref (build1 (NOP_EXPR, xarg1, error_mark_node),
|
||||
"new"),
|
||||
fnname, args, NULL_TREE, flags);
|
||||
if (rval == error_mark_node)
|
||||
/* User might declare fancy operator new, but invoke it
|
||||
like standard one. */
|
||||
return rval;
|
||||
|
||||
TREE_TYPE (rval) = xarg1;
|
||||
return rval;
|
||||
}
|
||||
break;
|
||||
|
||||
case VEC_DELETE_EXPR:
|
||||
case DELETE_EXPR:
|
||||
{
|
||||
fnname = ansi_opname[(int) code];
|
||||
if (flags & LOOKUP_GLOBAL)
|
||||
return build_overload_call (fnname,
|
||||
build_expr_list (NULL_TREE, xarg1),
|
||||
flags & LOOKUP_COMPLAIN);
|
||||
arg1 = TREE_TYPE (xarg1);
|
||||
|
||||
/* This handles the case where we're trying to delete
|
||||
X (*a)[10];
|
||||
a=new X[5][10];
|
||||
delete[] a; */
|
||||
|
||||
if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
|
||||
{
|
||||
/* Strip off the pointer and the array. */
|
||||
arg1 = TREE_TYPE (TREE_TYPE (arg1));
|
||||
|
||||
while (TREE_CODE (arg1) == ARRAY_TYPE)
|
||||
arg1 = (TREE_TYPE (arg1));
|
||||
|
||||
arg1 = build_pointer_type (arg1);
|
||||
}
|
||||
|
||||
rval = build_method_call
|
||||
(build_indirect_ref (build1 (NOP_EXPR, arg1,
|
||||
error_mark_node),
|
||||
NULL_PTR),
|
||||
fnname, expr_tree_cons (NULL_TREE, xarg1,
|
||||
build_expr_list (NULL_TREE, xarg2)),
|
||||
NULL_TREE, flags);
|
||||
#if 0
|
||||
/* This can happen when operator delete is protected. */
|
||||
my_friendly_assert (rval != error_mark_node, 250);
|
||||
TREE_TYPE (rval) = void_type_node;
|
||||
#endif
|
||||
return rval;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
binary_is_unary = 0;
|
||||
try_second = tree_code_length [(int) code] == 2;
|
||||
if (try_second && xarg2 == error_mark_node)
|
||||
return error_mark_node;
|
||||
break;
|
||||
}
|
||||
|
||||
if (try_second && xarg2 == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
/* What ever it was, we do not know how to deal with it. */
|
||||
if (type1 == NULL_TREE)
|
||||
return rval;
|
||||
|
||||
if (TREE_CODE (type1) == OFFSET_TYPE)
|
||||
type1 = TREE_TYPE (type1);
|
||||
|
||||
if (TREE_CODE (type1) == REFERENCE_TYPE)
|
||||
{
|
||||
arg1 = convert_from_reference (xarg1);
|
||||
type1 = TREE_TYPE (arg1);
|
||||
}
|
||||
else
|
||||
{
|
||||
arg1 = xarg1;
|
||||
}
|
||||
|
||||
if (!IS_AGGR_TYPE (type1) || TYPE_PTRMEMFUNC_P (type1))
|
||||
{
|
||||
/* Try to fail. First, fail if unary */
|
||||
if (! try_second)
|
||||
return rval;
|
||||
/* Second, see if second argument is non-aggregate. */
|
||||
type2 = TREE_TYPE (xarg2);
|
||||
if (TREE_CODE (type2) == OFFSET_TYPE)
|
||||
type2 = TREE_TYPE (type2);
|
||||
if (TREE_CODE (type2) == REFERENCE_TYPE)
|
||||
{
|
||||
arg2 = convert_from_reference (xarg2);
|
||||
type2 = TREE_TYPE (arg2);
|
||||
}
|
||||
else
|
||||
{
|
||||
arg2 = xarg2;
|
||||
}
|
||||
|
||||
if (!IS_AGGR_TYPE (type2))
|
||||
return rval;
|
||||
try_second = 0;
|
||||
}
|
||||
|
||||
if (try_second)
|
||||
{
|
||||
/* First arg may succeed; see whether second should. */
|
||||
type2 = TREE_TYPE (xarg2);
|
||||
if (TREE_CODE (type2) == OFFSET_TYPE)
|
||||
type2 = TREE_TYPE (type2);
|
||||
if (TREE_CODE (type2) == REFERENCE_TYPE)
|
||||
{
|
||||
arg2 = convert_from_reference (xarg2);
|
||||
type2 = TREE_TYPE (arg2);
|
||||
}
|
||||
else
|
||||
{
|
||||
arg2 = xarg2;
|
||||
}
|
||||
|
||||
if (! IS_AGGR_TYPE (type2))
|
||||
try_second = 0;
|
||||
}
|
||||
|
||||
if (type1 == unknown_type_node
|
||||
|| (try_second && TREE_TYPE (xarg2) == unknown_type_node))
|
||||
{
|
||||
/* This will not be implemented in the foreseeable future. */
|
||||
return rval;
|
||||
}
|
||||
|
||||
if (code == MODIFY_EXPR)
|
||||
fnname = ansi_assopname[(int) TREE_CODE (arg3)];
|
||||
else
|
||||
fnname = ansi_opname[(int) code];
|
||||
|
||||
global_fn = lookup_name_nonclass (fnname);
|
||||
|
||||
/* This is the last point where we will accept failure. This
|
||||
may be too eager if we wish an overloaded operator not to match,
|
||||
but would rather a normal operator be called on a type-converted
|
||||
argument. */
|
||||
|
||||
if (IS_AGGR_TYPE (type1))
|
||||
{
|
||||
fields1 = lookup_fnfields (TYPE_BINFO (type1), fnname, 0);
|
||||
/* ARM $13.4.7, prefix/postfix ++/--. */
|
||||
if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
|
||||
{
|
||||
xarg2 = integer_zero_node;
|
||||
binary_is_unary = 0;
|
||||
|
||||
if (fields1)
|
||||
{
|
||||
tree t, t2;
|
||||
int have_postfix = 0;
|
||||
|
||||
/* Look for an `operator++ (int)'. If they didn't have
|
||||
one, then we fall back to the old way of doing things. */
|
||||
for (t = TREE_VALUE (fields1); t ; t = DECL_CHAIN (t))
|
||||
{
|
||||
t2 = TYPE_ARG_TYPES (TREE_TYPE (t));
|
||||
if (TREE_CHAIN (t2) != NULL_TREE
|
||||
&& TREE_VALUE (TREE_CHAIN (t2)) == integer_type_node)
|
||||
{
|
||||
have_postfix = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! have_postfix)
|
||||
{
|
||||
char *op = POSTINCREMENT_EXPR ? "++" : "--";
|
||||
|
||||
/* There's probably a LOT of code in the world that
|
||||
relies upon this old behavior. */
|
||||
pedwarn ("no `operator%s (int)' declared for postfix `%s', using prefix operator instead",
|
||||
op, op);
|
||||
xarg2 = NULL_TREE;
|
||||
binary_is_unary = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fields1 == NULL_TREE && global_fn == NULL_TREE)
|
||||
return rval;
|
||||
|
||||
/* If RVAL winds up being `error_mark_node', we will return
|
||||
that... There is no way that normal semantics of these
|
||||
operators will succeed. */
|
||||
|
||||
/* This argument may be an uncommitted OFFSET_REF. This is
|
||||
the case for example when dealing with static class members
|
||||
which are referenced from their class name rather than
|
||||
from a class instance. */
|
||||
if (TREE_CODE (xarg1) == OFFSET_REF
|
||||
&& TREE_CODE (TREE_OPERAND (xarg1, 1)) == VAR_DECL)
|
||||
xarg1 = TREE_OPERAND (xarg1, 1);
|
||||
if (try_second && xarg2 && TREE_CODE (xarg2) == OFFSET_REF
|
||||
&& TREE_CODE (TREE_OPERAND (xarg2, 1)) == VAR_DECL)
|
||||
xarg2 = TREE_OPERAND (xarg2, 1);
|
||||
|
||||
if (global_fn)
|
||||
flags |= LOOKUP_GLOBAL;
|
||||
|
||||
if (code == CALL_EXPR)
|
||||
{
|
||||
/* This can only be a member function. */
|
||||
return build_method_call (xarg1, fnname, xarg2,
|
||||
NULL_TREE, LOOKUP_NORMAL);
|
||||
}
|
||||
else if (tree_code_length[(int) code] == 1 || binary_is_unary)
|
||||
{
|
||||
parms = NULL_TREE;
|
||||
rval = build_method_call (xarg1, fnname, NULL_TREE, NULL_TREE, flags);
|
||||
}
|
||||
else if (code == COND_EXPR)
|
||||
{
|
||||
parms = expr_tree_cons (NULL_TREE, xarg2, build_expr_list (NULL_TREE, arg3));
|
||||
rval = build_method_call (xarg1, fnname, parms, NULL_TREE, flags);
|
||||
}
|
||||
else if (code == METHOD_CALL_EXPR)
|
||||
{
|
||||
/* must be a member function. */
|
||||
parms = expr_tree_cons (NULL_TREE, xarg2, arg3);
|
||||
return build_method_call (xarg1, fnname, parms, NULL_TREE,
|
||||
LOOKUP_NORMAL);
|
||||
}
|
||||
else if (fields1)
|
||||
{
|
||||
parms = build_expr_list (NULL_TREE, xarg2);
|
||||
rval = build_method_call (xarg1, fnname, parms, NULL_TREE, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
parms = expr_tree_cons (NULL_TREE, xarg1,
|
||||
build_expr_list (NULL_TREE, xarg2));
|
||||
rval = build_overload_call (fnname, parms, flags);
|
||||
}
|
||||
|
||||
return rval;
|
||||
return build_new_op (code, flags, xarg1, xarg2, arg3);
|
||||
}
|
||||
|
||||
/* This function takes an identifier, ID, and attempts to figure out what
|
||||
|
|
34
gcc/cp/pt.c
34
gcc/cp/pt.c
|
@ -3890,38 +3890,6 @@ tsubst (t, args, in_decl)
|
|||
if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
|
||||
grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
|
||||
|
||||
/* Look for matching decls for the moment. */
|
||||
if (! member && ! flag_ansi_overloading)
|
||||
{
|
||||
tree decls = lookup_name_nonclass (DECL_NAME (t));
|
||||
tree d = NULL_TREE;
|
||||
|
||||
if (decls == NULL_TREE)
|
||||
/* no match */;
|
||||
else if (is_overloaded_fn (decls))
|
||||
for (decls = get_first_fn (decls); decls;
|
||||
decls = DECL_CHAIN (decls))
|
||||
{
|
||||
if (TREE_CODE (decls) == FUNCTION_DECL
|
||||
&& TREE_TYPE (decls) == type)
|
||||
{
|
||||
d = decls;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (d)
|
||||
{
|
||||
int dcl_only = ! DECL_INITIAL (d);
|
||||
if (dcl_only)
|
||||
DECL_INITIAL (r) = error_mark_node;
|
||||
duplicate_decls (r, d);
|
||||
r = d;
|
||||
if (dcl_only)
|
||||
DECL_INITIAL (r) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (DECL_TEMPLATE_INFO (t) != NULL_TREE)
|
||||
{
|
||||
DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
|
||||
|
@ -5539,7 +5507,7 @@ unify (tparms, targs, ntparms, parm, arg, strict)
|
|||
if (CLASSTYPE_TEMPLATE_INFO (parm) && uses_template_parms (parm))
|
||||
{
|
||||
tree t = NULL_TREE;
|
||||
if (flag_ansi_overloading && ! strict)
|
||||
if (! strict)
|
||||
t = get_template_base (CLASSTYPE_TI_TEMPLATE (parm), arg);
|
||||
else if
|
||||
(CLASSTYPE_TEMPLATE_INFO (arg)
|
||||
|
|
|
@ -118,8 +118,6 @@ print_lang_type (file, node, indent)
|
|||
fputs (" has=", file);
|
||||
if (TYPE_HAS_ASSIGN_REF (node))
|
||||
fputs (" this=(X&)", file);
|
||||
if (TYPE_OVERLOADS_METHOD_CALL_EXPR (node))
|
||||
fputs (" op->()", file);
|
||||
if (TYPE_GETS_INIT_AGGR (node))
|
||||
fputs (" gets X(X, ...)", file);
|
||||
if (TYPE_OVERLOADS_CALL_EXPR (node))
|
||||
|
|
141
gcc/cp/typeck.c
141
gcc/cp/typeck.c
|
@ -2470,24 +2470,10 @@ build_x_function_call (function, params, decl)
|
|||
}
|
||||
else
|
||||
{
|
||||
tree val = TREE_VALUE (function);
|
||||
|
||||
if (flag_ansi_overloading)
|
||||
{
|
||||
/* Put back explicit template arguments, if any. */
|
||||
if (template_id)
|
||||
function = template_id;
|
||||
return build_new_function_call (function, params);
|
||||
}
|
||||
|
||||
if (TREE_CODE (val) == TEMPLATE_DECL)
|
||||
return build_overload_call_real
|
||||
(function, params, LOOKUP_COMPLAIN, (struct candidate *)0, 0);
|
||||
else if (DECL_CHAIN (val) != NULL_TREE)
|
||||
return build_overload_call
|
||||
(function, params, LOOKUP_COMPLAIN);
|
||||
else
|
||||
my_friendly_abort (360);
|
||||
/* Put back explicit template arguments, if any. */
|
||||
if (template_id)
|
||||
function = template_id;
|
||||
return build_new_function_call (function, params);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3062,17 +3048,7 @@ build_x_binary_op (code, arg1, arg2)
|
|||
if (processing_template_decl)
|
||||
return build_min_nt (code, arg1, arg2);
|
||||
|
||||
if (flag_ansi_overloading)
|
||||
return build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
|
||||
|
||||
rval = build_opfncall (code, LOOKUP_SPECULATIVELY,
|
||||
arg1, arg2, NULL_TREE);
|
||||
if (rval)
|
||||
return build_opfncall (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
|
||||
if (code == MEMBER_REF)
|
||||
return build_m_component_ref (build_indirect_ref (arg1, NULL_PTR),
|
||||
arg2);
|
||||
return build_binary_op (code, arg1, arg2, 1);
|
||||
return build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
|
||||
}
|
||||
|
||||
tree
|
||||
|
@ -4131,21 +4107,10 @@ build_x_unary_op (code, xarg)
|
|||
{
|
||||
tree rval;
|
||||
|
||||
if (flag_ansi_overloading)
|
||||
{
|
||||
rval = build_new_op (code, LOOKUP_NORMAL, xarg,
|
||||
NULL_TREE, NULL_TREE);
|
||||
if (rval || code != ADDR_EXPR)
|
||||
return rval;
|
||||
}
|
||||
else
|
||||
{
|
||||
rval = build_opfncall (code, LOOKUP_SPECULATIVELY, xarg,
|
||||
NULL_TREE, NULL_TREE);
|
||||
if (rval)
|
||||
return build_opfncall (code, LOOKUP_NORMAL, xarg,
|
||||
NULL_TREE, NULL_TREE);
|
||||
}
|
||||
rval = build_new_op (code, LOOKUP_NORMAL, xarg,
|
||||
NULL_TREE, NULL_TREE);
|
||||
if (rval || code != ADDR_EXPR)
|
||||
return rval;
|
||||
}
|
||||
|
||||
if (code == ADDR_EXPR)
|
||||
|
@ -4907,16 +4872,7 @@ build_x_conditional_expr (ifexp, op1, op2)
|
|||
if (processing_template_decl)
|
||||
return build_min_nt (COND_EXPR, ifexp, op1, op2);
|
||||
|
||||
if (flag_ansi_overloading)
|
||||
return build_new_op (COND_EXPR, LOOKUP_NORMAL, ifexp, op1, op2);
|
||||
|
||||
/* See comments in `build_x_binary_op'. */
|
||||
if (op1 != 0)
|
||||
rval = build_opfncall (COND_EXPR, LOOKUP_SPECULATIVELY, ifexp, op1, op2);
|
||||
if (rval)
|
||||
return build_opfncall (COND_EXPR, LOOKUP_NORMAL, ifexp, op1, op2);
|
||||
|
||||
return build_conditional_expr (ifexp, op1, op2);
|
||||
return build_new_op (COND_EXPR, LOOKUP_NORMAL, ifexp, op1, op2);
|
||||
}
|
||||
|
||||
tree
|
||||
|
@ -7092,82 +7048,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
|
|||
|
||||
if (IS_AGGR_TYPE (type)
|
||||
&& (TYPE_NEEDS_CONSTRUCTING (type) || TREE_HAS_CONSTRUCTOR (rhs)))
|
||||
{
|
||||
if (flag_ansi_overloading)
|
||||
return ocp_convert (type, rhs, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
|
||||
|
||||
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
|
||||
{
|
||||
/* This is sufficient to perform initialization. No need,
|
||||
apparently, to go through X(X&) to do first-cut
|
||||
initialization. Return through a TARGET_EXPR so that we get
|
||||
cleanups if it is used. */
|
||||
if (TREE_CODE (rhs) == CALL_EXPR)
|
||||
{
|
||||
rhs = build_cplus_new (type, rhs);
|
||||
return rhs;
|
||||
}
|
||||
/* Handle the case of default parameter initialization and
|
||||
initialization of static variables. */
|
||||
else if (TREE_CODE (rhs) == TARGET_EXPR)
|
||||
return rhs;
|
||||
else if (TREE_CODE (rhs) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (rhs))
|
||||
{
|
||||
my_friendly_assert (TREE_CODE (TREE_OPERAND (rhs, 0)) == CALL_EXPR, 318);
|
||||
if (exp)
|
||||
{
|
||||
my_friendly_assert (TREE_VALUE (TREE_OPERAND (TREE_OPERAND (rhs, 0), 1)) == NULL_TREE, 316);
|
||||
TREE_VALUE (TREE_OPERAND (TREE_OPERAND (rhs, 0), 1))
|
||||
= build_unary_op (ADDR_EXPR, exp, 0);
|
||||
}
|
||||
else
|
||||
rhs = build_cplus_new (type, TREE_OPERAND (rhs, 0));
|
||||
return rhs;
|
||||
}
|
||||
else if (TYPE_HAS_TRIVIAL_INIT_REF (type))
|
||||
return rhs;
|
||||
}
|
||||
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype)
|
||||
|| (IS_AGGR_TYPE (rhstype) && UNIQUELY_DERIVED_FROM_P (type, rhstype)))
|
||||
{
|
||||
if (TYPE_HAS_INIT_REF (type))
|
||||
{
|
||||
tree init = build_method_call (exp, ctor_identifier,
|
||||
build_expr_list (NULL_TREE, rhs),
|
||||
TYPE_BINFO (type), LOOKUP_NORMAL);
|
||||
|
||||
if (init == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
if (exp == 0)
|
||||
{
|
||||
exp = build_cplus_new (type, init);
|
||||
return exp;
|
||||
}
|
||||
|
||||
return build (COMPOUND_EXPR, type, init, exp);
|
||||
}
|
||||
|
||||
/* ??? The following warnings are turned off because
|
||||
this is another place where the default X(X&) constructor
|
||||
is implemented. */
|
||||
if (TYPE_HAS_ASSIGNMENT (type))
|
||||
cp_warning ("bitwise copy: `%T' defines operator=", type);
|
||||
|
||||
if (TREE_CODE (TREE_TYPE (rhs)) == REFERENCE_TYPE)
|
||||
rhs = convert_from_reference (rhs);
|
||||
if (type != rhstype)
|
||||
{
|
||||
tree nrhs = build1 (NOP_EXPR, type, rhs);
|
||||
TREE_CONSTANT (nrhs) = TREE_CONSTANT (rhs);
|
||||
rhs = nrhs;
|
||||
}
|
||||
return rhs;
|
||||
}
|
||||
|
||||
return ocp_convert (type, rhs, CONV_OLD_CONVERT,
|
||||
flags | LOOKUP_NO_CONVERSION);
|
||||
}
|
||||
return ocp_convert (type, rhs, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
|
||||
|
||||
if (type == TREE_TYPE (rhs))
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue