summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/cp/call.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/cp/call.c')
-rw-r--r--contrib/gcc/cp/call.c2688
1 files changed, 1357 insertions, 1331 deletions
diff --git a/contrib/gcc/cp/call.c b/contrib/gcc/cp/call.c
index 1a1a493..b1353f5 100644
--- a/contrib/gcc/cp/call.c
+++ b/contrib/gcc/cp/call.c
@@ -1,23 +1,23 @@
/* Functions related to invoking methods and overloaded functions.
- Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003,
- 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com) and
modified by Brendan Kehoe (brendan@cygnus.com).
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC 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,
+GCC 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
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
@@ -26,6 +26,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "cp-tree.h"
#include "output.h"
@@ -33,18 +35,17 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "toplev.h"
#include "expr.h"
-#include "ggc.h"
#include "diagnostic.h"
-
-extern int inhibit_warnings;
-
-static tree build_field_call PARAMS ((tree, tree, tree));
-static struct z_candidate * tourney PARAMS ((struct z_candidate *));
-static int equal_functions PARAMS ((tree, tree));
-static int joust PARAMS ((struct z_candidate *, struct z_candidate *, int));
-static int compare_ics PARAMS ((tree, tree));
-static tree build_over_call PARAMS ((struct z_candidate *, tree, int));
-static tree build_java_interface_fn_ref PARAMS ((tree, tree));
+#include "intl.h"
+#include "target.h"
+#include "convert.h"
+
+static struct z_candidate * tourney (struct z_candidate *);
+static int equal_functions (tree, tree);
+static int joust (struct z_candidate *, struct z_candidate *, bool);
+static int compare_ics (tree, tree);
+static tree build_over_call (struct z_candidate *, int);
+static tree build_java_interface_fn_ref (tree, tree);
#define convert_like(CONV, EXPR) \
convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0, \
/*issue_conversion_warnings=*/true)
@@ -52,63 +53,67 @@ static tree build_java_interface_fn_ref PARAMS ((tree, tree));
convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0, \
/*issue_conversion_warnings=*/true)
static tree convert_like_real (tree, tree, tree, int, int, bool);
-static void op_error PARAMS ((enum tree_code, enum tree_code, tree, tree,
- tree, const char *));
-static tree build_object_call PARAMS ((tree, tree));
-static tree resolve_args PARAMS ((tree));
-static struct z_candidate * build_user_type_conversion_1
- PARAMS ((tree, tree, int));
-static void print_z_candidates PARAMS ((struct z_candidate *));
-static tree build_this PARAMS ((tree));
-static struct z_candidate * splice_viable PARAMS ((struct z_candidate *));
-static int any_viable PARAMS ((struct z_candidate *));
-static int any_strictly_viable PARAMS ((struct z_candidate *));
-static struct z_candidate * add_template_candidate
- PARAMS ((struct z_candidate **, tree, tree, tree, tree, tree,
- tree, tree, int, unification_kind_t));
-static struct z_candidate * add_template_candidate_real
- PARAMS ((struct z_candidate **, tree, tree, tree, tree, tree,
- tree, tree, int, tree, unification_kind_t));
-static struct z_candidate * add_template_conv_candidate
- PARAMS ((struct z_candidate **, tree, tree, tree, tree, tree, tree));
+static void op_error (enum tree_code, enum tree_code, tree, tree,
+ tree, const char *);
+static tree build_object_call (tree, tree);
+static tree resolve_args (tree);
+static struct z_candidate *build_user_type_conversion_1 (tree, tree, int);
+static void print_z_candidate (const char *, struct z_candidate *);
+static void print_z_candidates (struct z_candidate *);
+static tree build_this (tree);
+static struct z_candidate *splice_viable (struct z_candidate *, bool, bool *);
+static bool any_strictly_viable (struct z_candidate *);
+static struct z_candidate *add_template_candidate
+ (struct z_candidate **, tree, tree, tree, tree, tree,
+ tree, tree, int, unification_kind_t);
+static struct z_candidate *add_template_candidate_real
+ (struct z_candidate **, tree, tree, tree, tree, tree,
+ tree, tree, int, tree, unification_kind_t);
+static struct z_candidate *add_template_conv_candidate
+ (struct z_candidate **, tree, tree, tree, tree, tree, tree);
static void add_builtin_candidates
- PARAMS ((struct z_candidate **, enum tree_code, enum tree_code,
- tree, tree *, int));
+ (struct z_candidate **, enum tree_code, enum tree_code,
+ tree, tree *, int);
static void add_builtin_candidate
- PARAMS ((struct z_candidate **, enum tree_code, enum tree_code,
- tree, tree, tree, tree *, tree *, int));
-static int is_complete PARAMS ((tree));
+ (struct z_candidate **, enum tree_code, enum tree_code,
+ tree, tree, tree, tree *, tree *, int);
+static bool is_complete (tree);
static void build_builtin_candidate
- PARAMS ((struct z_candidate **, tree, tree, tree, tree *, tree *,
- int));
-static struct z_candidate * add_conv_candidate
- PARAMS ((struct z_candidate **, tree, tree, tree, tree, tree));
-static struct z_candidate * add_function_candidate
+ (struct z_candidate **, tree, tree, tree, tree *, tree *,
+ int);
+static struct z_candidate *add_conv_candidate
+ (struct z_candidate **, tree, tree, tree, tree, tree);
+static struct z_candidate *add_function_candidate
(struct z_candidate **, tree, tree, tree, tree, tree, int);
-static tree implicit_conversion PARAMS ((tree, tree, tree, int));
-static tree standard_conversion PARAMS ((tree, tree, tree));
+static tree implicit_conversion (tree, tree, tree, int);
+static tree standard_conversion (tree, tree, tree);
static tree reference_binding (tree, tree, tree, int);
-static tree non_reference PARAMS ((tree));
-static tree build_conv PARAMS ((enum tree_code, tree, tree));
-static int is_subseq PARAMS ((tree, tree));
-static tree maybe_handle_ref_bind PARAMS ((tree*));
-static void maybe_handle_implicit_object PARAMS ((tree*));
+static tree build_conv (enum tree_code, tree, tree);
+static bool is_subseq (tree, tree);
+static tree maybe_handle_ref_bind (tree *);
+static void maybe_handle_implicit_object (tree *);
static struct z_candidate *add_candidate
- (struct z_candidate **, tree, tree, tree, tree, int);
-static tree source_type PARAMS ((tree));
-static void add_warning PARAMS ((struct z_candidate *, struct z_candidate *));
-static int reference_related_p PARAMS ((tree, tree));
-static int reference_compatible_p PARAMS ((tree, tree));
-static tree convert_class_to_reference PARAMS ((tree, tree, tree));
-static tree direct_reference_binding PARAMS ((tree, tree));
-static int promoted_arithmetic_type_p PARAMS ((tree));
-static tree conditional_conversion PARAMS ((tree, tree));
-static tree call_builtin_trap PARAMS ((void));
+ (struct z_candidate **, tree, tree, tree, tree, tree, int);
+static tree source_type (tree);
+static void add_warning (struct z_candidate *, struct z_candidate *);
+static bool reference_related_p (tree, tree);
+static bool reference_compatible_p (tree, tree);
+static tree convert_class_to_reference (tree, tree, tree);
+static tree direct_reference_binding (tree, tree);
+static bool promoted_arithmetic_type_p (tree);
+static tree conditional_conversion (tree, tree);
+static char *name_as_c_string (tree, tree, bool *);
+static tree call_builtin_trap (void);
+static tree prep_operand (tree);
+static void add_candidates (tree, tree, tree, bool, tree, tree,
+ int, struct z_candidate **);
static tree merge_conversion_sequences (tree, tree);
+static bool magic_varargs_p (tree);
+static tree build_temp (tree, tree, int, void (**)(const char *, ...));
+static void check_constructor_callable (tree, tree);
tree
-build_vfield_ref (datum, type)
- tree datum, type;
+build_vfield_ref (tree datum, tree type)
{
if (datum == error_mark_node)
return error_mark_node;
@@ -124,55 +129,18 @@ build_vfield_ref (datum, type)
datum, TYPE_VFIELD (type));
}
-/* Build a call to a member of an object. I.e., one that overloads
- operator ()(), or is a pointer-to-function or pointer-to-method. */
-
-static tree
-build_field_call (tree instance_ptr, tree decl, tree parms)
-{
- tree instance;
-
- if (decl == error_mark_node || decl == NULL_TREE)
- return decl;
-
- if (TREE_CODE (decl) == FIELD_DECL || TREE_CODE (decl) == VAR_DECL)
- {
- /* If it's a field, try overloading operator (),
- or calling if the field is a pointer-to-function. */
- instance = build_indirect_ref (instance_ptr, NULL);
- instance = build_class_member_access_expr (instance, decl,
- /*access_path=*/NULL_TREE,
- /*preserve_reference=*/false);
-
- if (instance == error_mark_node)
- return error_mark_node;
-
- if (IS_AGGR_TYPE (TREE_TYPE (instance)))
- return build_opfncall (CALL_EXPR, LOOKUP_NORMAL,
- instance, parms, NULL_TREE);
- else if (TREE_CODE (TREE_TYPE (instance)) == FUNCTION_TYPE
- || (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE
- && (TREE_CODE (TREE_TYPE (TREE_TYPE (instance)))
- == FUNCTION_TYPE)))
- return build_function_call (instance, parms);
- }
-
- return NULL_TREE;
-}
-
/* Returns nonzero iff the destructor name specified in NAME
(a BIT_NOT_EXPR) matches BASETYPE. The operand of NAME can take many
forms... */
-int
-check_dtor_name (basetype, name)
- tree basetype, name;
+bool
+check_dtor_name (tree basetype, tree name)
{
name = TREE_OPERAND (name, 0);
/* Just accept something we've already complained about. */
if (name == error_mark_node)
- return 1;
+ return true;
if (TREE_CODE (name) == TYPE_DECL)
name = TREE_TYPE (name);
@@ -195,129 +163,20 @@ check_dtor_name (basetype, name)
NAME will be a class template. */
else if (DECL_CLASS_TEMPLATE_P (name))
- return 0;
+ return false;
else
abort ();
if (name && TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (name))
- return 1;
- return 0;
-}
-
-/* Build a method call of the form `EXP->SCOPES::NAME (PARMS)'.
- This is how virtual function calls are avoided. */
-
-tree
-build_scoped_method_call (exp, basetype, name, parms)
- tree exp, basetype, name, parms;
-{
- /* Because this syntactic form does not allow
- a pointer to a base class to be `stolen',
- we need not protect the derived->base conversion
- that happens here.
-
- @@ But we do have to check access privileges later. */
- tree binfo, decl;
- tree type = TREE_TYPE (exp);
-
- if (type == error_mark_node
- || basetype == error_mark_node)
- return error_mark_node;
-
- if (processing_template_decl)
- {
- if (TREE_CODE (name) == BIT_NOT_EXPR
- && TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE)
- {
- tree type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 0);
- if (type)
- name = build_min_nt (BIT_NOT_EXPR, type);
- }
- name = build_min_nt (SCOPE_REF, basetype, name);
- return build_min_nt (METHOD_CALL_EXPR, name, exp, parms, NULL_TREE);
- }
-
- if (TREE_CODE (type) == REFERENCE_TYPE)
- type = TREE_TYPE (type);
-
- if (TREE_CODE (basetype) == TREE_VEC)
- {
- binfo = basetype;
- basetype = BINFO_TYPE (binfo);
- }
- else
- binfo = NULL_TREE;
-
- /* Check the destructor call syntax. */
- if (TREE_CODE (name) == BIT_NOT_EXPR)
- {
- /* We can get here if someone writes their destructor call like
- `obj.NS::~T()'; this isn't really a scoped method call, so hand
- it off. */
- if (TREE_CODE (basetype) == NAMESPACE_DECL)
- return build_method_call (exp, name, parms, NULL_TREE, LOOKUP_NORMAL);
-
- if (! check_dtor_name (basetype, name))
- error ("qualified type `%T' does not match destructor name `~%T'",
- basetype, TREE_OPERAND (name, 0));
-
- /* Destructors can be "called" for simple types; see 5.2.4 and 12.4 Note
- that explicit ~int is caught in the parser; this deals with typedefs
- and template parms. */
- if (! IS_AGGR_TYPE (basetype))
- {
- if (TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (basetype))
- error ("type of `%E' does not match destructor type `%T' (type was `%T')",
- exp, basetype, type);
-
- return cp_convert (void_type_node, exp);
- }
- }
-
- if (TREE_CODE (basetype) == NAMESPACE_DECL)
- {
- error ("`%D' is a namespace", basetype);
- return error_mark_node;
- }
- if (! is_aggr_type (basetype, 1))
- return error_mark_node;
-
- if (! IS_AGGR_TYPE (type))
- {
- error ("base object `%E' of scoped method call is of non-aggregate type `%T'",
- exp, type);
- return error_mark_node;
- }
-
- decl = build_scoped_ref (exp, basetype, &binfo);
-
- if (binfo)
- {
- /* Call to a destructor. */
- if (TREE_CODE (name) == BIT_NOT_EXPR)
- {
- if (! TYPE_HAS_DESTRUCTOR (TREE_TYPE (decl)))
- return cp_convert (void_type_node, exp);
-
- return build_delete (TREE_TYPE (decl), decl,
- sfk_complete_destructor,
- LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR,
- 0);
- }
-
- /* Call to a method. */
- return build_method_call (decl, name, parms, binfo,
- LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
- }
- return error_mark_node;
+ return true;
+ return false;
}
/* We want the address of a function or method. We avoid creating a
pointer-to-member function. */
tree
-build_addr_func (function)
- tree function;
+build_addr_func (tree function)
{
tree type = TREE_TYPE (function);
@@ -325,24 +184,16 @@ build_addr_func (function)
functions. */
if (TREE_CODE (type) == METHOD_TYPE)
{
- tree addr;
-
- type = build_pointer_type (type);
-
- if (!cxx_mark_addressable (function))
- return error_mark_node;
-
- addr = build1 (ADDR_EXPR, type, function);
-
- /* Address of a static or external variable or function counts
- as a constant */
- if (staticp (function))
- TREE_CONSTANT (addr) = 1;
-
- function = addr;
+ if (TREE_CODE (function) == OFFSET_REF)
+ {
+ tree object = build_address (TREE_OPERAND (function, 0));
+ return get_member_function_from_ptrfunc (&object,
+ TREE_OPERAND (function, 1));
+ }
+ function = build_address (function);
}
else
- function = default_conversion (function);
+ function = decay_conversion (function);
return function;
}
@@ -352,8 +203,7 @@ build_addr_func (function)
(TYPE_PTRMEMFUNC_P) must be handled by our callers. */
tree
-build_call (function, parms)
- tree function, parms;
+build_call (tree function, tree parms)
{
int is_constructor = 0;
int nothrow;
@@ -419,10 +269,8 @@ build_call (function, parms)
TREE_VALUE (tmp), t);
}
- function = build_nt (CALL_EXPR, function, parms, NULL_TREE);
+ function = build (CALL_EXPR, result_type, function, parms);
TREE_HAS_CONSTRUCTOR (function) = is_constructor;
- TREE_TYPE (function) = result_type;
- TREE_SIDE_EFFECTS (function) = 1;
TREE_NOTHROW (function) = nothrow;
return function;
@@ -443,8 +291,7 @@ build_call (function, parms)
BASETYPE_PATH, if non-NULL, contains a chain from the type of INSTANCE
down to the real instance type to use for access checking. We need this
- information to get protected accesses correct. This parameter is used
- by build_member_call.
+ information to get protected accesses correct.
FLAGS is the logical disjunction of zero or more LOOKUP_
flags. See cp-tree.h for more info.
@@ -460,141 +307,20 @@ build_call (function, parms)
`operator()()' is defined for the type of that field, then we return
that result. */
-#ifdef GATHER_STATISTICS
-extern int n_build_method_call;
-#endif
-
-tree
-build_method_call (instance, name, parms, basetype_path, flags)
- tree instance, name, parms, basetype_path;
- int flags;
-{
- tree fn;
- tree object_type;
- tree template_args = NULL_TREE;
- bool has_template_args = false;
-
-#ifdef GATHER_STATISTICS
- n_build_method_call++;
-#endif
-
- if (instance == error_mark_node
- || name == error_mark_node
- || parms == error_mark_node
- || (instance && TREE_TYPE (instance) == error_mark_node))
- return error_mark_node;
-
- if (processing_template_decl)
- {
- /* We need to process template parm names here so that tsubst catches
- them properly. Other type names can wait. */
- if (TREE_CODE (name) == BIT_NOT_EXPR)
- {
- tree type = NULL_TREE;
-
- if (TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE)
- type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 0);
- else if (TREE_CODE (TREE_OPERAND (name, 0)) == TYPE_DECL)
- type = TREE_TYPE (TREE_OPERAND (name, 0));
-
- if (type && TREE_CODE (type) == TEMPLATE_TYPE_PARM)
- name = build_min_nt (BIT_NOT_EXPR, type);
- }
-
- return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE);
- }
-
- if (TREE_CODE (instance) == OFFSET_REF)
- instance = resolve_offset_ref (instance);
- if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
- instance = convert_from_reference (instance);
- object_type = TREE_TYPE (instance);
-
- if (TREE_CODE (name) == BIT_NOT_EXPR)
- {
- tree instance_ptr;
-
- if (parms)
- error ("destructors take no parameters");
-
- if (! check_dtor_name (object_type, name))
- error
- ("destructor name `~%T' does not match type `%T' of expression",
- TREE_OPERAND (name, 0), object_type);
-
- /* The destructor type must be complete. */
- object_type = complete_type_or_else (object_type, NULL_TREE);
- if (!object_type || object_type == error_mark_node)
- return error_mark_node;
-
- if (! TYPE_HAS_DESTRUCTOR (object_type))
- return cp_convert (void_type_node, instance);
- instance = default_conversion (instance);
- instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);
- return build_delete (build_pointer_type (object_type),
- instance_ptr, sfk_complete_destructor,
- LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
- }
-
- if (!CLASS_TYPE_P (object_type))
- {
- if ((flags & LOOKUP_COMPLAIN)
- && TREE_TYPE (instance) != error_mark_node)
- error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
- name, instance, object_type);
- return error_mark_node;
- }
-
- if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
- {
- template_args = TREE_OPERAND (name, 1);
- has_template_args = true;
- name = TREE_OPERAND (name, 0);
- }
- if (TREE_CODE (name) == OVERLOAD)
- name = DECL_NAME (get_first_fn (name));
- else if (TREE_CODE (name) == LOOKUP_EXPR)
- name = TREE_OPERAND (name, 0);
- else if (DECL_P (name))
- name = DECL_NAME (name);
- if (has_template_args)
- fn = lookup_fnfields (object_type, name, /*protect=*/2);
- else
- fn = lookup_member (object_type, name, /*protect=*/2, /*want_type=*/0);
-
- if (fn && TREE_CODE (fn) == TREE_LIST && !BASELINK_P (fn))
- {
- error ("request for member `%D' is ambiguous", name);
- print_candidates (fn);
- return error_mark_node;
- }
-
- /* If the name could not be found, issue an error. */
- if (!fn)
- {
- unqualified_name_lookup_error (name);
- return error_mark_node;
- }
-
- if (BASELINK_P (fn) && has_template_args)
- BASELINK_FUNCTIONS (fn)
- = build_nt (TEMPLATE_ID_EXPR,
- BASELINK_FUNCTIONS (fn),
- template_args);
- if (BASELINK_P (fn) && basetype_path)
- BASELINK_ACCESS_BINFO (fn) = basetype_path;
-
- return build_new_method_call (instance, fn, parms,
- /*conversion_path=*/NULL_TREE, flags);
-}
-
/* New overloading code. */
struct z_candidate GTY(()) {
/* The FUNCTION_DECL that will be called if this candidate is
selected by overload resolution. */
tree fn;
+ /* The arguments to use when calling this function. */
+ tree args;
+ /* The implicit conversion sequences for each of the arguments to
+ FN. */
tree convs;
+ /* If FN is a user-defined conversion, the standard conversion
+ sequence from the type returned by FN to the desired destination
+ type. */
tree second_conv;
int viable;
/* If FN is a member function, the binfo indicating the path used to
@@ -640,12 +366,15 @@ struct z_candidate GTY(()) {
should be created to hold the result of the conversion. */
#define NEED_TEMPORARY_P(NODE) TREE_LANG_FLAG_4 (NODE)
+/* TRUE in an IDENTITY_CONV or BASE_CONV if the copy constructor must
+ be accessible, even though it is not being used. */
+#define CHECK_COPY_CONSTRUCTOR_P(NODE) TREE_LANG_FLAG_5 (NODE)
+
#define USER_CONV_CAND(NODE) WRAPPER_ZC (TREE_OPERAND (NODE, 1))
#define USER_CONV_FN(NODE) (USER_CONV_CAND (NODE)->fn)
-int
-null_ptr_cst_p (t)
- tree t;
+bool
+null_ptr_cst_p (tree t)
{
/* [conv.ptr]
@@ -653,29 +382,26 @@ null_ptr_cst_p (t)
(_expr.const_) rvalue of integer type that evaluates to zero. */
if (t == null_node
|| (CP_INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t)))
- return 1;
- return 0;
+ return true;
+ return false;
}
/* Returns nonzero if PARMLIST consists of only default parms and/or
ellipsis. */
-int
-sufficient_parms_p (parmlist)
- tree parmlist;
+bool
+sufficient_parms_p (tree parmlist)
{
for (; parmlist && parmlist != void_list_node;
parmlist = TREE_CHAIN (parmlist))
if (!TREE_PURPOSE (parmlist))
- return 0;
- return 1;
+ return false;
+ return true;
}
static tree
-build_conv (code, type, from)
- enum tree_code code;
- tree type, from;
+build_conv (enum tree_code code, tree type, tree from)
{
tree t;
int rank = ICS_STD_RANK (from);
@@ -710,25 +436,12 @@ build_conv (code, type, from)
return t;
}
-/* If T is a REFERENCE_TYPE return the type to which T refers.
- Otherwise, return T itself. */
-
-static tree
-non_reference (t)
- tree t;
-{
- if (TREE_CODE (t) == REFERENCE_TYPE)
- t = TREE_TYPE (t);
- return t;
-}
-
tree
-strip_top_quals (t)
- tree t;
+strip_top_quals (tree t)
{
if (TREE_CODE (t) == ARRAY_TYPE)
return t;
- return TYPE_MAIN_VARIANT (t);
+ return cp_build_qualified_type (t, 0);
}
/* Returns the standard conversion path (see [conv]) from type FROM to type
@@ -736,18 +449,16 @@ strip_top_quals (t)
also pass the expression EXPR to convert from. */
static tree
-standard_conversion (to, from, expr)
- tree to, from, expr;
+standard_conversion (tree to, tree from, tree expr)
{
enum tree_code fcode, tcode;
tree conv;
- int fromref = 0;
+ bool fromref = false;
- if (TREE_CODE (to) == REFERENCE_TYPE)
- to = TREE_TYPE (to);
+ to = non_reference (to);
if (TREE_CODE (from) == REFERENCE_TYPE)
{
- fromref = 1;
+ fromref = true;
from = TREE_TYPE (from);
}
to = strip_top_quals (to);
@@ -782,7 +493,7 @@ standard_conversion (to, from, expr)
else if (fromref || (expr && lvalue_p (expr)))
conv = build_conv (RVALUE_CONV, from, conv);
- /* Allow conversion between `__complex__' data types */
+ /* Allow conversion between `__complex__' data types. */
if (tcode == COMPLEX_TYPE && fcode == COMPLEX_TYPE)
{
/* The standard conversion sequence to convert FROM to TO is
@@ -805,11 +516,15 @@ standard_conversion (to, from, expr)
if (same_type_p (from, to))
return conv;
- if ((tcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (to))
+ if ((tcode == POINTER_TYPE || TYPE_PTR_TO_MEMBER_P (to))
&& expr && null_ptr_cst_p (expr))
- {
- conv = build_conv (STD_CONV, to, conv);
- }
+ conv = build_conv (STD_CONV, to, conv);
+ else if (tcode == POINTER_TYPE && fcode == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (to)) == VECTOR_TYPE
+ && TREE_CODE (TREE_TYPE (from)) == VECTOR_TYPE
+ && ((*targetm.vector_opaque_p) (TREE_TYPE (to))
+ || (*targetm.vector_opaque_p) (TREE_TYPE (from))))
+ conv = build_conv (STD_CONV, to, conv);
else if ((tcode == INTEGER_TYPE && fcode == POINTER_TYPE)
|| (tcode == POINTER_TYPE && fcode == INTEGER_TYPE))
{
@@ -818,41 +533,44 @@ standard_conversion (to, from, expr)
conv = build_conv (STD_CONV, to, conv);
ICS_BAD_FLAG (conv) = 1;
}
- else if (tcode == ENUMERAL_TYPE && fcode == INTEGER_TYPE
- && TYPE_PRECISION (to) == TYPE_PRECISION (from))
+ else if (tcode == ENUMERAL_TYPE && fcode == INTEGER_TYPE)
{
/* For backwards brain damage compatibility, allow interconversion of
enums and integers with a pedwarn. */
conv = build_conv (STD_CONV, to, conv);
ICS_BAD_FLAG (conv) = 1;
}
- else if (tcode == POINTER_TYPE && fcode == POINTER_TYPE)
+ else if ((tcode == POINTER_TYPE && fcode == POINTER_TYPE)
+ || (TYPE_PTRMEM_P (to) && TYPE_PTRMEM_P (from)))
{
- enum tree_code ufcode = TREE_CODE (TREE_TYPE (from));
- enum tree_code utcode = TREE_CODE (TREE_TYPE (to));
+ tree to_pointee;
+ tree from_pointee;
- if (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (from),
- TREE_TYPE (to)))
+ if (tcode == POINTER_TYPE
+ && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (from),
+ TREE_TYPE (to)))
;
- else if (utcode == VOID_TYPE && ufcode != OFFSET_TYPE
- && ufcode != FUNCTION_TYPE)
+ else if (VOID_TYPE_P (TREE_TYPE (to))
+ && !TYPE_PTRMEM_P (from)
+ && TREE_CODE (TREE_TYPE (from)) != FUNCTION_TYPE)
{
from = build_pointer_type
(cp_build_qualified_type (void_type_node,
cp_type_quals (TREE_TYPE (from))));
conv = build_conv (PTR_CONV, from, conv);
}
- else if (ufcode == OFFSET_TYPE && utcode == OFFSET_TYPE)
+ else if (TYPE_PTRMEM_P (from))
{
- tree fbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (from));
- tree tbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (to));
+ tree fbase = TYPE_PTRMEM_CLASS_TYPE (from);
+ tree tbase = TYPE_PTRMEM_CLASS_TYPE (to);
if (DERIVED_FROM_P (fbase, tbase)
&& (same_type_ignoring_top_level_qualifiers_p
- (TREE_TYPE (TREE_TYPE (from)),
- TREE_TYPE (TREE_TYPE (to)))))
+ (TYPE_PTRMEM_POINTED_TO_TYPE (from),
+ TYPE_PTRMEM_POINTED_TO_TYPE (to))))
{
- from = build_ptrmem_type (tbase, TREE_TYPE (TREE_TYPE (from)));
+ from = build_ptrmem_type (tbase,
+ TYPE_PTRMEM_POINTED_TO_TYPE (from));
conv = build_conv (PMEM_CONV, from, conv);
}
}
@@ -878,14 +596,25 @@ standard_conversion (to, from, expr)
conv = build_conv (PTR_CONV, from, conv);
}
+ if (tcode == POINTER_TYPE)
+ {
+ to_pointee = TREE_TYPE (to);
+ from_pointee = TREE_TYPE (from);
+ }
+ else
+ {
+ to_pointee = TYPE_PTRMEM_POINTED_TO_TYPE (to);
+ from_pointee = TYPE_PTRMEM_POINTED_TO_TYPE (from);
+ }
+
if (same_type_p (from, to))
/* OK */;
- else if (comp_ptr_ttypes (TREE_TYPE (to), TREE_TYPE (from)))
+ else if (comp_ptr_ttypes (to_pointee, from_pointee))
conv = build_conv (QUAL_CONV, to, conv);
else if (expr && string_conv_p (to, expr, 0))
/* converting from string constant to char *. */
conv = build_conv (QUAL_CONV, to, conv);
- else if (ptr_reasonably_similar (TREE_TYPE (to), TREE_TYPE (from)))
+ else if (ptr_reasonably_similar (to_pointee, from_pointee))
{
conv = build_conv (PTR_CONV, to, conv);
ICS_BAD_FLAG (conv) = 1;
@@ -910,21 +639,33 @@ standard_conversion (to, from, expr)
return 0;
from = cp_build_qualified_type (tbase, cp_type_quals (fbase));
- from = build_cplus_method_type (from, TREE_TYPE (fromfn),
- TREE_CHAIN (TYPE_ARG_TYPES (fromfn)));
+ from = build_method_type_directly (from,
+ TREE_TYPE (fromfn),
+ TREE_CHAIN (TYPE_ARG_TYPES (fromfn)));
from = build_ptrmemfunc_type (build_pointer_type (from));
conv = build_conv (PMEM_CONV, from, conv);
}
else if (tcode == BOOLEAN_TYPE)
{
- if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE
- || fcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (from)))
- return 0;
+ /* [conv.bool]
- conv = build_conv (STD_CONV, to, conv);
- if (fcode == POINTER_TYPE
- || (TYPE_PTRMEMFUNC_P (from) && ICS_STD_RANK (conv) < PBOOL_RANK))
- ICS_STD_RANK (conv) = PBOOL_RANK;
+ An rvalue of arithmetic, enumeration, pointer, or pointer to
+ member type can be converted to an rvalue of type bool. */
+ if (ARITHMETIC_TYPE_P (from)
+ || fcode == ENUMERAL_TYPE
+ || fcode == POINTER_TYPE
+ || TYPE_PTR_TO_MEMBER_P (from))
+ {
+ conv = build_conv (STD_CONV, to, conv);
+ if (fcode == POINTER_TYPE
+ || TYPE_PTRMEM_P (from)
+ || (TYPE_PTRMEMFUNC_P (from)
+ && ICS_STD_RANK (conv) < PBOOL_RANK))
+ ICS_STD_RANK (conv) = PBOOL_RANK;
+ return conv;
+ }
+
+ return NULL_TREE;
}
/* We don't check for ENUMERAL_TYPE here because there are no standard
conversions to enum type. */
@@ -936,10 +677,14 @@ standard_conversion (to, from, expr)
conv = build_conv (STD_CONV, to, conv);
/* Give this a better rank if it's a promotion. */
- if (to == type_promotes_to (from)
+ if (same_type_p (to, type_promotes_to (from))
&& ICS_STD_RANK (TREE_OPERAND (conv, 0)) <= PROMO_RANK)
ICS_STD_RANK (conv) = PROMO_RANK;
}
+ else if (fcode == VECTOR_TYPE && tcode == VECTOR_TYPE
+ && ((*targetm.vector_opaque_p) (from)
+ || (*targetm.vector_opaque_p) (to)))
+ return build_conv (STD_CONV, to, conv);
else if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
&& is_properly_derived_from (from, to))
{
@@ -960,10 +705,8 @@ standard_conversion (to, from, expr)
/* Returns nonzero if T1 is reference-related to T2. */
-static int
-reference_related_p (t1, t2)
- tree t1;
- tree t2;
+static bool
+reference_related_p (tree t1, tree t2)
{
t1 = TYPE_MAIN_VARIANT (t1);
t2 = TYPE_MAIN_VARIANT (t2);
@@ -980,10 +723,8 @@ reference_related_p (t1, t2)
/* Returns nonzero if T1 is reference-compatible with T2. */
-static int
-reference_compatible_p (t1, t2)
- tree t1;
- tree t2;
+static bool
+reference_compatible_p (tree t1, tree t2)
{
/* [dcl.init.ref]
@@ -998,10 +739,7 @@ reference_compatible_p (t1, t2)
converted to T as in [over.match.ref]. */
static tree
-convert_class_to_reference (t, s, expr)
- tree t;
- tree s;
- tree expr;
+convert_class_to_reference (tree t, tree s, tree expr)
{
tree conversions;
tree arglist;
@@ -1009,6 +747,7 @@ convert_class_to_reference (t, s, expr)
tree reference_type;
struct z_candidate *candidates;
struct z_candidate *cand;
+ bool any_viable_p;
conversions = lookup_conversions (s);
if (!conversions)
@@ -1091,29 +830,39 @@ convert_class_to_reference (t, s, expr)
LOOKUP_NORMAL);
if (cand)
- /* Build a standard conversion sequence indicating the
- binding from the reference type returned by the
- function to the desired REFERENCE_TYPE. */
- cand->second_conv
- = (direct_reference_binding
- (reference_type,
- build1 (IDENTITY_CONV,
- TREE_TYPE (TREE_TYPE (TREE_TYPE (cand->fn))),
- NULL_TREE)));
+ {
+ /* Build a standard conversion sequence indicating the
+ binding from the reference type returned by the
+ function to the desired REFERENCE_TYPE. */
+ cand->second_conv
+ = (direct_reference_binding
+ (reference_type,
+ build1 (IDENTITY_CONV,
+ TREE_TYPE (TREE_TYPE (TREE_TYPE (cand->fn))),
+ NULL_TREE)));
+ ICS_BAD_FLAG (cand->second_conv)
+ |= ICS_BAD_FLAG (TREE_VEC_ELT (cand->convs, 0));
+ }
}
conversions = TREE_CHAIN (conversions);
}
+ candidates = splice_viable (candidates, pedantic, &any_viable_p);
/* If none of the conversion functions worked out, let our caller
know. */
- if (!any_viable (candidates))
+ if (!any_viable_p)
return NULL_TREE;
-
- candidates = splice_viable (candidates);
+
cand = tourney (candidates);
if (!cand)
return NULL_TREE;
+ /* Now that we know that this is the function we're going to use fix
+ the dummy first argument. */
+ cand->args = tree_cons (NULL_TREE,
+ build_this (expr),
+ TREE_CHAIN (cand->args));
+
/* Build a user-defined conversion sequence representing the
conversion. */
conv = build_conv (USER_CONV,
@@ -1127,7 +876,7 @@ convert_class_to_reference (t, s, expr)
if (cand->viable == -1)
ICS_BAD_FLAG (conv) = 1;
-
+
return cand->second_conv;
}
@@ -1136,16 +885,14 @@ convert_class_to_reference (t, s, expr)
Return a conversion sequence for this binding. */
static tree
-direct_reference_binding (type, conv)
- tree type;
- tree conv;
+direct_reference_binding (tree type, tree conv)
{
tree t;
my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 20030306);
my_friendly_assert (TREE_CODE (TREE_TYPE (conv)) != REFERENCE_TYPE,
20030306);
-
+
t = TREE_TYPE (type);
/* [over.ics.rank]
@@ -1188,8 +935,8 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags)
tree conv = NULL_TREE;
tree to = TREE_TYPE (rto);
tree from = rfrom;
- int related_p;
- int compatible_p;
+ bool related_p;
+ bool compatible_p;
cp_lvalue_kind lvalue_p = clk_none;
if (TREE_CODE (to) == FUNCTION_TYPE && expr && type_unknown_p (expr))
@@ -1224,14 +971,14 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags)
-- is an lvalue (but not an lvalue for a bit-field), and "cv1 T1"
is reference-compatible with "cv2 T2,"
- the reference is bound directly to the initializer exprssion
+ the reference is bound directly to the initializer expression
lvalue. */
conv = build1 (IDENTITY_CONV, from, expr);
conv = direct_reference_binding (rto, conv);
- if ((lvalue_p & clk_bitfield) != 0
- && CP_TYPE_CONST_NON_VOLATILE_P (to))
+ if ((lvalue_p & clk_bitfield) != 0
+ || ((lvalue_p & clk_packed) != 0 && !TYPE_PACKED (to)))
/* For the purposes of overload resolution, we ignore the fact
- this expression is a bitfield. (In particular,
+ this expression is a bitfield or packed field. (In particular,
[over.ics.ref] says specifically that a function with a
non-const reference parameter is viable even if the
argument is a bitfield.)
@@ -1242,13 +989,14 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags)
a temporary, so we just issue an error when the conversion
actually occurs. */
NEED_TEMPORARY_P (conv) = 1;
+
return conv;
}
else if (CLASS_TYPE_P (from) && !(flags & LOOKUP_NO_CONVERSION))
{
/* [dcl.init.ref]
- If the initializer exprsesion
+ If the initializer expression
-- has a class type (i.e., T2 is a class type) can be
implicitly converted to an lvalue of type "cv3 T3," where
@@ -1296,7 +1044,7 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags)
or to a sub-object within that object.
-- ...
-
+
We use the first alternative. The implicit conversion sequence
is supposed to be same as we would obtain by generating a
temporary. Fortunately, if the types are reference compatible,
@@ -1305,7 +1053,10 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags)
if (CLASS_TYPE_P (from) && compatible_p)
{
conv = build1 (IDENTITY_CONV, from, expr);
- return direct_reference_binding (rto, conv);
+ conv = direct_reference_binding (rto, conv);
+ if (!(flags & LOOKUP_CONSTRUCTOR_CALLABLE))
+ CHECK_COPY_CONSTRUCTOR_P (TREE_OPERAND (conv, 0)) = 1;
+ return conv;
}
/* [dcl.init.ref]
@@ -1336,20 +1087,10 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags)
significant. */
static tree
-implicit_conversion (to, from, expr, flags)
- tree to, from, expr;
- int flags;
+implicit_conversion (tree to, tree from, tree expr, int flags)
{
tree conv;
- /* Resolve expressions like `A::p' that we thought might become
- pointers-to-members. */
- if (expr && TREE_CODE (expr) == OFFSET_REF)
- {
- expr = resolve_offset_ref (expr);
- from = TREE_TYPE (expr);
- }
-
if (from == error_mark_node || to == error_mark_node
|| expr == error_mark_node)
return NULL_TREE;
@@ -1360,11 +1101,12 @@ implicit_conversion (to, from, expr, flags)
conv = standard_conversion (to, from, expr);
if (conv)
- ;
- else if (expr != NULL_TREE
- && (IS_AGGR_TYPE (from)
- || IS_AGGR_TYPE (to))
- && (flags & LOOKUP_NO_CONVERSION) == 0)
+ return conv;
+
+ if (expr != NULL_TREE
+ && (IS_AGGR_TYPE (from)
+ || IS_AGGR_TYPE (to))
+ && (flags & LOOKUP_NO_CONVERSION) == 0)
{
struct z_candidate *cand;
@@ -1376,9 +1118,10 @@ implicit_conversion (to, from, expr, flags)
/* We used to try to bind a reference to a temporary here, but that
is now handled by the recursive call to this function at the end
of reference_binding. */
+ return conv;
}
- return conv;
+ return NULL_TREE;
}
/* Add a new entry to the list of candidates. Used by the add_*_candidate
@@ -1386,13 +1129,13 @@ implicit_conversion (to, from, expr, flags)
static struct z_candidate *
add_candidate (struct z_candidate **candidates,
- tree fn, tree convs, tree access_path, tree
- conversion_path, int viable)
+ tree fn, tree args, tree convs, tree access_path,
+ tree conversion_path, int viable)
{
- struct z_candidate *cand
- = (struct z_candidate *) ggc_alloc_cleared (sizeof (struct z_candidate));
+ struct z_candidate *cand = ggc_alloc_cleared (sizeof (struct z_candidate));
cand->fn = fn;
+ cand->args = args;
cand->convs = convs;
cand->access_path = access_path;
cand->conversion_path = conversion_path;
@@ -1420,6 +1163,7 @@ add_function_candidate (struct z_candidate **candidates,
int i, len;
tree convs;
tree parmnode, argnode;
+ tree orig_arglist;
int viable = 1;
/* Built-in functions that haven't been declared don't really
@@ -1432,8 +1176,11 @@ add_function_candidate (struct z_candidate **candidates,
if (DECL_CONSTRUCTOR_P (fn))
{
parmlist = skip_artificial_parms_for (fn, parmlist);
+ orig_arglist = arglist;
arglist = skip_artificial_parms_for (fn, arglist);
}
+ else
+ orig_arglist = arglist;
len = list_length (arglist);
convs = make_tree_vec (len);
@@ -1531,7 +1278,7 @@ add_function_candidate (struct z_candidate **candidates,
}
out:
- return add_candidate (candidates, fn, convs, access_path,
+ return add_candidate (candidates, fn, orig_arglist, convs, access_path,
conversion_path, viable);
}
@@ -1547,12 +1294,8 @@ add_function_candidate (struct z_candidate **candidates,
instead of the function. */
static struct z_candidate *
-add_conv_candidate (candidates, fn, obj, arglist, access_path,
- conversion_path)
- struct z_candidate **candidates;
- tree fn, obj, arglist;
- tree access_path;
- tree conversion_path;
+add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
+ tree arglist, tree access_path, tree conversion_path)
{
tree totype = TREE_TYPE (TREE_TYPE (fn));
int i, len, viable, flags;
@@ -1612,17 +1355,14 @@ add_conv_candidate (candidates, fn, obj, arglist, access_path,
if (!sufficient_parms_p (parmnode))
viable = 0;
- return add_candidate (candidates, totype, convs, access_path,
+ return add_candidate (candidates, totype, arglist, convs, access_path,
conversion_path, viable);
}
static void
-build_builtin_candidate (candidates, fnname, type1, type2,
- args, argtypes, flags)
- struct z_candidate **candidates;
- tree fnname, type1, type2, *args, *argtypes;
- int flags;
-
+build_builtin_candidate (struct z_candidate **candidates, tree fnname,
+ tree type1, tree type2, tree *args, tree *argtypes,
+ int flags)
{
tree t, convs;
int viable = 1, i;
@@ -1662,24 +1402,22 @@ build_builtin_candidate (candidates, fnname, type1, type2,
viable = 0;
}
- add_candidate (candidates, fnname, convs,
+ add_candidate (candidates, fnname, /*args=*/NULL_TREE, convs,
/*access_path=*/NULL_TREE,
/*conversion_path=*/NULL_TREE,
viable);
}
-static int
-is_complete (t)
- tree t;
+static bool
+is_complete (tree t)
{
return COMPLETE_TYPE_P (complete_type (t));
}
/* Returns nonzero if TYPE is a promoted arithmetic type. */
-static int
-promoted_arithmetic_type_p (type)
- tree type;
+static bool
+promoted_arithmetic_type_p (tree type)
{
/* [over.built]
@@ -1704,12 +1442,9 @@ promoted_arithmetic_type_p (type)
CODE (TYPE1, TYPE1) and CODE (TYPE2, TYPE2). */
static void
-add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
- args, argtypes, flags)
- struct z_candidate **candidates;
- enum tree_code code, code2;
- tree fnname, type1, type2, *args, *argtypes;
- int flags;
+add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
+ enum tree_code code2, tree fnname, tree type1,
+ tree type2, tree *args, tree *argtypes, int flags)
{
switch (code)
{
@@ -1781,8 +1516,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
T operator-(T); */
case CONVERT_EXPR: /* unary + */
- if (TREE_CODE (type1) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (type1)) != OFFSET_TYPE)
+ if (TREE_CODE (type1) == POINTER_TYPE)
break;
case NEGATE_EXPR:
if (ARITHMETIC_TYPE_P (type1))
@@ -1807,12 +1541,10 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
case MEMBER_REF:
if (TREE_CODE (type1) == POINTER_TYPE
- && (TYPE_PTRMEMFUNC_P (type2) || TYPE_PTRMEM_P (type2)))
+ && TYPE_PTR_TO_MEMBER_P (type2))
{
tree c1 = TREE_TYPE (type1);
- tree c2 = (TYPE_PTRMEMFUNC_P (type2)
- ? TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type2)))
- : TYPE_OFFSET_BASETYPE (TREE_TYPE (type2)));
+ tree c2 = TYPE_PTRMEM_CLASS_TYPE (type2);
if (IS_AGGR_TYPE (c1) && DERIVED_FROM_P (c2, c1)
&& (TYPE_PTRMEMFUNC_P (type2)
@@ -1882,19 +1614,17 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
if ((TYPE_PTRMEMFUNC_P (type1) && TYPE_PTRMEMFUNC_P (type2))
|| (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2)))
break;
- if ((TYPE_PTRMEMFUNC_P (type1) || TYPE_PTRMEM_P (type1))
- && null_ptr_cst_p (args[1]))
+ if (TYPE_PTR_TO_MEMBER_P (type1) && null_ptr_cst_p (args[1]))
{
type2 = type1;
break;
}
- if ((TYPE_PTRMEMFUNC_P (type2) || TYPE_PTRMEM_P (type2))
- && null_ptr_cst_p (args[0]))
+ if (TYPE_PTR_TO_MEMBER_P (type2) && null_ptr_cst_p (args[0]))
{
type1 = type2;
break;
}
- /* FALLTHROUGH */
+ /* Fall through. */
case LT_EXPR:
case GT_EXPR:
case LE_EXPR:
@@ -2060,12 +1790,8 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
break;
/* Otherwise, the types should be pointers. */
- if (!(TREE_CODE (type1) == POINTER_TYPE
- || TYPE_PTRMEM_P (type1)
- || TYPE_PTRMEMFUNC_P (type1))
- || !(TREE_CODE (type2) == POINTER_TYPE
- || TYPE_PTRMEM_P (type2)
- || TYPE_PTRMEMFUNC_P (type2)))
+ if (!(TYPE_PTR_P (type1) || TYPE_PTR_TO_MEMBER_P (type1))
+ || !(TYPE_PTR_P (type2) || TYPE_PTR_TO_MEMBER_P (type2)))
return;
/* We don't check that the two types are the same; the logic
@@ -2083,8 +1809,8 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
if (type2 && !same_type_p (type1, type2)
&& TREE_CODE (type1) == TREE_CODE (type2)
&& (TREE_CODE (type1) == REFERENCE_TYPE
- || (TREE_CODE (type1) == POINTER_TYPE
- && TYPE_PTRMEM_P (type1) == TYPE_PTRMEM_P (type2))
+ || (TYPE_PTR_P (type1) && TYPE_PTR_P (type2))
+ || (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2))
|| TYPE_PTRMEMFUNC_P (type1)
|| IS_AGGR_TYPE (type1)
|| TREE_CODE (type1) == ENUMERAL_TYPE))
@@ -2101,8 +1827,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
}
tree
-type_decays_to (type)
- tree type;
+type_decays_to (tree type)
{
if (TREE_CODE (type) == ARRAY_TYPE)
return build_pointer_type (TREE_TYPE (type));
@@ -2125,11 +1850,9 @@ type_decays_to (type)
filter out the invalid set. */
static void
-add_builtin_candidates (candidates, code, code2, fnname, args, flags)
- struct z_candidate **candidates;
- enum tree_code code, code2;
- tree fnname, *args;
- int flags;
+add_builtin_candidates (struct z_candidate **candidates, enum tree_code code,
+ enum tree_code code2, tree fnname, tree *args,
+ int flags)
{
int ref1, i;
int enum_p = 0;
@@ -2194,7 +1917,7 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
case GT_EXPR:
case GE_EXPR:
enum_p = 1;
- /* FALLTHROUGH */
+ /* Fall through. */
default:
ref1 = 0;
@@ -2302,16 +2025,11 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
add_conv_candidate. */
static struct z_candidate*
-add_template_candidate_real (candidates, tmpl, ctype, explicit_targs,
- arglist, return_type, access_path,
- conversion_path, flags, obj, strict)
- struct z_candidate **candidates;
- tree tmpl, ctype, explicit_targs, arglist, return_type;
- tree access_path;
- tree conversion_path;
- int flags;
- tree obj;
- unification_kind_t strict;
+add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
+ tree ctype, tree explicit_targs, tree arglist,
+ tree return_type, tree access_path,
+ tree conversion_path, int flags, tree obj,
+ unification_kind_t strict)
{
int ntparms = DECL_NTPARMS (tmpl);
tree targs = make_tree_vec (ntparms);
@@ -2337,7 +2055,7 @@ add_template_candidate_real (candidates, tmpl, ctype, explicit_targs,
if (i != 0)
return NULL;
- fn = instantiate_template (tmpl, targs);
+ fn = instantiate_template (tmpl, targs, tf_none);
if (fn == error_mark_node)
return NULL;
@@ -2406,15 +2124,10 @@ add_template_candidate_real (candidates, tmpl, ctype, explicit_targs,
static struct z_candidate *
-add_template_candidate (candidates, tmpl, ctype, explicit_targs,
- arglist, return_type, access_path,
- conversion_path, flags, strict)
- struct z_candidate **candidates;
- tree tmpl, ctype, explicit_targs, arglist, return_type;
- tree access_path;
- tree conversion_path;
- int flags;
- unification_kind_t strict;
+add_template_candidate (struct z_candidate **candidates, tree tmpl, tree ctype,
+ tree explicit_targs, tree arglist, tree return_type,
+ tree access_path, tree conversion_path, int flags,
+ unification_kind_t strict)
{
return
add_template_candidate_real (candidates, tmpl, ctype,
@@ -2425,12 +2138,9 @@ add_template_candidate (candidates, tmpl, ctype, explicit_targs,
static struct z_candidate *
-add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type,
- access_path, conversion_path)
- struct z_candidate **candidates;
- tree tmpl, obj, arglist, return_type;
- tree access_path;
- tree conversion_path;
+add_template_conv_candidate (struct z_candidate **candidates, tree tmpl,
+ tree obj, tree arglist, tree return_type,
+ tree access_path, tree conversion_path)
{
return
add_template_candidate_real (candidates, tmpl, NULL_TREE, NULL_TREE,
@@ -2438,47 +2148,55 @@ add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type,
conversion_path, 0, obj, DEDUCE_CONV);
}
+/* The CANDS are the set of candidates that were considered for
+ overload resolution. Return the set of viable candidates. If none
+ of the candidates were viable, set *ANY_VIABLE_P to true. STRICT_P
+ is true if a candidate should be considered viable only if it is
+ strictly viable. */
-static int
-any_viable (cands)
- struct z_candidate *cands;
-{
- for (; cands; cands = cands->next)
- if (pedantic ? cands->viable == 1 : cands->viable)
- return 1;
- return 0;
-}
-
-static int
-any_strictly_viable (cands)
- struct z_candidate *cands;
+static struct z_candidate*
+splice_viable (struct z_candidate *cands,
+ bool strict_p,
+ bool *any_viable_p)
{
- for (; cands; cands = cands->next)
- if (cands->viable == 1)
- return 1;
- return 0;
-}
+ struct z_candidate *viable;
+ struct z_candidate **last_viable;
+ struct z_candidate **cand;
-static struct z_candidate *
-splice_viable (cands)
- struct z_candidate *cands;
-{
- struct z_candidate **p = &cands;
+ viable = NULL;
+ last_viable = &viable;
+ *any_viable_p = false;
- for (; *p; )
+ cand = &cands;
+ while (*cand)
{
- if (pedantic ? (*p)->viable == 1 : (*p)->viable)
- p = &((*p)->next);
+ struct z_candidate *c = *cand;
+ if (strict_p ? c->viable == 1 : c->viable)
+ {
+ *last_viable = c;
+ *cand = c->next;
+ c->next = NULL;
+ last_viable = &c->next;
+ *any_viable_p = true;
+ }
else
- *p = (*p)->next;
+ cand = &c->next;
}
- return cands;
+ return viable ? viable : cands;
+}
+
+static bool
+any_strictly_viable (struct z_candidate *cands)
+{
+ for (; cands; cands = cands->next)
+ if (cands->viable == 1)
+ return true;
+ return false;
}
static tree
-build_this (obj)
- tree obj;
+build_this (tree obj)
{
/* Fix this to work on non-lvalues. */
return build_unary_op (ADDR_EXPR, obj, 0);
@@ -2489,9 +2207,7 @@ build_this (obj)
both are extern "C". */
static inline int
-equal_functions (fn1, fn2)
- tree fn1;
- tree fn2;
+equal_functions (tree fn1, tree fn2)
{
if (DECL_LOCAL_FUNCTION_P (fn1) || DECL_LOCAL_FUNCTION_P (fn2)
|| DECL_EXTERN_C_FUNCTION_P (fn1))
@@ -2499,6 +2215,39 @@ equal_functions (fn1, fn2)
return fn1 == fn2;
}
+/* Print information about one overload candidate CANDIDATE. MSGSTR
+ is the text to print before the candidate itself.
+
+ NOTE: Unlike most diagnostic functions in GCC, MSGSTR is expected
+ to have been run through gettext by the caller. This wart makes
+ life simpler in print_z_candidates and for the translators. */
+
+static void
+print_z_candidate (const char *msgstr, struct z_candidate *candidate)
+{
+ if (TREE_CODE (candidate->fn) == IDENTIFIER_NODE)
+ {
+ if (TREE_VEC_LENGTH (candidate->convs) == 3)
+ inform ("%s %D(%T, %T, %T) <built-in>", msgstr, candidate->fn,
+ TREE_TYPE (TREE_VEC_ELT (candidate->convs, 0)),
+ TREE_TYPE (TREE_VEC_ELT (candidate->convs, 1)),
+ TREE_TYPE (TREE_VEC_ELT (candidate->convs, 2)));
+ else if (TREE_VEC_LENGTH (candidate->convs) == 2)
+ inform ("%s %D(%T, %T) <built-in>", msgstr, candidate->fn,
+ TREE_TYPE (TREE_VEC_ELT (candidate->convs, 0)),
+ TREE_TYPE (TREE_VEC_ELT (candidate->convs, 1)));
+ else
+ inform ("%s %D(%T) <built-in>", msgstr, candidate->fn,
+ TREE_TYPE (TREE_VEC_ELT (candidate->convs, 0)));
+ }
+ else if (TYPE_P (candidate->fn))
+ inform ("%s %T <conversion>", msgstr, candidate->fn);
+ else if (candidate->viable == -1)
+ inform ("%J%s %+#D <near match>", candidate->fn, msgstr, candidate->fn);
+ else
+ inform ("%J%s %+#D", candidate->fn, msgstr, candidate->fn);
+}
+
static void
print_z_candidates (struct z_candidate *candidates)
{
@@ -2528,30 +2277,27 @@ print_z_candidates (struct z_candidate *candidates)
}
}
- str = "candidates are:";
- for (; candidates; candidates = candidates->next)
+ if (!candidates)
+ return;
+
+ str = _("candidates are:");
+ print_z_candidate (str, candidates);
+ if (candidates->next)
{
- if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE)
+ /* Indent successive candidates by the width of the translation
+ of the above string. */
+ size_t len = gcc_gettext_width (str) + 1;
+ char *spaces = alloca (len);
+ memset (spaces, ' ', len-1);
+ spaces[len - 1] = '\0';
+
+ candidates = candidates->next;
+ do
{
- if (TREE_VEC_LENGTH (candidates->convs) == 3)
- error ("%s %D(%T, %T, %T) <built-in>", str, candidates->fn,
- TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)),
- TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)),
- TREE_TYPE (TREE_VEC_ELT (candidates->convs, 2)));
- else if (TREE_VEC_LENGTH (candidates->convs) == 2)
- error ("%s %D(%T, %T) <built-in>", str, candidates->fn,
- TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)),
- TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)));
- else
- error ("%s %D(%T) <built-in>", str, candidates->fn,
- TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)));
+ print_z_candidate (spaces, candidates);
+ candidates = candidates->next;
}
- else if (TYPE_P (candidates->fn))
- error ("%s %T <conversion>", str, candidates->fn);
- else
- cp_error_at ("%s %+#D%s", str, candidates->fn,
- candidates->viable == -1 ? " <near match>" : "");
- str = " ";
+ while (candidates);
}
}
@@ -2591,14 +2337,13 @@ merge_conversion_sequences (tree user_seq, tree std_seq)
per [dcl.init.ref], so we ignore temporary bindings. */
static struct z_candidate *
-build_user_type_conversion_1 (totype, expr, flags)
- tree totype, expr;
- int flags;
+build_user_type_conversion_1 (tree totype, tree expr, int flags)
{
struct z_candidate *candidates, *cand;
tree fromtype = TREE_TYPE (expr);
tree ctors = NULL_TREE, convs = NULL_TREE;
tree args = NULL_TREE;
+ bool any_viable_p;
/* We represent conversion within a hierarchy using RVALUE_CONV and
BASE_CONV, as specified by [over.best.ics]; these become plain
@@ -2684,7 +2429,8 @@ build_user_type_conversion_1 (totype, expr, flags)
So we pass fromtype as CTYPE to add_*_candidate. */
if (TREE_CODE (fn) == TEMPLATE_DECL)
- cand = add_template_candidate (&candidates, fn, fromtype, NULL_TREE,
+ cand = add_template_candidate (&candidates, fn, fromtype,
+ NULL_TREE,
args, totype,
TYPE_BINFO (fromtype),
conversion_path,
@@ -2699,26 +2445,25 @@ build_user_type_conversion_1 (totype, expr, flags)
if (cand)
{
- tree ics = implicit_conversion
- (totype, TREE_TYPE (TREE_TYPE (cand->fn)),
- 0, convflags);
+ tree ics = implicit_conversion (totype,
+ TREE_TYPE (TREE_TYPE (cand->fn)),
+ 0, convflags);
cand->second_conv = ics;
if (ics == NULL_TREE)
cand->viable = 0;
- else if (cand->viable == 1 && ICS_BAD_FLAG (ics))
+ else if (candidates->viable == 1 && ICS_BAD_FLAG (ics))
cand->viable = -1;
}
}
}
- if (! any_viable (candidates))
+ candidates = splice_viable (candidates, pedantic, &any_viable_p);
+ if (!any_viable_p)
return 0;
- candidates = splice_viable (candidates);
cand = tourney (candidates);
-
if (cand == 0)
{
if (flags & LOOKUP_COMPLAIN)
@@ -2759,9 +2504,7 @@ build_user_type_conversion_1 (totype, expr, flags)
}
tree
-build_user_type_conversion (totype, expr, flags)
- tree totype, expr;
- int flags;
+build_user_type_conversion (tree totype, tree expr, int flags)
{
struct z_candidate *cand
= build_user_type_conversion_1 (totype, expr, flags);
@@ -2775,83 +2518,10 @@ build_user_type_conversion (totype, expr, flags)
return NULL_TREE;
}
-/* Find the possibly overloaded set of functions corresponding to a
- call of the form SCOPE::NAME (...). NAME might be a
- TEMPLATE_ID_EXPR, OVERLOAD, _DECL, IDENTIFIER_NODE or LOOKUP_EXPR. */
-
-tree
-resolve_scoped_fn_name (tree scope, tree name)
-{
- tree fn;
- tree template_args = NULL_TREE;
- bool is_template_id = TREE_CODE (name) == TEMPLATE_ID_EXPR;
-
- if (is_template_id)
- {
- template_args = TREE_OPERAND (name, 1);
- name = TREE_OPERAND (name, 0);
- }
- if (TREE_CODE (name) == OVERLOAD)
- name = DECL_NAME (get_first_fn (name));
- else if (TREE_CODE (name) == LOOKUP_EXPR)
- name = TREE_OPERAND (name, 0);
-
- if (TREE_CODE (scope) == NAMESPACE_DECL)
- fn = lookup_namespace_name (scope, name);
- else if (!CLASS_TYPE_P (scope))
- {
- error ("`%T' is not a class type", scope);
- return error_mark_node;
- }
- else
- {
- if (!TYPE_BEING_DEFINED (scope)
- && !COMPLETE_TYPE_P (complete_type (scope)))
- {
- error ("incomplete type '%T' cannot be used to name a scope",
- scope);
- return error_mark_node;
- }
-
- if (BASELINK_P (name))
- fn = name;
- else
- fn = lookup_member (scope, name, /*protect=*/1, /*prefer_type=*/0);
- if (fn && current_class_type)
- fn = (adjust_result_of_qualified_name_lookup
- (fn, scope, current_class_type));
-
- /* It might be the name of a function pointer member. */
- if (fn && TREE_CODE (fn) == FIELD_DECL)
- fn = resolve_offset_ref (build_offset_ref (scope, fn));
- }
-
- if (!fn)
- {
- error ("'%D' has no member named '%E'", scope, name);
- return error_mark_node;
- }
- if (is_template_id)
- {
- tree fns = fn;
-
- if (BASELINK_P (fn))
- fns = BASELINK_FUNCTIONS (fns);
- fns = build_nt (TEMPLATE_ID_EXPR, fns, template_args);
- if (BASELINK_P (fn))
- BASELINK_FUNCTIONS (fn) = fns;
- else
- fn = fns;
- }
-
- return fn;
-}
-
/* Do any initial processing on the arguments to a function call. */
static tree
-resolve_args (args)
- tree args;
+resolve_args (tree args)
{
tree t;
for (t = args; t; t = TREE_CHAIN (t))
@@ -2865,25 +2535,37 @@ resolve_args (args)
error ("invalid use of void expression");
return error_mark_node;
}
- else if (TREE_CODE (arg) == OFFSET_REF)
- arg = resolve_offset_ref (arg);
arg = convert_from_reference (arg);
TREE_VALUE (t) = arg;
}
return args;
}
-/* Return an expression for a call to FN (a namespace-scope function)
- with the ARGS. */
-
-tree
-build_new_function_call (fn, args)
- tree fn, args;
+/* Perform overload resolution on FN, which is called with the ARGS.
+
+ Return the candidate function selected by overload resolution, or
+ NULL if the event that overload resolution failed. In the case
+ that overload resolution fails, *CANDIDATES will be the set of
+ candidates considered, and ANY_VIABLE_P will be set to true or
+ false to indicate whether or not any of the candidates were
+ viable.
+
+ The ARGS should already have gone through RESOLVE_ARGS before this
+ function is called. */
+
+static struct z_candidate *
+perform_overload_resolution (tree fn,
+ tree args,
+ struct z_candidate **candidates,
+ bool *any_viable_p)
{
- struct z_candidate *candidates = 0, *cand;
+ struct z_candidate *cand;
tree explicit_targs = NULL_TREE;
int template_only = 0;
+ *candidates = NULL;
+ *any_viable_p = true;
+
/* Check FN and ARGS. */
my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL
|| TREE_CODE (fn) == TEMPLATE_DECL
@@ -2900,69 +2582,151 @@ build_new_function_call (fn, args)
template_only = 1;
}
- if (really_overloaded_fn (fn)
- || TREE_CODE (fn) == TEMPLATE_DECL)
- {
- tree t1;
+ /* Add the various candidate functions. */
+ add_candidates (fn, args, explicit_targs, template_only,
+ /*conversion_path=*/NULL_TREE,
+ /*access_path=*/NULL_TREE,
+ LOOKUP_NORMAL,
+ candidates);
- args = resolve_args (args);
+ *candidates = splice_viable (*candidates, pedantic, any_viable_p);
+ if (!*any_viable_p)
+ return NULL;
- if (args == error_mark_node)
- return error_mark_node;
+ cand = tourney (*candidates);
+ return cand;
+}
- for (t1 = fn; t1; t1 = OVL_NEXT (t1))
- {
- tree t = OVL_CURRENT (t1);
-
- if (TREE_CODE (t) == TEMPLATE_DECL)
- add_template_candidate
- (&candidates, t, NULL_TREE, explicit_targs, args,
- NULL_TREE,
- /*access_path=*/NULL_TREE, /*conversion_path=*/NULL_TREE,
- LOOKUP_NORMAL, DEDUCE_CALL);
- else if (! template_only)
- add_function_candidate
- (&candidates, t, NULL_TREE, args, /*access_path=*/NULL_TREE,
- /*conversion_path=*/NULL_TREE, LOOKUP_NORMAL);
- }
+/* Return an expression for a call to FN (a namespace-scope function,
+ or a static member function) with the ARGS. */
+
+tree
+build_new_function_call (tree fn, tree args)
+{
+ struct z_candidate *candidates, *cand;
+ bool any_viable_p;
- if (! any_viable (candidates))
- {
- if (candidates && ! candidates->next)
- return build_function_call (candidates->fn, args);
- error ("no matching function for call to `%D(%A)'",
- DECL_NAME (OVL_CURRENT (fn)), args);
- if (candidates)
- print_z_candidates (candidates);
- return error_mark_node;
- }
- candidates = splice_viable (candidates);
- cand = tourney (candidates);
+ args = resolve_args (args);
+ if (args == error_mark_node)
+ return error_mark_node;
- if (cand == 0)
- {
- error ("call of overloaded `%D(%A)' is ambiguous",
- DECL_NAME (OVL_FUNCTION (fn)), args);
- print_z_candidates (candidates);
- return error_mark_node;
- }
+ cand = perform_overload_resolution (fn, args, &candidates, &any_viable_p);
- return build_over_call (cand, args, LOOKUP_NORMAL);
+ if (!cand)
+ {
+ if (!any_viable_p && candidates && ! candidates->next)
+ return build_function_call (candidates->fn, args);
+ if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
+ fn = TREE_OPERAND (fn, 0);
+ if (!any_viable_p)
+ error ("no matching function for call to `%D(%A)'",
+ DECL_NAME (OVL_CURRENT (fn)), args);
+ else
+ error ("call of overloaded `%D(%A)' is ambiguous",
+ DECL_NAME (OVL_CURRENT (fn)), args);
+ if (candidates)
+ print_z_candidates (candidates);
+ return error_mark_node;
}
- /* This is not really overloaded. */
- fn = OVL_CURRENT (fn);
+ return build_over_call (cand, LOOKUP_NORMAL);
+}
+
+/* Build a call to a global operator new. FNNAME is the name of the
+ operator (either "operator new" or "operator new[]") and ARGS are
+ the arguments provided. *SIZE points to the total number of bytes
+ required by the allocation, and is updated if that is changed here.
+ *COOKIE_SIZE is non-NULL if a cookie should be used. If this
+ function determines that no cookie should be used, after all,
+ *COOKIE_SIZE is set to NULL_TREE. */
+
+tree
+build_operator_new_call (tree fnname, tree args, tree *size, tree *cookie_size)
+{
+ tree fns;
+ struct z_candidate *candidates;
+ struct z_candidate *cand;
+ bool any_viable_p;
+
+ args = tree_cons (NULL_TREE, *size, args);
+ args = resolve_args (args);
+ if (args == error_mark_node)
+ return args;
+
+ fns = lookup_function_nonclass (fnname, args);
+
+ /* Figure out what function is being called. */
+ cand = perform_overload_resolution (fns, args, &candidates, &any_viable_p);
+
+ /* If no suitable function could be found, issue an error message
+ and give up. */
+ if (!cand)
+ {
+ if (!any_viable_p)
+ error ("no matching function for call to `%D(%A)'",
+ DECL_NAME (OVL_CURRENT (fns)), args);
+ else
+ error ("call of overloaded `%D(%A)' is ambiguous",
+ DECL_NAME (OVL_CURRENT (fns)), args);
+ if (candidates)
+ print_z_candidates (candidates);
+ return error_mark_node;
+ }
- return build_function_call (fn, args);
+ /* If a cookie is required, add some extra space. Whether
+ or not a cookie is required cannot be determined until
+ after we know which function was called. */
+ if (*cookie_size)
+ {
+ bool use_cookie = true;
+ if (!abi_version_at_least (2))
+ {
+ tree placement = TREE_CHAIN (args);
+ /* In G++ 3.2, the check was implemented incorrectly; it
+ looked at the placement expression, rather than the
+ type of the function. */
+ if (placement && !TREE_CHAIN (placement)
+ && same_type_p (TREE_TYPE (TREE_VALUE (placement)),
+ ptr_type_node))
+ use_cookie = false;
+ }
+ else
+ {
+ tree arg_types;
+
+ arg_types = TYPE_ARG_TYPES (TREE_TYPE (cand->fn));
+ /* Skip the size_t parameter. */
+ arg_types = TREE_CHAIN (arg_types);
+ /* Check the remaining parameters (if any). */
+ if (arg_types
+ && TREE_CHAIN (arg_types) == void_list_node
+ && same_type_p (TREE_VALUE (arg_types),
+ ptr_type_node))
+ use_cookie = false;
+ }
+ /* If we need a cookie, adjust the number of bytes allocated. */
+ if (use_cookie)
+ {
+ /* Update the total size. */
+ *size = size_binop (PLUS_EXPR, *size, *cookie_size);
+ /* Update the argument list to reflect the adjusted size. */
+ TREE_VALUE (args) = *size;
+ }
+ else
+ *cookie_size = NULL_TREE;
+ }
+
+ /* Build the CALL_EXPR. */
+ return build_over_call (cand, LOOKUP_NORMAL);
}
static tree
-build_object_call (obj, args)
- tree obj, args;
+build_object_call (tree obj, tree args)
{
struct z_candidate *candidates = 0, *cand;
tree fns, convs, mem_args = NULL_TREE;
tree type = TREE_TYPE (obj);
+ bool any_viable_p;
if (TYPE_PTRMEMFUNC_P (type))
{
@@ -3031,16 +2795,15 @@ build_object_call (obj, args)
}
}
- if (! any_viable (candidates))
+ candidates = splice_viable (candidates, pedantic, &any_viable_p);
+ if (!any_viable_p)
{
error ("no match for call to `(%T) (%A)'", TREE_TYPE (obj), args);
print_z_candidates (candidates);
return error_mark_node;
}
- candidates = splice_viable (candidates);
cand = tourney (candidates);
-
if (cand == 0)
{
error ("call of `(%T) (%A)' is ambiguous", TREE_TYPE (obj), args);
@@ -3053,7 +2816,7 @@ build_object_call (obj, args)
DECL_NAME here. */
if (TREE_CODE (cand->fn) == FUNCTION_DECL
&& DECL_OVERLOADED_OPERATOR_P (cand->fn) == CALL_EXPR)
- return build_over_call (cand, mem_args, LOOKUP_NORMAL);
+ return build_over_call (cand, LOOKUP_NORMAL);
obj = convert_like_with_context
(TREE_VEC_ELT (cand->convs, 0), obj, cand->fn, -1);
@@ -3063,10 +2826,8 @@ build_object_call (obj, args)
}
static void
-op_error (code, code2, arg1, arg2, arg3, problem)
- enum tree_code code, code2;
- tree arg1, arg2, arg3;
- const char *problem;
+op_error (enum tree_code code, enum tree_code code2,
+ tree arg1, tree arg2, tree arg3, const char *problem)
{
const char *opname;
@@ -3090,6 +2851,11 @@ op_error (code, code2, arg1, arg2, arg3, problem)
case ARRAY_REF:
error ("%s for 'operator[]' in '%E[%E]'", problem, arg1, arg2);
break;
+
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ error ("%s for '%s' in '%s %E'", problem, opname, opname, arg1);
+ break;
default:
if (arg2)
@@ -3106,9 +2872,7 @@ op_error (code, code2, arg1, arg2, arg3, problem)
convert E1 to E2 in [expr.cond]. */
static tree
-conditional_conversion (e1, e2)
- tree e1;
- tree e2;
+conditional_conversion (tree e1, tree e2)
{
tree t1 = non_reference (TREE_TYPE (e1));
tree t2 = non_reference (TREE_TYPE (e2));
@@ -3150,6 +2914,8 @@ conditional_conversion (e1, e2)
if (!same_type_p (TYPE_MAIN_VARIANT (t1),
TYPE_MAIN_VARIANT (t2)))
conv = build_conv (BASE_CONV, t2, conv);
+ else
+ conv = build_conv (RVALUE_CONV, t2, conv);
return conv;
}
else
@@ -3168,16 +2934,13 @@ conditional_conversion (e1, e2)
arguments to the conditional expression. */
tree
-build_conditional_expr (arg1, arg2, arg3)
- tree arg1;
- tree arg2;
- tree arg3;
+build_conditional_expr (tree arg1, tree arg2, tree arg3)
{
tree arg2_type;
tree arg3_type;
tree result;
tree result_type = NULL_TREE;
- int lvalue_p = 1;
+ bool lvalue_p = true;
struct z_candidate *candidates = 0;
struct z_candidate *cand;
@@ -3189,23 +2952,25 @@ build_conditional_expr (arg1, arg2, arg3)
{
if (pedantic)
pedwarn ("ISO C++ forbids omitting the middle term of a ?: expression");
- arg1 = arg2 = save_expr (arg1);
+
+ /* Make sure that lvalues remain lvalues. See g++.oliva/ext1.C. */
+ if (real_lvalue_p (arg1))
+ arg2 = arg1 = stabilize_reference (arg1);
+ else
+ arg2 = arg1 = save_expr (arg1);
}
/* [expr.cond]
The first expr ession is implicitly converted to bool (clause
_conv_). */
- arg1 = cp_convert (boolean_type_node, arg1);
+ arg1 = perform_implicit_conversion (boolean_type_node, arg1);
/* If something has already gone wrong, just pass that fact up the
tree. */
- if (arg1 == error_mark_node
- || arg2 == error_mark_node
- || arg3 == error_mark_node
- || TREE_TYPE (arg1) == error_mark_node
- || TREE_TYPE (arg2) == error_mark_node
- || TREE_TYPE (arg3) == error_mark_node)
+ if (error_operand_p (arg1)
+ || error_operand_p (arg2)
+ || error_operand_p (arg3))
return error_mark_node;
/* [expr.cond]
@@ -3238,11 +3003,27 @@ build_conditional_expr (arg1, arg2, arg3)
type of the other and is an rvalue.
--Both the second and the third operands have type void; the
- result is of type void and is an rvalue. */
- if ((TREE_CODE (arg2) == THROW_EXPR)
- ^ (TREE_CODE (arg3) == THROW_EXPR))
- result_type = ((TREE_CODE (arg2) == THROW_EXPR)
- ? arg3_type : arg2_type);
+ result is of type void and is an rvalue.
+
+ We must avoid calling force_rvalue for expressions of type
+ "void" because it will complain that their value is being
+ used. */
+ if (TREE_CODE (arg2) == THROW_EXPR
+ && TREE_CODE (arg3) != THROW_EXPR)
+ {
+ if (!VOID_TYPE_P (arg3_type))
+ arg3 = force_rvalue (arg3);
+ arg3_type = TREE_TYPE (arg3);
+ result_type = arg3_type;
+ }
+ else if (TREE_CODE (arg2) != THROW_EXPR
+ && TREE_CODE (arg3) == THROW_EXPR)
+ {
+ if (!VOID_TYPE_P (arg2_type))
+ arg2 = force_rvalue (arg2);
+ arg2_type = TREE_TYPE (arg2);
+ result_type = arg2_type;
+ }
else if (VOID_TYPE_P (arg2_type) && VOID_TYPE_P (arg3_type))
result_type = void_type_node;
else
@@ -3252,7 +3033,7 @@ build_conditional_expr (arg1, arg2, arg3)
return error_mark_node;
}
- lvalue_p = 0;
+ lvalue_p = false;
goto valid_operands;
}
/* [expr.cond]
@@ -3287,33 +3068,46 @@ build_conditional_expr (arg1, arg2, arg3)
{
arg2 = convert_like (conv2, arg2);
arg2 = convert_from_reference (arg2);
- /* That may not quite have done the trick. If the two types
- are cv-qualified variants of one another, we will have
- just used an IDENTITY_CONV. (There's no conversion from
- an lvalue of one class type to an lvalue of another type,
- even a cv-qualified variant, and we don't want to lose
- lvalue-ness here.) So, we manually add a NOP_EXPR here
- if necessary. */
- if (!same_type_p (TREE_TYPE (arg2), arg3_type))
- arg2 = build1 (NOP_EXPR, arg3_type, arg2);
arg2_type = TREE_TYPE (arg2);
}
else if (conv3 && !ICS_BAD_FLAG (conv3))
{
arg3 = convert_like (conv3, arg3);
arg3 = convert_from_reference (arg3);
- if (!same_type_p (TREE_TYPE (arg3), arg2_type))
- arg3 = build1 (NOP_EXPR, arg2_type, arg3);
arg3_type = TREE_TYPE (arg3);
}
+
+ /* If, after the conversion, both operands have class type,
+ treat the cv-qualification of both operands as if it were the
+ union of the cv-qualification of the operands.
+
+ The standard is not clear about what to do in this
+ circumstance. For example, if the first operand has type
+ "const X" and the second operand has a user-defined
+ conversion to "volatile X", what is the type of the second
+ operand after this step? Making it be "const X" (matching
+ the first operand) seems wrong, as that discards the
+ qualification without actuall performing a copy. Leaving it
+ as "volatile X" seems wrong as that will result in the
+ conditional expression failing altogether, even though,
+ according to this step, the one operand could be converted to
+ the type of the other. */
+ if ((conv2 || conv3)
+ && CLASS_TYPE_P (arg2_type)
+ && TYPE_QUALS (arg2_type) != TYPE_QUALS (arg3_type))
+ arg2_type = arg3_type =
+ cp_build_qualified_type (arg2_type,
+ TYPE_QUALS (arg2_type)
+ | TYPE_QUALS (arg3_type));
}
/* [expr.cond]
If the second and third operands are lvalues and have the same
type, the result is of that type and is an lvalue. */
- if (real_lvalue_p (arg2) && real_lvalue_p (arg3) &&
- same_type_p (arg2_type, arg3_type))
+ if (real_lvalue_p (arg2)
+ && real_lvalue_p (arg3)
+ && same_type_p (arg2_type, arg3_type))
{
result_type = arg2_type;
goto valid_operands;
@@ -3326,12 +3120,13 @@ build_conditional_expr (arg1, arg2, arg3)
cv-qualified) class type, overload resolution is used to
determine the conversions (if any) to be applied to the operands
(_over.match.oper_, _over.built_). */
- lvalue_p = 0;
+ lvalue_p = false;
if (!same_type_p (arg2_type, arg3_type)
&& (CLASS_TYPE_P (arg2_type) || CLASS_TYPE_P (arg3_type)))
{
tree args[3];
tree conv;
+ bool any_viable_p;
/* Rearrange the arguments so that add_builtin_candidate only has
to know about two args. In build_builtin_candidates, the
@@ -3350,13 +3145,13 @@ build_conditional_expr (arg1, arg2, arg3)
If the overload resolution fails, the program is
ill-formed. */
- if (!any_viable (candidates))
+ candidates = splice_viable (candidates, pedantic, &any_viable_p);
+ if (!any_viable_p)
{
op_error (COND_EXPR, NOP_EXPR, arg1, arg2, arg3, "no match");
print_z_candidates (candidates);
return error_mark_node;
}
- candidates = splice_viable (candidates);
cand = tourney (candidates);
if (!cand)
{
@@ -3387,16 +3182,15 @@ build_conditional_expr (arg1, arg2, arg3)
We need to force the lvalue-to-rvalue conversion here for class types,
so we get TARGET_EXPRs; trying to deal with a COND_EXPR of class rvalues
that isn't wrapped with a TARGET_EXPR plays havoc with exception
- regions.
-
- We use ocp_convert rather than build_user_type_conversion because the
- latter returns NULL_TREE on failure, while the former gives an error. */
+ regions. */
arg2 = force_rvalue (arg2);
- arg2_type = TREE_TYPE (arg2);
+ if (!CLASS_TYPE_P (arg2_type))
+ arg2_type = TREE_TYPE (arg2);
arg3 = force_rvalue (arg3);
- arg3_type = TREE_TYPE (arg3);
+ if (!CLASS_TYPE_P (arg2_type))
+ arg3_type = TREE_TYPE (arg3);
if (arg2 == error_mark_node || arg3 == error_mark_node)
return error_mark_node;
@@ -3454,18 +3248,17 @@ build_conditional_expr (arg1, arg2, arg3)
cv-qualification of either the second or the third operand.
The result is of the common type. */
else if ((null_ptr_cst_p (arg2)
- && (TYPE_PTR_P (arg3_type) || TYPE_PTRMEM_P (arg3_type)
- || TYPE_PTRMEMFUNC_P (arg3_type)))
+ && (TYPE_PTR_P (arg3_type) || TYPE_PTR_TO_MEMBER_P (arg3_type)))
|| (null_ptr_cst_p (arg3)
- && (TYPE_PTR_P (arg2_type) || TYPE_PTRMEM_P (arg2_type)
- || TYPE_PTRMEMFUNC_P (arg2_type)))
+ && (TYPE_PTR_P (arg2_type) || TYPE_PTR_TO_MEMBER_P (arg2_type)))
|| (TYPE_PTR_P (arg2_type) && TYPE_PTR_P (arg3_type))
|| (TYPE_PTRMEM_P (arg2_type) && TYPE_PTRMEM_P (arg3_type))
- || (TYPE_PTRMEMFUNC_P (arg2_type)
- && TYPE_PTRMEMFUNC_P (arg3_type)))
+ || (TYPE_PTRMEMFUNC_P (arg2_type) && TYPE_PTRMEMFUNC_P (arg3_type)))
{
result_type = composite_pointer_type (arg2_type, arg3_type, arg2,
arg3, "conditional expression");
+ if (result_type == error_mark_node)
+ return error_mark_node;
arg2 = perform_implicit_conversion (result_type, arg2);
arg3 = perform_implicit_conversion (result_type, arg3);
}
@@ -3478,45 +3271,125 @@ build_conditional_expr (arg1, arg2, arg3)
valid_operands:
result = fold (build (COND_EXPR, result_type, arg1, arg2, arg3));
+ /* We can't use result_type below, as fold might have returned a
+ throw_expr. */
+
/* Expand both sides into the same slot, hopefully the target of the
?: expression. We used to check for TARGET_EXPRs here, but now we
sometimes wrap them in NOP_EXPRs so the test would fail. */
- if (!lvalue_p && IS_AGGR_TYPE (result_type))
- result = build_target_expr_with_type (result, result_type);
+ if (!lvalue_p && CLASS_TYPE_P (TREE_TYPE (result)))
+ result = get_target_expr (result);
/* If this expression is an rvalue, but might be mistaken for an
lvalue, we must add a NON_LVALUE_EXPR. */
if (!lvalue_p && real_lvalue_p (result))
- result = build1 (NON_LVALUE_EXPR, result_type, result);
+ result = build1 (NON_LVALUE_EXPR, TREE_TYPE (result), result);
return result;
}
+/* OPERAND is an operand to an expression. Perform necessary steps
+ required before using it. If OPERAND is NULL_TREE, NULL_TREE is
+ returned. */
+
+static tree
+prep_operand (tree operand)
+{
+ if (operand)
+ {
+ operand = convert_from_reference (operand);
+ if (CLASS_TYPE_P (TREE_TYPE (operand))
+ && CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (operand)))
+ /* Make sure the template type is instantiated now. */
+ instantiate_class_template (TYPE_MAIN_VARIANT (TREE_TYPE (operand)));
+ }
+
+ return operand;
+}
+
+/* Add each of the viable functions in FNS (a FUNCTION_DECL or
+ OVERLOAD) to the CANDIDATES, returning an updated list of
+ CANDIDATES. The ARGS are the arguments provided to the call,
+ without any implicit object parameter. The EXPLICIT_TARGS are
+ explicit template arguments provided. TEMPLATE_ONLY is true if
+ only template functions should be considered. CONVERSION_PATH,
+ ACCESS_PATH, and FLAGS are as for add_function_candidate. */
+
+static void
+add_candidates (tree fns, tree args,
+ tree explicit_targs, bool template_only,
+ tree conversion_path, tree access_path,
+ int flags,
+ struct z_candidate **candidates)
+{
+ tree ctype;
+ tree non_static_args;
+
+ ctype = conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE;
+ /* Delay creating the implicit this parameter until it is needed. */
+ non_static_args = NULL_TREE;
+
+ while (fns)
+ {
+ tree fn;
+ tree fn_args;
+
+ fn = OVL_CURRENT (fns);
+ /* Figure out which set of arguments to use. */
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
+ {
+ /* If this function is a non-static member, prepend the implicit
+ object parameter. */
+ if (!non_static_args)
+ non_static_args = tree_cons (NULL_TREE,
+ build_this (TREE_VALUE (args)),
+ TREE_CHAIN (args));
+ fn_args = non_static_args;
+ }
+ else
+ /* Otherwise, just use the list of arguments provided. */
+ fn_args = args;
+
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ add_template_candidate (candidates,
+ fn,
+ ctype,
+ explicit_targs,
+ fn_args,
+ NULL_TREE,
+ access_path,
+ conversion_path,
+ flags,
+ DEDUCE_CALL);
+ else if (!template_only)
+ add_function_candidate (candidates,
+ fn,
+ ctype,
+ fn_args,
+ access_path,
+ conversion_path,
+ flags);
+ fns = OVL_NEXT (fns);
+ }
+}
+
tree
-build_new_op (code, flags, arg1, arg2, arg3)
- enum tree_code code;
- int flags;
- tree arg1, arg2, arg3;
+build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
+ bool *overloaded_p)
{
struct z_candidate *candidates = 0, *cand;
- tree fns, mem_arglist = NULL_TREE, arglist, fnname;
+ tree arglist, fnname;
+ tree args[3];
enum tree_code code2 = NOP_EXPR;
tree conv;
- bool viable_candidates;
+ bool strict_p;
+ bool any_viable_p;
- if (arg1 == error_mark_node
- || arg2 == error_mark_node
- || arg3 == error_mark_node)
+ if (error_operand_p (arg1)
+ || error_operand_p (arg2)
+ || error_operand_p (arg3))
return error_mark_node;
- /* This can happen if a template takes all non-type parameters, e.g.
- undeclared_template<1, 5, 72>a; */
- if (code == LT_EXPR && TREE_CODE (arg1) == TEMPLATE_DECL)
- {
- error ("`%D' must be declared before use", arg1);
- return error_mark_node;
- }
-
if (code == MODIFY_EXPR)
{
code2 = TREE_CODE (arg3);
@@ -3526,13 +3399,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
else
fnname = ansi_opname (code);
- if (TREE_CODE (arg1) == OFFSET_REF)
- arg1 = resolve_offset_ref (arg1);
- arg1 = convert_from_reference (arg1);
- if (CLASS_TYPE_P (TREE_TYPE (arg1))
- && CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (arg1)))
- /* Make sure the template type is instantiated now. */
- instantiate_class_template (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)));
+ arg1 = prep_operand (arg1);
switch (code)
{
@@ -3550,24 +3417,8 @@ build_new_op (code, flags, arg1, arg2, arg3)
break;
}
- if (arg2)
- {
- if (TREE_CODE (arg2) == OFFSET_REF)
- arg2 = resolve_offset_ref (arg2);
- arg2 = convert_from_reference (arg2);
- if (CLASS_TYPE_P (TREE_TYPE (arg2))
- && CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (arg2)))
- instantiate_class_template (TYPE_MAIN_VARIANT (TREE_TYPE (arg2)));
- }
- if (arg3)
- {
- if (TREE_CODE (arg3) == OFFSET_REF)
- arg3 = resolve_offset_ref (arg3);
- arg3 = convert_from_reference (arg3);
- if (CLASS_TYPE_P (TREE_TYPE (arg3))
- && CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (arg3)))
- instantiate_class_template (TYPE_MAIN_VARIANT (TREE_TYPE (arg3)));
- }
+ arg2 = prep_operand (arg2);
+ arg3 = prep_operand (arg3);
if (code == COND_EXPR)
{
@@ -3592,89 +3443,45 @@ build_new_op (code, flags, arg1, arg2, arg3)
arglist = tree_cons (NULL_TREE, arg2, arglist);
arglist = tree_cons (NULL_TREE, arg1, arglist);
- fns = lookup_function_nonclass (fnname, arglist);
-
- if (fns && TREE_CODE (fns) == TREE_LIST)
- fns = TREE_VALUE (fns);
- for (; fns; fns = OVL_NEXT (fns))
+ /* Add namespace-scope operators to the list of functions to
+ consider. */
+ add_candidates (lookup_function_nonclass (fnname, arglist),
+ arglist, NULL_TREE, false, NULL_TREE, NULL_TREE,
+ flags, &candidates);
+ /* Add class-member operators to the candidate set. */
+ if (CLASS_TYPE_P (TREE_TYPE (arg1)))
{
- tree fn = OVL_CURRENT (fns);
- if (TREE_CODE (fn) == TEMPLATE_DECL)
- add_template_candidate (&candidates, fn, NULL_TREE, NULL_TREE,
- arglist, TREE_TYPE (fnname),
- /*access_path=*/NULL_TREE,
- /*conversion_path=*/NULL_TREE,
- flags, DEDUCE_CALL);
- else
- add_function_candidate (&candidates, fn, NULL_TREE,
- arglist,
- /*access_path=*/NULL_TREE,
- /*conversion_path=*/NULL_TREE,
- flags);
- }
+ tree fns;
- if (IS_AGGR_TYPE (TREE_TYPE (arg1)))
- {
fns = lookup_fnfields (TYPE_BINFO (TREE_TYPE (arg1)), fnname, 1);
if (fns == error_mark_node)
return fns;
+ if (fns)
+ add_candidates (BASELINK_FUNCTIONS (fns), arglist,
+ NULL_TREE, false,
+ BASELINK_BINFO (fns),
+ TYPE_BINFO (TREE_TYPE (arg1)),
+ flags, &candidates);
+ }
+
+ /* Rearrange the arguments for ?: so that add_builtin_candidate only has
+ to know about two args; a builtin candidate will always have a first
+ parameter of type bool. We'll handle that in
+ build_builtin_candidate. */
+ if (code == COND_EXPR)
+ {
+ args[0] = arg2;
+ args[1] = arg3;
+ args[2] = arg1;
}
else
- fns = NULL_TREE;
-
- if (fns)
{
- tree conversion_path = BASELINK_BINFO (fns);
-
- mem_arglist = tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist));
- for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
- {
- tree fn = OVL_CURRENT (fns);
- tree this_arglist;
- tree access_path = TYPE_BINFO (TREE_TYPE (arg1));
-
- if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
- this_arglist = mem_arglist;
- else
- this_arglist = arglist;
-
- if (TREE_CODE (fn) == TEMPLATE_DECL)
- /* A member template. */
- add_template_candidate (&candidates, fn,
- BINFO_TYPE (conversion_path),
- NULL_TREE,
- this_arglist, TREE_TYPE (fnname),
- access_path, conversion_path,
- flags, DEDUCE_CALL);
- else
- add_function_candidate
- (&candidates, fn, BINFO_TYPE (conversion_path), this_arglist,
- access_path, conversion_path, flags);
- }
+ args[0] = arg1;
+ args[1] = arg2;
+ args[2] = NULL_TREE;
}
- {
- tree args[3];
-
- /* Rearrange the arguments for ?: so that add_builtin_candidate only has
- to know about two args; a builtin candidate will always have a first
- parameter of type bool. We'll handle that in
- build_builtin_candidate. */
- if (code == COND_EXPR)
- {
- args[0] = arg2;
- args[1] = arg3;
- args[2] = arg1;
- }
- else
- {
- args[0] = arg1;
- args[1] = arg2;
- args[2] = NULL_TREE;
- }
-
- add_builtin_candidates (&candidates, code, code2, fnname, args, flags);
- }
+ add_builtin_candidates (&candidates, code, code2, fnname, args, flags);
switch (code)
{
@@ -3686,15 +3493,16 @@ build_new_op (code, flags, arg1, arg2, arg3)
operators. The built-in candidate set for COMPONENT_REF
would be empty too, but since there are no such built-in
operators, we accept non-strict matches for them. */
- viable_candidates = any_strictly_viable (candidates);
+ strict_p = true;
break;
default:
- viable_candidates = any_viable (candidates);
+ strict_p = pedantic;
break;
}
- if (! viable_candidates)
+ candidates = splice_viable (candidates, strict_p, &any_viable_p);
+ if (!any_viable_p)
{
switch (code)
{
@@ -3710,7 +3518,8 @@ build_new_op (code, flags, arg1, arg2, arg3)
code = PREINCREMENT_EXPR;
else
code = PREDECREMENT_EXPR;
- return build_new_op (code, flags, arg1, NULL_TREE, NULL_TREE);
+ return build_new_op (code, flags, arg1, NULL_TREE, NULL_TREE,
+ overloaded_p);
/* The caller will deal with these. */
case ADDR_EXPR:
@@ -3728,9 +3537,8 @@ build_new_op (code, flags, arg1, arg2, arg3)
}
return error_mark_node;
}
- candidates = splice_viable (candidates);
- cand = tourney (candidates);
+ cand = tourney (candidates);
if (cand == 0)
{
if (flags & LOOKUP_COMPLAIN)
@@ -3743,7 +3551,9 @@ build_new_op (code, flags, arg1, arg2, arg3)
if (TREE_CODE (cand->fn) == FUNCTION_DECL)
{
- extern int warn_synth;
+ if (overloaded_p)
+ *overloaded_p = true;
+
if (warn_synth
&& fnname == ansi_assopname (NOP_EXPR)
&& DECL_ARTIFICIAL (cand->fn)
@@ -3758,11 +3568,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
: candidates->fn);
}
- return build_over_call
- (cand,
- TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
- ? mem_arglist : arglist,
- LOOKUP_NORMAL);
+ return build_over_call (cand, LOOKUP_NORMAL);
}
/* Check for comparison of different enum types. */
@@ -3887,21 +3693,17 @@ builtin:
PLACEMENT is the corresponding placement new call, or NULL_TREE. */
tree
-build_op_delete_call (code, addr, size, flags, placement)
- enum tree_code code;
- tree addr, size, placement;
- int flags;
+build_op_delete_call (enum tree_code code, tree addr, tree size,
+ int flags, tree placement)
{
tree fn = NULL_TREE;
- tree fns, fnname, fntype, argtypes, args, type;
+ tree fns, fnname, argtypes, args, type;
int pass;
if (addr == error_mark_node)
return error_mark_node;
- type = TREE_TYPE (TREE_TYPE (addr));
- while (TREE_CODE (type) == ARRAY_TYPE)
- type = TREE_TYPE (type);
+ type = strip_array_types (TREE_TYPE (TREE_TYPE (addr)));
fnname = ansi_opname (code);
@@ -3912,7 +3714,7 @@ build_op_delete_call (code, addr, size, flags, placement)
the lookup selects a placement deallocation function, the
program is ill-formed.
- Therefore, we ask lookup_fnfields to complain ambout ambiguity. */
+ Therefore, we ask lookup_fnfields to complain about ambiguity. */
{
fns = lookup_fnfields (TYPE_BINFO (type), fnname, 1);
if (fns == error_mark_node)
@@ -3931,10 +3733,6 @@ build_op_delete_call (code, addr, size, flags, placement)
/* Find the allocation function that is being called. */
call_expr = placement;
- /* Sometimes we have a COMPOUND_EXPR, rather than a simple
- CALL_EXPR. */
- while (TREE_CODE (call_expr) == COMPOUND_EXPR)
- call_expr = TREE_OPERAND (call_expr, 1);
/* Extract the function. */
alloc_fn = get_callee_fndecl (call_expr);
my_friendly_assert (alloc_fn != NULL_TREE, 20020327);
@@ -3954,21 +3752,11 @@ build_op_delete_call (code, addr, size, flags, placement)
addr = cp_convert (ptr_type_node, addr);
/* We make two tries at finding a matching `operator delete'. On
- the first pass, we look for an one-operator (or placement)
+ the first pass, we look for a one-operator (or placement)
operator delete. If we're not doing placement delete, then on
the second pass we look for a two-argument delete. */
for (pass = 0; pass < (placement ? 1 : 2); ++pass)
{
- if (pass == 0)
- argtypes = tree_cons (NULL_TREE, ptr_type_node, argtypes);
- else
- /* Normal delete; now try to find a match including the size
- argument. */
- argtypes = tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE, sizetype,
- void_list_node));
- fntype = build_function_type (void_type_node, argtypes);
-
/* Go through the `operator delete' functions looking for one
with a matching type. */
for (fn = BASELINK_P (fns) ? BASELINK_FUNCTIONS (fns) : fns;
@@ -3977,13 +3765,30 @@ build_op_delete_call (code, addr, size, flags, placement)
{
tree t;
- /* Exception specifications on the `delete' operator do not
- matter. */
- t = build_exception_variant (TREE_TYPE (OVL_CURRENT (fn)),
- NULL_TREE);
- /* We also don't compare attributes. We're really just
- trying to check the types of the first two parameters. */
- if (comptypes (t, fntype, COMPARE_NO_ATTRIBUTES))
+ /* The first argument must be "void *". */
+ t = TYPE_ARG_TYPES (TREE_TYPE (OVL_CURRENT (fn)));
+ if (!same_type_p (TREE_VALUE (t), ptr_type_node))
+ continue;
+ t = TREE_CHAIN (t);
+ /* On the first pass, check the rest of the arguments. */
+ if (pass == 0)
+ {
+ tree a = argtypes;
+ while (a && t)
+ {
+ if (!same_type_p (TREE_VALUE (a), TREE_VALUE (t)))
+ break;
+ a = TREE_CHAIN (a);
+ t = TREE_CHAIN (t);
+ }
+ if (!a && !t)
+ break;
+ }
+ /* On the second pass, the second argument must be
+ "size_t". */
+ else if (pass == 1
+ && same_type_p (TREE_VALUE (t), sizetype)
+ && TREE_CHAIN (t) == void_list_node)
break;
}
@@ -4002,7 +3807,7 @@ build_op_delete_call (code, addr, size, flags, placement)
/* If the FN is a member function, make sure that it is
accessible. */
if (DECL_CLASS_SCOPE_P (fn))
- enforce_access (type, fn);
+ perform_or_defer_access_check (TYPE_BINFO (type), fn);
if (pass == 0)
args = tree_cons (NULL_TREE, addr, args);
@@ -4010,7 +3815,15 @@ build_op_delete_call (code, addr, size, flags, placement)
args = tree_cons (NULL_TREE, addr,
build_tree_list (NULL_TREE, size));
- return build_function_call (fn, args);
+ if (placement)
+ {
+ /* The placement args might not be suitable for overload
+ resolution at this point, so build the call directly. */
+ mark_used (fn);
+ return build_cxx_call (fn, args, args);
+ }
+ else
+ return build_function_call (fn, args);
}
/* If we are doing placement delete we do nothing if we don't find a
@@ -4018,7 +3831,8 @@ build_op_delete_call (code, addr, size, flags, placement)
if (placement)
return NULL_TREE;
- error ("no suitable `operator delete' for `%T'", type);
+ error ("no suitable `operator %s' for `%T'",
+ operator_name_info[(int)code].name, type);
return error_mark_node;
}
@@ -4026,15 +3840,12 @@ build_op_delete_call (code, addr, size, flags, placement)
BASETYPE_PATH, give an error. The most derived class in
BASETYPE_PATH is the one used to qualify DECL. */
-int
-enforce_access (basetype_path, decl)
- tree basetype_path;
- tree decl;
+bool
+enforce_access (tree basetype_path, tree decl)
{
- int accessible;
-
- accessible = accessible_p (basetype_path, decl);
- if (!accessible)
+ my_friendly_assert (TREE_CODE (basetype_path) == TREE_VEC, 20030624);
+
+ if (!accessible_p (basetype_path, decl))
{
if (TREE_PRIVATE (decl))
cp_error_at ("`%+#D' is private", decl);
@@ -4043,11 +3854,53 @@ enforce_access (basetype_path, decl)
else
cp_error_at ("`%+#D' is inaccessible", decl);
error ("within this context");
- return 0;
+ return false;
}
- return 1;
+ return true;
+}
+
+/* Check that a callable constructor to initialize a temporary of
+ TYPE from an EXPR exists. */
+
+static void
+check_constructor_callable (tree type, tree expr)
+{
+ build_special_member_call (NULL_TREE,
+ complete_ctor_identifier,
+ build_tree_list (NULL_TREE, expr),
+ TYPE_BINFO (type),
+ LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING
+ | LOOKUP_CONSTRUCTOR_CALLABLE);
+}
+
+/* Initialize a temporary of type TYPE with EXPR. The FLAGS are a
+ bitwise or of LOOKUP_* values. If any errors are warnings are
+ generated, set *DIAGNOSTIC_FN to "error" or "warning",
+ respectively. If no diagnostics are generated, set *DIAGNOSTIC_FN
+ to NULL. */
+
+static tree
+build_temp (tree expr, tree type, int flags,
+ void (**diagnostic_fn)(const char *, ...))
+{
+ int savew, savee;
+
+ savew = warningcount, savee = errorcount;
+ expr = build_special_member_call (NULL_TREE,
+ complete_ctor_identifier,
+ build_tree_list (NULL_TREE, expr),
+ TYPE_BINFO (type),
+ flags);
+ if (warningcount > savew)
+ *diagnostic_fn = warning;
+ else if (errorcount > savee)
+ *diagnostic_fn = error;
+ else
+ *diagnostic_fn = NULL;
+ return expr;
}
+
/* Perform the conversions in CONVS on the expression EXPR. FN and
ARGNUM are used for diagnostics. ARGNUM is zero based, -1
@@ -4061,9 +3914,8 @@ static tree
convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner,
bool issue_conversion_warnings)
{
- int savew, savee;
-
tree totype = TREE_TYPE (convs);
+ void (*diagnostic_fn)(const char *, ...);
if (ICS_BAD_FLAG (convs)
&& TREE_CODE (convs) != USER_CONV
@@ -4093,7 +3945,7 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner,
if (issue_conversion_warnings)
expr = dubious_conversion_warnings
- (totype, expr, "argument", fn, argnum);
+ (totype, expr, "converting", fn, argnum);
switch (TREE_CODE (convs))
{
case USER_CONV:
@@ -4117,7 +3969,7 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner,
}
else
args = build_this (expr);
- expr = build_over_call (cand, args, LOOKUP_NORMAL);
+ expr = build_over_call (cand, LOOKUP_NORMAL);
/* If this is a constructor or a function returning an aggr type,
we need to build up a TARGET_EXPR. */
@@ -4135,35 +3987,24 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner,
if (IS_AGGR_TYPE (totype)
&& (inner >= 0 || !lvalue_p (expr)))
{
- savew = warningcount, savee = errorcount;
- expr = build_special_member_call
- (NULL_TREE, complete_ctor_identifier,
- build_tree_list (NULL_TREE, expr), TYPE_BINFO (totype),
- /* Core issue 84, now a DR, says that we don't allow UDCs
- for these args (which deliberately breaks copy-init of an
- auto_ptr<Base> from an auto_ptr<Derived>). */
- LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING|LOOKUP_NO_CONVERSION);
-
- /* Tell the user where this failing constructor call came from. */
- if (fn)
+ expr = (build_temp
+ (expr, totype,
+ /* Core issue 84, now a DR, says that we don't
+ allow UDCs for these args (which deliberately
+ breaks copy-init of an auto_ptr<Base> from an
+ auto_ptr<Derived>). */
+ LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING|LOOKUP_NO_CONVERSION,
+ &diagnostic_fn));
+
+ if (diagnostic_fn)
{
- if (warningcount > savew)
- warning
+ if (fn)
+ diagnostic_fn
(" initializing argument %P of `%D' from result of `%D'",
argnum, fn, convfn);
- else if (errorcount > savee)
- error
- (" initializing argument %P of `%D' from result of `%D'",
- argnum, fn, convfn);
- }
- else
- {
- if (warningcount > savew)
- warning (" initializing temporary from result of `%D'",
- convfn);
- else if (errorcount > savee)
- error (" initializing temporary from result of `%D'",
- convfn);
+ else
+ diagnostic_fn
+ (" initializing temporary from result of `%D'", convfn);
}
expr = build_cplus_new (totype, expr);
}
@@ -4172,6 +4013,15 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner,
case IDENTITY_CONV:
if (type_unknown_p (expr))
expr = instantiate_type (totype, expr, tf_error | tf_warning);
+ /* Convert a non-array constant variable to its underlying
+ value, unless we are about to bind it to a reference, in
+ which case we need to leave it as an lvalue. */
+ if (inner >= 0
+ && TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
+ expr = decl_constant_value (expr);
+ if (CHECK_COPY_CONSTRUCTOR_P (convs))
+ check_constructor_callable (totype, expr);
+
return expr;
case AMBIG_CONV:
/* Call build_user_type_conversion again for the error. */
@@ -4188,29 +4038,23 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner,
if (expr == error_mark_node)
return error_mark_node;
- /* Convert a non-array constant variable to its underlying value, unless we
- are about to bind it to a reference, in which case we need to
- leave it as an lvalue. */
- if (TREE_CODE (convs) != REF_BIND
- && TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
- expr = decl_constant_value (expr);
-
switch (TREE_CODE (convs))
{
case RVALUE_CONV:
if (! IS_AGGR_TYPE (totype))
return expr;
- /* else fall through */
+ /* Else fall through. */
case BASE_CONV:
if (TREE_CODE (convs) == BASE_CONV && !NEED_TEMPORARY_P (convs))
{
/* We are going to bind a reference directly to a base-class
subobject of EXPR. */
- tree base_ptr = build_pointer_type (totype);
-
+ if (CHECK_COPY_CONSTRUCTOR_P (convs))
+ check_constructor_callable (TREE_TYPE (expr), expr);
/* Build an expression for `*((base*) &expr)'. */
expr = build_unary_op (ADDR_EXPR, expr, 0);
- expr = perform_implicit_conversion (base_ptr, expr);
+ expr = perform_implicit_conversion (build_pointer_type (totype),
+ expr);
expr = build_indirect_ref (expr, "implicit conversion");
return expr;
}
@@ -4218,18 +4062,10 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner,
/* Copy-initialization where the cv-unqualified version of the source
type is the same class as, or a derived class of, the class of the
destination [is treated as direct-initialization]. [dcl.init] */
- savew = warningcount, savee = errorcount;
- expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
- build_tree_list (NULL_TREE, expr),
- TYPE_BINFO (totype),
- LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING);
- if (fn)
- {
- if (warningcount > savew)
- warning (" initializing argument %P of `%D'", argnum, fn);
- else if (errorcount > savee)
- error (" initializing argument %P of `%D'", argnum, fn);
- }
+ expr = build_temp (expr, totype, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING,
+ &diagnostic_fn);
+ if (diagnostic_fn && fn)
+ diagnostic_fn (" initializing argument %P of `%D'", argnum, fn);
return build_cplus_new (totype, expr);
case REF_BIND:
@@ -4237,9 +4073,26 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner,
tree ref_type = totype;
/* If necessary, create a temporary. */
- if (NEED_TEMPORARY_P (convs) || !non_cast_lvalue_p (expr))
+ if (NEED_TEMPORARY_P (convs) || !lvalue_p (expr))
{
tree type = TREE_TYPE (TREE_OPERAND (convs, 0));
+
+ if (!CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (ref_type)))
+ {
+ /* If the reference is volatile or non-const, we
+ cannot create a temporary. */
+ cp_lvalue_kind lvalue = real_lvalue_p (expr);
+
+ if (lvalue & clk_bitfield)
+ error ("cannot bind bitfield `%E' to `%T'",
+ expr, ref_type);
+ else if (lvalue & clk_packed)
+ error ("cannot bind packed field `%E' to `%T'",
+ expr, ref_type);
+ else
+ error ("cannot bind rvalue `%E' to `%T'", expr, ref_type);
+ return error_mark_node;
+ }
expr = build_target_expr_with_type (expr, type);
}
@@ -4273,50 +4126,60 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner,
LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
}
-/* Build a call to __builtin_trap which can be used in an expression. */
+/* Build a call to __builtin_trap. */
static tree
-call_builtin_trap ()
+call_builtin_trap (void)
{
- tree fn = get_identifier ("__builtin_trap");
- if (IDENTIFIER_GLOBAL_VALUE (fn))
- fn = IDENTIFIER_GLOBAL_VALUE (fn);
- else
- abort ();
+ tree fn = IDENTIFIER_GLOBAL_VALUE (get_identifier ("__builtin_trap"));
+ my_friendly_assert (fn != NULL, 20030927);
fn = build_call (fn, NULL_TREE);
- fn = build (COMPOUND_EXPR, integer_type_node, fn, integer_zero_node);
return fn;
}
/* ARG is being passed to a varargs function. Perform any conversions
- required. Array/function to pointer decay must have already happened.
- Return the converted value. */
+ required. Return the converted value. */
tree
-convert_arg_to_ellipsis (arg)
- tree arg;
+convert_arg_to_ellipsis (tree arg)
{
+ /* [expr.call]
+
+ The lvalue-to-rvalue, array-to-pointer, and function-to-pointer
+ standard conversions are performed. */
+ arg = decay_conversion (arg);
+ /* [expr.call]
+
+ If the argument has integral or enumeration type that is subject
+ to the integral promotions (_conv.prom_), or a floating point
+ type that is subject to the floating point promotion
+ (_conv.fpprom_), the value of the argument is converted to the
+ promoted type before the call. */
if (TREE_CODE (TREE_TYPE (arg)) == REAL_TYPE
&& (TYPE_PRECISION (TREE_TYPE (arg))
< TYPE_PRECISION (double_type_node)))
- /* Convert `float' to `double'. */
- arg = cp_convert (double_type_node, arg);
- else
- /* Convert `short' and `char' to full-size `int'. */
- arg = default_conversion (arg);
+ arg = convert_to_real (double_type_node, arg);
+ else if (INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (arg)))
+ arg = perform_integral_promotions (arg);
arg = require_complete_type (arg);
- if (arg != error_mark_node && ! pod_type_p (TREE_TYPE (arg)))
+ if (arg != error_mark_node
+ && !pod_type_p (TREE_TYPE (arg)))
{
/* Undefined behavior [expr.call] 5.2.2/7. We used to just warn
here and do a bitwise copy, but now cp_expr_size will abort if we
- try to do that. */
- warning ("cannot pass objects of non-POD type `%#T' through `...'; \
-call will abort at runtime",
- TREE_TYPE (arg));
+ try to do that.
+ If the call appears in the context of a sizeof expression,
+ there is no need to emit a warning, since the expression won't be
+ evaluated. We keep the builtin_trap just as a safety check. */
+ if (!skip_evaluation)
+ warning ("cannot pass objects of non-POD type `%#T' through `...'; "
+ "call will abort at runtime", TREE_TYPE (arg));
arg = call_builtin_trap ();
+ arg = build (COMPOUND_EXPR, integer_type_node, arg,
+ integer_zero_node);
}
return arg;
@@ -4325,9 +4188,7 @@ call will abort at runtime",
/* va_arg (EXPR, TYPE) is a builtin. Make sure it is not abused. */
tree
-build_x_va_arg (expr, type)
- tree expr;
- tree type;
+build_x_va_arg (tree expr, tree type)
{
if (processing_template_decl)
return build_min (VA_ARG_EXPR, type, expr);
@@ -4340,8 +4201,14 @@ build_x_va_arg (expr, type)
if (! pod_type_p (type))
{
/* Undefined behavior [expr.call] 5.2.2/7. */
- warning ("cannot receive objects of non-POD type `%#T' through `...'",
- type);
+ warning ("cannot receive objects of non-POD type `%#T' through `...'; \
+call will abort at runtime",
+ type);
+ expr = convert (build_pointer_type (type), null_node);
+ expr = build (COMPOUND_EXPR, TREE_TYPE (expr),
+ call_builtin_trap (), expr);
+ expr = build_indirect_ref (expr, NULL);
+ return expr;
}
return build_va_arg (expr, type);
@@ -4352,16 +4219,13 @@ build_x_va_arg (expr, type)
type, or the passed type if there is no change. */
tree
-cxx_type_promotes_to (type)
- tree type;
+cxx_type_promotes_to (tree type)
{
tree promote;
- if (TREE_CODE (type) == ARRAY_TYPE)
- return build_pointer_type (TREE_TYPE (type));
-
- if (TREE_CODE (type) == FUNCTION_TYPE)
- return build_pointer_type (type);
+ /* Perform the array-to-pointer and function-to-pointer
+ conversions. */
+ type = type_decays_to (type);
promote = type_promotes_to (type);
if (same_type_p (type, promote))
@@ -4375,30 +4239,16 @@ cxx_type_promotes_to (type)
conversions. Return the converted value. */
tree
-convert_default_arg (type, arg, fn, parmnum)
- tree type;
- tree arg;
- tree fn;
- int parmnum;
+convert_default_arg (tree type, tree arg, tree fn, int parmnum)
{
+ /* If the ARG is an unparsed default argument expression, the
+ conversion cannot be performed. */
if (TREE_CODE (arg) == DEFAULT_ARG)
{
- /* When processing the default args for a class, we can find that
- there is an ordering constraint, and we call a function who's
- default args have not yet been converted. For instance,
- class A {
- A (int = 0);
- void Foo (A const & = A ());
- };
- We must process A::A before A::Foo's default arg can be converted.
- Remember the dependent function, so do_pending_defargs can retry,
- and check loops. */
- unprocessed_defarg_fn (fn);
-
- /* Don't return error_mark node, as we won't be able to distinguish
- genuine errors from this case, and that would lead to repeated
- diagnostics. Just make something of the right type. */
- return build1 (NOP_EXPR, type, integer_zero_node);
+ error ("the default argument for parameter %d of `%D' has "
+ "not yet been parsed",
+ parmnum, fn);
+ return error_mark_node;
}
if (fn && DECL_TEMPLATE_INFO (fn))
@@ -4430,15 +4280,16 @@ convert_default_arg (type, arg, fn, parmnum)
type TYPE. */
tree
-type_passed_as (type)
- tree type;
+type_passed_as (tree type)
{
/* Pass classes with copy ctors by invisible reference. */
if (TREE_ADDRESSABLE (type))
type = build_reference_type (type);
else if (PROMOTE_PROTOTYPES
&& INTEGRAL_TYPE_P (type)
- && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+ && COMPLETE_TYPE_P (type)
+ && INT_CST_LT_UNSIGNED (TYPE_SIZE (type),
+ TYPE_SIZE (integer_type_node)))
type = integer_type_node;
return type;
@@ -4447,8 +4298,7 @@ type_passed_as (type)
/* Actually perform the appropriate conversion. */
tree
-convert_for_arg_passing (type, val)
- tree type, val;
+convert_for_arg_passing (tree type, tree val)
{
if (val == error_mark_node)
;
@@ -4457,23 +4307,46 @@ convert_for_arg_passing (type, val)
val = build1 (ADDR_EXPR, build_reference_type (type), val);
else if (PROMOTE_PROTOTYPES
&& INTEGRAL_TYPE_P (type)
- && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
- val = default_conversion (val);
+ && COMPLETE_TYPE_P (type)
+ && INT_CST_LT_UNSIGNED (TYPE_SIZE (type),
+ TYPE_SIZE (integer_type_node)))
+ val = perform_integral_promotions (val);
return val;
}
+/* Returns true iff FN is a function with magic varargs, i.e. ones for
+ which no conversions at all should be done. This is true for some
+ builtins which don't act like normal functions. */
+
+static bool
+magic_varargs_p (tree fn)
+{
+ if (DECL_BUILT_IN (fn))
+ switch (DECL_FUNCTION_CODE (fn))
+ {
+ case BUILT_IN_CLASSIFY_TYPE:
+ case BUILT_IN_CONSTANT_P:
+ case BUILT_IN_NEXT_ARG:
+ case BUILT_IN_STDARG_START:
+ case BUILT_IN_VA_START:
+ return true;
+
+ default:;
+ }
+
+ return false;
+}
+
/* Subroutine of the various build_*_call functions. Overload resolution
has chosen a winning candidate CAND; build up a CALL_EXPR accordingly.
ARGS is a TREE_LIST of the unconverted arguments to the call. FLAGS is a
bitmask of various LOOKUP_* flags which apply to the call itself. */
static tree
-build_over_call (cand, args, flags)
- struct z_candidate *cand;
- tree args;
- int flags;
+build_over_call (struct z_candidate *cand, int flags)
{
tree fn = cand->fn;
+ tree args = cand->args;
tree convs = cand->convs;
tree converted_args = NULL_TREE;
tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
@@ -4481,13 +4354,62 @@ build_over_call (cand, args, flags)
int i = 0;
int is_method = 0;
+ /* In a template, there is no need to perform all of the work that
+ is normally done. We are only interested in the type of the call
+ expression, i.e., the return type of the function. Any semantic
+ errors will be deferred until the template is instantiated. */
+ if (processing_template_decl)
+ {
+ tree expr;
+ tree return_type;
+ return_type = TREE_TYPE (TREE_TYPE (fn));
+ expr = build (CALL_EXPR, return_type, fn, args);
+ if (TREE_THIS_VOLATILE (fn) && cfun)
+ current_function_returns_abnormally = 1;
+ if (!VOID_TYPE_P (return_type))
+ require_complete_type (return_type);
+ return convert_from_reference (expr);
+ }
+
/* Give any warnings we noticed during overload resolution. */
if (cand->warnings)
for (val = cand->warnings; val; val = TREE_CHAIN (val))
joust (cand, WRAPPER_ZC (TREE_VALUE (val)), 1);
if (DECL_FUNCTION_MEMBER_P (fn))
- enforce_access (cand->access_path, fn);
+ {
+ /* If FN is a template function, two cases must be considered.
+ For example:
+
+ struct A {
+ protected:
+ template <class T> void f();
+ };
+ template <class T> struct B {
+ protected:
+ void g();
+ };
+ struct C : A, B<int> {
+ using A::f; // #1
+ using B<int>::g; // #2
+ };
+
+ In case #1 where `A::f' is a member template, DECL_ACCESS is
+ recorded in the primary template but not in its specialization.
+ We check access of FN using its primary template.
+
+ In case #2, where `B<int>::g' has a DECL_TEMPLATE_INFO simply
+ because it is a member of class template B, DECL_ACCESS is
+ recorded in the specialization `B<int>::g'. We cannot use its
+ primary template because `B<T>::g' and `B<int>::g' may have
+ different access. */
+ if (DECL_TEMPLATE_INFO (fn)
+ && is_member_template (DECL_TI_TEMPLATE (fn)))
+ perform_or_defer_access_check (cand->access_path,
+ DECL_TI_TEMPLATE (fn));
+ else
+ perform_or_defer_access_check (cand->access_path, fn);
+ }
if (args && TREE_CODE (args) != TREE_LIST)
args = build_tree_list (NULL_TREE, args);
@@ -4581,10 +4503,14 @@ build_over_call (cand, args, flags)
/* Ellipsis */
for (; arg; arg = TREE_CHAIN (arg))
- converted_args
- = tree_cons (NULL_TREE,
- convert_arg_to_ellipsis (TREE_VALUE (arg)),
- converted_args);
+ {
+ tree a = TREE_VALUE (arg);
+ if (magic_varargs_p (fn))
+ /* Do no conversions for magic varargs. */;
+ else
+ a = convert_arg_to_ellipsis (a);
+ converted_args = tree_cons (NULL_TREE, a, converted_args);
+ }
converted_args = nreverse (converted_args);
@@ -4645,16 +4571,11 @@ build_over_call (cand, args, flags)
else if (TREE_CODE (arg) == TARGET_EXPR
|| TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
{
- tree address;
tree to = stabilize_reference
(build_indirect_ref (TREE_VALUE (args), 0));
val = build (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
- address = build_unary_op (ADDR_EXPR, val, 0);
- /* Avoid a warning about this expression, if the address is
- never used. */
- TREE_USED (address) = 1;
- return address;
+ return val;
}
}
else if (DECL_OVERLOADED_OPERATOR_P (fn) == NOP_EXPR
@@ -4663,9 +4584,36 @@ build_over_call (cand, args, flags)
{
tree to = stabilize_reference
(build_indirect_ref (TREE_VALUE (converted_args), 0));
+ tree type = TREE_TYPE (to);
+ tree as_base = CLASSTYPE_AS_BASE (type);
arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0);
- val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
+ if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base)))
+ val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
+ else
+ {
+ /* We must only copy the non-tail padding parts. Use
+ CLASSTYPE_AS_BASE for the bitwise copy. */
+ tree to_ptr, arg_ptr, to_as_base, arg_as_base, base_ptr_type;
+ tree save_to;
+
+ to_ptr = save_expr (build_unary_op (ADDR_EXPR, to, 0));
+ arg_ptr = build_unary_op (ADDR_EXPR, arg, 0);
+
+ base_ptr_type = build_pointer_type (as_base);
+ to_as_base = build_nop (base_ptr_type, to_ptr);
+ to_as_base = build_indirect_ref (to_as_base, 0);
+ arg_as_base = build_nop (base_ptr_type, arg_ptr);
+ arg_as_base = build_indirect_ref (arg_as_base, 0);
+
+ save_to = build_indirect_ref (to_ptr, 0);
+
+ val = build (MODIFY_EXPR, as_base, to_as_base, arg_as_base);
+ val = convert_to_void (val, NULL);
+ val = build (COMPOUND_EXPR, type, val, save_to);
+ TREE_NO_UNUSED_WARNING (val) = 1;
+ }
+
return val;
}
@@ -4752,8 +4700,7 @@ static GTY(()) tree java_iface_lookup_fn;
_Jv_LookupInterfaceMethodIdx(). */
static tree
-build_java_interface_fn_ref (fn, instance)
- tree fn, instance;
+build_java_interface_fn_ref (tree fn, tree instance)
{
tree lookup_args, lookup_fn, method, idx;
tree klass_ref, iface, iface_ref;
@@ -4779,7 +4726,7 @@ build_java_interface_fn_ref (fn, instance)
/* Get the java.lang.Class pointer for the interface being called. */
iface = DECL_CONTEXT (fn);
- iface_ref = lookup_field (iface, get_identifier ("class$"), 0, 0);
+ iface_ref = lookup_field (iface, get_identifier ("class$"), 0, false);
if (!iface_ref || TREE_CODE (iface_ref) != VAR_DECL
|| DECL_CONTEXT (iface_ref) != iface)
{
@@ -4814,8 +4761,7 @@ build_java_interface_fn_ref (fn, instance)
call to a function with the indicated NAME. */
tree
-in_charge_arg_for_name (name)
- tree name;
+in_charge_arg_for_name (tree name)
{
if (name == base_ctor_identifier
|| name == base_dtor_identifier)
@@ -4878,14 +4824,23 @@ build_special_member_call (tree instance, tree name, tree args,
|| name == deleting_dtor_identifier)
my_friendly_assert (args == NULL_TREE, 20020712);
- /* We must perform the conversion here so that we do not
- subsequently check to see whether BINFO is an accessible
- base. (It is OK for a constructor to call a constructor in
- an inaccessible base as long as the constructor being called
- is accessible.) */
+ /* Convert to the base class, if necessary. */
if (!same_type_ignoring_top_level_qualifiers_p
(TREE_TYPE (instance), BINFO_TYPE (binfo)))
- instance = convert_to_base_statically (instance, binfo);
+ {
+ if (name != ansi_assopname (NOP_EXPR))
+ /* For constructors and destructors, either the base is
+ non-virtual, or it is virtual but we are doing the
+ conversion from a constructor or destructor for the
+ complete object. In either case, we can convert
+ statically. */
+ instance = convert_to_base_statically (instance, binfo);
+ else
+ /* However, for assignment operators, we must convert
+ dynamically if the base is virtual. */
+ instance = build_base_path (PLUS_EXPR, instance,
+ binfo, /*nonnull=*/1);
+ }
}
my_friendly_assert (instance != NULL_TREE, 20020712);
@@ -4916,8 +4871,6 @@ build_special_member_call (tree instance, tree name, tree args,
current_in_charge_parm, integer_zero_node),
current_vtt_parm,
vtt);
- if (TREE_VIA_VIRTUAL (binfo))
- binfo = binfo_for_vbase (class_type, current_class_type);
my_friendly_assert (BINFO_SUBVTT_INDEX (binfo), 20010110);
sub_vtt = build (PLUS_EXPR, TREE_TYPE (vtt), vtt,
BINFO_SUBVTT_INDEX (binfo));
@@ -4930,6 +4883,51 @@ build_special_member_call (tree instance, tree name, tree args,
flags);
}
+/* Return the NAME, as a C string. The NAME indicates a function that
+ is a member of TYPE. *FREE_P is set to true if the caller must
+ free the memory returned.
+
+ Rather than go through all of this, we should simply set the names
+ of constructors and destructors appropriately, and dispense with
+ ctor_identifier, dtor_identifier, etc. */
+
+static char *
+name_as_c_string (tree name, tree type, bool *free_p)
+{
+ char *pretty_name;
+
+ /* Assume that we will not allocate memory. */
+ *free_p = false;
+ /* Constructors and destructors are special. */
+ if (IDENTIFIER_CTOR_OR_DTOR_P (name))
+ {
+ pretty_name
+ = (char *) IDENTIFIER_POINTER (constructor_name (type));
+ /* For a destructor, add the '~'. */
+ if (name == complete_dtor_identifier
+ || name == base_dtor_identifier
+ || name == deleting_dtor_identifier)
+ {
+ pretty_name = concat ("~", pretty_name, NULL);
+ /* Remember that we need to free the memory allocated. */
+ *free_p = true;
+ }
+ }
+ else if (IDENTIFIER_TYPENAME_P (name))
+ {
+ pretty_name = concat ("operator ",
+ type_as_string (TREE_TYPE (name),
+ TFF_PLAIN_IDENTIFIER),
+ NULL);
+ /* Remember that we need to free the memory allocated. */
+ *free_p = true;
+ }
+ else
+ pretty_name = (char *) IDENTIFIER_POINTER (name);
+
+ return pretty_name;
+}
+
/* Build a call to "INSTANCE.FN (ARGS)". */
tree
@@ -4942,25 +4940,44 @@ build_new_method_call (tree instance, tree fns, tree args,
tree access_binfo;
tree optype;
tree mem_args = NULL_TREE, instance_ptr;
- tree name, pretty_name;
+ tree name;
tree user_args;
tree call;
+ tree fn;
+ tree class_type;
int template_only = 0;
+ bool any_viable_p;
+ tree orig_instance;
+ tree orig_fns;
+ tree orig_args;
my_friendly_assert (instance != NULL_TREE, 20020729);
- if (instance == error_mark_node || fns == error_mark_node
+ if (error_operand_p (instance)
+ || error_operand_p (fns)
|| args == error_mark_node)
return error_mark_node;
+ orig_instance = instance;
+ orig_fns = fns;
+ orig_args = args;
+
+ if (processing_template_decl)
+ {
+ instance = build_non_dependent_expr (instance);
+ if (!BASELINK_P (fns)
+ && TREE_CODE (fns) != PSEUDO_DTOR_EXPR
+ && TREE_TYPE (fns) != unknown_type_node)
+ fns = build_non_dependent_expr (fns);
+ args = build_non_dependent_args (orig_args);
+ }
+
/* Process the argument list. */
user_args = args;
args = resolve_args (args);
if (args == error_mark_node)
return error_mark_node;
- if (TREE_CODE (instance) == OFFSET_REF)
- instance = resolve_offset_ref (instance);
if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
instance = convert_from_reference (instance);
basetype = TYPE_MAIN_VARIANT (TREE_TYPE (instance));
@@ -4968,9 +4985,6 @@ build_new_method_call (tree instance, tree fns, tree args,
if (!BASELINK_P (fns))
{
- call = build_field_call (instance_ptr, fns, args);
- if (call)
- return call;
error ("call to non-function `%D'", fns);
return error_mark_node;
}
@@ -5003,7 +5017,8 @@ build_new_method_call (tree instance, tree fns, tree args,
return error_mark_node;
}
- name = DECL_NAME (get_first_fn (fns));
+ fn = get_first_fn (fns);
+ name = DECL_NAME (fn);
if (IDENTIFIER_CTOR_OR_DTOR_P (name))
{
@@ -5012,60 +5027,56 @@ build_new_method_call (tree instance, tree fns, tree args,
my_friendly_assert (name != ctor_identifier, 20000408);
/* Similarly for destructors. */
my_friendly_assert (name != dtor_identifier, 20000408);
-
- if (name == complete_ctor_identifier
- || name == base_ctor_identifier)
- pretty_name = constructor_name (basetype);
- else
- pretty_name = dtor_identifier;
}
- else
- pretty_name = name;
- if (fns)
+ /* It's OK to call destructors on cv-qualified objects. Therefore,
+ convert the INSTANCE_PTR to the unqualified type, if necessary. */
+ if (DECL_DESTRUCTOR_P (fn))
{
- tree fn;
- tree class_type = (conversion_path
- ? BINFO_TYPE (conversion_path)
- : NULL_TREE);
+ tree type = build_pointer_type (basetype);
+ if (!same_type_p (type, TREE_TYPE (instance_ptr)))
+ instance_ptr = build_nop (type, instance_ptr);
+ }
- mem_args = tree_cons (NULL_TREE, instance_ptr, args);
- for (fn = fns; fn; fn = OVL_NEXT (fn))
- {
- tree t = OVL_CURRENT (fn);
- tree this_arglist;
+ class_type = (conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE);
+ mem_args = tree_cons (NULL_TREE, instance_ptr, args);
- /* We can end up here for copy-init of same or base class. */
- if ((flags & LOOKUP_ONLYCONVERTING)
- && DECL_NONCONVERTING_P (t))
- continue;
+ for (fn = fns; fn; fn = OVL_NEXT (fn))
+ {
+ tree t = OVL_CURRENT (fn);
+ tree this_arglist;
- if (DECL_NONSTATIC_MEMBER_FUNCTION_P (t))
- this_arglist = mem_args;
- else
- this_arglist = args;
-
- if (TREE_CODE (t) == TEMPLATE_DECL)
- /* A member template. */
- add_template_candidate (&candidates, t,
- class_type,
- explicit_targs,
- this_arglist, optype,
- access_binfo,
- conversion_path,
- flags,
- DEDUCE_CALL);
- else if (! template_only)
- add_function_candidate (&candidates, t,
- class_type,
- this_arglist,
- access_binfo,
- conversion_path,
- flags);
- }
+ /* We can end up here for copy-init of same or base class. */
+ if ((flags & LOOKUP_ONLYCONVERTING)
+ && DECL_NONCONVERTING_P (t))
+ continue;
+
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (t))
+ this_arglist = mem_args;
+ else
+ this_arglist = args;
+
+ if (TREE_CODE (t) == TEMPLATE_DECL)
+ /* A member template. */
+ add_template_candidate (&candidates, t,
+ class_type,
+ explicit_targs,
+ this_arglist, optype,
+ access_binfo,
+ conversion_path,
+ flags,
+ DEDUCE_CALL);
+ else if (! template_only)
+ add_function_candidate (&candidates, t,
+ class_type,
+ this_arglist,
+ access_binfo,
+ conversion_path,
+ flags);
}
- if (! any_viable (candidates))
+ candidates = splice_viable (candidates, pedantic, &any_viable_p);
+ if (!any_viable_p)
{
/* XXX will LOOKUP_SPECULATIVELY be needed when this is done? */
if (flags & LOOKUP_SPECULATIVELY)
@@ -5073,20 +5084,33 @@ build_new_method_call (tree instance, tree fns, tree args,
if (!COMPLETE_TYPE_P (basetype))
cxx_incomplete_type_error (instance_ptr, basetype);
else
- error ("no matching function for call to `%T::%D(%A)%#V'",
- basetype, pretty_name, user_args,
- TREE_TYPE (TREE_TYPE (instance_ptr)));
+ {
+ char *pretty_name;
+ bool free_p;
+
+ pretty_name = name_as_c_string (name, basetype, &free_p);
+ error ("no matching function for call to `%T::%s(%A)%#V'",
+ basetype, pretty_name, user_args,
+ TREE_TYPE (TREE_TYPE (instance_ptr)));
+ if (free_p)
+ free (pretty_name);
+ }
print_z_candidates (candidates);
return error_mark_node;
}
- candidates = splice_viable (candidates);
- cand = tourney (candidates);
+ cand = tourney (candidates);
if (cand == 0)
{
- error ("call of overloaded `%D(%A)' is ambiguous", pretty_name,
- user_args);
+ char *pretty_name;
+ bool free_p;
+
+ pretty_name = name_as_c_string (name, basetype, &free_p);
+ error ("call of overloaded `%s(%A)' is ambiguous", pretty_name,
+ user_args);
print_z_candidates (candidates);
+ if (free_p)
+ free (pretty_name);
return error_mark_node;
}
@@ -5112,25 +5136,29 @@ build_new_method_call (tree instance, tree fns, tree args,
flags |= LOOKUP_NONVIRTUAL;
if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE)
- call = build_over_call (cand, mem_args, flags);
+ call = build_over_call (cand, flags);
else
{
- call = build_over_call (cand, args, flags);
+ call = build_over_call (cand, flags);
/* In an expression of the form `a->f()' where `f' turns out to
be a static member function, `a' is none-the-less evaluated. */
- if (instance && TREE_SIDE_EFFECTS (instance))
+ if (!is_dummy_object (instance_ptr) && TREE_SIDE_EFFECTS (instance))
call = build (COMPOUND_EXPR, TREE_TYPE (call), instance, call);
}
-
+
+ if (processing_template_decl && call != error_mark_node)
+ return build_min_non_dep
+ (CALL_EXPR, call,
+ build_min_nt (COMPONENT_REF, orig_instance, orig_fns),
+ orig_args);
return call;
}
-/* Returns nonzero iff standard conversion sequence ICS1 is a proper
+/* Returns true iff standard conversion sequence ICS1 is a proper
subsequence of ICS2. */
-static int
-is_subseq (ics1, ics2)
- tree ics1, ics2;
+static bool
+is_subseq (tree ics1, tree ics2)
{
/* We can assume that a conversion of the same code
between the same types indicates a subsequence since we only get
@@ -5153,7 +5181,7 @@ is_subseq (ics1, ics2)
ICS2. We can get a USER_CONV when we are comparing the
second standard conversion sequence of two user conversion
sequences. */
- return 0;
+ return false;
ics2 = TREE_OPERAND (ics2, 0);
@@ -5161,21 +5189,19 @@ is_subseq (ics1, ics2)
&& same_type_p (TREE_TYPE (ics2), TREE_TYPE (ics1))
&& same_type_p (TREE_TYPE (TREE_OPERAND (ics2, 0)),
TREE_TYPE (TREE_OPERAND (ics1, 0))))
- return 1;
+ return true;
}
}
/* Returns nonzero iff DERIVED is derived from BASE. The inputs may
be any _TYPE nodes. */
-int
-is_properly_derived_from (derived, base)
- tree derived;
- tree base;
+bool
+is_properly_derived_from (tree derived, tree base)
{
if (!IS_AGGR_TYPE_CODE (TREE_CODE (derived))
|| !IS_AGGR_TYPE_CODE (TREE_CODE (base)))
- return 0;
+ return false;
/* We only allow proper derivation here. The DERIVED_FROM_P macro
considers every class derived from itself. */
@@ -5190,8 +5216,7 @@ is_properly_derived_from (derived, base)
modify it accordingly. */
static void
-maybe_handle_implicit_object (ics)
- tree* ics;
+maybe_handle_implicit_object (tree *ics)
{
if (ICS_THIS_FLAG (*ics))
{
@@ -5206,7 +5231,7 @@ maybe_handle_implicit_object (ics)
tree reference_type;
/* The `this' parameter is a pointer to a class type. Make the
- implict conversion talk about a reference to that same class
+ implicit conversion talk about a reference to that same class
type. */
reference_type = TREE_TYPE (TREE_TYPE (*ics));
reference_type = build_reference_type (reference_type);
@@ -5226,8 +5251,7 @@ maybe_handle_implicit_object (ics)
leave *ICS unchanged and return NULL_TREE. */
static tree
-maybe_handle_ref_bind (ics)
- tree* ics;
+maybe_handle_ref_bind (tree *ics)
{
if (TREE_CODE (*ics) == REF_BIND)
{
@@ -5250,8 +5274,7 @@ maybe_handle_ref_bind (ics)
0: ics1 and ics2 are indistinguishable */
static int
-compare_ics (ics1, ics2)
- tree ics1, ics2;
+compare_ics (tree ics1, tree ics2)
{
tree from_type1;
tree from_type2;
@@ -5301,7 +5324,7 @@ compare_ics (ics1, ics2)
{
/* XXX Isn't this an extension? */
/* Both ICS are bad. We try to make a decision based on what
- would have happenned if they'd been good. */
+ would have happened if they'd been good. */
if (ICS_USER_FLAG (ics1) > ICS_USER_FLAG (ics2)
|| ICS_STD_RANK (ics1) > ICS_STD_RANK (ics2))
return -1;
@@ -5421,25 +5444,17 @@ compare_ics (ics1, ics2)
for pointers A*, except opposite: if B is derived from A then
A::* converts to B::*, not vice versa. For that reason, we
switch the from_ and to_ variables here. */
- else if (TYPE_PTRMEM_P (from_type1)
- && TYPE_PTRMEM_P (from_type2)
- && TYPE_PTRMEM_P (to_type1)
- && TYPE_PTRMEM_P (to_type2))
+ else if ((TYPE_PTRMEM_P (from_type1) && TYPE_PTRMEM_P (from_type2)
+ && TYPE_PTRMEM_P (to_type1) && TYPE_PTRMEM_P (to_type2))
+ || (TYPE_PTRMEMFUNC_P (from_type1)
+ && TYPE_PTRMEMFUNC_P (from_type2)
+ && TYPE_PTRMEMFUNC_P (to_type1)
+ && TYPE_PTRMEMFUNC_P (to_type2)))
{
- deref_to_type1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (from_type1));
- deref_to_type2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (from_type2));
- deref_from_type1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (to_type1));
- deref_from_type2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (to_type2));
- }
- else if (TYPE_PTRMEMFUNC_P (from_type1)
- && TYPE_PTRMEMFUNC_P (from_type2)
- && TYPE_PTRMEMFUNC_P (to_type1)
- && TYPE_PTRMEMFUNC_P (to_type2))
- {
- deref_to_type1 = TYPE_PTRMEMFUNC_OBJECT_TYPE (from_type1);
- deref_to_type2 = TYPE_PTRMEMFUNC_OBJECT_TYPE (from_type2);
- deref_from_type1 = TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type1);
- deref_from_type2 = TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type2);
+ deref_to_type1 = TYPE_PTRMEM_CLASS_TYPE (from_type1);
+ deref_to_type2 = TYPE_PTRMEM_CLASS_TYPE (from_type2);
+ deref_from_type1 = TYPE_PTRMEM_CLASS_TYPE (to_type1);
+ deref_from_type2 = TYPE_PTRMEM_CLASS_TYPE (to_type2);
}
if (deref_from_type1 != NULL_TREE
@@ -5587,8 +5602,7 @@ compare_ics (ics1, ics2)
/* The source type for this standard conversion sequence. */
static tree
-source_type (t)
- tree t;
+source_type (tree t)
{
for (;; t = TREE_OPERAND (t, 0))
{
@@ -5605,8 +5619,7 @@ source_type (t)
is actually used. */
static void
-add_warning (winner, loser)
- struct z_candidate *winner, *loser;
+add_warning (struct z_candidate *winner, struct z_candidate *loser)
{
winner->warnings = tree_cons (NULL_TREE,
build_zc_wrapper (loser),
@@ -5621,9 +5634,7 @@ add_warning (winner, loser)
0: cand1 and cand2 are indistinguishable */
static int
-joust (cand1, cand2, warn)
- struct z_candidate *cand1, *cand2;
- int warn;
+joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn)
{
int winner = 0;
int i, off1 = 0, off2 = 0, len;
@@ -5721,45 +5732,52 @@ joust (cand1, cand2, warn)
/* warn about confusing overload resolution for user-defined conversions,
either between a constructor and a conversion op, or between two
conversion ops. */
- if (winner && cand1->second_conv
- && ((DECL_CONSTRUCTOR_P (cand1->fn)
- != DECL_CONSTRUCTOR_P (cand2->fn))
- /* Don't warn if the two conv ops convert to the same type... */
- || (! DECL_CONSTRUCTOR_P (cand1->fn)
- && ! same_type_p (TREE_TYPE (TREE_TYPE (cand1->fn)),
- TREE_TYPE (TREE_TYPE (cand2->fn))))))
- {
- int comp = compare_ics (cand1->second_conv, cand2->second_conv);
- if (comp != winner)
+ if (winner && warn_conversion && cand1->second_conv
+ && (!DECL_CONSTRUCTOR_P (cand1->fn) || !DECL_CONSTRUCTOR_P (cand2->fn))
+ && winner != compare_ics (cand1->second_conv, cand2->second_conv))
+ {
+ struct z_candidate *w, *l;
+ bool give_warning = false;
+
+ if (winner == 1)
+ w = cand1, l = cand2;
+ else
+ w = cand2, l = cand1;
+
+ /* We don't want to complain about `X::operator T1 ()'
+ beating `X::operator T2 () const', when T2 is a no less
+ cv-qualified version of T1. */
+ if (DECL_CONTEXT (w->fn) == DECL_CONTEXT (l->fn)
+ && !DECL_CONSTRUCTOR_P (w->fn) && !DECL_CONSTRUCTOR_P (l->fn))
{
- struct z_candidate *w, *l;
- tree convn;
- if (winner == 1)
- w = cand1, l = cand2;
- else
- w = cand2, l = cand1;
- if (DECL_CONTEXT (cand1->fn) == DECL_CONTEXT (cand2->fn)
- && ! DECL_CONSTRUCTOR_P (cand1->fn)
- && ! DECL_CONSTRUCTOR_P (cand2->fn)
- && (convn = standard_conversion
- (TREE_TYPE (TREE_TYPE (l->fn)),
- TREE_TYPE (TREE_TYPE (w->fn)), NULL_TREE))
- && TREE_CODE (convn) == QUAL_CONV)
- /* Don't complain about `operator char *()' beating
- `operator const char *() const'. */;
- else if (warn && warn_conversion)
+ tree t = TREE_TYPE (TREE_TYPE (l->fn));
+ tree f = TREE_TYPE (TREE_TYPE (w->fn));
+
+ if (TREE_CODE (t) == TREE_CODE (f) && POINTER_TYPE_P (t))
{
- tree source = source_type (TREE_VEC_ELT (w->convs, 0));
- if (! DECL_CONSTRUCTOR_P (w->fn))
- source = TREE_TYPE (source);
- warning ("choosing `%D' over `%D'", w->fn, l->fn);
- warning (" for conversion from `%T' to `%T'",
- source, TREE_TYPE (w->second_conv));
- warning (" because conversion sequence for the argument is better");
+ t = TREE_TYPE (t);
+ f = TREE_TYPE (f);
}
- else
- add_warning (w, l);
+ if (!comp_ptr_ttypes (t, f))
+ give_warning = true;
}
+ else
+ give_warning = true;
+
+ if (!give_warning)
+ /*NOP*/;
+ else if (warn)
+ {
+ tree source = source_type (TREE_VEC_ELT (w->convs, 0));
+ if (! DECL_CONSTRUCTOR_P (w->fn))
+ source = TREE_TYPE (source);
+ warning ("choosing `%D' over `%D'", w->fn, l->fn);
+ warning (" for conversion from `%T' to `%T'",
+ source, TREE_TYPE (w->second_conv));
+ warning (" because conversion sequence for the argument is better");
+ }
+ else
+ add_warning (w, l);
}
if (winner)
@@ -5795,7 +5813,6 @@ joust (cand1, cand2, warn)
TREE_VEC_LENGTH (cand1->convs)
- (DECL_NONSTATIC_MEMBER_FUNCTION_P (cand1->fn)
- DECL_CONSTRUCTOR_P (cand1->fn)));
- /* HERE */
if (winner)
return winner;
}
@@ -5852,7 +5869,7 @@ joust (cand1, cand2, warn)
if (DECL_P (cand1->fn) && DECL_P (cand2->fn)
&& equal_functions (cand1->fn, cand2->fn))
return 1;
-
+
tweak:
/* Extension: If the worst conversion for one candidate is worse than the
@@ -5876,9 +5893,14 @@ tweak:
if (winner)
{
if (warn)
- pedwarn ("ISO C++ says that `%D' and `%D' are ambiguous \
-even though the worst conversion for the former is better than the worst \
-conversion for the latter", w->fn, l->fn);
+ {
+ pedwarn ("\
+ISO C++ says that these are ambiguous, even \
+though the worst conversion for the first is better than \
+the worst conversion for the second:");
+ print_z_candidate (_("candidate 1:"), w);
+ print_z_candidate (_("candidate 2:"), l);
+ }
else
add_warning (w, l);
return winner;
@@ -5895,8 +5917,7 @@ conversion for the latter", w->fn, l->fn);
algorithm. */
static struct z_candidate *
-tourney (candidates)
- struct z_candidate *candidates;
+tourney (struct z_candidate *candidates)
{
struct z_candidate *champ = candidates, *challenger;
int fate;
@@ -5947,18 +5968,16 @@ tourney (candidates)
/* Returns nonzero if things of type FROM can be converted to TO. */
-int
-can_convert (to, from)
- tree to, from;
+bool
+can_convert (tree to, tree from)
{
return can_convert_arg (to, from, NULL_TREE);
}
/* Returns nonzero if ARG (of type FROM) can be converted to TO. */
-int
-can_convert_arg (to, from, arg)
- tree to, from, arg;
+bool
+can_convert_arg (tree to, tree from, tree arg)
{
tree t = implicit_conversion (to, from, arg, LOOKUP_NORMAL);
return (t && ! ICS_BAD_FLAG (t));
@@ -5966,12 +5985,10 @@ can_convert_arg (to, from, arg)
/* Like can_convert_arg, but allows dubious conversions as well. */
-int
-can_convert_arg_bad (to, from, arg)
- tree to, from, arg;
+bool
+can_convert_arg_bad (tree to, tree from, tree arg)
{
- tree t = implicit_conversion (to, from, arg, LOOKUP_NORMAL);
- return !!t;
+ return implicit_conversion (to, from, arg, LOOKUP_NORMAL) != 0;
}
/* Convert EXPR to TYPE. Return the converted expression.
@@ -5981,13 +5998,11 @@ can_convert_arg_bad (to, from, arg)
doing a bad conversion, convert_like will complain. */
tree
-perform_implicit_conversion (type, expr)
- tree type;
- tree expr;
+perform_implicit_conversion (tree type, tree expr)
{
tree conv;
- if (expr == error_mark_node)
+ if (error_operand_p (expr))
return error_mark_node;
conv = implicit_conversion (type, TREE_TYPE (expr), expr,
LOOKUP_NORMAL);
@@ -6074,23 +6089,19 @@ make_temporary_var_for_ref_to_temp (tree decl, tree type)
return var;
}
- /* Convert EXPR to the indicated reference TYPE, in a way suitable
- for initializing a variable of that TYPE. If DECL is non-NULL,
- it is the VAR_DECL being initialized with the EXPR. (In that
- case, the type of DECL will be TYPE.) If DECL is non-NULL, then
- CLEANUP must also be non-NULL, and with *CLEANUP initialized to
- NULL. Upon return, if *CLEANUP is no longer NULL, it will be a
- CLEANUP_STMT that should be inserted after the returned
- expression is used to initialize DECL.
+/* Convert EXPR to the indicated reference TYPE, in a way suitable for
+ initializing a variable of that TYPE. If DECL is non-NULL, it is
+ the VAR_DECL being initialized with the EXPR. (In that case, the
+ type of DECL will be TYPE.) If DECL is non-NULL, then CLEANUP must
+ also be non-NULL, and with *CLEANUP initialized to NULL. Upon
+ return, if *CLEANUP is no longer NULL, it will be a CLEANUP_STMT
+ that should be inserted after the returned expression is used to
+ initialize DECL.
- Return the converted expression. */
+ Return the converted expression. */
tree
-initialize_reference (type, expr, decl, cleanup)
- tree type;
- tree expr;
- tree decl;
- tree *cleanup;
+initialize_reference (tree type, tree expr, tree decl, tree *cleanup)
{
tree conv;
@@ -6158,14 +6169,19 @@ initialize_reference (type, expr, decl, cleanup)
remember that the conversion was required. */
if (TREE_CODE (conv) == BASE_CONV && !NEED_TEMPORARY_P (conv))
{
+ if (CHECK_COPY_CONSTRUCTOR_P (conv))
+ check_constructor_callable (TREE_TYPE (expr), expr);
base_conv_type = TREE_TYPE (conv);
conv = TREE_OPERAND (conv, 0);
}
else
base_conv_type = NULL_TREE;
/* Perform the remainder of the conversion. */
- expr = convert_like (conv, expr);
- if (!real_non_cast_lvalue_p (expr))
+ expr = convert_like_real (conv, expr,
+ /*fn=*/NULL_TREE, /*argnum=*/0,
+ /*inner=*/-1,
+ /*issue_conversion_warnings=*/true);
+ if (!real_lvalue_p (expr))
{
tree init;
tree type;
@@ -6174,6 +6190,16 @@ initialize_reference (type, expr, decl, cleanup)
type = TREE_TYPE (expr);
var = make_temporary_var_for_ref_to_temp (decl, type);
layout_decl (var, 0);
+ /* If the rvalue is the result of a function call it will be
+ a TARGET_EXPR. If it is some other construct (such as a
+ member access expression where the underlying object is
+ itself the result of a function call), turn it into a
+ TARGET_EXPR here. It is important that EXPR be a
+ TARGET_EXPR below since otherwise the INIT_EXPR will
+ attempt to make a bitwise copy of EXPR to intialize
+ VAR. */
+ if (TREE_CODE (expr) != TARGET_EXPR)
+ expr = get_target_expr (expr);
/* Create the INIT_EXPR that will initialize the temporary
variable. */
init = build (INIT_EXPR, type, var, expr);
OpenPOWER on IntegriCloud