/* Build expressions with type checking for C++ compiler.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
#include "cp-tree.h"
#include "flags.h"
#include "output.h"
-#include "toplev.h"
#include "diagnostic.h"
#include "intl.h"
#include "target.h"
#include "convert.h"
#include "c-family/c-common.h"
+#include "c-family/c-objc.h"
#include "params.h"
static tree pfn_from_ptrmemfunc (tree);
/* Do `exp = require_complete_type (exp);' to make sure exp
does not have an incomplete type. (That includes void types.)
- Returns the error_mark_node if the VALUE does not have
+ Returns error_mark_node if the VALUE does not have
complete type when this function returns. */
tree
-require_complete_type (tree value)
+require_complete_type_sfinae (tree value, tsubst_flags_t complain)
{
tree type;
if (COMPLETE_TYPE_P (type))
return value;
- if (complete_type_or_else (type, value))
+ if (complete_type_or_maybe_complain (type, value, complain))
return value;
else
return error_mark_node;
}
+tree
+require_complete_type (tree value)
+{
+ return require_complete_type_sfinae (value, tf_warning_or_error);
+}
+
/* Try to complete TYPE, if it is incomplete. For example, if TYPE is
a template instantiation, do the instantiation. Returns TYPE,
whether or not it could be completed, unless something goes
return cp_common_type (t1, t2);
}
+static void
+composite_pointer_error (diagnostic_t kind, tree t1, tree t2,
+ composite_pointer_operation operation)
+{
+ switch (operation)
+ {
+ case CPO_COMPARISON:
+ emit_diagnostic (kind, input_location, 0,
+ "comparison between "
+ "distinct pointer types %qT and %qT lacks a cast",
+ t1, t2);
+ break;
+ case CPO_CONVERSION:
+ emit_diagnostic (kind, input_location, 0,
+ "conversion between "
+ "distinct pointer types %qT and %qT lacks a cast",
+ t1, t2);
+ break;
+ case CPO_CONDITIONAL_EXPR:
+ emit_diagnostic (kind, input_location, 0,
+ "conditional expression between "
+ "distinct pointer types %qT and %qT lacks a cast",
+ t1, t2);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+}
+
/* Subroutine of composite_pointer_type to implement the recursive
case. See that function for documentation of the parameters. */
else
{
if (complain & tf_error)
- {
- switch (operation)
- {
- case CPO_COMPARISON:
- permerror (input_location, "comparison between "
- "distinct pointer types %qT and %qT lacks a cast",
- t1, t2);
- break;
- case CPO_CONVERSION:
- permerror (input_location, "conversion between "
- "distinct pointer types %qT and %qT lacks a cast",
- t1, t2);
- break;
- case CPO_CONDITIONAL_EXPR:
- permerror (input_location, "conditional expression between "
- "distinct pointer types %qT and %qT lacks a cast",
- t1, t2);
- break;
- default:
- gcc_unreachable ();
- }
- }
+ composite_pointer_error (DK_PERMERROR, t1, t2, operation);
+ else
+ return error_mark_node;
result_type = void_type_node;
}
result_type = cp_build_qualified_type (result_type,
if (TYPE_PTR_TO_MEMBER_P (t1))
{
if (!same_type_p (TYPE_PTRMEM_CLASS_TYPE (t1),
- TYPE_PTRMEM_CLASS_TYPE (t2))
- && (complain & tf_error))
- {
- switch (operation)
- {
- case CPO_COMPARISON:
- permerror (input_location, "comparison between "
- "distinct pointer types %qT and %qT lacks a cast",
- t1, t2);
- break;
- case CPO_CONVERSION:
- permerror (input_location, "conversion between "
- "distinct pointer types %qT and %qT lacks a cast",
- t1, t2);
- break;
- case CPO_CONDITIONAL_EXPR:
- permerror (input_location, "conditional expression between "
- "distinct pointer types %qT and %qT lacks a cast",
- t1, t2);
- break;
- default:
- gcc_unreachable ();
- }
- }
+ TYPE_PTRMEM_CLASS_TYPE (t2)))
+ {
+ if (complain & tf_error)
+ composite_pointer_error (DK_PERMERROR, t1, t2, operation);
+ else
+ return error_mark_node;
+ }
result_type = build_ptrmem_type (TYPE_PTRMEM_CLASS_TYPE (t1),
result_type);
}
if (c_dialect_objc () && TREE_CODE (t1) == POINTER_TYPE
&& TREE_CODE (t2) == POINTER_TYPE)
{
- if (objc_compare_types (t1, t2, -3, NULL_TREE))
- return t1;
+ if (objc_have_common_type (t1, t2, -3, NULL_TREE))
+ return objc_common_type (t1, t2);
}
/* [expr.eq] permits the application of a pointer conversion to
else
{
if (complain & tf_error)
- switch (operation)
- {
- case CPO_COMPARISON:
- error ("comparison between distinct "
- "pointer types %qT and %qT lacks a cast", t1, t2);
- break;
- case CPO_CONVERSION:
- error ("conversion between distinct "
- "pointer types %qT and %qT lacks a cast", t1, t2);
- break;
- case CPO_CONDITIONAL_EXPR:
- error ("conditional expression between distinct "
- "pointer types %qT and %qT lacks a cast", t1, t2);
- break;
- default:
- gcc_unreachable ();
- }
+ composite_pointer_error (DK_ERROR, t1, t2, operation);
return error_mark_node;
}
}
gcc_assert (type_memfn_quals (t1) == type_memfn_quals (t2));
rval = apply_memfn_quals (rval, type_memfn_quals (t1));
raises = merge_exception_specifiers (TYPE_RAISES_EXCEPTIONS (t1),
- TYPE_RAISES_EXCEPTIONS (t2));
+ TYPE_RAISES_EXCEPTIONS (t2),
+ NULL_TREE);
t1 = build_exception_variant (rval, raises);
break;
}
{
/* Get this value the long way, since TYPE_METHOD_BASETYPE
is just the main variant of this. */
- tree basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t2)));
+ tree basetype = class_of_this_parm (t2);
tree raises = merge_exception_specifiers (TYPE_RAISES_EXCEPTIONS (t1),
- TYPE_RAISES_EXCEPTIONS (t2));
+ TYPE_RAISES_EXCEPTIONS (t2),
+ NULL_TREE);
tree t3;
/* If this was a member function type, get back to the
/* First handle noexcept. */
if (exact < ce_exact)
{
- /* noexcept(false) is compatible with any throwing dynamic-exc-spec
+ /* noexcept(false) is compatible with no exception-specification,
and stricter than any spec. */
if (t1 == noexcept_false_spec)
- return !nothrow_spec_p (t2) || exact == ce_derived;
- /* Even a derived noexcept(false) is compatible with a throwing
- dynamic spec. */
+ return t2 == NULL_TREE || exact == ce_derived;
+ /* Even a derived noexcept(false) is compatible with no
+ exception-specification. */
if (t2 == noexcept_false_spec)
- return !nothrow_spec_p (t1);
+ return t1 == NULL_TREE;
/* Otherwise, if we aren't looking for an exact match, noexcept is
equivalent to throw(). */
static bool
comp_template_parms_position (tree t1, tree t2)
{
+ tree index1, index2;
gcc_assert (t1 && t2
&& TREE_CODE (t1) == TREE_CODE (t2)
&& (TREE_CODE (t1) == BOUND_TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (t1) == TEMPLATE_TYPE_PARM));
- if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
- || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
- || (TEMPLATE_TYPE_PARAMETER_PACK (t1)
- != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
- return false;
-
- return true;
-}
-
-/* Subroutine of incompatible_dependent_types_p.
- Return the template parameter of the dependent type T.
- If T is a typedef, return the template parameters of
- the _decl_ of the typedef. T must be a dependent type. */
-
-static tree
-get_template_parms_of_dependent_type (tree t)
-{
- tree tinfo = NULL_TREE, tparms = NULL_TREE;
+ index1 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t1));
+ index2 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t2));
- /* First, try the obvious case of getting the
- template info from T itself. */
- if ((tinfo = get_template_info (t)))
- ;
- else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
- return TEMPLATE_TYPE_PARM_SIBLING_PARMS (t);
- else if (typedef_variant_p (t)
- && !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
- tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t)));
- /* If T is a TYPENAME_TYPE which context is a template type
- parameter, get the template parameters from that context. */
- else if (TYPE_CONTEXT (t)
- && TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM)
- return TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_CONTEXT (t));
- else if (TYPE_CONTEXT (t)
- && !NAMESPACE_SCOPE_P (t))
- tinfo = get_template_info (TYPE_CONTEXT (t));
-
- if (tinfo)
- tparms = DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo));
-
- return tparms;
-}
-
-/* Subroutine of structural_comptypes.
- Compare the dependent types T1 and T2.
- Return TRUE if we are sure they can't be equal, FALSE otherwise.
- The whole point of this function is to support cases where either T1 or
- T2 is a typedef. In those cases, we need to compare the template parameters
- of the _decl_ of the typedef. If those don't match then we know T1
- and T2 cannot be equal. */
-
-static bool
-incompatible_dependent_types_p (tree t1, tree t2)
-{
- tree tparms1 = NULL_TREE, tparms2 = NULL_TREE;
- bool t1_typedef_variant_p, t2_typedef_variant_p;
-
- if (!uses_template_parms (t1) || !uses_template_parms (t2))
+ /* If T1 and T2 belong to template parm lists of different size,
+ let's assume they are different. */
+ if (TEMPLATE_PARM_NUM_SIBLINGS (index1)
+ != TEMPLATE_PARM_NUM_SIBLINGS (index2))
return false;
- if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM)
- {
- /* If T1 and T2 don't have the same relative position in their
- template parameters set, they can't be equal. */
- if (!comp_template_parms_position (t1, t2))
- return true;
- }
-
- t1_typedef_variant_p = typedef_variant_p (t1);
- t2_typedef_variant_p = typedef_variant_p (t2);
-
- /* Either T1 or T2 must be a typedef. */
- if (!t1_typedef_variant_p && !t2_typedef_variant_p)
+ /* Then compare their relative position. */
+ if (TEMPLATE_PARM_IDX (index1) != TEMPLATE_PARM_IDX (index2)
+ || TEMPLATE_PARM_LEVEL (index1) != TEMPLATE_PARM_LEVEL (index2)
+ || (TEMPLATE_PARM_PARAMETER_PACK (index1)
+ != TEMPLATE_PARM_PARAMETER_PACK (index2)))
return false;
- if (!t1_typedef_variant_p || !t2_typedef_variant_p)
- /* Either T1 or T2 is not a typedef so we cannot compare the
- template parms of the typedefs of T1 and T2.
- At this point, if the main variant type of T1 and T2 are equal
- it means the two types can't be incompatible, from the perspective
- of this function. */
- if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
- return false;
-
- /* So if we reach this point, it means either T1 or T2 is a typedef variant.
- Let's compare their template parameters. */
-
- tparms1 = get_template_parms_of_dependent_type (t1);
- tparms2 = get_template_parms_of_dependent_type (t2);
-
- /* If T2 is a template type parm and if we could not get the template
- parms it belongs to, that means we have not finished parsing the
- full set of template parameters of the template declaration it
- belongs to yet. If we could get the template parms T1 belongs to,
- that mostly means T1 and T2 belongs to templates that are
- different and incompatible. */
- if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM
- && (tparms1 == NULL_TREE || tparms2 == NULL_TREE)
- && tparms1 != tparms2)
- return true;
-
- if (tparms1 == NULL_TREE
- || tparms2 == NULL_TREE
- || tparms1 == tparms2)
- return false;
-
- /* And now compare the mighty template parms! */
- return !comp_template_parms (tparms1, tparms2);
+ return true;
}
/* Subroutine in comptypes. */
if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
return false;
- /* If T1 and T2 are dependent typedefs then check upfront that
- the template parameters of their typedef DECLs match before
- going down checking their subtypes. */
- if (incompatible_dependent_types_p (t1, t2))
- return false;
-
/* Allow for two different type nodes which have essentially the same
definition. Note that we already checked for equality of the type
qualifiers (just above). */
break;
case TEMPLATE_TYPE_PARM:
- /* If incompatible_dependent_types_p called earlier didn't decide
- T1 and T2 were different, they might be equal. */
+ /* If T1 and T2 don't have the same relative position in their
+ template parameters set, they can't be equal. */
+ if (!comp_template_parms_position (t1, t2))
+ return false;
break;
case TYPENAME_TYPE:
!= DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t2)
|| (DECLTYPE_FOR_LAMBDA_CAPTURE (t1)
!= DECLTYPE_FOR_LAMBDA_CAPTURE (t2))
- || (DECLTYPE_FOR_LAMBDA_RETURN (t1)
- != DECLTYPE_FOR_LAMBDA_RETURN (t2))
+ || (DECLTYPE_FOR_LAMBDA_PROXY (t1)
+ != DECLTYPE_FOR_LAMBDA_PROXY (t2))
|| !cp_tree_equal (DECLTYPE_TYPE_EXPR (t1),
DECLTYPE_TYPE_EXPR (t2)))
return false;
break;
+ case UNDERLYING_TYPE:
+ return same_type_p (UNDERLYING_TYPE_TYPE (t1),
+ UNDERLYING_TYPE_TYPE (t2));
+
default:
return false;
}
/* If we get here, we know that from a target independent POV the
types are the same. Make sure the target attributes are also
the same. */
- return targetm.comp_type_attributes (t1, t2);
+ return comp_type_attributes (t1, t2);
}
/* Return true if T1 and T2 are related as allowed by STRICT. STRICT
unlowered_expr_type (const_tree exp)
{
tree type;
+ tree etype = TREE_TYPE (exp);
type = is_bitfield_expr_with_lowered_type (exp);
- if (!type)
- type = TREE_TYPE (exp);
+ if (type)
+ type = cp_build_qualified_type (type, cp_type_quals (etype));
+ else
+ type = etype;
return type;
}
return error_mark_node;
}
+ /* FIXME remove? at least need to remember that this isn't really a
+ constant expression if EXP isn't decl_constant_var_p, like with
+ C_MAYBE_CONST_EXPR. */
exp = decl_constant_value (exp);
if (error_operand_p (exp))
return error_mark_node;
if (invalid_nonstatic_memfn_p (exp, tf_warning_or_error))
return error_mark_node;
if (code == FUNCTION_TYPE || is_overloaded_fn (exp))
- return cp_build_unary_op (ADDR_EXPR, exp, 0, tf_warning_or_error);
+ return cp_build_addr_expr (exp, tf_warning_or_error);
if (code == ARRAY_TYPE)
{
tree adr;
}
/* This way is better for a COMPONENT_REF since it can
simplify the offset for a component. */
- adr = cp_build_unary_op (ADDR_EXPR, exp, 1, tf_warning_or_error);
+ adr = cp_build_addr_expr (exp, tf_warning_or_error);
return cp_convert (ptrtype, adr);
}
if (!type || TREE_CODE (type) != ENUMERAL_TYPE)
type = TREE_TYPE (expr);
gcc_assert (INTEGRAL_OR_ENUMERATION_TYPE_P (type));
+ /* Scoped enums don't promote. */
+ if (SCOPED_ENUM_P (type))
+ return expr;
promoted_type = type_promotes_to (type);
if (type != promoted_type)
expr = cp_convert (promoted_type, expr);
? LE_EXPR : GE_EXPR),
op0, TREE_CODE (op0),
op1, TREE_CODE (op1),
- /*overloaded_p=*/NULL,
+ /*overload=*/NULL,
complain),
cp_build_unary_op (code, op0, 0, complain),
cp_build_unary_op (code, op1, 0, complain),
/* Convert to the base. */
object = build_base_path (PLUS_EXPR, object, binfo,
- /*nonnull=*/1);
+ /*nonnull=*/1, complain);
/* If we found the base successfully then we should be able
to convert to it successfully. */
gcc_assert (object != error_mark_node);
return build_min_nt (COMPONENT_REF, object, name, NULL_TREE);
object = build_non_dependent_expr (object);
}
-
+ else if (c_dialect_objc ()
+ && TREE_CODE (name) == IDENTIFIER_NODE
+ && (expr = objc_maybe_build_component_ref (object, name)))
+ return expr;
+
/* [expr.ref]
The type of the first expression shall be "class object" (of a
if (processing_template_decl)
{
- /* Retain the type if we know the operand is a pointer so that
- describable_type doesn't make auto deduction break. */
+ /* Retain the type if we know the operand is a pointer. */
if (TREE_TYPE (expr) && POINTER_TYPE_P (TREE_TYPE (expr)))
return build_min (INDIRECT_REF, TREE_TYPE (TREE_TYPE (expr)), expr);
if (type_dependent_expression_p (expr))
}
rval = build_new_op (INDIRECT_REF, LOOKUP_NORMAL, expr, NULL_TREE,
- NULL_TREE, /*overloaded_p=*/NULL, complain);
+ NULL_TREE, /*overload=*/NULL, complain);
if (!rval)
rval = cp_build_indirect_ref (expr, errorstring, complain);
gcc_unreachable ();
}
else if (pointer != error_mark_node)
- switch (errorstring)
- {
- case RO_NULL:
- error ("invalid type argument");
- break;
- case RO_ARRAY_INDEXING:
- error ("invalid type argument of array indexing");
- break;
- case RO_UNARY_STAR:
- error ("invalid type argument of unary %<*%>");
- break;
- case RO_IMPLICIT_CONVERSION:
- error ("invalid type argument of implicit conversion");
- break;
- default:
- gcc_unreachable ();
- }
+ invalid_indirection_error (input_location, type, errorstring);
+
return error_mark_node;
}
|= (CP_TYPE_VOLATILE_P (type) | TREE_SIDE_EFFECTS (array));
TREE_THIS_VOLATILE (rval)
|= (CP_TYPE_VOLATILE_P (type) | TREE_THIS_VOLATILE (array));
- ret = require_complete_type (fold_if_not_in_template (rval));
+ ret = require_complete_type_sfinae (fold_if_not_in_template (rval),
+ complain);
protected_set_expr_location (ret, loc);
return ret;
}
basetype = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)),
basetype, ba_check, NULL);
instance_ptr = build_base_path (PLUS_EXPR, instance_ptr, basetype,
- 1);
+ 1, tf_warning_or_error);
if (instance_ptr == error_mark_node)
return error_mark_node;
}
/* ...and then the delta in the PMF. */
- instance_ptr = build2 (POINTER_PLUS_EXPR, TREE_TYPE (instance_ptr),
- instance_ptr, fold_convert (sizetype, delta));
+ instance_ptr = fold_build_pointer_plus (instance_ptr, delta);
/* Hand back the adjusted 'this' argument to our caller. */
*instance_ptrptr = instance_ptr;
TREE_NO_WARNING (vtbl) = 1;
/* Finally, extract the function pointer from the vtable. */
- e2 = fold_build2_loc (input_location,
- POINTER_PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
- fold_convert (sizetype, idx));
+ e2 = fold_build_pointer_plus_loc (input_location, vtbl, idx);
e2 = cp_build_indirect_ref (e2, RO_NULL, tf_warning_or_error);
TREE_CONSTANT (e2) = 1;
vtable entry is treated as a function pointer. */
if (TARGET_VTABLE_USES_DESCRIPTORS)
e2 = build1 (NOP_EXPR, TREE_TYPE (e2),
- cp_build_unary_op (ADDR_EXPR, e2, /*noconvert=*/1,
- tf_warning_or_error));
+ cp_build_addr_expr (e2, tf_warning_or_error));
e2 = fold_convert (TREE_TYPE (e3), e2);
e1 = build_conditional_expr (e1, e2, e3, tf_warning_or_error);
/* Check for errors in format strings and inappropriately
null parameters. */
- check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray,
- parm_types);
+ check_function_arguments (fntype, nargs, argarray);
ret = build_cxx_call (function, nargs, argarray);
"declared here");
}
else
- error_at (loc, too_many_p ? G_("too many arguments to function")
- : G_("too few arguments to function"));
+ {
+ if (c_dialect_objc () && objc_message_selector ())
+ error_at (loc,
+ too_many_p
+ ? G_("too many arguments to method %q#D")
+ : G_("too few arguments to method %q#D"),
+ objc_message_selector ());
+ else
+ error_at (loc, too_many_p ? G_("too many arguments to function")
+ : G_("too few arguments to function"));
+ }
}
/* Convert the actual parameter expressions in the list VALUES to the
/* Don't do ellipsis conversion for __built_in_constant_p
as this will result in spurious errors for non-trivial
types. */
- val = require_complete_type (val);
+ val = require_complete_type_sfinae (val, complain);
else
val = convert_arg_to_ellipsis (val);
tree
build_x_binary_op (enum tree_code code, tree arg1, enum tree_code arg1_code,
- tree arg2, enum tree_code arg2_code, bool *overloaded_p,
+ tree arg2, enum tree_code arg2_code, tree *overload,
tsubst_flags_t complain)
{
tree orig_arg1;
expr = build_m_component_ref (arg1, arg2);
else
expr = build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE,
- overloaded_p, complain);
+ overload, complain);
/* Check for cases such as x+y<<z which users are likely to
misinterpret. But don't warn about obj << x + y, since that is a
}
expr = build_new_op (ARRAY_REF, LOOKUP_NORMAL, arg1, arg2, NULL_TREE,
- /*overloaded_p=*/NULL, complain);
+ /*overload=*/NULL, complain);
if (processing_template_decl && expr != error_mark_node)
return build_min_non_dep (ARRAY_REF, expr, orig_arg1, orig_arg2,
|| code == TRUTH_OR_EXPR || code == TRUTH_ORIF_EXPR
|| code == TRUTH_XOR_EXPR)
{
- if (!really_overloaded_fn (op0))
+ if (!really_overloaded_fn (op0) && !VOID_TYPE_P (TREE_TYPE (op0)))
op0 = decay_conversion (op0);
- if (!really_overloaded_fn (op1))
+ if (!really_overloaded_fn (op1) && !VOID_TYPE_P (TREE_TYPE (op1)))
op1 = decay_conversion (op1);
}
else
{
- if (!really_overloaded_fn (op0))
+ if (!really_overloaded_fn (op0) && !VOID_TYPE_P (TREE_TYPE (op0)))
op0 = default_conversion (op0);
- if (!really_overloaded_fn (op1))
+ if (!really_overloaded_fn (op1) && !VOID_TYPE_P (TREE_TYPE (op1)))
op1 = default_conversion (op1);
}
tree e1 = cp_build_binary_op (location,
EQ_EXPR,
pfn0,
- fold_convert (TREE_TYPE (pfn0),
- integer_zero_node),
+ build_zero_cst (TREE_TYPE (pfn0)),
complain);
tree e2 = cp_build_binary_op (location,
BIT_AND_EXPR,
complain);
e2 = cp_build_binary_op (location, EQ_EXPR,
pfn0,
- fold_convert (TREE_TYPE (pfn0),
- integer_zero_node),
+ build_zero_cst (TREE_TYPE (pfn0)),
complain);
e2 = cp_build_binary_op (location,
TRUTH_ANDIF_EXPR, e2, e1, complain);
e2 = cp_build_binary_op (location,
EQ_EXPR,
pfn0,
- fold_convert (TREE_TYPE (pfn0),
- integer_zero_node),
+ build_zero_cst (TREE_TYPE (pfn0)),
complain);
e1 = cp_build_binary_op (location,
TRUTH_ORIF_EXPR, e1, e2, complain);
{
case MULT_EXPR:
case TRUNC_DIV_EXPR:
+ op1 = save_expr (op1);
imag = build2 (resultcode, real_type, imag, op1);
/* Fall through. */
case PLUS_EXPR:
switch (code)
{
case MULT_EXPR:
+ op0 = save_expr (op0);
imag = build2 (resultcode, real_type, op0, imag);
/* Fall through. */
case PLUS_EXPR:
gcc_unreachable();
}
}
- return build2 (COMPLEX_EXPR, result_type, real, imag);
+ real = fold_if_not_in_template (real);
+ imag = fold_if_not_in_template (imag);
+ result = build2 (COMPLEX_EXPR, result_type, real, imag);
+ result = fold_if_not_in_template (result);
+ return result;
}
/* For certain operations (which identify themselves by shorten != 0)
/* Don't look for a function. */;
else
exp = build_new_op (code, LOOKUP_NORMAL, xarg, NULL_TREE, NULL_TREE,
- /*overloaded_p=*/NULL, complain);
+ /*overload=*/NULL, complain);
if (!exp && code == ADDR_EXPR)
{
if (is_overloaded_fn (xarg))
PTRMEM_OK_P (xarg) = ptrmem;
}
}
- else if (TREE_CODE (xarg) == TARGET_EXPR && (complain & tf_warning))
- warning (0, "taking address of temporary");
- exp = cp_build_unary_op (ADDR_EXPR, xarg, 0, complain);
+
+ exp = cp_build_addr_expr_strict (xarg, complain);
}
if (processing_template_decl && exp != error_mark_node)
return build1 (NOP_EXPR, type, expr);
}
+/* Take the address of ARG, whatever that means under C++ semantics.
+ If STRICT_LVALUE is true, require an lvalue; otherwise, allow xvalues
+ and class rvalues as well.
+
+ Nothing should call this function directly; instead, callers should use
+ cp_build_addr_expr or cp_build_addr_expr_strict. */
+
+static tree
+cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain)
+{
+ tree argtype;
+ tree val;
+
+ if (!arg || error_operand_p (arg))
+ return error_mark_node;
+
+ arg = mark_lvalue_use (arg);
+ argtype = lvalue_type (arg);
+
+ gcc_assert (TREE_CODE (arg) != IDENTIFIER_NODE
+ || !IDENTIFIER_OPNAME_P (arg));
+
+ if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg)
+ && !really_overloaded_fn (TREE_OPERAND (arg, 1)))
+ {
+ /* They're trying to take the address of a unique non-static
+ member function. This is ill-formed (except in MS-land),
+ but let's try to DTRT.
+ Note: We only handle unique functions here because we don't
+ want to complain if there's a static overload; non-unique
+ cases will be handled by instantiate_type. But we need to
+ handle this case here to allow casts on the resulting PMF.
+ We could defer this in non-MS mode, but it's easier to give
+ a useful error here. */
+
+ /* Inside constant member functions, the `this' pointer
+ contains an extra const qualifier. TYPE_MAIN_VARIANT
+ is used here to remove this const from the diagnostics
+ and the created OFFSET_REF. */
+ tree base = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg, 0)));
+ tree fn = get_first_fn (TREE_OPERAND (arg, 1));
+ mark_used (fn);
+
+ if (! flag_ms_extensions)
+ {
+ tree name = DECL_NAME (fn);
+ if (!(complain & tf_error))
+ return error_mark_node;
+ else if (current_class_type
+ && TREE_OPERAND (arg, 0) == current_class_ref)
+ /* An expression like &memfn. */
+ permerror (input_location, "ISO C++ forbids taking the address of an unqualified"
+ " or parenthesized non-static member function to form"
+ " a pointer to member function. Say %<&%T::%D%>",
+ base, name);
+ else
+ permerror (input_location, "ISO C++ forbids taking the address of a bound member"
+ " function to form a pointer to member function."
+ " Say %<&%T::%D%>",
+ base, name);
+ }
+ arg = build_offset_ref (base, fn, /*address_p=*/true);
+ }
+
+ /* Uninstantiated types are all functions. Taking the
+ address of a function is a no-op, so just return the
+ argument. */
+ if (type_unknown_p (arg))
+ return build1 (ADDR_EXPR, unknown_type_node, arg);
+
+ if (TREE_CODE (arg) == OFFSET_REF)
+ /* We want a pointer to member; bypass all the code for actually taking
+ the address of something. */
+ goto offset_ref;
+
+ /* Anything not already handled and not a true memory reference
+ is an error. */
+ if (TREE_CODE (argtype) != FUNCTION_TYPE
+ && TREE_CODE (argtype) != METHOD_TYPE)
+ {
+ cp_lvalue_kind kind = lvalue_kind (arg);
+ if (kind == clk_none)
+ {
+ if (complain & tf_error)
+ lvalue_error (input_location, lv_addressof);
+ return error_mark_node;
+ }
+ if (strict_lvalue && (kind & (clk_rvalueref|clk_class)))
+ {
+ if (!(complain & tf_error))
+ return error_mark_node;
+ if (kind & clk_class)
+ /* Make this a permerror because we used to accept it. */
+ permerror (input_location, "taking address of temporary");
+ else
+ error ("taking address of xvalue (rvalue reference)");
+ }
+ }
+
+ if (TREE_CODE (argtype) == REFERENCE_TYPE)
+ {
+ tree type = build_pointer_type (TREE_TYPE (argtype));
+ arg = build1 (CONVERT_EXPR, type, arg);
+ return arg;
+ }
+ else if (pedantic && DECL_MAIN_P (arg))
+ {
+ /* ARM $3.4 */
+ /* Apparently a lot of autoconf scripts for C++ packages do this,
+ so only complain if -pedantic. */
+ if (complain & (flag_pedantic_errors ? tf_error : tf_warning))
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C++ forbids taking address of function %<::main%>");
+ else if (flag_pedantic_errors)
+ return error_mark_node;
+ }
+
+ /* Let &* cancel out to simplify resulting code. */
+ if (TREE_CODE (arg) == INDIRECT_REF)
+ {
+ /* We don't need to have `current_class_ptr' wrapped in a
+ NON_LVALUE_EXPR node. */
+ if (arg == current_class_ref)
+ return current_class_ptr;
+
+ arg = TREE_OPERAND (arg, 0);
+ if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
+ {
+ tree type = build_pointer_type (TREE_TYPE (TREE_TYPE (arg)));
+ arg = build1 (CONVERT_EXPR, type, arg);
+ }
+ else
+ /* Don't let this be an lvalue. */
+ arg = rvalue (arg);
+ return arg;
+ }
+
+ /* ??? Cope with user tricks that amount to offsetof. */
+ if (TREE_CODE (argtype) != FUNCTION_TYPE
+ && TREE_CODE (argtype) != METHOD_TYPE
+ && argtype != unknown_type_node
+ && (val = get_base_address (arg))
+ && COMPLETE_TYPE_P (TREE_TYPE (val))
+ && TREE_CODE (val) == INDIRECT_REF
+ && TREE_CONSTANT (TREE_OPERAND (val, 0)))
+ {
+ tree type = build_pointer_type (argtype);
+ tree op0 = fold_convert (type, TREE_OPERAND (val, 0));
+ tree op1 = fold_offsetof (arg, val);
+ return fold_build_pointer_plus (op0, op1);
+ }
+
+ /* Handle complex lvalues (when permitted)
+ by reduction to simpler cases. */
+ val = unary_complex_lvalue (ADDR_EXPR, arg);
+ if (val != 0)
+ return val;
+
+ switch (TREE_CODE (arg))
+ {
+ CASE_CONVERT:
+ case FLOAT_EXPR:
+ case FIX_TRUNC_EXPR:
+ /* Even if we're not being pedantic, we cannot allow this
+ extension when we're instantiating in a SFINAE
+ context. */
+ if (! lvalue_p (arg) && complain == tf_none)
+ {
+ if (complain & tf_error)
+ permerror (input_location, "ISO C++ forbids taking the address of a cast to a non-lvalue expression");
+ else
+ return error_mark_node;
+ }
+ break;
+
+ case BASELINK:
+ arg = BASELINK_FUNCTIONS (arg);
+ /* Fall through. */
+
+ case OVERLOAD:
+ arg = OVL_CURRENT (arg);
+ break;
+
+ case OFFSET_REF:
+ offset_ref:
+ /* Turn a reference to a non-static data member into a
+ pointer-to-member. */
+ {
+ tree type;
+ tree t;
+
+ gcc_assert (PTRMEM_OK_P (arg));
+
+ t = TREE_OPERAND (arg, 1);
+ if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
+ {
+ if (complain & tf_error)
+ error ("cannot create pointer to reference member %qD", t);
+ return error_mark_node;
+ }
+
+ type = build_ptrmem_type (context_for_name_lookup (t),
+ TREE_TYPE (t));
+ t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1));
+ return t;
+ }
+
+ default:
+ break;
+ }
+
+ if (argtype != error_mark_node)
+ argtype = build_pointer_type (argtype);
+
+ /* In a template, we are processing a non-dependent expression
+ so we can just form an ADDR_EXPR with the correct type. */
+ if (processing_template_decl || TREE_CODE (arg) != COMPONENT_REF)
+ {
+ val = build_address (arg);
+ if (TREE_CODE (arg) == OFFSET_REF)
+ PTRMEM_OK_P (val) = PTRMEM_OK_P (arg);
+ }
+ else if (TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK)
+ {
+ tree fn = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1));
+
+ /* We can only get here with a single static member
+ function. */
+ gcc_assert (TREE_CODE (fn) == FUNCTION_DECL
+ && DECL_STATIC_FUNCTION_P (fn));
+ mark_used (fn);
+ val = build_address (fn);
+ if (TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0)))
+ /* Do not lose object's side effects. */
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (val),
+ TREE_OPERAND (arg, 0), val);
+ }
+ else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
+ {
+ if (complain & tf_error)
+ error ("attempt to take address of bit-field structure member %qD",
+ TREE_OPERAND (arg, 1));
+ return error_mark_node;
+ }
+ else
+ {
+ tree object = TREE_OPERAND (arg, 0);
+ tree field = TREE_OPERAND (arg, 1);
+ gcc_assert (same_type_ignoring_top_level_qualifiers_p
+ (TREE_TYPE (object), decl_type_context (field)));
+ val = build_address (arg);
+ }
+
+ if (TREE_CODE (argtype) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE)
+ {
+ build_ptrmemfunc_type (argtype);
+ val = build_ptrmemfunc (argtype, val, 0,
+ /*c_cast_p=*/false,
+ tf_warning_or_error);
+ }
+
+ return val;
+}
+
+/* Take the address of ARG if it has one, even if it's an rvalue. */
+
+tree
+cp_build_addr_expr (tree arg, tsubst_flags_t complain)
+{
+ return cp_build_addr_expr_1 (arg, 0, complain);
+}
+
+/* Take the address of ARG, but only if it's an lvalue. */
+
+tree
+cp_build_addr_expr_strict (tree arg, tsubst_flags_t complain)
+{
+ return cp_build_addr_expr_1 (arg, 1, complain);
+}
+
/* C++: Must handle pointers to members.
Perhaps type instantiation should be extended to handle conversion
break;
case REALPART_EXPR:
- if (TREE_CODE (arg) == COMPLEX_CST)
- return TREE_REALPART (arg);
- else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
- {
- arg = build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
- return fold_if_not_in_template (arg);
- }
- else
- return arg;
-
case IMAGPART_EXPR:
- if (TREE_CODE (arg) == COMPLEX_CST)
- return TREE_IMAGPART (arg);
- else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
- {
- arg = build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
- return fold_if_not_in_template (arg);
- }
+ arg = build_real_imag_expr (input_location, code, arg);
+ if (arg == error_mark_node)
+ return arg;
else
- return cp_convert (TREE_TYPE (arg), integer_zero_node);
+ return fold_if_not_in_template (arg);
case PREINCREMENT_EXPR:
case POSTINCREMENT_EXPR:
|| TREE_READONLY (arg))
{
if (complain & tf_error)
- readonly_error (arg, ((code == PREINCREMENT_EXPR
- || code == POSTINCREMENT_EXPR)
- ? REK_INCREMENT : REK_DECREMENT));
+ cxx_readonly_error (arg, ((code == PREINCREMENT_EXPR
+ || code == POSTINCREMENT_EXPR)
+ ? lv_increment : lv_decrement));
else
return error_mark_node;
}
inc = cp_convert (argtype, inc);
+ /* If 'arg' is an Objective-C PROPERTY_REF expression, then we
+ need to ask Objective-C to build the increment or decrement
+ expression for it. */
+ if (objc_is_property_ref (arg))
+ return objc_build_incr_expr_for_property_ref (input_location, code,
+ arg, inc);
+
/* Complain about anything else that is not a true lvalue. */
if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
}
val = boolean_increment (code, arg);
}
+ else if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
+ /* An rvalue has no cv-qualifiers. */
+ val = build2 (code, cv_unqualified (TREE_TYPE (arg)), arg, inc);
else
val = build2 (code, TREE_TYPE (arg), arg, inc);
case ADDR_EXPR:
/* Note that this operation never does default_conversion
regardless of NOCONVERT. */
-
- argtype = lvalue_type (arg);
-
- arg = mark_lvalue_use (arg);
-
- if (TREE_CODE (arg) == OFFSET_REF)
- goto offset_ref;
-
- if (TREE_CODE (argtype) == REFERENCE_TYPE)
- {
- tree type = build_pointer_type (TREE_TYPE (argtype));
- arg = build1 (CONVERT_EXPR, type, arg);
- return arg;
- }
- else if (pedantic && DECL_MAIN_P (arg))
- {
- /* ARM $3.4 */
- /* Apparently a lot of autoconf scripts for C++ packages do this,
- so only complain if -pedantic. */
- if (complain & (flag_pedantic_errors ? tf_error : tf_warning))
- pedwarn (input_location, OPT_pedantic,
- "ISO C++ forbids taking address of function %<::main%>");
- else if (flag_pedantic_errors)
- return error_mark_node;
- }
-
- /* Let &* cancel out to simplify resulting code. */
- if (TREE_CODE (arg) == INDIRECT_REF)
- {
- /* We don't need to have `current_class_ptr' wrapped in a
- NON_LVALUE_EXPR node. */
- if (arg == current_class_ref)
- return current_class_ptr;
-
- arg = TREE_OPERAND (arg, 0);
- if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
- {
- tree type = build_pointer_type (TREE_TYPE (TREE_TYPE (arg)));
- arg = build1 (CONVERT_EXPR, type, arg);
- }
- else
- /* Don't let this be an lvalue. */
- arg = rvalue (arg);
- return arg;
- }
-
- /* ??? Cope with user tricks that amount to offsetof. */
- if (TREE_CODE (argtype) != FUNCTION_TYPE
- && TREE_CODE (argtype) != METHOD_TYPE
- && argtype != unknown_type_node
- && (val = get_base_address (arg))
- && TREE_CODE (val) == INDIRECT_REF
- && TREE_CONSTANT (TREE_OPERAND (val, 0)))
- {
- tree type = build_pointer_type (argtype);
- tree op0 = fold_convert (type, TREE_OPERAND (val, 0));
- tree op1 = fold_convert (sizetype, fold_offsetof (arg, val));
- return fold_build2 (POINTER_PLUS_EXPR, type, op0, op1);
- }
-
- /* Uninstantiated types are all functions. Taking the
- address of a function is a no-op, so just return the
- argument. */
-
- gcc_assert (TREE_CODE (arg) != IDENTIFIER_NODE
- || !IDENTIFIER_OPNAME_P (arg));
-
- if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg)
- && !really_overloaded_fn (TREE_OPERAND (arg, 1)))
- {
- /* They're trying to take the address of a unique non-static
- member function. This is ill-formed (except in MS-land),
- but let's try to DTRT.
- Note: We only handle unique functions here because we don't
- want to complain if there's a static overload; non-unique
- cases will be handled by instantiate_type. But we need to
- handle this case here to allow casts on the resulting PMF.
- We could defer this in non-MS mode, but it's easier to give
- a useful error here. */
-
- /* Inside constant member functions, the `this' pointer
- contains an extra const qualifier. TYPE_MAIN_VARIANT
- is used here to remove this const from the diagnostics
- and the created OFFSET_REF. */
- tree base = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg, 0)));
- tree fn = get_first_fn (TREE_OPERAND (arg, 1));
- mark_used (fn);
-
- if (! flag_ms_extensions)
- {
- tree name = DECL_NAME (fn);
- if (!(complain & tf_error))
- return error_mark_node;
- else if (current_class_type
- && TREE_OPERAND (arg, 0) == current_class_ref)
- /* An expression like &memfn. */
- permerror (input_location, "ISO C++ forbids taking the address of an unqualified"
- " or parenthesized non-static member function to form"
- " a pointer to member function. Say %<&%T::%D%>",
- base, name);
- else
- permerror (input_location, "ISO C++ forbids taking the address of a bound member"
- " function to form a pointer to member function."
- " Say %<&%T::%D%>",
- base, name);
- }
- arg = build_offset_ref (base, fn, /*address_p=*/true);
- }
-
- offset_ref:
- if (type_unknown_p (arg))
- return build1 (ADDR_EXPR, unknown_type_node, arg);
-
- /* Handle complex lvalues (when permitted)
- by reduction to simpler cases. */
- val = unary_complex_lvalue (code, arg);
- if (val != 0)
- return val;
-
- switch (TREE_CODE (arg))
- {
- CASE_CONVERT:
- case FLOAT_EXPR:
- case FIX_TRUNC_EXPR:
- /* Even if we're not being pedantic, we cannot allow this
- extension when we're instantiating in a SFINAE
- context. */
- if (! lvalue_p (arg) && complain == tf_none)
- {
- if (complain & tf_error)
- permerror (input_location, "ISO C++ forbids taking the address of a cast to a non-lvalue expression");
- else
- return error_mark_node;
- }
- break;
-
- case BASELINK:
- arg = BASELINK_FUNCTIONS (arg);
- /* Fall through. */
-
- case OVERLOAD:
- arg = OVL_CURRENT (arg);
- break;
-
- case OFFSET_REF:
- /* Turn a reference to a non-static data member into a
- pointer-to-member. */
- {
- tree type;
- tree t;
-
- if (!PTRMEM_OK_P (arg))
- return cp_build_unary_op (code, arg, 0, complain);
-
- t = TREE_OPERAND (arg, 1);
- if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
- {
- if (complain & tf_error)
- error ("cannot create pointer to reference member %qD", t);
- return error_mark_node;
- }
-
- type = build_ptrmem_type (context_for_name_lookup (t),
- TREE_TYPE (t));
- t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1));
- return t;
- }
-
- default:
- break;
- }
-
- /* Anything not already handled and not a true memory reference
- is an error. */
- if (TREE_CODE (argtype) != FUNCTION_TYPE
- && TREE_CODE (argtype) != METHOD_TYPE
- && TREE_CODE (arg) != OFFSET_REF
- && !lvalue_or_else (arg, lv_addressof, complain))
- return error_mark_node;
-
- if (argtype != error_mark_node)
- argtype = build_pointer_type (argtype);
-
- /* In a template, we are processing a non-dependent expression
- so we can just form an ADDR_EXPR with the correct type. */
- if (processing_template_decl || TREE_CODE (arg) != COMPONENT_REF)
- {
- val = build_address (arg);
- if (TREE_CODE (arg) == OFFSET_REF)
- PTRMEM_OK_P (val) = PTRMEM_OK_P (arg);
- }
- else if (TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK)
- {
- tree fn = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1));
-
- /* We can only get here with a single static member
- function. */
- gcc_assert (TREE_CODE (fn) == FUNCTION_DECL
- && DECL_STATIC_FUNCTION_P (fn));
- mark_used (fn);
- val = build_address (fn);
- if (TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0)))
- /* Do not lose object's side effects. */
- val = build2 (COMPOUND_EXPR, TREE_TYPE (val),
- TREE_OPERAND (arg, 0), val);
- }
- else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
- {
- if (complain & tf_error)
- error ("attempt to take address of bit-field structure member %qD",
- TREE_OPERAND (arg, 1));
- return error_mark_node;
- }
- else
- {
- tree object = TREE_OPERAND (arg, 0);
- tree field = TREE_OPERAND (arg, 1);
- gcc_assert (same_type_ignoring_top_level_qualifiers_p
- (TREE_TYPE (object), decl_type_context (field)));
- val = build_address (arg);
- }
-
- if (TREE_CODE (argtype) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE)
- {
- build_ptrmemfunc_type (argtype);
- val = build_ptrmemfunc (argtype, val, 0,
- /*c_cast_p=*/false,
- tf_warning_or_error);
- }
-
- return val;
+ return cp_build_addr_expr (arg, complain);
default:
break;
if (TREE_CODE (arg) == SAVE_EXPR)
targ = arg;
else
- targ = build_cplus_new (TREE_TYPE (arg), arg);
+ targ = build_cplus_new (TREE_TYPE (arg), arg, tf_warning_or_error);
return build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg)), targ);
}
|| DECL_EXTERNAL (x));
/* Fall through. */
- case CONST_DECL:
case RESULT_DECL:
if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
&& !DECL_ARTIFICIAL (x))
TREE_ADDRESSABLE (x) = 1;
return true;
+ case CONST_DECL:
case FUNCTION_DECL:
TREE_ADDRESSABLE (x) = 1;
return true;
{
tree expr = TREE_VALUE (list);
+ if (BRACE_ENCLOSED_INITIALIZER_P (expr)
+ && !CONSTRUCTOR_IS_DIRECT_INIT (expr))
+ {
+ if (complain & tf_error)
+ pedwarn (EXPR_LOC_OR_HERE (expr), 0, "list-initializer for "
+ "non-class type must not be parenthesized");
+ else
+ return error_mark_node;
+ }
+
if (TREE_CHAIN (list))
{
if (complain & tf_error)
default:
gcc_unreachable ();
}
+ else
+ return error_mark_node;
for (list = TREE_CHAIN (list); list; list = TREE_CHAIN (list))
expr = build_x_compound_expr (expr, TREE_VALUE (list),
}
result = build_new_op (COMPOUND_EXPR, LOOKUP_NORMAL, op1, op2, NULL_TREE,
- /*overloaded_p=*/NULL, complain);
+ /*overload=*/NULL, complain);
if (!result)
result = cp_build_compound_expr (op1, op2, complain);
}
/* Issue a diagnostic message if casting from SRC_TYPE to DEST_TYPE
- casts away constness. CAST gives the type of cast.
+ casts away constness. CAST gives the type of cast. Returns true
+ if the cast is ill-formed, false if it is well-formed.
??? This function warns for casting away any qualifier not just
const. We would like to specify exactly what qualifiers are casted
away.
*/
-static void
+static bool
check_for_casting_away_constness (tree src_type, tree dest_type,
- enum tree_code cast)
+ enum tree_code cast, tsubst_flags_t complain)
{
/* C-style casts are allowed to cast away constness. With
WARN_CAST_QUAL, we still want to issue a warning. */
if (cast == CAST_EXPR && !warn_cast_qual)
- return;
+ return false;
if (!casts_away_constness (src_type, dest_type))
- return;
+ return false;
switch (cast)
{
case CAST_EXPR:
- warning (OPT_Wcast_qual,
- "cast from type %qT to type %qT casts away qualifiers",
- src_type, dest_type);
- return;
+ if (complain & tf_warning)
+ warning (OPT_Wcast_qual,
+ "cast from type %qT to type %qT casts away qualifiers",
+ src_type, dest_type);
+ return false;
case STATIC_CAST_EXPR:
- error ("static_cast from type %qT to type %qT casts away qualifiers",
- src_type, dest_type);
- return;
+ if (complain & tf_error)
+ error ("static_cast from type %qT to type %qT casts away qualifiers",
+ src_type, dest_type);
+ return true;
case REINTERPRET_CAST_EXPR:
- error ("reinterpret_cast from type %qT to type %qT casts away qualifiers",
- src_type, dest_type);
- return;
+ if (complain & tf_error)
+ error ("reinterpret_cast from type %qT to type %qT casts away qualifiers",
+ src_type, dest_type);
+ return true;
+
default:
gcc_unreachable();
}
allow_inverse_p, c_cast_p, complain);
}
-/* If EXPR is an INTEGER_CST and ORIG is an arithmetic constant, return
- a version of EXPR that has TREE_OVERFLOW set if it is set in ORIG.
- Otherwise, return EXPR unchanged. */
-
-static tree
-ignore_overflows (tree expr, tree orig)
-{
- if (TREE_CODE (expr) == INTEGER_CST
- && CONSTANT_CLASS_P (orig)
- && TREE_CODE (orig) != STRING_CST
- && TREE_OVERFLOW (expr) != TREE_OVERFLOW (orig))
- {
- if (!TREE_OVERFLOW (orig))
- /* Ensure constant sharing. */
- expr = build_int_cst_wide (TREE_TYPE (expr),
- TREE_INT_CST_LOW (expr),
- TREE_INT_CST_HIGH (expr));
- else
- {
- /* Avoid clobbering a shared constant. */
- expr = copy_node (expr);
- TREE_OVERFLOW (expr) = TREE_OVERFLOW (orig);
- }
- }
- return expr;
-}
-
/* Perform a static_cast from EXPR to TYPE. When C_CAST_P is true,
this static_cast is being attempted as one of the possible casts
allowed by a C-style cast. (In that case, accessibility of base
{
tree intype;
tree result;
- tree orig;
/* Assume the cast is valid. */
*valid_p = true;
/* Convert from "B*" to "D*". This function will check that "B"
is not a virtual base of "D". */
expr = build_base_path (MINUS_EXPR, build_address (expr),
- base, /*nonnull=*/false);
+ base, /*nonnull=*/false, complain);
/* Convert the pointer to a reference -- but then remember that
- there are no expressions with reference type in C++. */
- return convert_from_reference (cp_fold_convert (type, expr));
+ there are no expressions with reference type in C++.
+
+ We call rvalue so that there's an actual tree code
+ (NON_LVALUE_EXPR) for the static_cast; otherwise, if the operand
+ is a variable with the same type, the conversion would get folded
+ away, leaving just the variable and causing lvalue_kind to give
+ the wrong answer. */
+ return convert_from_reference (rvalue (cp_fold_convert (type, expr)));
}
- /* "An lvalue of type cv1 T1 can be cast to type rvalue reference to
+ /* "A glvalue of type cv1 T1 can be cast to type rvalue reference to
cv2 T2 if cv2 T2 is reference-compatible with cv1 T1 (8.5.3)." */
if (TREE_CODE (type) == REFERENCE_TYPE
&& TYPE_REF_IS_RVALUE (type)
- && real_lvalue_p (expr)
+ && lvalue_or_rvalue_with_address_p (expr)
&& reference_related_p (TREE_TYPE (type), intype)
&& (c_cast_p || at_least_as_qualified_p (TREE_TYPE (type), intype)))
{
return convert_from_reference (expr);
}
- orig = expr;
-
/* Resolve overloaded address here rather than once in
implicit_conversion and again in the inverse code below. */
if (TYPE_PTRMEMFUNC_P (type) && type_unknown_p (expr))
{
result = convert_from_reference (result);
- /* Ignore any integer overflow caused by the cast. */
- result = ignore_overflows (result, orig);
-
/* [expr.static.cast]
If T is a reference type, the result is an lvalue; otherwise,
|| SCALAR_FLOAT_TYPE_P (type))
&& (INTEGRAL_OR_ENUMERATION_TYPE_P (intype)
|| SCALAR_FLOAT_TYPE_P (intype)))
- {
- expr = ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL);
-
- /* Ignore any integer overflow caused by the cast. */
- expr = ignore_overflows (expr, orig);
- return expr;
- }
+ return ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL);
if (TYPE_PTR_P (type) && TYPE_PTR_P (intype)
&& CLASS_TYPE_P (TREE_TYPE (type))
{
tree base;
- if (!c_cast_p)
- check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR);
+ if (!c_cast_p
+ && check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR,
+ complain))
+ return error_mark_node;
base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
c_cast_p ? ba_unique : ba_check,
NULL);
- return build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false);
+ expr = build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false,
+ complain);
+ return cp_fold_convert(type, expr);
}
if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
}
if (can_convert (t1, t2) || can_convert (t2, t1))
{
- if (!c_cast_p)
- check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR);
+ if (!c_cast_p
+ && check_for_casting_away_constness (intype, type,
+ STATIC_CAST_EXPR,
+ complain))
+ return error_mark_node;
return convert_ptrmem (type, expr, /*allow_inverse_p=*/1,
- c_cast_p, tf_warning_or_error);
+ c_cast_p, complain);
}
}
&& VOID_TYPE_P (TREE_TYPE (intype))
&& TYPE_PTROB_P (type))
{
- if (!c_cast_p)
- check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR);
+ if (!c_cast_p
+ && check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR,
+ complain))
+ return error_mark_node;
return build_nop (type, expr);
}
warning (0, "casting %qT to %qT does not dereference pointer",
intype, type);
- expr = cp_build_unary_op (ADDR_EXPR, expr, 0, complain);
+ expr = cp_build_addr_expr (expr, complain);
if (warn_strict_aliasing > 2)
strict_aliasing_warning (TREE_TYPE (expr), type, expr);
{
tree sexpr = expr;
- if (!c_cast_p)
- check_for_casting_away_constness (intype, type, REINTERPRET_CAST_EXPR);
+ if (!c_cast_p
+ && check_for_casting_away_constness (intype, type,
+ REINTERPRET_CAST_EXPR,
+ complain))
+ return error_mark_node;
/* Warn about possible alignment problems. */
if (STRICT_ALIGNMENT && warn_cast_align
&& (complain & tf_warning)
whether or not the conversion succeeded. */
static tree
-build_const_cast_1 (tree dst_type, tree expr, bool complain,
+build_const_cast_1 (tree dst_type, tree expr, tsubst_flags_t complain,
bool *valid_p)
{
tree src_type;
if (!POINTER_TYPE_P (dst_type) && !TYPE_PTRMEM_P (dst_type))
{
- if (complain)
+ if (complain & tf_error)
error ("invalid use of const_cast with type %qT, "
"which is not a pointer, "
"reference, nor a pointer-to-data-member type", dst_type);
if (TREE_CODE (TREE_TYPE (dst_type)) == FUNCTION_TYPE)
{
- if (complain)
+ if (complain & tf_error)
error ("invalid use of const_cast with type %qT, which is a pointer "
"or reference to a function type", dst_type);
return error_mark_node;
/* [expr.const.cast]
- An lvalue of type T1 can be explicitly converted to an lvalue of
- type T2 using the cast const_cast<T2&> (where T1 and T2 are object
- types) if a pointer to T1 can be explicitly converted to the type
- pointer to T2 using a const_cast. */
+ For two object types T1 and T2, if a pointer to T1 can be explicitly
+ converted to the type "pointer to T2" using a const_cast, then the
+ following conversions can also be made:
+
+ -- an lvalue of type T1 can be explicitly converted to an lvalue of
+ type T2 using the cast const_cast<T2&>;
+
+ -- a glvalue of type T1 can be explicitly converted to an xvalue of
+ type T2 using the cast const_cast<T2&&>; and
+
+ -- if T1 is a class type, a prvalue of type T1 can be explicitly
+ converted to an xvalue of type T2 using the cast const_cast<T2&&>. */
+
if (TREE_CODE (dst_type) == REFERENCE_TYPE)
{
reference_type = dst_type;
- if (! real_lvalue_p (expr))
+ if (!TYPE_REF_IS_RVALUE (dst_type)
+ ? real_lvalue_p (expr)
+ : (CLASS_TYPE_P (TREE_TYPE (dst_type))
+ ? lvalue_p (expr)
+ : lvalue_or_rvalue_with_address_p (expr)))
+ /* OK. */;
+ else
{
- if (complain)
+ if (complain & tf_error)
error ("invalid const_cast of an rvalue of type %qT to type %qT",
src_type, dst_type);
return error_mark_node;
*valid_p = true;
/* This cast is actually a C-style cast. Issue a warning if
the user is making a potentially unsafe cast. */
- check_for_casting_away_constness (src_type, dst_type, CAST_EXPR);
+ check_for_casting_away_constness (src_type, dst_type, CAST_EXPR,
+ complain);
}
if (reference_type)
{
- expr = cp_build_unary_op (ADDR_EXPR, expr, 0,
- complain? tf_warning_or_error : tf_none);
+ expr = cp_build_addr_expr (expr, complain);
expr = build_nop (reference_type, expr);
return convert_from_reference (expr);
}
}
}
- if (complain)
+ if (complain & tf_error)
error ("invalid const_cast from type %qT to type %qT",
src_type, dst_type);
return error_mark_node;
return convert_from_reference (t);
}
- return build_const_cast_1 (type, expr, complain & tf_error,
+ return build_const_cast_1 (type, expr, complain,
/*valid_p=*/NULL);
}
"cast to pointer from integer of different size");
/* A C-style cast can be a const_cast. */
- result = build_const_cast_1 (type, value, /*complain=*/false,
+ result = build_const_cast_1 (type, value, complain & tf_warning,
&valid_p);
if (valid_p)
return result;
if (!CLASS_TYPE_P (type))
type = TYPE_MAIN_VARIANT (type);
result_type = TREE_TYPE (result);
- if (!CLASS_TYPE_P (result_type))
+ if (!CLASS_TYPE_P (result_type) && TREE_CODE (type) != REFERENCE_TYPE)
result_type = TYPE_MAIN_VARIANT (result_type);
/* If the type of RESULT does not match TYPE, perform a
const_cast to make it match. If the static_cast or
}
else
{
- lhs = require_complete_type (lhs);
+ lhs = require_complete_type_sfinae (lhs, complain);
if (lhs == error_mark_node)
return error_mark_node;
if (modifycode == NOP_EXPR)
{
+ if (c_dialect_objc ())
+ {
+ result = objc_maybe_build_modify_expr (lhs, rhs);
+ if (result)
+ return result;
+ }
+
/* `operator=' is not an inheritable operator. */
if (! MAYBE_CLASS_TYPE_P (lhstype))
/* Do the default thing. */;
{
result = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL,
lhs, rhs, make_node (NOP_EXPR),
- /*overloaded_p=*/NULL,
+ /*overload=*/NULL,
complain);
if (result == NULL_TREE)
return error_mark_node;
}
else
{
+ tree init = NULL_TREE;
+
/* A binary op has been requested. Combine the old LHS
value with the RHS producing the value we should actually
store into the LHS. */
&& MAYBE_CLASS_TYPE_P (TREE_TYPE (lhstype)))
|| MAYBE_CLASS_TYPE_P (lhstype)));
+ /* Preevaluate the RHS to make sure its evaluation is complete
+ before the lvalue-to-rvalue conversion of the LHS:
+
+ [expr.ass] With respect to an indeterminately-sequenced
+ function call, the operation of a compound assignment is a
+ single evaluation. [ Note: Therefore, a function call shall
+ not intervene between the lvalue-to-rvalue conversion and the
+ side effect associated with any single compound assignment
+ operator. -- end note ] */
lhs = stabilize_reference (lhs);
+ if (TREE_SIDE_EFFECTS (rhs))
+ rhs = mark_rvalue_use (rhs);
+ rhs = stabilize_expr (rhs, &init);
newrhs = cp_build_binary_op (input_location,
modifycode, lhs, rhs,
complain);
return error_mark_node;
}
+ if (init)
+ newrhs = build2 (COMPOUND_EXPR, TREE_TYPE (newrhs), init, newrhs);
+
/* Now it looks like a plain assignment. */
modifycode = NOP_EXPR;
+ if (c_dialect_objc ())
+ {
+ result = objc_maybe_build_modify_expr (lhs, newrhs);
+ if (result)
+ return result;
+ }
}
gcc_assert (TREE_CODE (lhstype) != REFERENCE_TYPE);
gcc_assert (TREE_CODE (TREE_TYPE (newrhs)) != REFERENCE_TYPE);
&& C_TYPE_FIELDS_READONLY (lhstype))))
{
if (complain & tf_error)
- readonly_error (lhs, REK_ASSIGNMENT);
+ cxx_readonly_error (lhs, lv_assign);
else
return error_mark_node;
}
}
if (check_array_initializer (lhs, lhstype, newrhs))
return error_mark_node;
- newrhs = digest_init (lhstype, newrhs);
+ newrhs = digest_init (lhstype, newrhs, complain);
+ if (newrhs == error_mark_node)
+ return error_mark_node;
}
else if (!same_or_base_type_p (TYPE_MAIN_VARIANT (lhstype),
/* Allow array assignment in compiler-generated code. */
else if (!current_function_decl
- || !DECL_ARTIFICIAL (current_function_decl))
+ || !DECL_DEFAULTED_FN (current_function_decl))
{
/* This routine is used for both initialization and assignment.
Make sure the diagnostic message differentiates the context. */
{
if (TREE_CODE (newrhs) == CALL_EXPR
&& TYPE_NEEDS_CONSTRUCTING (lhstype))
- newrhs = build_cplus_new (lhstype, newrhs);
+ newrhs = build_cplus_new (lhstype, newrhs, complain);
/* Can't initialize directly from a TARGET_EXPR, since that would
cause the lhs to be constructed twice, and possibly result in
{
tree rval = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs,
make_node (modifycode),
- /*overloaded_p=*/NULL,
+ /*overload=*/NULL,
complain);
if (rval)
{
break;
case ICR_CONVERTING:
warning (OPT_Wmissing_format_attribute,
- "target of conversion might be might be a candidate "
+ "target of conversion might be a candidate "
"for a format attribute");
break;
case ICR_INIT:
&& TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE
&& (complain & tf_warning))
{
- location_t loc = EXPR_HAS_LOCATION (rhs)
- ? EXPR_LOCATION (rhs) : input_location;
+ location_t loc = EXPR_LOC_OR_HERE (rhs);
warning_at (loc, OPT_Wparentheses,
"suggest parentheses around assignment used as truth value");
if (fndecl)
savew = warningcount, savee = errorcount;
rhs = initialize_reference (type, rhs, /*decl=*/NULL_TREE,
- /*cleanup=*/NULL, complain);
+ /*cleanup=*/NULL, flags, complain);
if (fndecl)
{
if (warningcount > savew)
}
if (exp != 0)
- exp = require_complete_type (exp);
+ exp = require_complete_type_sfinae (exp, complain);
if (exp == error_mark_node)
return error_mark_node;
return rhs;
if (MAYBE_CLASS_TYPE_P (type))
- return ocp_convert (type, rhs, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
+ return perform_implicit_conversion_flags (type, rhs, complain, flags);
return convert_for_assignment (type, rhs, errtype, fndecl, parmnum,
complain, flags);
tree type = lambda_return_type (retval);
tree oldtype = LAMBDA_EXPR_RETURN_TYPE (lambda);
- if (VOID_TYPE_P (type))
- { /* Nothing. */ }
- else if (oldtype == NULL_TREE)
- {
- pedwarn (input_location, OPT_pedantic, "lambda return type "
- "can only be deduced when the return statement is "
- "the only statement in the function body");
- apply_lambda_return_type (lambda, type);
- }
+ if (oldtype == NULL_TREE)
+ apply_lambda_return_type (lambda, type);
+ /* If one of the answers is type-dependent, we can't do any
+ better until instantiation time. */
+ else if (oldtype == dependent_lambda_return_type_node)
+ /* Leave it. */;
+ else if (type == dependent_lambda_return_type_node)
+ apply_lambda_return_type (lambda, type);
else if (!same_type_p (type, oldtype))
error ("inconsistent types %qT and %qT deduced for "
"lambda return type", type, oldtype);
/* Under C++0x [12.8/16 class.copy], a returned lvalue is sometimes
treated as an rvalue for the purposes of overload resolution to
- favor move constructors over copy constructors. */
- if ((cxx_dialect != cxx98)
- && named_return_value_okay_p
- /* The variable must not have the `volatile' qualifier. */
- && !CP_TYPE_VOLATILE_P (TREE_TYPE (retval))
- /* The return type must be a class type. */
+ favor move constructors over copy constructors.
+
+ Note that these conditions are similar to, but not as strict as,
+ the conditions for the named return value optimization. */
+ if ((cxx_dialect != cxx98)
+ && (TREE_CODE (retval) == VAR_DECL
+ || TREE_CODE (retval) == PARM_DECL)
+ && DECL_CONTEXT (retval) == current_function_decl
+ && !TREE_STATIC (retval)
+ && same_type_p ((TYPE_MAIN_VARIANT (TREE_TYPE (retval))),
+ (TYPE_MAIN_VARIANT
+ (TREE_TYPE (TREE_TYPE (current_function_decl)))))
+ /* This is only interesting for class type. */
&& CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))))
flags = flags | LOOKUP_PREFER_RVALUE;
so the usual checks are not appropriate. */
if (TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE)
{
- /* In Objective-C++, some types may have been 'volatilized' by
- the compiler for EH; when comparing them here, the volatile
- qualification must be ignored. */
- bool objc_quals_match = objc_type_quals_match (to, from);
-
- if (!at_least_as_qualified_p (to, from) && !objc_quals_match)
+ if (!at_least_as_qualified_p (to, from))
return 0;
- if (!at_least_as_qualified_p (from, to) && !objc_quals_match)
+ if (!at_least_as_qualified_p (from, to))
{
if (constp == 0)
return 0;
if (TREE_CODE (type) == FUNCTION_TYPE)
return TYPE_QUALS (type);
else if (TREE_CODE (type) == METHOD_TYPE)
- return cp_type_quals (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type))));
+ return cp_type_quals (class_of_this_parm (type));
else
gcc_unreachable ();
}
&& type_quals != TYPE_UNQUALIFIED));
/* Avoid setting TREE_READONLY incorrectly. */
- if (/* If the object has a constructor, the constructor may modify
- the object. */
- TYPE_NEEDS_CONSTRUCTING (type)
- /* If the type isn't complete, we don't know yet if it will need
- constructing. */
- || !COMPLETE_TYPE_P (type)
- /* If the type has a mutable component, that component might be
- modified. */
- || TYPE_HAS_MUTABLE_P (type))
+ /* We used to check TYPE_NEEDS_CONSTRUCTING here, but now a constexpr
+ constructor can produce constant init, so rely on cp_finish_decl to
+ clear TREE_READONLY if the variable has non-constant init. */
+
+ /* If the type has a mutable component, that component might be
+ modified. */
+ if (TYPE_HAS_MUTABLE_P (type))
type_quals &= ~TYPE_QUAL_CONST;
c_apply_type_quals_to_decl (type_quals, decl);
int
lvalue_or_else (tree ref, enum lvalue_use use, tsubst_flags_t complain)
{
- int win = lvalue_p (ref);
-
- if (!win && (complain & tf_error))
- lvalue_error (use);
+ cp_lvalue_kind kind = lvalue_kind (ref);
- return win;
+ if (kind == clk_none)
+ {
+ if (complain & tf_error)
+ lvalue_error (input_location, use);
+ return 0;
+ }
+ else if (kind & (clk_rvalueref|clk_class))
+ {
+ if (!(complain & tf_error))
+ return 0;
+ if (kind & clk_class)
+ /* Make this a permerror because we used to accept it. */
+ permerror (input_location, "using temporary as lvalue");
+ else
+ error ("using xvalue (rvalue reference) as lvalue");
+ }
+ return 1;
}