GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* This file is part of the C++ front end.
static int comp_ptr_ttypes_real (tree, tree, int);
static bool comp_except_types (tree, tree, bool);
static bool comp_array_types (tree, tree, bool);
-static tree common_base_type (tree, tree);
static tree pointer_diff (tree, tree, tree);
static tree get_delta_difference (tree, tree, bool, bool);
static void casts_away_constness_r (tree *, tree *);
static bool casts_away_constness (tree, tree);
static void maybe_warn_about_returning_address_of_local (tree);
static tree lookup_destructor (tree, tree, tree);
-static tree convert_arguments (tree, tree, tree, int);
+static int convert_arguments (int, tree *, tree, tree, tree, int);
/* Do `exp = require_complete_type (exp);' to make sure exp
does not have an incomplete type. (That includes void types.)
/* FIXME: Attributes. */
gcc_assert (ARITHMETIC_TYPE_P (t1)
- || TREE_CODE (t1) == COMPLEX_TYPE
|| TREE_CODE (t1) == VECTOR_TYPE
|| TREE_CODE (t1) == ENUMERAL_TYPE);
gcc_assert (ARITHMETIC_TYPE_P (t2)
- || TREE_CODE (t2) == COMPLEX_TYPE
|| TREE_CODE (t2) == VECTOR_TYPE
|| TREE_CODE (t2) == ENUMERAL_TYPE);
code2 = TREE_CODE (t2);
if ((ARITHMETIC_TYPE_P (t1) || code1 == ENUMERAL_TYPE
- || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)
+ || code1 == VECTOR_TYPE)
&& (ARITHMETIC_TYPE_P (t2) || code2 == ENUMERAL_TYPE
- || code2 == COMPLEX_TYPE || code2 == VECTOR_TYPE))
+ || code2 == VECTOR_TYPE))
return type_after_usual_arithmetic_conversions (t1, t2);
else if ((TYPE_PTR_P (t1) && TYPE_PTR_P (t2))
/* TYPENAME_TYPEs should be resolved if the qualifying scope is the
current instantiation. */
if (TREE_CODE (t1) == TYPENAME_TYPE)
- {
- tree resolved = resolve_typename_type (t1, /*only_current_p=*/true);
-
- if (resolved != error_mark_node)
- t1 = resolved;
- }
+ t1 = resolve_typename_type (t1, /*only_current_p=*/true);
if (TREE_CODE (t2) == TYPENAME_TYPE)
- {
- tree resolved = resolve_typename_type (t2, /*only_current_p=*/true);
-
- if (resolved != error_mark_node)
- t2 = resolved;
- }
+ t2 = resolve_typename_type (t2, /*only_current_p=*/true);
if (TYPE_PTRMEMFUNC_P (t1))
t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);
case TEMPLATE_TEMPLATE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
- || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2))
+ || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
+ || (TEMPLATE_TYPE_PARAMETER_PACK (t1)
+ != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
return false;
if (!comp_template_parms
(DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t1)),
return false;
break;
- case POINTER_TYPE:
case REFERENCE_TYPE:
+ if (TYPE_REF_IS_RVALUE (t1) != TYPE_REF_IS_RVALUE (t2))
+ return false;
+ /* fall through to checks for pointer types */
+
+ case POINTER_TYPE:
if (TYPE_MODE (t1) != TYPE_MODE (t2)
|| TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2)
|| !same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
case TEMPLATE_TYPE_PARM:
if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
- || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2))
+ || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
+ || (TEMPLATE_TYPE_PARAMETER_PACK (t1)
+ != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
return false;
break;
return false;
break;
+ case TYPE_PACK_EXPANSION:
+ return same_type_p (PACK_EXPANSION_PATTERN (t1),
+ PACK_EXPANSION_PATTERN (t2));
+
+ case DECLTYPE_TYPE:
+ if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t1)
+ != DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t2)
+ || !cp_tree_equal (DECLTYPE_TYPE_EXPR (t1),
+ DECLTYPE_TYPE_EXPR (t2)))
+ return false;
+ break;
+
default:
return false;
}
{
if (strict == COMPARE_STRICT)
{
- bool result;
-
if (t1 == t2)
return true;
perform a deep check. */
return structural_comptypes (t1, t2, strict);
- if (VERIFY_CANONICAL_TYPES)
+#ifdef ENABLE_CHECKING
+ if (USE_CANONICAL_TYPES)
{
- result = structural_comptypes (t1, t2, strict);
-
+ bool result = structural_comptypes (t1, t2, strict);
+
if (result && TYPE_CANONICAL (t1) != TYPE_CANONICAL (t2))
- {
- /* The two types are structurally equivalent, but their
- canonical types were different. This is a failure of the
- canonical type propagation code.*/
- warning(0,
- "canonical types differ for identical types %T and %T",
- t1, t2);
- debug_tree (t1);
- debug_tree (t2);
- }
+ /* The two types are structurally equivalent, but their
+ canonical types were different. This is a failure of the
+ canonical type propagation code.*/
+ internal_error
+ ("canonical types differ for identical types %T and %T",
+ t1, t2);
else if (!result && TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2))
- {
- /* Two types are structurally different, but the canonical
- types are the same. This means we were over-eager in
- assigning canonical types. */
- warning (0,
- "same canonical type node for different types %T and %T",
- t1, t2);
- debug_tree (t1);
- debug_tree (t2);
- }
+ /* Two types are structurally different, but the canonical
+ types are the same. This means we were over-eager in
+ assigning canonical types. */
+ internal_error
+ ("same canonical type node for different types %T and %T",
+ t1, t2);
return result;
}
- else
+#else
+ if (USE_CANONICAL_TYPES)
return TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2);
+#endif
+ else
+ return structural_comptypes (t1, t2, strict);
}
else if (strict == COMPARE_STRUCTURAL)
return structural_comptypes (t1, t2, COMPARE_STRICT);
else
return 0;
}
-
-/* If two types share a common base type, return that basetype.
- If there is not a unique most-derived base type, this function
- returns ERROR_MARK_NODE. */
-
-static tree
-common_base_type (tree tt1, tree tt2)
-{
- tree best = NULL_TREE;
- int i;
-
- /* If one is a baseclass of another, that's good enough. */
- if (UNIQUELY_DERIVED_FROM_P (tt1, tt2))
- return tt1;
- if (UNIQUELY_DERIVED_FROM_P (tt2, tt1))
- return tt2;
-
- /* Otherwise, try to find a unique baseclass of TT1
- that is shared by TT2, and follow that down. */
- for (i = BINFO_N_BASE_BINFOS (TYPE_BINFO (tt1))-1; i >= 0; i--)
- {
- tree basetype = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (tt1), i));
- tree trial = common_base_type (basetype, tt2);
-
- if (trial)
- {
- if (trial == error_mark_node)
- return trial;
- if (best == NULL_TREE)
- best = trial;
- else if (best != trial)
- return error_mark_node;
- }
- }
-
- /* Same for TT2. */
- for (i = BINFO_N_BASE_BINFOS (TYPE_BINFO (tt2))-1; i >= 0; i--)
- {
- tree basetype = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (tt2), i));
- tree trial = common_base_type (tt1, basetype);
-
- if (trial)
- {
- if (trial == error_mark_node)
- return trial;
- if (best == NULL_TREE)
- best = trial;
- else if (best != trial)
- return error_mark_node;
- }
- }
- return best;
-}
\f
/* Subroutines of `comptypes'. */
{
pedwarn ("ISO C++ forbids applying %<__alignof%> to an expression of "
"function type");
- t = size_one_node;
+ if (TREE_CODE (e) == FUNCTION_DECL)
+ t = size_int (DECL_ALIGN_UNIT (e));
+ else
+ t = size_one_node;
}
else if (type_unknown_p (e))
{
tree
is_bitfield_expr_with_lowered_type (tree exp)
{
- tree field;
-
- if (TREE_CODE (exp) == COND_EXPR)
+ switch (TREE_CODE (exp))
{
+ case COND_EXPR:
if (!is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 1)))
return NULL_TREE;
return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 2));
+
+ case COMPOUND_EXPR:
+ return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 1));
+
+ case MODIFY_EXPR:
+ case SAVE_EXPR:
+ return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0));
+
+ case COMPONENT_REF:
+ {
+ tree field;
+
+ field = TREE_OPERAND (exp, 1);
+ if (TREE_CODE (field) != FIELD_DECL || !DECL_C_BIT_FIELD (field))
+ return NULL_TREE;
+ if (same_type_ignoring_top_level_qualifiers_p
+ (TREE_TYPE (exp), DECL_BIT_FIELD_TYPE (field)))
+ return NULL_TREE;
+ return DECL_BIT_FIELD_TYPE (field);
+ }
+
+ default:
+ return NULL_TREE;
}
- if (TREE_CODE (exp) != COMPONENT_REF)
- return NULL_TREE;
- field = TREE_OPERAND (exp, 1);
- if (TREE_CODE (field) != FIELD_DECL || !DECL_C_BIT_FIELD (field))
- return NULL_TREE;
- if (same_type_ignoring_top_level_qualifiers_p
- (TREE_TYPE (exp), DECL_BIT_FIELD_TYPE (field)))
- return NULL_TREE;
- return DECL_BIT_FIELD_TYPE (field);
+}
+
+/* Like is_bitfield_with_lowered_type, except that if EXP is not a
+ bitfield with a lowered type, the type of EXP is returned, rather
+ than NULL_TREE. */
+
+tree
+unlowered_expr_type (tree exp)
+{
+ tree type;
+
+ type = is_bitfield_expr_with_lowered_type (exp);
+ if (!type)
+ type = TREE_TYPE (exp);
+
+ return type;
}
/* Perform the conversions in [expr] that apply when an lvalue appears
/* Transform `(a, b).x' into `(*(a, &b)).x', `(a ? b : c).x' into
`(*(a ? &b : &c)).x', and so on. A COND_EXPR is only an lvalue
- in the frontend; only _DECLs and _REFs are lvalues in the backend. */
+ in the front end; only _DECLs and _REFs are lvalues in the back end. */
{
tree temp = unary_complex_lvalue (ADDR_EXPR, object);
if (temp)
types. */
tree t = canonical_type_variant (TREE_TYPE (type));
+ if (TREE_CODE (ptr) == CONVERT_EXPR
+ || TREE_CODE (ptr) == NOP_EXPR
+ || TREE_CODE (ptr) == VIEW_CONVERT_EXPR)
+ {
+ /* If a warning is issued, mark it to avoid duplicates from
+ the backend. This only needs to be done at
+ warn_strict_aliasing > 2. */
+ if (warn_strict_aliasing > 2)
+ if (strict_aliasing_warning (TREE_TYPE (TREE_OPERAND (ptr, 0)),
+ type, TREE_OPERAND (ptr, 0)))
+ TREE_NO_WARNING (ptr) = 1;
+ }
+
if (VOID_TYPE_P (t))
{
/* A pointer to incomplete type (other than cv void) can be
return error_mark_node;
}
/* ...and then the delta in the PMF. */
- instance_ptr = build2 (PLUS_EXPR, TREE_TYPE (instance_ptr),
- instance_ptr, delta);
+ instance_ptr = build2 (POINTER_PLUS_EXPR, TREE_TYPE (instance_ptr),
+ instance_ptr, fold_convert (sizetype, delta));
/* Hand back the adjusted 'this' argument to our caller. */
*instance_ptrptr = instance_ptr;
vtbl = build_indirect_ref (vtbl, NULL);
/* Finally, extract the function pointer from the vtable. */
- e2 = fold_build2 (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, idx);
+ e2 = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
+ fold_convert (sizetype, idx));
e2 = build_indirect_ref (e2, NULL);
TREE_CONSTANT (e2) = 1;
TREE_INVARIANT (e2) = 1;
build_function_call (tree function, tree params)
{
tree fntype, fndecl;
- tree coerced_params;
tree name = NULL_TREE;
int is_method;
tree original = function;
+ int nargs, parm_types_len;
+ tree *argarray;
+ tree parm_types;
/* For Objective-C, convert any calls via a cast to OBJC_TYPE_REF
expressions, like those used for ObjC messenger dispatches. */
/* fntype now gets the type of function pointed to. */
fntype = TREE_TYPE (fntype);
+ parm_types = TYPE_ARG_TYPES (fntype);
+
+ /* Allocate storage for converted arguments. */
+ parm_types_len = list_length (parm_types);
+ nargs = list_length (params);
+ if (parm_types_len > nargs)
+ nargs = parm_types_len;
+ argarray = (tree *) alloca (nargs * sizeof (tree));
/* Convert the parameters to the types declared in the
function prototype, or apply default promotions. */
-
- coerced_params = convert_arguments (TYPE_ARG_TYPES (fntype),
- params, fndecl, LOOKUP_NORMAL);
- if (coerced_params == error_mark_node)
+ nargs = convert_arguments (nargs, argarray, parm_types,
+ params, fndecl, LOOKUP_NORMAL);
+ if (nargs < 0)
return error_mark_node;
/* Check for errors in format strings and inappropriately
null parameters. */
- check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params,
- TYPE_ARG_TYPES (fntype));
+ check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray,
+ parm_types);
- return build_cxx_call (function, coerced_params);
+ return build_cxx_call (function, nargs, argarray);
}
\f
/* Convert the actual parameter expressions in the list VALUES
If parmdecls is exhausted, or when an element has NULL as its type,
perform the default conversions.
+ Store the converted arguments in ARGARRAY. NARGS is the size of this array.
+
NAME is an IDENTIFIER_NODE or 0. It is used only for error messages.
This is also where warnings about wrong number of args are generated.
- Return a list of expressions for the parameters as converted.
+ Returns the actual number of arguments processed (which might be less
+ than NARGS), or -1 on error.
- Both VALUES and the returned value are chains of TREE_LIST nodes
- with the elements of the list in the TREE_VALUE slots of those nodes.
+ VALUES is a chain of TREE_LIST nodes with the elements of the list
+ in the TREE_VALUE slots of those nodes.
In C++, unspecified trailing parameters can be filled in with their
default arguments, if such were specified. Do so here. */
-static tree
-convert_arguments (tree typelist, tree values, tree fndecl, int flags)
+static int
+convert_arguments (int nargs, tree *argarray,
+ tree typelist, tree values, tree fndecl, int flags)
{
tree typetail, valtail;
- tree result = NULL_TREE;
const char *called_thing = 0;
int i = 0;
tree val = TREE_VALUE (valtail);
if (val == error_mark_node || type == error_mark_node)
- return error_mark_node;
+ return -1;
if (type == void_type_node)
{
}
else
error ("too many arguments to function");
- /* In case anybody wants to know if this argument
- list is valid. */
- if (result)
- TREE_TYPE (tree_last (result)) = error_mark_node;
- break;
+ return i;
}
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
}
if (val == error_mark_node)
- return error_mark_node;
+ return -1;
if (type != 0)
{
}
if (parmval == error_mark_node)
- return error_mark_node;
+ return -1;
- result = tree_cons (NULL_TREE, parmval, result);
+ argarray[i] = parmval;
}
else
{
else
val = convert_arg_to_ellipsis (val);
- result = tree_cons (NULL_TREE, val, result);
+ argarray[i] = val;
}
if (typetail)
if (typetail != 0 && typetail != void_list_node)
{
- /* See if there are default arguments that can be used. */
- if (TREE_PURPOSE (typetail)
+ /* See if there are default arguments that can be used. Because
+ we hold default arguments in the FUNCTION_TYPE (which is so
+ wrong), we can see default parameters here from deduced
+ contexts (and via typeof) for indirect function calls.
+ Fortunately we know whether we have a function decl to
+ provide default arguments in a language conformant
+ manner. */
+ if (fndecl && TREE_PURPOSE (typetail)
&& TREE_CODE (TREE_PURPOSE (typetail)) != DEFAULT_ARG)
{
for (; typetail != void_list_node; ++i)
fndecl, i);
if (parmval == error_mark_node)
- return error_mark_node;
+ return -1;
- result = tree_cons (0, parmval, result);
+ argarray[i] = parmval;
typetail = TREE_CHAIN (typetail);
/* ends with `...'. */
if (typetail == NULL_TREE)
}
else
error ("too few arguments to function");
- return error_mark_node;
+ return -1;
}
}
- return nreverse (result);
+ gcc_assert (i <= nargs);
+ return i;
}
\f
/* Build a binary-operation expression, after performing default
{
enum tree_code tcode0 = code0, tcode1 = code1;
- if (TREE_CODE (op1) == INTEGER_CST && integer_zerop (op1))
- warning (OPT_Wdiv_by_zero, "division by zero in %<%E / 0%>", op0);
- else if (TREE_CODE (op1) == REAL_CST && real_zerop (op1))
- warning (OPT_Wdiv_by_zero, "division by zero in %<%E / 0.%>", op0);
+ warn_for_div_by_zero (op1);
if (tcode0 == COMPLEX_TYPE || tcode0 == VECTOR_TYPE)
tcode0 = TREE_CODE (TREE_TYPE (TREE_TYPE (op0)));
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
if ((code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
- || (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE))
+ || (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+ && !VECTOR_FLOAT_TYPE_P (type0)
+ && !VECTOR_FLOAT_TYPE_P (type1)))
shorten = -1;
break;
case TRUNC_MOD_EXPR:
case FLOOR_MOD_EXPR:
- if (code1 == INTEGER_TYPE && integer_zerop (op1))
- warning (OPT_Wdiv_by_zero, "division by zero in %<%E %% 0%>", op0);
- else if (code1 == REAL_TYPE && real_zerop (op1))
- warning (OPT_Wdiv_by_zero, "division by zero in %<%E %% 0.%>", op0);
+ warn_for_div_by_zero (op1);
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
{
"comparing floating point with == or != is unsafe");
if ((TREE_CODE (orig_op0) == STRING_CST && !integer_zerop (op1))
|| (TREE_CODE (orig_op1) == STRING_CST && !integer_zerop (op0)))
- warning (OPT_Wstring_literal_comparison,
- "comparison with string literal");
+ warning (OPT_Waddress, "comparison with string literal results in unspecified behaviour");
build_type = boolean_type_node;
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
{
if (TREE_CODE (op0) == ADDR_EXPR
&& decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0)))
- warning (OPT_Walways_true, "the address of %qD will never be NULL",
+ warning (OPT_Waddress, "the address of %qD will never be NULL",
TREE_OPERAND (op0, 0));
result_type = type0;
}
{
if (TREE_CODE (op1) == ADDR_EXPR
&& decl_with_nonnull_addr_p (TREE_OPERAND (op1, 0)))
- warning (OPT_Walways_true, "the address of %qD will never be NULL",
+ warning (OPT_Waddress, "the address of %qD will never be NULL",
TREE_OPERAND (op1, 0));
result_type = type1;
}
case GT_EXPR:
if (TREE_CODE (orig_op0) == STRING_CST
|| TREE_CODE (orig_op1) == STRING_CST)
- warning (OPT_Wstring_literal_comparison,
- "comparison with string literal");
+ warning (OPT_Waddress, "comparison with string literal results in unspecified behaviour");
build_type = boolean_type_node;
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
|| !same_scalar_type_ignoring_signedness (TREE_TYPE (type0),
TREE_TYPE (type1)))
{
- binary_op_error (code);
+ binary_op_error (code, type0, type1);
return error_mark_node;
}
arithmetic_types_p = 1;
/* If we're in a template, the only thing we need to know is the
RESULT_TYPE. */
if (processing_template_decl)
- return build2 (resultcode,
- build_type ? build_type : result_type,
- op0, op1);
+ {
+ /* Since the middle-end checks the type when doing a build2, we
+ need to build the tree in pieces. This built tree will never
+ get out of the front-end as we replace it when instantiating
+ the template. */
+ tree tmp = build2 (resultcode,
+ build_type ? build_type : result_type,
+ NULL_TREE, op1);
+ TREE_OPERAND (tmp, 0) = op0;
+ return tmp;
+ }
if (arithmetic_types_p)
{
}
}
- /* If CONVERTED is zero, both args will be converted to type RESULT_TYPE.
- Then the expression will be built.
- It will be given type FINAL_TYPE if that is nonzero;
- otherwise, it will be given type RESULT_TYPE. */
-
/* Issue warnings about peculiar, but valid, uses of NULL. */
- if (/* It's reasonable to use pointer values as operands of &&
+ if ((orig_op0 == null_node || orig_op1 == null_node)
+ /* It's reasonable to use pointer values as operands of &&
and ||, so NULL is no exception. */
- !(code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
- && (/* If OP0 is NULL and OP1 is not a pointer, or vice versa. */
- (orig_op0 == null_node
- && TREE_CODE (TREE_TYPE (op1)) != POINTER_TYPE)
- /* Or vice versa. */
- || (orig_op1 == null_node
- && TREE_CODE (TREE_TYPE (op0)) != POINTER_TYPE)
- /* Or, both are NULL and the operation was not a comparison. */
- || (orig_op0 == null_node && orig_op1 == null_node
- && code != EQ_EXPR && code != NE_EXPR)))
+ && code != TRUTH_ANDIF_EXPR && code != TRUTH_ORIF_EXPR
+ && ( /* Both are NULL (or 0) and the operation was not a comparison. */
+ (null_ptr_cst_p (orig_op0) && null_ptr_cst_p (orig_op1)
+ && code != EQ_EXPR && code != NE_EXPR)
+ /* Or if one of OP0 or OP1 is neither a pointer nor NULL. */
+ || (!null_ptr_cst_p (orig_op0) && TREE_CODE (TREE_TYPE (op0)) != POINTER_TYPE)
+ || (!null_ptr_cst_p (orig_op1) && TREE_CODE (TREE_TYPE (op1)) != POINTER_TYPE)))
/* Some sort of arithmetic operation involving NULL was
performed. Note that pointer-difference and pointer-addition
have already been handled above, and so we don't end up here in
that case. */
- warning (0, "NULL used in arithmetic");
+ warning (OPT_Wpointer_arith, "NULL used in arithmetic");
+
+ /* If CONVERTED is zero, both args will be converted to type RESULT_TYPE.
+ Then the expression will be built.
+ It will be given type FINAL_TYPE if that is nonzero;
+ otherwise, it will be given type RESULT_TYPE. */
if (! converted)
{
if (TREE_TYPE (op0) != result_type)
- op0 = cp_convert (result_type, op0);
+ op0 = cp_convert_and_check (result_type, op0);
if (TREE_TYPE (op1) != result_type)
- op1 = cp_convert (result_type, op1);
+ op1 = cp_convert_and_check (result_type, op1);
if (op0 == error_mark_node || op1 == error_mark_node)
return error_mark_node;
arg = stabilize_reference (arg);
real = build_unary_op (REALPART_EXPR, arg, 1);
imag = build_unary_op (IMAGPART_EXPR, arg, 1);
+ real = build_unary_op (code, real, 1);
+ if (real == error_mark_node || imag == error_mark_node)
+ return error_mark_node;
return build2 (COMPLEX_EXPR, TREE_TYPE (arg),
- build_unary_op (code, real, 1), imag);
+ real, imag);
}
/* Report invalid types. */
|| TREE_READONLY (arg))
readonly_error (arg, ((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
- ? "increment" : "decrement"),
- 0);
+ ? "increment" : "decrement"));
{
tree inc;
+ tree declared_type;
tree result_type = TREE_TYPE (arg);
+ declared_type = unlowered_expr_type (arg);
+
arg = get_unwidened (arg, 0);
argtype = TREE_TYPE (arg);
inc = cp_convert (argtype, inc);
- /* Handle incrementing a cast-expression. */
-
- switch (TREE_CODE (arg))
- {
- case NOP_EXPR:
- case CONVERT_EXPR:
- case FLOAT_EXPR:
- case FIX_TRUNC_EXPR:
- {
- tree incremented, modify, value, compound;
- if (! lvalue_p (arg) && pedantic)
- pedwarn ("cast to non-reference type used as lvalue");
- arg = stabilize_reference (arg);
- if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
- value = arg;
- else
- value = save_expr (arg);
- incremented = build2 (((code == PREINCREMENT_EXPR
- || code == POSTINCREMENT_EXPR)
- ? PLUS_EXPR : MINUS_EXPR),
- argtype, value, inc);
-
- modify = build_modify_expr (arg, NOP_EXPR, incremented);
- compound = build2 (COMPOUND_EXPR, TREE_TYPE (arg),
- modify, value);
-
- /* Eliminate warning about unused result of + or -. */
- TREE_NO_WARNING (compound) = 1;
- return compound;
- }
-
- default:
- break;
- }
-
/* Complain about anything else that is not a true lvalue. */
if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
return error_mark_node;
/* Forbid using -- on `bool'. */
- if (same_type_p (TREE_TYPE (arg), boolean_type_node))
+ if (same_type_p (declared_type, boolean_type_node))
{
if (code == POSTDECREMENT_EXPR || code == PREDECREMENT_EXPR)
{
}
/* If EXPR is an INTEGER_CST and ORIG is an arithmetic constant, return
- a version of EXPR that has TREE_OVERFLOW and/or TREE_CONSTANT_OVERFLOW
- set iff they are set in ORIG. Otherwise, return EXPR unchanged. */
+ 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)
- || TREE_CONSTANT_OVERFLOW (expr)
- != TREE_CONSTANT_OVERFLOW (orig)))
+ && TREE_OVERFLOW (expr) != TREE_OVERFLOW (orig))
{
- if (!TREE_OVERFLOW (orig) && !TREE_CONSTANT_OVERFLOW (orig))
+ if (!TREE_OVERFLOW (orig))
/* Ensure constant sharing. */
expr = build_int_cst_wide (TREE_TYPE (expr),
TREE_INT_CST_LOW (expr),
/* Avoid clobbering a shared constant. */
expr = copy_node (expr);
TREE_OVERFLOW (expr) = TREE_OVERFLOW (orig);
- TREE_CONSTANT_OVERFLOW (expr)
- = TREE_CONSTANT_OVERFLOW (orig);
}
}
return expr;
"target type",
intype, type);
- /* We need to strip nops here, because the frontend likes to
+ /* We need to strip nops here, because the front end likes to
create (int *)&a for array-to-pointer decay, instead of &a[0]. */
STRIP_NOPS (sexpr);
- strict_aliasing_warning (intype, type, sexpr);
+ if (warn_strict_aliasing <= 2)
+ strict_aliasing_warning (intype, type, sexpr);
return fold_if_not_in_template (build_nop (type, expr));
}
}
else if (TREE_CODE (type) == VECTOR_TYPE)
return fold_if_not_in_template (convert_to_vector (type, expr));
- else if (TREE_CODE (intype) == VECTOR_TYPE)
+ else if (TREE_CODE (intype) == VECTOR_TYPE && INTEGRAL_TYPE_P (type))
return fold_if_not_in_template (convert_to_integer (type, expr));
else
{
tree cond;
tree preeval = NULL_TREE;
+ if (VOID_TYPE_P (TREE_TYPE (rhs)))
+ {
+ error ("void value not ignored as it ought to be");
+ return error_mark_node;
+ }
+
rhs = stabilize_expr (rhs, &preeval);
/* Check this here to avoid odd errors when trying to convert
effectively const. */
|| (CLASS_TYPE_P (lhstype)
&& C_TYPE_FIELDS_READONLY (lhstype))))
- readonly_error (lhs, "assignment", 0);
+ readonly_error (lhs, "assignment");
/* If storing into a structure or union member, it has probably been
given type `int'. Compute the type that would go with the actual
coder = TREE_CODE (rhstype);
if (TREE_CODE (type) == VECTOR_TYPE && coder == VECTOR_TYPE
- && vector_types_convertible_p (type, rhstype))
+ && vector_types_convertible_p (type, rhstype, true))
return convert (type, rhs);
if (rhs == error_mark_node || rhstype == error_mark_node)
errtype);
}
- /* If -Wparentheses, warn about a = b = c when a has type bool. */
+ /* If -Wparentheses, warn about a = b = c when a has type bool and b
+ does not. */
if (warn_parentheses
&& type == boolean_type_node
&& TREE_CODE (rhs) == MODIFY_EXPR
- && !TREE_NO_WARNING (rhs))
+ && !TREE_NO_WARNING (rhs)
+ && TREE_TYPE (rhs) != boolean_type_node)
{
warning (OPT_Wparentheses,
"suggest parentheses around assignment used as truth value");
promotions. */
tree valtype;
int fn_returns_value_p;
+ bool named_return_value_okay_p;
*no_warning = false;
if (processing_template_decl)
{
current_function_returns_value = 1;
+ check_for_bare_parameter_packs (retval);
return retval;
}
|| DECL_OVERLOADED_OPERATOR_P (current_function_decl) == VEC_NEW_EXPR)
&& !TYPE_NOTHROW_P (TREE_TYPE (current_function_decl))
&& ! flag_check_new
- && null_ptr_cst_p (retval))
+ && retval && null_ptr_cst_p (retval))
warning (0, "%<operator new%> must not return NULL unless it is "
"declared %<throw()%> (or -fcheck-new is in effect)");
See finish_function and finalize_nrv for the rest of this optimization. */
+ named_return_value_okay_p =
+ (retval != NULL_TREE
+ /* Must be a local, automatic variable. */
+ && TREE_CODE (retval) == VAR_DECL
+ && DECL_CONTEXT (retval) == current_function_decl
+ && ! TREE_STATIC (retval)
+ && ! DECL_ANON_UNION_VAR_P (retval)
+ && (DECL_ALIGN (retval)
+ >= DECL_ALIGN (DECL_RESULT (current_function_decl)))
+ /* The cv-unqualified type of the returned value must be the
+ same as the cv-unqualified return type of the
+ function. */
+ && same_type_p ((TYPE_MAIN_VARIANT (TREE_TYPE (retval))),
+ (TYPE_MAIN_VARIANT
+ (TREE_TYPE (TREE_TYPE (current_function_decl))))));
+
if (fn_returns_value_p && flag_elide_constructors)
{
- if (retval != NULL_TREE
- && (current_function_return_value == NULL_TREE
- || current_function_return_value == retval)
- && TREE_CODE (retval) == VAR_DECL
- && DECL_CONTEXT (retval) == current_function_decl
- && ! TREE_STATIC (retval)
- && (DECL_ALIGN (retval)
- >= DECL_ALIGN (DECL_RESULT (current_function_decl)))
- && same_type_p ((TYPE_MAIN_VARIANT
- (TREE_TYPE (retval))),
- (TYPE_MAIN_VARIANT
- (TREE_TYPE (TREE_TYPE (current_function_decl))))))
+ if (named_return_value_okay_p
+ && (current_function_return_value == NULL_TREE
+ || current_function_return_value == retval))
current_function_return_value = retval;
else
current_function_return_value = error_mark_node;
{
/* The type the function is declared to return. */
tree functype = TREE_TYPE (TREE_TYPE (current_function_decl));
+ int flags = LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING;
/* The functype's return type will have been set to void, if it
was an incomplete type. Just treat this as 'return;' */
if (VOID_TYPE_P (functype))
return error_mark_node;
+ /* 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_quals (TREE_TYPE (retval)) & TYPE_QUAL_VOLATILE)
+ /* The return type must be a class type. */
+ && CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))))
+ flags = flags | LOOKUP_PREFER_RVALUE;
+
/* First convert the value to the function's return type, then
to the type of return value's location to handle the
case that functype is smaller than the valtype. */
retval = convert_for_initialization
- (NULL_TREE, functype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING,
- "return", NULL_TREE, 0);
+ (NULL_TREE, functype, retval, flags, "return", NULL_TREE, 0);
retval = convert (valtype, retval);
/* If the conversion failed, treat this just like `return;'. */
continue;
if (TREE_CODE (to) == VECTOR_TYPE
- && vector_types_convertible_p (to, from))
+ && vector_types_convertible_p (to, from, false))
return 1;
if (TREE_CODE (to) == INTEGER_TYPE
return TYPE_QUALS (type);
}
+/* Returns nonzero if the TYPE is const from a C++ perspective: look inside
+ arrays. */
+
+bool
+cp_type_readonly (tree type)
+{
+ type = strip_array_types (type);
+ return TYPE_READONLY (type);
+}
+
/* Returns nonzero if the TYPE contains a mutable member. */
bool