/* 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);
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);
}
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(). */
!= 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;
}
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);
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;
}
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;
/* 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);
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);
}
{
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))
if (kind == clk_none)
{
if (complain & tf_error)
- lvalue_error (lv_addressof);
+ lvalue_error (input_location, lv_addressof);
return error_mark_node;
}
if (strict_lvalue && (kind & (clk_rvalueref|clk_class)))
{
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);
+ tree op1 = fold_offsetof (arg, val);
+ return fold_build_pointer_plus (op0, op1);
}
/* Handle complex lvalues (when permitted)
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);
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);
}
{
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_addr_expr (expr,
- 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
{
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 ())
&& 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:
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)
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. */
- tree nv_to = objc_non_volatilized_type (to);
- tree nv_from = objc_non_volatilized_type (from);
-
- if (!at_least_as_qualified_p (nv_to, nv_from))
+ if (!at_least_as_qualified_p (to, from))
return 0;
- if (!at_least_as_qualified_p (nv_from, nv_to))
+ if (!at_least_as_qualified_p (from, to))
{
if (constp == 0)
return 0;
}
if (constp > 0)
- constp &= TYPE_READONLY (nv_to);
+ constp &= TYPE_READONLY (to);
}
if (TREE_CODE (to) == VECTOR_TYPE)
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);
if (kind == clk_none)
{
if (complain & tf_error)
- lvalue_error (use);
+ lvalue_error (input_location, use);
return 0;
}
else if (kind & (clk_rvalueref|clk_class))