-/* Functions related to invoking methods and overloaded functions.
- Copyright (C) 1987-2015 Free Software Foundation, Inc.
+/* Functions related to invoking -*- C++ -*- methods and overloaded functions.
+ Copyright (C) 1987-2016 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com) and
modified by Brendan Kehoe (brendan@cygnus.com).
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
-#include "alias.h"
-#include "tree.h"
+#include "target.h"
+#include "cp-tree.h"
+#include "timevar.h"
+#include "stringpool.h"
+#include "cgraph.h"
#include "stor-layout.h"
#include "trans-mem.h"
-#include "stringpool.h"
-#include "cp-tree.h"
#include "flags.h"
#include "toplev.h"
-#include "diagnostic-core.h"
#include "intl.h"
-#include "target.h"
#include "convert.h"
#include "langhooks.h"
#include "c-family/c-objc.h"
-#include "timevar.h"
-#include "hard-reg-set.h"
-#include "function.h"
-#include "cgraph.h"
#include "internal-fn.h"
/* The various kinds of conversion. */
-typedef enum conversion_kind {
+enum conversion_kind {
ck_identity,
ck_lvalue,
+ ck_fnptr,
ck_qual,
ck_std,
ck_ptr,
ck_list,
ck_aggr,
ck_rvalue
-} conversion_kind;
+};
/* The rank of the conversion. Order of the enumerals matters; better
conversions should come earlier in the list. */
-typedef enum conversion_rank {
+enum conversion_rank {
cr_identity,
cr_exact,
cr_promotion,
cr_user,
cr_ellipsis,
cr_bad
-} conversion_rank;
+};
/* An implicit conversion sequence, in the sense of [over.best.ics].
The first conversion to be performed is at the end of the chain.
That conversion is always a cr_identity conversion. */
-typedef struct conversion conversion;
struct conversion {
/* The kind of conversion represented by this step. */
conversion_kind kind;
tsubst_flags_t);
static int compare_ics (conversion *, conversion *);
static tree build_over_call (struct z_candidate *, int, tsubst_flags_t);
-static tree build_java_interface_fn_ref (tree, tree);
#define convert_like(CONV, EXPR, COMPLAIN) \
convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0, \
/*issue_conversion_warnings=*/true, \
static struct z_candidate *add_template_candidate_real
(struct z_candidate **, tree, tree, tree, tree, const vec<tree, va_gc> *,
tree, tree, tree, int, tree, unification_kind_t, tsubst_flags_t);
-static struct z_candidate *add_template_conv_candidate
- (struct z_candidate **, tree, tree, tree, const vec<tree, va_gc> *,
- tree, tree, tree, tsubst_flags_t);
static void add_builtin_candidates
(struct z_candidate **, enum tree_code, enum tree_code,
tree, tree *, int, tsubst_flags_t);
(struct z_candidate **, tree, tree, tree, tree *, tree *,
int, tsubst_flags_t);
static struct z_candidate *add_conv_candidate
- (struct z_candidate **, tree, tree, tree, const vec<tree, va_gc> *, tree,
+ (struct z_candidate **, tree, tree, const vec<tree, va_gc> *, tree,
tree, tsubst_flags_t);
static struct z_candidate *add_function_candidate
(struct z_candidate **, tree, tree, tree, const vec<tree, va_gc> *, tree,
tree, int, tsubst_flags_t);
static conversion *implicit_conversion (tree, tree, tree, bool, int,
tsubst_flags_t);
-static conversion *standard_conversion (tree, tree, tree, bool, int);
static conversion *reference_binding (tree, tree, tree, bool, int,
tsubst_flags_t);
static conversion *build_conv (conversion_kind, tree, conversion *);
function = build_address (function);
}
else
- function = decay_conversion (function, complain);
+ function = decay_conversion (function, complain, /*reject_builtin=*/false);
return function;
}
/* New overloading code. */
-typedef struct z_candidate z_candidate;
+struct z_candidate;
-typedef struct candidate_warning candidate_warning;
struct candidate_warning {
z_candidate *loser;
candidate_warning *next;
rr_bad_arg_conversion,
rr_template_unification,
rr_invalid_copy,
+ rr_inherited_ctor,
rr_constraint_failure
};
bool
null_ptr_cst_p (tree t)
{
+ tree type = TREE_TYPE (t);
+
/* [conv.ptr]
A null pointer constant is an integral constant expression
(_expr.const_) rvalue of integer type that evaluates to zero or
an rvalue of type std::nullptr_t. */
- if (NULLPTR_TYPE_P (TREE_TYPE (t)))
+ if (NULLPTR_TYPE_P (type))
return true;
- if (CP_INTEGRAL_TYPE_P (TREE_TYPE (t)))
+
+ if (cxx_dialect >= cxx11)
{
/* Core issue 903 says only literal 0 is a null pointer constant. */
- if (cxx_dialect < cxx11)
- t = fold_non_dependent_expr (t);
+ if (TREE_CODE (type) == INTEGER_TYPE
+ && !char_type_p (type)
+ && TREE_CODE (t) == INTEGER_CST
+ && integer_zerop (t)
+ && !TREE_OVERFLOW (t))
+ return true;
+ }
+ else if (CP_INTEGRAL_TYPE_P (type))
+ {
+ t = fold_non_dependent_expr (t);
STRIP_NOPS (t);
if (integer_zerop (t) && !TREE_OVERFLOW (t))
return true;
}
+
return false;
}
return r;
}
+static struct rejection_reason *
+inherited_ctor_rejection (void)
+{
+ struct rejection_reason *r = alloc_rejection (rr_inherited_ctor);
+ return r;
+}
+
// Build a constraint failure record, saving information into the
// template_instantiation field of the rejection. If FN is not a template
// declaration, the TMPL member is the FN declaration and TARGS is empty.
return c;
}
-#ifdef ENABLE_CHECKING
-
/* Make sure that all memory on the conversion obstack has been
freed. */
== obstack_base (&conversion_obstack)));
}
-#endif /* ENABLE_CHECKING */
-
/* Dynamically allocate an array of N conversions. */
static conversion **
break;
case ck_qual:
+ case ck_fnptr:
if (rank < cr_exact)
rank = cr_exact;
break;
if (i < CONSTRUCTOR_NELTS (ctor))
val = CONSTRUCTOR_ELT (ctor, i)->value;
+ else if (DECL_INITIAL (field))
+ val = get_nsdmi (field, /*ctor*/false);
else if (TREE_CODE (ftype) == REFERENCE_TYPE)
/* Value-initialization of reference is ill-formed. */
return NULL;
static conversion *
standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
- int flags)
+ int flags, tsubst_flags_t complain)
{
enum tree_code fcode, tcode;
conversion *conv;
else if (TREE_CODE (to) == BOOLEAN_TYPE)
{
/* Necessary for eg, TEMPLATE_ID_EXPRs (c++/50961). */
- expr = resolve_nondeduced_context (expr);
+ expr = resolve_nondeduced_context (expr, complain);
from = TREE_TYPE (expr);
}
}
fcode = TREE_CODE (from);
conv = build_conv (ck_lvalue, from, conv);
}
- else if (fromref || (expr && lvalue_p (expr)))
+ /* Wrapping a ck_rvalue around a class prvalue (as a result of using
+ obvalue_p) seems odd, since it's already a prvalue, but that's how we
+ express the copy constructor call required by copy-initialization. */
+ else if (fromref || (expr && obvalue_p (expr)))
{
if (expr)
{
the standard conversion sequence to perform componentwise
conversion. */
conversion *part_conv = standard_conversion
- (TREE_TYPE (to), TREE_TYPE (from), NULL_TREE, c_cast_p, flags);
+ (TREE_TYPE (to), TREE_TYPE (from), NULL_TREE, c_cast_p, flags,
+ complain);
if (part_conv)
{
tree to_pointee;
tree from_pointee;
+ if (tcode == POINTER_TYPE)
+ {
+ to_pointee = TREE_TYPE (to);
+ from_pointee = TREE_TYPE (from);
+
+ /* Since this is the target of a pointer, it can't have function
+ qualifiers, so any TYPE_QUALS must be for attributes const or
+ noreturn. Strip them. */
+ if (TREE_CODE (to_pointee) == FUNCTION_TYPE
+ && TYPE_QUALS (to_pointee))
+ to_pointee = build_qualified_type (to_pointee, TYPE_UNQUALIFIED);
+ if (TREE_CODE (from_pointee) == FUNCTION_TYPE
+ && TYPE_QUALS (from_pointee))
+ from_pointee = build_qualified_type (from_pointee, TYPE_UNQUALIFIED);
+ }
+ else
+ {
+ to_pointee = TYPE_PTRMEM_POINTED_TO_TYPE (to);
+ from_pointee = TYPE_PTRMEM_POINTED_TO_TYPE (from);
+ }
+
if (tcode == POINTER_TYPE
- && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (from),
- TREE_TYPE (to)))
+ && same_type_ignoring_top_level_qualifiers_p (from_pointee,
+ to_pointee))
;
- else if (VOID_TYPE_P (TREE_TYPE (to))
+ else if (VOID_TYPE_P (to_pointee)
&& !TYPE_PTRDATAMEM_P (from)
- && TREE_CODE (TREE_TYPE (from)) != FUNCTION_TYPE)
+ && TREE_CODE (from_pointee) != FUNCTION_TYPE)
{
tree nfrom = TREE_TYPE (from);
/* Don't try to apply restrict to void. */
int quals = cp_type_quals (nfrom) & ~TYPE_QUAL_RESTRICT;
- from = build_pointer_type
- (cp_build_qualified_type (void_type_node, quals));
+ from_pointee = cp_build_qualified_type (void_type_node, quals);
+ from = build_pointer_type (from_pointee);
conv = build_conv (ck_ptr, from, conv);
}
else if (TYPE_PTRDATAMEM_P (from))
if (DERIVED_FROM_P (fbase, tbase)
&& (same_type_ignoring_top_level_qualifiers_p
- (TYPE_PTRMEM_POINTED_TO_TYPE (from),
- TYPE_PTRMEM_POINTED_TO_TYPE (to))))
+ (from_pointee, to_pointee)))
{
- from = build_ptrmem_type (tbase,
- TYPE_PTRMEM_POINTED_TO_TYPE (from));
+ from = build_ptrmem_type (tbase, from_pointee);
conv = build_conv (ck_pmem, from, conv);
}
else if (!same_type_p (fbase, tbase))
return NULL;
}
- else if (CLASS_TYPE_P (TREE_TYPE (from))
- && CLASS_TYPE_P (TREE_TYPE (to))
+ else if (CLASS_TYPE_P (from_pointee)
+ && CLASS_TYPE_P (to_pointee)
/* [conv.ptr]
An rvalue of type "pointer to cv D," where D is a
that necessitates this conversion is ill-formed.
Therefore, we use DERIVED_FROM_P, and do not check
access or uniqueness. */
- && DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from)))
+ && DERIVED_FROM_P (to_pointee, from_pointee))
{
- from =
- cp_build_qualified_type (TREE_TYPE (to),
- cp_type_quals (TREE_TYPE (from)));
- from = build_pointer_type (from);
+ from_pointee
+ = cp_build_qualified_type (to_pointee,
+ cp_type_quals (from_pointee));
+ from = build_pointer_type (from_pointee);
conv = build_conv (ck_ptr, from, conv);
conv->base_p = true;
}
- 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 (c_cast_p && comp_ptr_ttypes_const (to, from))
else if (expr && string_conv_p (to, expr, 0))
/* converting from string constant to char *. */
conv = build_conv (ck_qual, to, conv);
+ else if (fnptr_conv_p (to, from))
+ conv = build_conv (ck_fnptr, to, conv);
/* Allow conversions among compatible ObjC pointer types (base
conversions have been already handled above). */
else if (c_dialect_objc ()
tree fbase = class_of_this_parm (fromfn);
tree tbase = class_of_this_parm (tofn);
- if (!DERIVED_FROM_P (fbase, tbase)
- || !same_type_p (static_fn_type (fromfn),
- static_fn_type (tofn)))
+ if (!DERIVED_FROM_P (fbase, tbase))
+ return NULL;
+
+ tree fstat = static_fn_type (fromfn);
+ tree tstat = static_fn_type (tofn);
+ if (same_type_p (tstat, fstat)
+ || fnptr_conv_p (tstat, fstat))
+ /* OK */;
+ else
return NULL;
- from = build_memfn_type (fromfn,
- tbase,
- cp_type_quals (tbase),
- type_memfn_rqual (tofn));
- from = build_ptrmemfunc_type (build_pointer_type (from));
- conv = build_conv (ck_pmem, from, conv);
- conv->base_p = true;
+ if (!same_type_p (fbase, tbase))
+ {
+ from = build_memfn_type (fstat,
+ tbase,
+ cp_type_quals (tbase),
+ type_memfn_rqual (tofn));
+ from = build_ptrmemfunc_type (build_pointer_type (from));
+ conv = build_conv (ck_pmem, from, conv);
+ conv->base_p = true;
+ }
+ if (fnptr_conv_p (tstat, fstat))
+ conv = build_conv (ck_fnptr, to, conv);
}
else if (tcode == BOOLEAN_TYPE)
{
{
/* [dcl.init.ref]
- "cv1 T1" is reference compatible with "cv2 T2" if T1 is
- reference-related to T2 and cv1 is the same cv-qualification as,
- or greater cv-qualification than, cv2. */
- return (reference_related_p (t1, t2)
+ "cv1 T1" is reference compatible with "cv2 T2" if
+ * T1 is reference-related to T2 or
+ * T2 is "noexcept function" and T1 is "function", where the
+ function types are otherwise the same,
+ and cv1 is the same cv-qualification as, or greater cv-qualification
+ than, cv2. */
+ return ((reference_related_p (t1, t2)
+ || fnptr_conv_p (t1, t2))
&& at_least_as_qualified_p (t1, t2));
}
either an identity conversion or, if the conversion function
returns an entity of a type that is a derived class of the
parameter type, a derived-to-base conversion. */
- if (!same_type_ignoring_top_level_qualifiers_p (t, conv->type))
+ if (is_properly_derived_from (conv->type, t))
{
/* Represent the derived-to-base conversion. */
conv = build_conv (ck_base, t, conv);
gl_kind = clk_rvalueref;
}
else if (expr)
- {
- gl_kind = lvalue_kind (expr);
- if (gl_kind & clk_class)
- /* A class prvalue is not a glvalue. */
- gl_kind = clk_none;
- }
+ gl_kind = lvalue_kind (expr);
+ else if (CLASS_TYPE_P (from)
+ || TREE_CODE (from) == ARRAY_TYPE)
+ gl_kind = clk_class;
else
gl_kind = clk_none;
- is_lvalue = gl_kind && !(gl_kind & clk_rvalueref);
+
+ /* Don't allow a class prvalue when LOOKUP_NO_TEMP_BIND. */
+ if ((flags & LOOKUP_NO_TEMP_BIND)
+ && (gl_kind & clk_class))
+ gl_kind = clk_none;
+
+ /* Same mask as real_lvalue_p. */
+ is_lvalue = gl_kind && !(gl_kind & (clk_rvalueref|clk_class));
tfrom = from;
if ((gl_kind & clk_bitfield) != 0)
[8.5.3/5 dcl.init.ref] is changed to also require direct bindings for
const and rvalue references to rvalues of compatible class type.
We should also do direct bindings for non-class xvalues. */
- if (related_p
- && (gl_kind
- || (!(flags & LOOKUP_NO_TEMP_BIND)
- && (CLASS_TYPE_P (from)
- || TREE_CODE (from) == ARRAY_TYPE))))
+ if ((related_p || compatible_p) && gl_kind)
{
/* [dcl.init.ref]
if (TREE_CODE (to) == REFERENCE_TYPE)
conv = reference_binding (to, from, expr, c_cast_p, flags, complain);
else
- conv = standard_conversion (to, from, expr, c_cast_p, flags);
+ conv = standard_conversion (to, from, expr, c_cast_p, flags, complain);
if (conv)
return conv;
cand = build_user_type_conversion_1 (to, expr, flags, complain);
if (cand)
- conv = cand->second_conv;
+ {
+ if (BRACE_ENCLOSED_INITIALIZER_P (expr)
+ && CONSTRUCTOR_NELTS (expr) == 1
+ && !is_list_ctor (cand->fn))
+ {
+ /* "If C is not an initializer-list constructor and the
+ initializer list has a single element of type cv U, where U is
+ X or a class derived from X, the implicit conversion sequence
+ has Exact Match rank if U is X, or Conversion rank if U is
+ derived from X." */
+ tree elt = CONSTRUCTOR_ELT (expr, 0)->value;
+ tree elttype = TREE_TYPE (elt);
+ if (reference_related_p (to, elttype))
+ return implicit_conversion (to, elttype, elt,
+ c_cast_p, flags, complain);
+ }
+ conv = cand->second_conv;
+ }
/* We used to try to bind a reference to a temporary here, but that
is now handled after the recursive call to this function at the end
/* Return the number of remaining arguments in the parameter list
beginning with ARG. */
-static int
+int
remaining_arguments (tree arg)
{
int n;
}
}
+ /* Don't consider inherited constructors for initialization from an
+ expression of the same or derived type. */
+ /* FIXME extend to operator=. */
+ if (i == 0 && len == 1
+ && DECL_INHERITED_CTOR (fn)
+ && reference_related_p (ctype, argtype))
+ {
+ viable = 0;
+ reason = inherited_ctor_rejection ();
+ goto out;
+ }
+
/* Core issue 899: When [copy-]initializing a temporary to be bound
to the first parameter of a copy constructor (12.8) called with
a single argument in the context of direct-initialization,
static struct z_candidate *
add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
- tree first_arg, const vec<tree, va_gc> *arglist,
+ const vec<tree, va_gc> *arglist,
tree access_path, tree conversion_path,
tsubst_flags_t complain)
{
parmlist = TREE_TYPE (parmlist);
parmlist = TYPE_ARG_TYPES (parmlist);
- len = vec_safe_length (arglist) + (first_arg != NULL_TREE ? 1 : 0) + 1;
+ len = vec_safe_length (arglist) + 1;
convs = alloc_conversions (len);
parmnode = parmlist;
viable = 1;
if (i == 0)
arg = obj;
- else if (i == 1 && first_arg != NULL_TREE)
- arg = first_arg;
else
- arg = (*arglist)[i - (first_arg != NULL_TREE ? 1 : 0) - 1];
+ arg = (*arglist)[i - 1];
argtype = lvalue_type (arg);
if (i == 0)
reason = arity_rejection (NULL_TREE, i + remaining, len);
}
- return add_candidate (candidates, totype, first_arg, arglist, len, convs,
+ return add_candidate (candidates, totype, obj, arglist, len, convs,
access_path, conversion_path, viable, reason, flags);
}
case PREDECREMENT_EXPR:
if (TREE_CODE (type1) == BOOLEAN_TYPE)
return;
+ /* FALLTHRU */
case POSTINCREMENT_EXPR:
case PREINCREMENT_EXPR:
if (ARITHMETIC_TYPE_P (type1) || TYPE_PTROB_P (type1))
case UNARY_PLUS_EXPR: /* unary + */
if (TYPE_PTR_P (type1))
break;
+ /* FALLTHRU */
case NEGATE_EXPR:
if (ARITHMETIC_TYPE_P (type1))
break;
type2 = ptrdiff_type_node;
break;
}
+ /* FALLTHRU */
case MULT_EXPR:
case TRUNC_DIV_EXPR:
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
case PLUS_EXPR:
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
break;
+ /* FALLTHRU */
case ARRAY_REF:
if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type1) && TYPE_PTROB_P (type2))
{
type2 = ptrdiff_type_node;
break;
}
+ /* FALLTHRU */
case MULT_EXPR:
case TRUNC_DIV_EXPR:
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
if (code == COND_EXPR)
{
- if (real_lvalue_p (args[i]))
+ if (lvalue_p (args[i]))
vec_safe_push (types[i], build_reference_type (argtypes[i]));
vec_safe_push (types[i], TYPE_MAIN_VARIANT (argtypes[i]));
}
else
{
- if (code == COND_EXPR && real_lvalue_p (args[i]))
+ if (code == COND_EXPR && lvalue_p (args[i]))
vec_safe_push (types[i], build_reference_type (argtypes[i]));
type = non_reference (argtypes[i]);
if (i != 0 || ! ref1)
{
if (first_arg_without_in_chrg != NULL_TREE)
first_arg_without_in_chrg = NULL_TREE;
+ else if (return_type && strict == DEDUCE_CALL)
+ /* We're deducing for a call to the result of a template conversion
+ function, so the args don't contain 'this'; leave them alone. */;
else
++skip_without_in_chrg;
}
if (len < skip_without_in_chrg)
return NULL;
+ if (DECL_CONSTRUCTOR_P (tmpl) && nargs == 2
+ && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (first_arg),
+ TREE_TYPE ((*arglist)[0])))
+ {
+ /* 12.8/6 says, "A declaration of a constructor for a class X is
+ ill-formed if its first parameter is of type (optionally cv-qualified)
+ X and either there are no other parameters or else all other
+ parameters have default arguments. A member function template is never
+ instantiated to produce such a constructor signature."
+
+ So if we're trying to copy an object of the containing class, don't
+ consider a template constructor that has a first parameter type that
+ is just a template parameter, as we would deduce a signature that we
+ would then reject in the code below. */
+ if (tree firstparm = FUNCTION_FIRST_USER_PARMTYPE (tmpl))
+ {
+ firstparm = TREE_VALUE (firstparm);
+ if (PACK_EXPANSION_P (firstparm))
+ firstparm = PACK_EXPANSION_PATTERN (firstparm);
+ if (TREE_CODE (firstparm) == TEMPLATE_TYPE_PARM)
+ {
+ gcc_assert (!explicit_targs);
+ reason = invalid_copy_with_fn_template_rejection ();
+ goto fail;
+ }
+ }
+ }
+
nargs_without_in_chrg = ((first_arg_without_in_chrg != NULL_TREE ? 1 : 0)
+ (len - skip_without_in_chrg));
args_without_in_chrg = XALLOCAVEC (tree, nargs_without_in_chrg);
goto fail;
}
- /* In [class.copy]:
-
- A member function template is never instantiated to perform the
- copy of a class object to an object of its class type.
-
- It's a little unclear what this means; the standard explicitly
- does allow a template to be used to copy a class. For example,
- in:
-
- struct A {
- A(A&);
- template <class T> A(const T&);
- };
- const A f ();
- void g () { A a (f ()); }
-
- the member template will be used to make the copy. The section
- quoted above appears in the paragraph that forbids constructors
- whose only parameter is (a possibly cv-qualified variant of) the
- class type, and a logical interpretation is that the intent was
- to forbid the instantiation of member templates which would then
- have that form. */
if (DECL_CONSTRUCTOR_P (fn) && nargs == 2)
{
tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (fn);
if (arg_types && same_type_p (TYPE_MAIN_VARIANT (TREE_VALUE (arg_types)),
ctype))
{
+ /* We're trying to produce a constructor with a prohibited signature,
+ as discussed above; handle here any cases we didn't catch then,
+ such as X(X<T>). */
reason = invalid_copy_with_fn_template_rejection ();
goto fail;
}
if (obj != NULL_TREE)
/* Aha, this is a conversion function. */
- cand = add_conv_candidate (candidates, fn, obj, first_arg, arglist,
+ cand = add_conv_candidate (candidates, fn, obj, arglist,
access_path, conversion_path, complain);
else
cand = add_function_candidate (candidates, fn, ctype,
flags, NULL_TREE, strict, complain);
}
+/* Create an overload candidate for the conversion function template TMPL,
+ returning RETURN_TYPE, which will be invoked for expression OBJ to produce a
+ pointer-to-function which will in turn be called with the argument list
+ ARGLIST, and add it to CANDIDATES. This does not change ARGLIST. FLAGS is
+ passed on to implicit_conversion. */
static struct z_candidate *
add_template_conv_candidate (struct z_candidate **candidates, tree tmpl,
- tree obj, tree first_arg,
+ tree obj,
const vec<tree, va_gc> *arglist,
tree return_type, tree access_path,
tree conversion_path, tsubst_flags_t complain)
{
+ /* Making this work broke PR 71117, so until the committee resolves core
+ issue 2189, let's disable this candidate if there are any viable call
+ operators. */
+ if (any_strictly_viable (*candidates))
+ return NULL;
+
return
add_template_candidate_real (candidates, tmpl, NULL_TREE, NULL_TREE,
- first_arg, arglist, return_type, access_path,
- conversion_path, 0, obj, DEDUCE_CONV,
+ NULL_TREE, arglist, return_type, access_path,
+ conversion_path, 0, obj, DEDUCE_CALL,
complain);
}
const char *msg = (msgstr == NULL
? ""
: ACONCAT ((msgstr, " ", NULL)));
- location_t cloc = location_of (candidate->fn);
+ tree fn = candidate->fn;
+ if (flag_new_inheriting_ctors)
+ fn = strip_inheriting_ctors (fn);
+ location_t cloc = location_of (fn);
- if (identifier_p (candidate->fn))
+ if (identifier_p (fn))
{
cloc = loc;
if (candidate->num_convs == 3)
- inform (cloc, "%s%D(%T, %T, %T) <built-in>", msg, candidate->fn,
+ inform (cloc, "%s%D(%T, %T, %T) <built-in>", msg, fn,
candidate->convs[0]->type,
candidate->convs[1]->type,
candidate->convs[2]->type);
else if (candidate->num_convs == 2)
- inform (cloc, "%s%D(%T, %T) <built-in>", msg, candidate->fn,
+ inform (cloc, "%s%D(%T, %T) <built-in>", msg, fn,
candidate->convs[0]->type,
candidate->convs[1]->type);
else
- inform (cloc, "%s%D(%T) <built-in>", msg, candidate->fn,
+ inform (cloc, "%s%D(%T) <built-in>", msg, fn,
candidate->convs[0]->type);
}
- else if (TYPE_P (candidate->fn))
- inform (cloc, "%s%T <conversion>", msg, candidate->fn);
+ else if (TYPE_P (fn))
+ inform (cloc, "%s%T <conversion>", msg, fn);
else if (candidate->viable == -1)
- inform (cloc, "%s%#D <near match>", msg, candidate->fn);
- else if (DECL_DELETED_FN (candidate->fn))
- inform (cloc, "%s%#D <deleted>", msg, candidate->fn);
+ inform (cloc, "%s%#D <near match>", msg, fn);
+ else if (DECL_DELETED_FN (fn))
+ inform (cloc, "%s%#D <deleted>", msg, fn);
else
- inform (cloc, "%s%#D", msg, candidate->fn);
+ inform (cloc, "%s%#D", msg, fn);
+ if (fn != candidate->fn)
+ {
+ cloc = location_of (candidate->fn);
+ inform (cloc, " inherited here");
+ }
/* Give the user some information about why this candidate failed. */
if (candidate->reason != NULL)
{
diagnose_constraints (cloc, tmpl, args);
}
break;
+ case rr_inherited_ctor:
+ inform (cloc, " an inherited constructor is not a candidate for "
+ "initialization from an expression of the same or derived "
+ "type");
+ break;
case rr_none:
default:
/* This candidate didn't have any issues or we failed to
static void
add_list_candidates (tree fns, tree first_arg,
- tree init_list, tree totype,
+ const vec<tree, va_gc> *args, tree totype,
tree explicit_targs, bool template_only,
tree conversion_path, tree access_path,
int flags,
struct z_candidate **candidates,
tsubst_flags_t complain)
{
- vec<tree, va_gc> *args;
-
gcc_assert (*candidates == NULL);
/* We're looking for a ctor for list-initialization. */
avoid the copy constructor call for copy-list-initialization. */
flags |= LOOKUP_NO_NARROWING;
+ unsigned nart = num_artificial_parms_for (get_first_fn (fns)) - 1;
+ tree init_list = (*args)[nart];
+
/* Always use the default constructor if the list is empty (DR 990). */
if (CONSTRUCTOR_NELTS (init_list) == 0
&& TYPE_HAS_DEFAULT_CONSTRUCTOR (totype))
else if (TYPE_HAS_LIST_CTOR (totype))
{
flags |= LOOKUP_LIST_ONLY;
- args = make_tree_vector_single (init_list);
add_candidates (fns, first_arg, args, NULL_TREE,
explicit_targs, template_only, conversion_path,
access_path, flags, candidates, complain);
return;
}
- args = ctor_to_vec (init_list);
+ /* Expand the CONSTRUCTOR into a new argument vec. */
+ vec<tree, va_gc> *new_args;
+ vec_alloc (new_args, nart + CONSTRUCTOR_NELTS (init_list));
+ for (unsigned i = 0; i < nart; ++i)
+ new_args->quick_push ((*args)[i]);
+ for (unsigned i = 0; i < CONSTRUCTOR_NELTS (init_list); ++i)
+ new_args->quick_push (CONSTRUCTOR_ELT (init_list, i)->value);
/* We aren't looking for list-ctors anymore. */
flags &= ~LOOKUP_LIST_ONLY;
/* We allow more user-defined conversions within an init-list. */
flags &= ~LOOKUP_NO_CONVERSION;
- add_candidates (fns, first_arg, args, NULL_TREE,
+ add_candidates (fns, first_arg, new_args, NULL_TREE,
explicit_targs, template_only, conversion_path,
access_path, flags, candidates, complain);
}
creating a garbage BASELINK; constructors can't be inherited. */
ctors = lookup_fnfields_slot (totype, complete_ctor_identifier);
+ /* FIXME P0135 doesn't say what to do in C++17 about list-initialization from
+ a single element. For now, let's handle constructors as before and also
+ consider conversion operators from the element. */
+ if (cxx_dialect >= cxx1z
+ && BRACE_ENCLOSED_INITIALIZER_P (expr)
+ && CONSTRUCTOR_NELTS (expr) == 1)
+ fromtype = TREE_TYPE (CONSTRUCTOR_ELT (expr, 0)->value);
+
if (MAYBE_CLASS_TYPE_P (fromtype))
{
tree to_nonref = non_reference (totype);
gcc_assert (!DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors))
&& !DECL_HAS_VTT_PARM_P (OVL_CURRENT (ctors)));
+ args = make_tree_vector_single (expr);
if (BRACE_ENCLOSED_INITIALIZER_P (expr))
{
/* List-initialization. */
- add_list_candidates (ctors, first_arg, expr, totype, NULL_TREE,
+ add_list_candidates (ctors, first_arg, args, totype, NULL_TREE,
false, TYPE_BINFO (totype), TYPE_BINFO (totype),
ctorflags, &candidates, complain);
}
else
{
- args = make_tree_vector_single (expr);
add_candidates (ctors, first_arg, args, NULL_TREE, NULL_TREE, false,
TYPE_BINFO (totype), TYPE_BINFO (totype),
ctorflags, &candidates, complain);
}
if (conv_fns)
- first_arg = expr;
+ {
+ if (BRACE_ENCLOSED_INITIALIZER_P (expr))
+ /* FIXME see above about C++17. */
+ first_arg = CONSTRUCTOR_ELT (expr, 0)->value;
+ else
+ first_arg = expr;
+ }
for (; conv_fns; conv_fns = TREE_CHAIN (conv_fns))
{
if (complain & tf_error)
error_at (loc, "conversion from %qT to %qT not considered for "
"non-type template argument", t, type);
- /* and fall through. */
+ /* fall through. */
default:
conv = NULL;
tree
build_operator_new_call (tree fnname, vec<tree, va_gc> **args,
- tree *size, tree *cookie_size, tree size_check,
+ tree *size, tree *cookie_size,
+ tree align_arg, tree size_check,
tree *fn, tsubst_flags_t complain)
{
tree original_size = *size;
tree fns;
struct z_candidate *candidates;
- struct z_candidate *cand;
+ struct z_candidate *cand = NULL;
bool any_viable_p;
if (fn)
we disregard block-scope declarations of "operator new". */
fns = lookup_function_nonclass (fnname, *args, /*block_p=*/false);
+ if (align_arg)
+ {
+ vec<tree, va_gc>* align_args
+ = vec_copy_and_insert (*args, align_arg, 1);
+ cand = perform_overload_resolution (fns, align_args, &candidates,
+ &any_viable_p, tf_none);
+ /* If no aligned allocation function matches, try again without the
+ alignment. */
+ }
+
/* Figure out what function is being called. */
- cand = perform_overload_resolution (fns, *args, &candidates, &any_viable_p,
- complain);
+ if (!cand)
+ cand = perform_overload_resolution (fns, *args, &candidates, &any_viable_p,
+ complain);
/* If no suitable function could be found, issue an error message
and give up. */
{
/* Update the total size. */
*size = size_binop (PLUS_EXPR, original_size, *cookie_size);
- /* Set to (size_t)-1 if the size check fails. */
- gcc_assert (size_check != NULL_TREE);
- *size = fold_build3 (COND_EXPR, sizetype, size_check,
- *size, TYPE_MAX_VALUE (sizetype));
+ if (size_check)
+ {
+ /* Set to (size_t)-1 if the size check fails. */
+ gcc_assert (size_check != NULL_TREE);
+ *size = fold_build3 (COND_EXPR, sizetype, size_check,
+ *size, TYPE_MAX_VALUE (sizetype));
+ }
/* Update the argument list to reflect the adjusted size. */
(**args)[0] = *size;
}
if (TREE_CODE (fn) == TEMPLATE_DECL)
add_template_conv_candidate
- (&candidates, fn, obj, NULL_TREE, *args, totype,
+ (&candidates, fn, obj, *args, totype,
/*access_path=*/NULL_TREE,
/*conversion_path=*/NULL_TREE, complain);
else
- add_conv_candidate (&candidates, fn, obj, NULL_TREE,
+ add_conv_candidate (&candidates, fn, obj,
*args, /*conversion_path=*/NULL_TREE,
/*access_path=*/NULL_TREE, complain);
}
result = build_over_call (cand, LOOKUP_NORMAL, complain);
else
{
- obj = convert_like_with_context (cand->convs[0], obj, cand->fn, -1,
- complain);
+ if (DECL_P (cand->fn))
+ obj = convert_like_with_context (cand->convs[0], obj, cand->fn,
+ -1, complain);
+ else
+ obj = convert_like (cand->convs[0], obj, complain);
obj = convert_from_reference (obj);
result = cp_build_function_call_vec (obj, args, complain);
}
If E2 is an xvalue: E1 can be converted to match E2 if E1 can be
implicitly converted to the type "rvalue reference to T2", subject to
the constraint that the reference must bind directly. */
- if (lvalue_or_rvalue_with_address_p (e2))
+ if (glvalue_p (e2))
{
- tree rtype = cp_build_reference_type (t2, !real_lvalue_p (e2));
+ tree rtype = cp_build_reference_type (t2, !lvalue_p (e2));
conv = implicit_conversion (rtype,
t1,
e1,
tree arg3_type;
tree result = NULL_TREE;
tree result_type = NULL_TREE;
- bool lvalue_p = true;
+ bool is_lvalue = true;
struct z_candidate *candidates = 0;
struct z_candidate *cand;
void *p;
if (!arg2)
{
if (complain & tf_error)
- pedwarn (loc, OPT_Wpedantic,
+ pedwarn (loc, OPT_Wpedantic,
"ISO C++ forbids omitting the middle term of a ?: expression");
+ if ((complain & tf_warning) && !truth_value_p (TREE_CODE (arg1)))
+ warn_for_omitted_condop (loc, arg1);
+
/* Make sure that lvalues remain lvalues. See g++.oliva/ext1.C. */
- if (real_lvalue_p (arg1))
- arg2 = arg1 = stabilize_reference (arg1);
+ if (lvalue_p (arg1))
+ arg2 = arg1 = cp_stabilize_reference (arg1);
else
arg2 = arg1 = save_expr (arg1);
}
if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (arg1)))
{
+ tree arg1_type = TREE_TYPE (arg1);
+
+ /* If arg1 is another cond_expr choosing between -1 and 0,
+ then we can use its comparison. It may help to avoid
+ additional comparison, produce more accurate diagnostics
+ and enables folding. */
+ if (TREE_CODE (arg1) == VEC_COND_EXPR
+ && integer_minus_onep (TREE_OPERAND (arg1, 1))
+ && integer_zerop (TREE_OPERAND (arg1, 2)))
+ arg1 = TREE_OPERAND (arg1, 0);
+
arg1 = force_rvalue (arg1, complain);
arg2 = force_rvalue (arg2, complain);
arg3 = force_rvalue (arg3, complain);
|| error_operand_p (arg3))
return error_mark_node;
- tree arg1_type = TREE_TYPE (arg1);
arg2_type = TREE_TYPE (arg2);
arg3_type = TREE_TYPE (arg3);
}
if (!COMPARISON_CLASS_P (arg1))
- arg1 = cp_build_binary_op (loc, NE_EXPR, arg1,
- build_zero_cst (arg1_type), complain);
- return fold_build3 (VEC_COND_EXPR, arg2_type, arg1, arg2, arg3);
+ {
+ tree cmp_type = build_same_sized_truth_vector_type (arg1_type);
+ arg1 = build2 (NE_EXPR, cmp_type, arg1, build_zero_cst (arg1_type));
+ }
+ return build3_loc (loc, VEC_COND_EXPR, arg2_type, arg1, arg2, arg3);
}
/* [expr.cond]
return error_mark_node;
}
- lvalue_p = false;
+ is_lvalue = false;
goto valid_operands;
}
/* [expr.cond]
&& (CLASS_TYPE_P (arg2_type) || CLASS_TYPE_P (arg3_type)
|| (same_type_ignoring_top_level_qualifiers_p (arg2_type,
arg3_type)
- && lvalue_or_rvalue_with_address_p (arg2)
- && lvalue_or_rvalue_with_address_p (arg3)
- && real_lvalue_p (arg2) == real_lvalue_p (arg3))))
+ && glvalue_p (arg2) && glvalue_p (arg3)
+ && lvalue_p (arg2) == lvalue_p (arg3))))
{
conversion *conv2;
conversion *conv3;
If the second and third operands are glvalues of the same value
category and have the same type, the result is of that type and
value category. */
- if (((real_lvalue_p (arg2) && real_lvalue_p (arg3))
+ if (((lvalue_p (arg2) && lvalue_p (arg3))
|| (xvalue_p (arg2) && xvalue_p (arg3)))
&& same_type_p (arg2_type, arg3_type))
{
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 = false;
+ is_lvalue = false;
if (!same_type_p (arg2_type, arg3_type)
&& (CLASS_TYPE_P (arg2_type) || CLASS_TYPE_P (arg3_type)))
{
return error_mark_node;
valid_operands:
- result = build3 (COND_EXPR, result_type, arg1, arg2, arg3);
- if (!cp_unevaluated_operand)
- /* Avoid folding within decltype (c++/42013) and noexcept. */
- result = fold_if_not_in_template (result);
+ result = build3_loc (loc, COND_EXPR, result_type, arg1, arg2, arg3);
/* We can't use result_type below, as fold might have returned a
throw_expr. */
- if (!lvalue_p)
+ if (!is_lvalue)
{
/* Expand both sides into the same slot, hopefully the target of
the ?: expression. We used to check for TARGET_EXPRs here,
}
}
+/* Returns 1 if P0145R2 says that the LHS of operator CODE is evaluated first,
+ -1 if the RHS is evaluated first, or 0 if the order is unspecified. */
+
+static int
+op_is_ordered (tree_code code)
+{
+ switch (code)
+ {
+ // 5. b @= a
+ case MODIFY_EXPR:
+ return (flag_strong_eval_order > 1 ? -1 : 0);
+
+ // 6. a[b]
+ case ARRAY_REF:
+ return (flag_strong_eval_order > 1 ? 1 : 0);
+
+ // 1. a.b
+ // Not overloadable (yet).
+ // 2. a->b
+ // Only one argument.
+ // 3. a->*b
+ case MEMBER_REF:
+ // 7. a << b
+ case LSHIFT_EXPR:
+ // 8. a >> b
+ case RSHIFT_EXPR:
+ return (flag_strong_eval_order ? 1 : 0);
+
+ default:
+ return 0;
+ }
+}
+
static tree
build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
tree arg2, tree arg3, tree *overload, tsubst_flags_t complain)
case MODIFY_EXPR:
if (code2 != NOP_EXPR)
break;
+ /* FALLTHRU */
case COMPONENT_REF:
case ARRAY_REF:
memonly = true;
result = error_mark_node;
else
result = build_over_call (cand, LOOKUP_NORMAL, complain);
+
+ if (trivial_fn_p (cand->fn))
+ /* There won't be a CALL_EXPR. */;
+ else if (result && result != error_mark_node)
+ {
+ tree call = extract_call_expr (result);
+ CALL_EXPR_OPERATOR_SYNTAX (call) = true;
+
+ if (processing_template_decl && DECL_HIDDEN_FRIEND_P (cand->fn))
+ /* This prevents build_new_function_call from discarding this
+ function during instantiation of the enclosing template. */
+ KOENIG_LOOKUP_P (call) = 1;
+
+ /* Specify evaluation order as per P0145R2. */
+ CALL_EXPR_ORDERED_ARGS (call) = false;
+ switch (op_is_ordered (code))
+ {
+ case -1:
+ CALL_EXPR_REVERSE_ARGS (call) = true;
+ break;
+
+ case 1:
+ CALL_EXPR_ORDERED_ARGS (call) = true;
+ break;
+
+ default:
+ break;
+ }
+ }
}
else
{
switch (code)
{
case MODIFY_EXPR:
- return cp_build_modify_expr (arg1, code2, arg2, complain);
+ return cp_build_modify_expr (loc, arg1, code2, arg2, complain);
case INDIRECT_REF:
return cp_build_indirect_ref (arg1, RO_UNARY_STAR, complain);
case TRUTH_OR_EXPR:
if (complain & tf_warning)
warn_logical_operator (loc, code, boolean_type_node,
- code_orig_arg1, arg1, code_orig_arg2, arg2);
+ code_orig_arg1, arg1,
+ code_orig_arg2, arg2);
/* Fall through. */
case GT_EXPR:
case LT_EXPR:
return ret;
}
+/* CALL was returned by some call-building function; extract the actual
+ CALL_EXPR from any bits that have been tacked on, e.g. by
+ convert_from_reference. */
+
+tree
+extract_call_expr (tree call)
+{
+ while (TREE_CODE (call) == COMPOUND_EXPR)
+ call = TREE_OPERAND (call, 1);
+ if (REFERENCE_REF_P (call))
+ call = TREE_OPERAND (call, 0);
+ if (TREE_CODE (call) == TARGET_EXPR)
+ call = TARGET_EXPR_INITIAL (call);
+ gcc_assert (TREE_CODE (call) == CALL_EXPR
+ || TREE_CODE (call) == AGGR_INIT_EXPR
+ || call == error_mark_node);
+ return call;
+}
+
/* Returns true if FN has two parameters, of which the second has type
size_t. */
second_parm_is_size_t (tree fn)
{
tree t = FUNCTION_ARG_CHAIN (fn);
- return (t
- && same_type_p (TREE_VALUE (t), size_type_node)
- && TREE_CHAIN (t) == void_list_node);
+ if (!t || !same_type_p (TREE_VALUE (t), size_type_node))
+ return false;
+ t = TREE_CHAIN (t);
+ if (t == void_list_node)
+ return true;
+ if (aligned_new_threshold && t
+ && same_type_p (TREE_VALUE (t), align_type_node)
+ && TREE_CHAIN (t) == void_list_node)
+ return true;
+ return false;
+}
+
+/* True if T, an allocation function, has std::align_val_t as its second
+ argument. */
+
+bool
+aligned_allocation_fn_p (tree t)
+{
+ if (!aligned_new_threshold)
+ return false;
+
+ tree a = FUNCTION_ARG_CHAIN (t);
+ return (a && same_type_p (TREE_VALUE (a), align_type_node));
+}
+
+/* Returns true iff T, an element of an OVERLOAD chain, is a usual deallocation
+ function (3.7.4.2 [basic.stc.dynamic.deallocation]) with a parameter of
+ std::align_val_t. */
+
+static bool
+aligned_deallocation_fn_p (tree t)
+{
+ if (!aligned_new_threshold)
+ return false;
+
+ /* A template instance is never a usual deallocation function,
+ regardless of its signature. */
+ if (TREE_CODE (t) == TEMPLATE_DECL
+ || primary_template_instantiation_p (t))
+ return false;
+
+ tree a = FUNCTION_ARG_CHAIN (t);
+ if (same_type_p (TREE_VALUE (a), align_type_node)
+ && TREE_CHAIN (a) == void_list_node)
+ return true;
+ if (!same_type_p (TREE_VALUE (a), size_type_node))
+ return false;
+ a = TREE_CHAIN (a);
+ if (a && same_type_p (TREE_VALUE (a), align_type_node)
+ && TREE_CHAIN (a) == void_list_node)
+ return true;
+ return false;
}
/* Returns true iff T, an element of an OVERLOAD chain, is a usual
deallocation function (3.7.4.2 [basic.stc.dynamic.deallocation]). */
bool
-non_placement_deallocation_fn_p (tree t)
+usual_deallocation_fn_p (tree t)
{
/* A template instance is never a usual deallocation function,
regardless of its signature. */
of which has type std::size_t (18.2), then this function is a usual
deallocation function. */
bool global = DECL_NAMESPACE_SCOPE_P (t);
- if (FUNCTION_ARG_CHAIN (t) == void_list_node
+ tree chain = FUNCTION_ARG_CHAIN (t);
+ if (!chain)
+ return false;
+ if (chain == void_list_node
|| ((!global || flag_sized_deallocation)
&& second_parm_is_size_t (t)))
return true;
+ if (aligned_deallocation_fn_p (t))
+ return true;
return false;
}
t; t = OVL_NEXT (t))
{
tree elt = OVL_CURRENT (t);
- if (non_placement_deallocation_fn_p (elt)
+ if (usual_deallocation_fn_p (elt)
&& FUNCTION_ARG_CHAIN (elt) == void_list_node)
goto ok;
}
t; t = OVL_NEXT (t))
{
tree elt = OVL_CURRENT (t);
- if (non_placement_deallocation_fn_p (elt))
+ if (usual_deallocation_fn_p (elt))
{
- fn = elt;
- /* "If a class T has a member deallocation function named
- operator delete with exactly one parameter, then that
- function is a usual (non-placement) deallocation
- function. If class T does not declare such an operator
- delete but does declare a member deallocation function named
- operator delete with exactly two parameters, the second of
- which has type std::size_t (18.2), then this function is a
- usual deallocation function."
-
- So in a class (void*) beats (void*, size_t). */
- if (DECL_CLASS_SCOPE_P (fn))
+ if (!fn)
{
- if (FUNCTION_ARG_CHAIN (fn) == void_list_node)
- break;
+ fn = elt;
+ continue;
}
- /* At global scope (in C++14 and above) the rules are different:
-
- If deallocation function lookup finds both a usual
- deallocation function with only a pointer parameter and a
- usual deallocation function with both a pointer parameter
- and a size parameter, the function to be called is selected
- as follows:
-
- * If the type is complete and if, for the second alternative
- (delete array) only, the operand is a pointer to a class
- type with a non-trivial destructor or a (possibly
- multi-dimensional) array thereof, the function with two
- parameters is selected.
-
- * Otherwise, it is unspecified which of the two deallocation
- functions is selected. */
+
+ /* -- If the type has new-extended alignment, a function with a
+ parameter of type std::align_val_t is preferred; otherwise a
+ function without such a parameter is preferred. If exactly one
+ preferred function is found, that function is selected and the
+ selection process terminates. If more than one preferred
+ function is found, all non-preferred functions are eliminated
+ from further consideration. */
+ if (aligned_new_threshold)
+ {
+ bool want_align = type_has_new_extended_alignment (type);
+ bool fn_align = aligned_deallocation_fn_p (fn);
+ bool elt_align = aligned_deallocation_fn_p (elt);
+
+ if (elt_align != fn_align)
+ {
+ if (want_align == elt_align)
+ fn = elt;
+ continue;
+ }
+ }
+
+ /* -- If the deallocation functions have class scope, the one
+ without a parameter of type std::size_t is selected. */
+ bool want_size;
+ if (DECL_CLASS_SCOPE_P (fn))
+ want_size = false;
+
+ /* -- If the type is complete and if, for the second alternative
+ (delete array) only, the operand is a pointer to a class type
+ with a non-trivial destructor or a (possibly multi-dimensional)
+ array thereof, the function with a parameter of type std::size_t
+ is selected.
+
+ -- Otherwise, it is unspecified whether a deallocation function
+ with a parameter of type std::size_t is selected. */
else
{
- bool want_size = COMPLETE_TYPE_P (type);
+ want_size = COMPLETE_TYPE_P (type);
if (code == VEC_DELETE_EXPR
&& !TYPE_VEC_NEW_USES_COOKIE (type))
/* We need a cookie to determine the array size. */
want_size = false;
- bool have_size = (FUNCTION_ARG_CHAIN (fn) != void_list_node);
- if (want_size == have_size)
- break;
}
+ bool fn_size = second_parm_is_size_t (fn);
+ bool elt_size = second_parm_is_size_t (elt);
+ gcc_assert (fn_size != elt_size);
+ if (want_size == elt_size)
+ fn = elt;
}
}
tree ret;
vec<tree, va_gc> *args = make_tree_vector ();
args->quick_push (addr);
- if (FUNCTION_ARG_CHAIN (fn) != void_list_node)
+ if (second_parm_is_size_t (fn))
args->quick_push (size);
+ if (aligned_deallocation_fn_p (fn))
+ {
+ tree al = build_int_cst (align_type_node, TYPE_ALIGN_UNIT (type));
+ args->quick_push (al);
+ }
ret = cp_build_function_call_vec (fn, &args, complain);
release_tree_vector (args);
return ret;
{
gcc_assert (TREE_CODE (basetype_path) == TREE_BINFO);
+ if (flag_new_inheriting_ctors
+ && DECL_INHERITED_CTOR (decl))
+ {
+ /* 7.3.3/18: The additional constructors are accessible if they would be
+ accessible when used to construct an object of the corresponding base
+ class. */
+ decl = strip_inheriting_ctors (decl);
+ basetype_path = TYPE_BINFO (DECL_CONTEXT (decl));
+ }
+
if (!accessible_p (basetype_path, decl, true))
{
if (complain & tf_error)
{
+ if (flag_new_inheriting_ctors)
+ diag_decl = strip_inheriting_ctors (diag_decl);
if (TREE_PRIVATE (decl))
{
error ("%q#D is private within this context", diag_decl);
int savew, savee;
vec<tree, va_gc> *args;
+ *diagnostic_kind = DK_UNSPECIFIED;
+
+ /* If the source is a packed field, calling the copy constructor will require
+ binding the field to the reference parameter to the copy constructor, and
+ we'll end up with an infinite loop. If we can use a bitwise copy, then
+ do that now. */
+ if ((lvalue_kind (expr) & clk_packed)
+ && CLASS_TYPE_P (TREE_TYPE (expr))
+ && !type_has_nontrivial_copy_init (TREE_TYPE (expr)))
+ return get_target_expr_sfinae (expr, complain);
+
savew = warningcount + werrorcount, savee = errorcount;
args = make_tree_vector_single (expr);
expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
*diagnostic_kind = DK_WARNING;
else if (errorcount > savee)
*diagnostic_kind = DK_ERROR;
- else
- *diagnostic_kind = DK_UNSPECIFIED;
return expr;
}
{
struct z_candidate *cand = convs->cand;
tree convfn = cand->fn;
- unsigned i;
- /* If we're initializing from {}, it's value-initialization. Note
- that under the resolution of core 1630, value-initialization can
- use explicit constructors. */
+ /* When converting from an init list we consider explicit
+ constructors, but actually trying to call one is an error. */
+ if (DECL_NONCONVERTING_P (convfn) && DECL_CONSTRUCTOR_P (convfn)
+ && BRACE_ENCLOSED_INITIALIZER_P (expr)
+ /* Unless this is for direct-list-initialization. */
+ && !CONSTRUCTOR_IS_DIRECT_INIT (expr)
+ /* And in C++98 a default constructor can't be explicit. */
+ && cxx_dialect >= cxx11)
+ {
+ if (!(complain & tf_error))
+ return error_mark_node;
+ location_t loc = location_of (expr);
+ if (CONSTRUCTOR_NELTS (expr) == 0
+ && FUNCTION_FIRST_USER_PARMTYPE (convfn) != void_list_node)
+ {
+ if (pedwarn (loc, 0, "converting to %qT from initializer list "
+ "would use explicit constructor %qD",
+ totype, convfn))
+ inform (loc, "in C++11 and above a default constructor "
+ "can be explicit");
+ }
+ else
+ error ("converting to %qT from initializer list would use "
+ "explicit constructor %qD", totype, convfn);
+ }
+
+ /* If we're initializing from {}, it's value-initialization. */
if (BRACE_ENCLOSED_INITIALIZER_P (expr)
&& CONSTRUCTOR_NELTS (expr) == 0
&& TYPE_HAS_DEFAULT_CONSTRUCTOR (totype))
return expr;
}
- /* When converting from an init list we consider explicit
- constructors, but actually trying to call one is an error. */
- if (DECL_NONCONVERTING_P (convfn) && DECL_CONSTRUCTOR_P (convfn)
- /* Unless this is for direct-list-initialization. */
- && !DIRECT_LIST_INIT_P (expr))
- {
- if (!(complain & tf_error))
- return error_mark_node;
- error ("converting to %qT from initializer list would use "
- "explicit constructor %qD", totype, convfn);
- }
-
expr = mark_rvalue_use (expr);
- /* Set user_conv_p on the argument conversions, so rvalue/base
- handling knows not to allow any more UDCs. */
- for (i = 0; i < cand->num_convs; ++i)
- cand->convs[i]->user_conv_p = true;
-
- expr = build_over_call (cand, LOOKUP_NORMAL, complain);
+ /* Pass LOOKUP_NO_CONVERSION so rvalue/base handling knows not to allow
+ any more UDCs. */
+ expr = build_over_call (cand, LOOKUP_NORMAL|LOOKUP_NO_CONVERSION,
+ complain);
/* If this is a constructor or a function returning an aggr type,
we need to build up a TARGET_EXPR. */
imag = perform_implicit_conversion (TREE_TYPE (totype),
imag, complain);
expr = build2 (COMPLEX_EXPR, totype, real, imag);
- return fold_if_not_in_template (expr);
+ return expr;
}
expr = reshape_init (totype, expr, complain);
expr = get_target_expr_sfinae (digest_init (totype, expr, complain),
case ck_rvalue:
expr = decay_conversion (expr, complain);
if (expr == error_mark_node)
- return error_mark_node;
+ {
+ if (complain & tf_error)
+ {
+ maybe_print_user_conv_context (convs);
+ if (fn)
+ inform (DECL_SOURCE_LOCATION (fn),
+ " initializing argument %P of %qD", argnum, fn);
+ }
+ return error_mark_node;
+ }
if (! MAYBE_CLASS_TYPE_P (totype))
return expr;
- /* Else fall through. */
+
+ /* Don't introduce copies when passing arguments along to the inherited
+ constructor. */
+ if (current_function_decl
+ && flag_new_inheriting_ctors
+ && DECL_INHERITED_CTOR (current_function_decl)
+ && TREE_ADDRESSABLE (totype))
+ return expr;
+
+ /* Fall through. */
case ck_base:
if (convs->kind == ck_base && !convs->need_temporary_p)
{
{
tree extype = TREE_TYPE (expr);
if (TYPE_REF_IS_RVALUE (ref_type)
- && real_lvalue_p (expr))
- error_at (loc, "cannot bind %qT lvalue to %qT",
- extype, totype);
- else if (!TYPE_REF_IS_RVALUE (ref_type) && !real_lvalue_p (expr)
+ && lvalue_p (expr))
+ error_at (loc, "cannot bind rvalue reference of type %qT to "
+ "lvalue of type %qT", totype, extype);
+ else if (!TYPE_REF_IS_RVALUE (ref_type) && !lvalue_p (expr)
&& !CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (ref_type)))
- error_at (loc, "invalid initialization of non-const reference of "
- "type %qT from an rvalue of type %qT", totype, extype);
+ error_at (loc, "cannot bind non-const lvalue reference of "
+ "type %qT to an rvalue of type %qT", totype, extype);
else if (!reference_compatible_p (TREE_TYPE (totype), extype))
- error_at (loc, "binding %qT to reference of type %qT "
- "discards qualifiers", extype, totype);
+ error_at (loc, "binding reference of type %qT to %qT "
+ "discards qualifiers", totype, extype);
else
gcc_unreachable ();
maybe_print_user_conv_context (convs);
for a non-reference copy-initialization (8.5). */
tree type = TREE_TYPE (ref_type);
- cp_lvalue_kind lvalue = real_lvalue_p (expr);
+ cp_lvalue_kind lvalue = lvalue_kind (expr);
gcc_assert (same_type_ignoring_top_level_qualifiers_p
(type, next_conversion (convs)->type));
case ck_lvalue:
return decay_conversion (expr, complain);
+ case ck_fnptr:
+ /* ??? Should the address of a transaction-safe pointer point to the TM
+ clone, and this conversion look up the primary function? */
+ return build_nop (totype, expr);
+
case ck_qual:
/* Warn about deprecated conversion if appropriate. */
string_conv_p (totype, expr, 1);
"implicit conversion from %qT to %qT when passing "
"argument to function",
arg_type, double_type_node);
- arg = convert_to_real (double_type_node, arg);
+ arg = convert_to_real_nofold (double_type_node, arg);
}
else if (NULLPTR_TYPE_P (arg_type))
arg = null_pointer_node;
return convert_from_reference (expr);
}
- return build_va_arg (loc, expr, type);
+ tree ret = build_va_arg (loc, expr, type);
+ if (CLASS_TYPE_P (type))
+ /* Wrap the VA_ARG_EXPR in a TARGET_EXPR now so other code doesn't need to
+ know how to handle it. */
+ ret = get_target_expr (ret);
+ return ret;
}
/* TYPE has been given to va_arg. Apply the default conversions which
/* See through clones. */
fn = DECL_ORIGIN (fn);
+ /* And inheriting ctors. */
+ if (flag_new_inheriting_ctors)
+ fn = strip_inheriting_ctors (fn);
/* Detect recursion. */
FOR_EACH_VEC_SAFE_ELT (default_arg_context, i, t)
bitfield_type = is_bitfield_expr_with_lowered_type (val);
if (bitfield_type
&& TYPE_PRECISION (TREE_TYPE (val)) < TYPE_PRECISION (type))
- val = convert_to_integer (TYPE_MAIN_VARIANT (bitfield_type), val);
+ val = convert_to_integer_nofold (TYPE_MAIN_VARIANT (bitfield_type), val);
if (val == error_mark_node)
;
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. */
+/* Returns non-zero iff FN is a function with magic varargs, i.e. ones for
+ which just decay_conversion or no conversions at all should be done.
+ This is true for some builtins which don't act like normal functions.
+ Return 2 if no conversions at all should be done, 1 if just
+ decay_conversion. Return 3 for special treatment of the 3rd argument
+ for __builtin_*_overflow_p. */
-bool
+int
magic_varargs_p (tree fn)
{
if (flag_cilkplus && is_cilkplus_reduce_builtin (fn) != BUILT_IN_NONE)
- return true;
+ return 2;
- if (DECL_BUILT_IN (fn))
+ if (DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL)
switch (DECL_FUNCTION_CODE (fn))
{
case BUILT_IN_CLASSIFY_TYPE:
case BUILT_IN_CONSTANT_P:
case BUILT_IN_NEXT_ARG:
case BUILT_IN_VA_START:
- return true;
+ return 1;
+
+ case BUILT_IN_ADD_OVERFLOW_P:
+ case BUILT_IN_SUB_OVERFLOW_P:
+ case BUILT_IN_MUL_OVERFLOW_P:
+ return 3;
default:;
return lookup_attribute ("type generic",
TYPE_ATTRIBUTES (TREE_TYPE (fn))) != 0;
}
- return false;
+ return 0;
}
/* Returns the decl of the dispatcher function if FN is a function version. */
return r;
}
+/* Return true iff T refers to a base field. */
+
+static bool
+is_base_field_ref (tree t)
+{
+ STRIP_NOPS (t);
+ if (TREE_CODE (t) == ADDR_EXPR)
+ t = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == COMPONENT_REF)
+ t = TREE_OPERAND (t, 1);
+ if (TREE_CODE (t) == FIELD_DECL)
+ return DECL_FIELD_IS_BASE (t);
+ return false;
+}
+
+/* We can't elide a copy from a function returning by value to a base
+ subobject, as the callee might clobber tail padding. Return true iff this
+ could be that case. */
+
+static bool
+unsafe_copy_elision_p (tree target, tree exp)
+{
+ /* Copy elision only happens with a TARGET_EXPR. */
+ if (TREE_CODE (exp) != TARGET_EXPR)
+ return false;
+ tree type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
+ /* It's safe to elide the copy for a class with no tail padding. */
+ if (tree_int_cst_equal (TYPE_SIZE (type), CLASSTYPE_SIZE (type)))
+ return false;
+ /* It's safe to elide the copy if we aren't initializing a base object. */
+ if (!is_base_field_ref (target))
+ return false;
+ tree init = TARGET_EXPR_INITIAL (exp);
+ /* build_compound_expr pushes COMPOUND_EXPR inside TARGET_EXPR. */
+ while (TREE_CODE (init) == COMPOUND_EXPR)
+ init = TREE_OPERAND (init, 1);
+ return (TREE_CODE (init) == AGGR_INIT_EXPR
+ && !AGGR_INIT_VIA_CTOR_P (init));
+}
+
/* 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
" (you can disable this with -fno-deduce-init-list)");
}
}
+
+ /* Set user_conv_p on the argument conversions, so rvalue/base handling
+ knows not to allow any more UDCs. This needs to happen after we
+ process cand->warnings. */
+ if (flags & LOOKUP_NO_CONVERSION)
+ conv->user_conv_p = true;
+
val = convert_like_with_context (conv, arg, fn, i - is_method,
conversion_warning
? complain
}
/* Ellipsis */
+ int magic = magic_varargs_p (fn);
for (; arg_index < vec_safe_length (args); ++arg_index)
{
tree a = (*args)[arg_index];
- if (magic_varargs_p (fn))
- /* Do no conversions for magic varargs. */
- a = mark_type_use (a);
+ if ((magic == 3 && arg_index == 2) || magic == 2)
+ {
+ /* Do no conversions for certain magic varargs. */
+ a = mark_type_use (a);
+ if (TREE_CODE (a) == FUNCTION_DECL && reject_gcc_builtin (a))
+ return error_mark_node;
+ }
+ else if (magic != 0)
+ /* For other magic varargs only do decay_conversion. */
+ a = decay_conversion (a, complain);
else if (DECL_CONSTRUCTOR_P (fn)
&& same_type_ignoring_top_level_qualifiers_p (DECL_CONTEXT (fn),
TREE_TYPE (a)))
}
else
a = convert_arg_to_ellipsis (a, complain);
+ if (a == error_mark_node)
+ return error_mark_node;
argarray[j++] = a;
}
gcc_assert (j <= nargs);
nargs = j;
- check_function_arguments (TREE_TYPE (fn), nargs, argarray);
+ /* Avoid to do argument-transformation, if warnings for format, and for
+ nonnull are disabled. Just in case that at least one of them is active
+ the check_function_arguments function might warn about something. */
+
+ if (warn_nonnull || warn_format || warn_suggest_attribute_format)
+ {
+ tree *fargs = (!nargs ? argarray
+ : (tree *) alloca (nargs * sizeof (tree)));
+ for (j = 0; j < nargs; j++)
+ fargs[j] = maybe_constant_value (argarray[j]);
+
+ check_function_arguments (input_location, TREE_TYPE (fn), nargs, fargs);
+ }
+
+ if (DECL_INHERITED_CTOR (fn))
+ {
+ /* Check for passing ellipsis arguments to an inherited constructor. We
+ could handle this by open-coding the inherited constructor rather than
+ defining it, but let's not bother now. */
+ if (!cp_unevaluated_operand
+ && cand->convs[cand->num_convs-1]->ellipsis_p)
+ {
+ if (complain & tf_error)
+ {
+ sorry ("passing arguments to ellipsis of inherited constructor "
+ "%qD", cand->fn);
+ inform (DECL_SOURCE_LOCATION (cand->fn), "declared here");
+ }
+ return error_mark_node;
+ }
+
+ /* A base constructor inheriting from a virtual base doesn't get the
+ inherited arguments, just this and __vtt. */
+ if (ctor_omit_inherited_parms (fn))
+ nargs = 2;
+ }
/* Avoid actually calling copy constructors and copy assignment operators,
if possible. */
else
arg = cp_build_indirect_ref (arg, RO_NULL, complain);
+ /* In C++17 we shouldn't be copying a TARGET_EXPR except into a base
+ subobject. */
+ if (CHECKING_P && cxx_dialect >= cxx1z)
+ gcc_assert (TREE_CODE (arg) != TARGET_EXPR
+ || seen_error ()
+ /* See unsafe_copy_elision_p. */
+ || DECL_BASE_CONSTRUCTOR_P (fn));
+
/* [class.copy]: the copy constructor is implicitly defined even if
the implementation elided its use. */
if (!trivial || DECL_DELETED_FN (fn))
else if (trivial)
return force_target_expr (DECL_CONTEXT (fn), arg, complain);
}
- else if (TREE_CODE (arg) == TARGET_EXPR || trivial)
+ else if ((trivial || TREE_CODE (arg) == TARGET_EXPR)
+ && !unsafe_copy_elision_p (fa, arg))
{
- tree to = stabilize_reference (cp_build_indirect_ref (fa, RO_NULL,
- complain));
+ tree to = cp_stabilize_reference (cp_build_indirect_ref (fa,
+ RO_NULL,
+ complain));
val = build2 (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
return val;
&& trivial_fn_p (fn)
&& !DECL_DELETED_FN (fn))
{
- tree to = stabilize_reference
+ tree to = cp_stabilize_reference
(cp_build_indirect_ref (argarray[0], RO_NULL, complain));
tree type = TREE_TYPE (to);
tree as_base = CLASSTYPE_AS_BASE (type);
if (is_really_empty_class (type))
{
/* Avoid copying empty classes. */
- val = build2 (COMPOUND_EXPR, void_type_node, to, arg);
- TREE_NO_WARNING (val) = 1;
- val = build2 (COMPOUND_EXPR, type, val, to);
+ val = build2 (COMPOUND_EXPR, type, arg, to);
TREE_NO_WARNING (val) = 1;
}
else if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base)))
arg2 = TYPE_SIZE_UNIT (as_base);
arg0 = cp_build_addr_expr (to, complain);
- array_type = build_array_type (char_type_node,
+ array_type = build_array_type (unsigned_char_type_node,
build_index_type
(size_binop (MINUS_EXPR,
arg2, size_int (1))));
return val;
}
- else if (DECL_DESTRUCTOR_P (fn)
- && trivial_fn_p (fn)
- && !DECL_DELETED_FN (fn))
- return fold_convert (void_type_node, argarray[0]);
- /* FIXME handle trivial default constructor, too. */
+ else if (!DECL_DELETED_FN (fn)
+ && trivial_fn_p (fn))
+ {
+ if (DECL_DESTRUCTOR_P (fn))
+ return fold_convert (void_type_node, argarray[0]);
+ else if (default_ctor_p (fn))
+ {
+ if (is_dummy_object (argarray[0]))
+ return force_target_expr (DECL_CONTEXT (fn), void_node, complain);
+ else
+ return cp_build_indirect_ref (argarray[0], RO_NULL, complain);
+ }
+ }
/* For calls to a multi-versioned function, overload resolution
returns the function with the highest target priority, that is,
if (TREE_SIDE_EFFECTS (argarray[0]))
argarray[0] = save_expr (argarray[0]);
t = build_pointer_type (TREE_TYPE (fn));
- if (DECL_CONTEXT (fn) && TYPE_JAVA_INTERFACE (DECL_CONTEXT (fn)))
- fn = build_java_interface_fn_ref (fn, argarray[0]);
- else
- fn = build_vfn_ref (argarray[0], DECL_VINDEX (fn));
+ fn = build_vfn_ref (argarray[0], DECL_VINDEX (fn));
TREE_TYPE (fn) = t;
}
else
}
tree call = build_cxx_call (fn, nargs, argarray, complain|decltype_flag);
- if (TREE_CODE (call) == CALL_EXPR
- && (cand->flags & LOOKUP_LIST_INIT_CTOR))
- CALL_EXPR_LIST_INIT_P (call) = true;
+ if (call == error_mark_node)
+ return call;
+ if (cand->flags & LOOKUP_LIST_INIT_CTOR)
+ {
+ tree c = extract_call_expr (call);
+ /* build_new_op_1 will clear this when appropriate. */
+ CALL_EXPR_ORDERED_ARGS (c) = true;
+ }
+ if (current_function_decl
+ && flag_new_inheriting_ctors
+ && DECL_INHERITED_CTOR (current_function_decl)
+ && cand->num_convs)
+ /* Don't introduce copies when passing arguments along to the inherited
+ constructor. */
+ CALL_FROM_THUNK_P (call) = true;
return call;
}
tsubst_flags_t complain)
{
tree fndecl;
- int optimize_sav;
/* Remember roughly where this call is. */
location_t loc = EXPR_LOC_OR_LOC (fn, input_location);
/* Check that arguments to builtin functions match the expectations. */
if (fndecl
&& DECL_BUILT_IN (fndecl)
- && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
- && !check_builtin_function_arguments (fndecl, nargs, argarray))
- return error_mark_node;
+ && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+ {
+ int i;
+
+ /* We need to take care that values to BUILT_IN_NORMAL
+ are reduced. */
+ for (i = 0; i < nargs; i++)
+ argarray[i] = fold_non_dependent_expr (argarray[i]);
+
+ if (!check_builtin_function_arguments (EXPR_LOCATION (fn), vNULL, fndecl,
+ nargs, argarray))
+ return error_mark_node;
+ }
/* If it is a built-in array notation function, then the return type of
the function is the element type of the array passed in as array
}
}
- /* Some built-in function calls will be evaluated at compile-time in
- fold (). Set optimize to 1 when folding __builtin_constant_p inside
- a constexpr function so that fold_builtin_1 doesn't fold it to 0. */
- optimize_sav = optimize;
- if (!optimize && fndecl && DECL_IS_BUILTIN_CONSTANT_P (fndecl)
- && current_function_decl
- && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
- optimize = 1;
- fn = fold_if_not_in_template (fn);
- optimize = optimize_sav;
-
if (VOID_TYPE_P (TREE_TYPE (fn)))
return fn;
return convert_from_reference (fn);
}
-static GTY(()) tree java_iface_lookup_fn;
-
-/* Make an expression which yields the address of the Java interface
- method FN. This is achieved by generating a call to libjava's
- _Jv_LookupInterfaceMethodIdx(). */
-
-static tree
-build_java_interface_fn_ref (tree fn, tree instance)
-{
- tree lookup_fn, method, idx;
- tree klass_ref, iface, iface_ref;
- int i;
-
- if (!java_iface_lookup_fn)
- {
- tree ftype = build_function_type_list (ptr_type_node,
- ptr_type_node, ptr_type_node,
- java_int_type_node, NULL_TREE);
- java_iface_lookup_fn
- = add_builtin_function ("_Jv_LookupInterfaceMethodIdx", ftype,
- 0, NOT_BUILT_IN, NULL, NULL_TREE);
- }
-
- /* Look up the pointer to the runtime java.lang.Class object for `instance'.
- This is the first entry in the vtable. */
- klass_ref = build_vtbl_ref (cp_build_indirect_ref (instance, RO_NULL,
- tf_warning_or_error),
- integer_zero_node);
-
- /* Get the java.lang.Class pointer for the interface being called. */
- iface = DECL_CONTEXT (fn);
- iface_ref = lookup_field (iface, get_identifier ("class$"), 0, false);
- if (!iface_ref || !VAR_P (iface_ref)
- || DECL_CONTEXT (iface_ref) != iface)
- {
- error ("could not find class$ field in java interface type %qT",
- iface);
- return error_mark_node;
- }
- iface_ref = build_address (iface_ref);
- iface_ref = convert (build_pointer_type (iface), iface_ref);
-
- /* Determine the itable index of FN. */
- i = 1;
- for (method = TYPE_METHODS (iface); method; method = DECL_CHAIN (method))
- {
- if (!DECL_VIRTUAL_P (method))
- continue;
- if (fn == method)
- break;
- i++;
- }
- idx = build_int_cst (NULL_TREE, i);
-
- lookup_fn = build1 (ADDR_EXPR,
- build_pointer_type (TREE_TYPE (java_iface_lookup_fn)),
- java_iface_lookup_fn);
- return build_call_nary (ptr_type_node, lookup_fn,
- 3, klass_ref, iface_ref, idx);
-}
-
/* Returns the value to use for the in-charge parameter when making a
call to a function with the indicated NAME.
return NULL_TREE;
}
+/* We've built up a constructor call RET. Complain if it delegates to the
+ constructor we're currently compiling. */
+
+static void
+check_self_delegation (tree ret)
+{
+ if (TREE_CODE (ret) == TARGET_EXPR)
+ ret = TARGET_EXPR_INITIAL (ret);
+ tree fn = cp_get_callee_fndecl (ret);
+ if (fn && DECL_ABSTRACT_ORIGIN (fn) == current_function_decl)
+ error ("constructor delegates to itself");
+}
+
/* Build a call to a constructor, destructor, or an assignment
operator for INSTANCE, an expression with class type. NAME
indicates the special member function to call; *ARGS are the
gcc_assert (instance != NULL_TREE);
+ /* In C++17, "If the initializer expression is a prvalue and the
+ cv-unqualified version of the source type is the same class as the class
+ of the destination, the initializer expression is used to initialize the
+ destination object." Handle that here to avoid doing overload
+ resolution. */
+ if (cxx_dialect >= cxx1z
+ && args && vec_safe_length (*args) == 1
+ && name == complete_ctor_identifier)
+ {
+ tree arg = (**args)[0];
+
+ /* FIXME P0135 doesn't say how to handle direct initialization from a
+ type with a suitable conversion operator. Let's handle it like
+ copy-initialization, but allowing explict conversions. */
+ if (!reference_related_p (class_type, TREE_TYPE (arg)))
+ arg = perform_implicit_conversion_flags (class_type, arg,
+ tf_warning, flags);
+ if (TREE_CODE (arg) == TARGET_EXPR
+ && (same_type_ignoring_top_level_qualifiers_p
+ (class_type, TREE_TYPE (arg))))
+ {
+ if (is_dummy_object (instance))
+ return arg;
+ if ((complain & tf_error)
+ && (flags & LOOKUP_DELEGATING_CONS))
+ check_self_delegation (arg);
+ /* Avoid change of behavior on Wunused-var-2.C. */
+ mark_lvalue_use (instance);
+ return build2 (INIT_EXPR, class_type, instance, arg);
+ }
+ }
+
fns = lookup_fnfields (binfo, name, 1);
/* When making a call to a constructor or destructor for a subobject
vtt = decay_conversion (vtt, complain);
if (vtt == error_mark_node)
return error_mark_node;
- vtt = build3 (COND_EXPR, TREE_TYPE (vtt),
- build2 (EQ_EXPR, boolean_type_node,
- current_in_charge_parm, integer_zero_node),
- current_vtt_parm,
- vtt);
+ vtt = build_if_in_charge (vtt, current_vtt_parm);
if (BINFO_SUBVTT_INDEX (binfo))
sub_vtt = fold_build_pointer_plus (vtt, BINFO_SUBVTT_INDEX (binfo));
else
if ((complain & tf_error)
&& (flags & LOOKUP_DELEGATING_CONS)
- && name == complete_ctor_identifier
- && TREE_CODE (ret) == CALL_EXPR
- && (DECL_ABSTRACT_ORIGIN (TREE_OPERAND (CALL_EXPR_FN (ret), 0))
- == current_function_decl))
- error ("constructor delegates to itself");
+ && name == complete_ctor_identifier)
+ check_self_delegation (ret);
return ret;
}
/* Get the high-water mark for the CONVERSION_OBSTACK. */
p = conversion_obstack_alloc (0);
+ /* The number of arguments artificial parms in ARGS; we subtract one because
+ there's no 'this' in ARGS. */
+ unsigned skip = num_artificial_parms_for (fn) - 1;
+
/* If CONSTRUCTOR_IS_DIRECT_INIT is set, this was a T{ } form
initializer, not T({ }). */
- if (DECL_CONSTRUCTOR_P (fn) && args != NULL && !vec_safe_is_empty (*args)
- && DIRECT_LIST_INIT_P ((**args)[0]))
+ if (DECL_CONSTRUCTOR_P (fn)
+ && vec_safe_length (user_args) > skip
+ && DIRECT_LIST_INIT_P ((*user_args)[skip]))
{
- tree init_list = (**args)[0];
+ tree init_list = (*user_args)[skip];
tree init = NULL_TREE;
- gcc_assert ((*args)->length () == 1
+ gcc_assert (user_args->length () == skip + 1
&& !(flags & LOOKUP_ONLYCONVERTING));
/* If the initializer list has no elements and T is a class type with
}
/* Otherwise go ahead with overload resolution. */
- add_list_candidates (fns, first_mem_arg, init_list,
+ add_list_candidates (fns, first_mem_arg, user_args,
basetype, explicit_targs, template_only,
conversion_path, access_binfo, flags,
&candidates, complain);
we know we really need it. */
cand->first_arg = instance;
}
+ else if (any_dependent_bases_p ())
+ /* We can't tell until instantiation time whether we can use
+ *this as the implicit object argument. */;
else
{
if (complain & tf_error)
ics2 = next_conversion (ics2);
+ while (ics2->kind == ck_rvalue
+ || ics2->kind == ck_lvalue)
+ ics2 = next_conversion (ics2);
+
if (ics2->kind == ics1->kind
&& same_type_p (ics2->type, ics1->type)
- && same_type_p (next_conversion (ics2)->type,
- next_conversion (ics1)->type))
+ && (ics1->kind == ck_identity
+ || same_type_p (next_conversion (ics2)->type,
+ next_conversion (ics1)->type)))
return true;
}
}
return winner;
}
+ /* or, if not that, F2 is from a using-declaration, F1 is not, and the
+ conversion sequences are equivalent.
+ (proposed in http://lists.isocpp.org/core/2016/10/1142.php) */
+ if (DECL_P (cand1->fn) && DECL_CLASS_SCOPE_P (cand1->fn)
+ && !DECL_CONV_FN_P (cand1->fn)
+ && DECL_P (cand2->fn) && DECL_CLASS_SCOPE_P (cand2->fn)
+ && !DECL_CONV_FN_P (cand2->fn))
+ {
+ bool used1 = (DECL_INHERITED_CTOR (cand1->fn)
+ || (BINFO_TYPE (cand1->access_path)
+ != DECL_CONTEXT (cand1->fn)));
+ bool used2 = (DECL_INHERITED_CTOR (cand2->fn)
+ || (BINFO_TYPE (cand2->access_path)
+ != DECL_CONTEXT (cand2->fn)));
+ if (int diff = used2 - used1)
+ {
+ for (i = 0; i < len; ++i)
+ {
+ conversion *t1 = cand1->convs[i + off1];
+ conversion *t2 = cand2->convs[i + off2];
+ if (!same_type_p (t1->type, t2->type))
+ break;
+ }
+ if (i == len)
+ return diff;
+ }
+ }
+
/* Check whether we can discard a builtin candidate, either because we
have two identical ones or matching builtin and non-builtin candidates.
"default argument mismatch in "
"overload resolution"))
{
- inform (input_location,
- " candidate 1: %q+#F", cand1->fn);
- inform (input_location,
- " candidate 2: %q+#F", cand2->fn);
+ inform (DECL_SOURCE_LOCATION (cand1->fn),
+ " candidate 1: %q#F", cand1->fn);
+ inform (DECL_SOURCE_LOCATION (cand2->fn),
+ " candidate 2: %q#F", cand2->fn);
}
}
else
convert_like (conv, expr, complain);
else if (!CP_TYPE_CONST_P (TREE_TYPE (type))
&& !TYPE_REF_IS_RVALUE (type)
- && !real_lvalue_p (expr))
+ && !lvalue_p (expr))
error_at (loc, "invalid initialization of non-const reference of "
"type %qT from an rvalue of type %qT",
type, TREE_TYPE (expr));
return init;
if (TREE_CODE (type) == REFERENCE_TYPE)
init = extend_ref_init_temps_1 (decl, init, cleanups);
- else if (is_std_init_list (type))
+ else
{
- /* The temporary array underlying a std::initializer_list
- is handled like a reference temporary. */
tree ctor = init;
if (TREE_CODE (ctor) == TARGET_EXPR)
ctor = TARGET_EXPR_INITIAL (ctor);
if (TREE_CODE (ctor) == CONSTRUCTOR)
{
- tree array = CONSTRUCTOR_ELT (ctor, 0)->value;
- array = extend_ref_init_temps_1 (decl, array, cleanups);
- CONSTRUCTOR_ELT (ctor, 0)->value = array;
+ if (is_std_init_list (type))
+ {
+ /* The temporary array underlying a std::initializer_list
+ is handled like a reference temporary. */
+ tree array = CONSTRUCTOR_ELT (ctor, 0)->value;
+ array = extend_ref_init_temps_1 (decl, array, cleanups);
+ CONSTRUCTOR_ELT (ctor, 0)->value = array;
+ }
+ else
+ {
+ unsigned i;
+ constructor_elt *p;
+ vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (ctor);
+ FOR_EACH_VEC_SAFE_ELT (elts, i, p)
+ p->value = extend_ref_init_temps (decl, p->value, cleanups);
+ }
}
}
- else if (TREE_CODE (init) == CONSTRUCTOR)
- {
- unsigned i;
- constructor_elt *p;
- vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (init);
- FOR_EACH_VEC_SAFE_ELT (elts, i, p)
- p->value = extend_ref_init_temps (decl, p->value, cleanups);
- }
return init;
}