/* 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 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
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.
#include "output.h"
#include "toplev.h"
#include "diagnostic.h"
+#include "intl.h"
#include "target.h"
#include "convert.h"
#include "c-common.h"
+#include "params.h"
static tree pfn_from_ptrmemfunc (tree);
+static tree delta_from_ptrmemfunc (tree);
static tree convert_for_assignment (tree, tree, const char *, tree, int);
static tree cp_pointer_int_sum (enum tree_code, tree, tree);
static tree rationalize_conditional_expr (enum tree_code, tree);
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 bool comp_array_types (const_tree, const_tree, bool);
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.)
/* Return truthvalue of whether type of EXP is instantiated. */
int
-type_unknown_p (tree exp)
+type_unknown_p (const_tree exp)
{
return (TREE_CODE (exp) == TREE_LIST
|| TREE_TYPE (exp) == unknown_type_node);
\f
/* Return the common type of two parameter lists.
- We assume that comptypes has already been done and returned 1;
+ We assume that cp_comptypes has already been done and returned 1;
if that isn't so, this may crash.
As an optimization, free the space we allocate if the parameter
static tree
original_type (tree t)
{
- while (TYPE_NAME (t) != NULL_TREE)
+ int quals = cp_type_quals (t);
+ while (t != error_mark_node
+ && TYPE_NAME (t) != NULL_TREE)
{
tree x = TYPE_NAME (t);
if (TREE_CODE (x) != TYPE_DECL)
break;
t = x;
}
- return t;
+ return cp_build_qualified_type (t, quals);
}
/* T1 and T2 are arithmetic or enumeration types. Return the type
/* 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 (t1) == VECTOR_TYPE
+ || TREE_CODE (t2) == VECTOR_TYPE
|| TREE_CODE (t2) == ENUMERAL_TYPE);
/* In what follows, we slightly generalize the rules given in [expr] so
if (code1 != REAL_TYPE)
{
- /* If one is a sizetype, use it so size_binop doesn't blow up. */
- if (TYPE_IS_SIZETYPE (t1) > TYPE_IS_SIZETYPE (t2))
- return build_type_attribute_variant (t1, attributes);
- if (TYPE_IS_SIZETYPE (t2) > TYPE_IS_SIZETYPE (t1))
- return build_type_attribute_variant (t2, attributes);
-
/* If one is unsigned long long, then convert the other to unsigned
long long. */
if (same_type_p (TYPE_MAIN_VARIANT (t1), long_long_unsigned_type_node)
}
/* Return the merged type of two types.
- We assume that comptypes has already been done and returned 1;
+ We assume that cp_comptypes has already been done and returned 1;
if that isn't so, this may crash.
This just combines attributes and default arguments; any other
if (code1 == POINTER_TYPE)
t1 = build_pointer_type (target);
else
- t1 = build_reference_type (target);
+ t1 = cp_build_reference_type (target, TYPE_REF_IS_RVALUE (t1));
t1 = build_type_attribute_variant (t1, attributes);
t1 = cp_build_qualified_type (t1, quals);
default:;
}
- return cp_build_type_attribute_variant (t1, attributes);
+
+ if (attribute_list_equal (TYPE_ATTRIBUTES (t1), attributes))
+ return t1;
+ else if (attribute_list_equal (TYPE_ATTRIBUTES (t2), attributes))
+ return t2;
+ else
+ return cp_build_type_attribute_variant (t1, attributes);
}
/* Return the common type of two types.
- We assume that comptypes has already been done and returned 1;
+ We assume that cp_comptypes has already been done and returned 1;
if that isn't so, this may crash.
This is the type for the result of most arithmetic operations
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))
we should try to make use of that. */
bool
-comp_except_specs (tree t1, tree t2, bool exact)
+comp_except_specs (const_tree t1, const_tree t2, bool exact)
{
- tree probe;
- tree base;
+ const_tree probe;
+ const_tree base;
int length = 0;
if (t1 == t2)
[] can match [size]. */
static bool
-comp_array_types (tree t1, tree t2, bool allow_redeclaration)
+comp_array_types (const_tree t1, const_tree t2, bool allow_redeclaration)
{
tree d1;
tree d2;
return true;
}
-/* Return true if T1 and T2 are related as allowed by STRICT. STRICT
- is a bitwise-or of the COMPARE_* flags. */
+/* Subroutine in cp_comptypes. */
-bool
-comptypes (tree t1, tree t2, int strict)
+static bool
+structural_comptypes (tree t1, tree t2, int strict)
{
if (t1 == t2)
return true;
/* 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;
- }
-
- /* If either type is the internal version of sizetype, use the
- language version. */
- if (TREE_CODE (t1) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t1)
- && TYPE_ORIG_SIZE_TYPE (t1))
- t1 = TYPE_ORIG_SIZE_TYPE (t1);
-
- if (TREE_CODE (t2) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t2)
- && TYPE_ORIG_SIZE_TYPE (t2))
- t2 = TYPE_ORIG_SIZE_TYPE (t2);
+ t2 = resolve_typename_type (t2, /*only_current_p=*/true);
if (TYPE_PTRMEMFUNC_P (t1))
t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);
if (TREE_CODE (t1) != ARRAY_TYPE
&& TYPE_QUALS (t1) != TYPE_QUALS (t2))
return false;
- if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (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
&& TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
return true;
+ if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
+ return false;
+
/* Compare the types. Break out if they could be the same. */
switch (TREE_CODE (t1))
{
+ case VOID_TYPE:
+ case BOOLEAN_TYPE:
+ /* All void and bool types are the same. */
+ break;
+
+ case INTEGER_TYPE:
+ case FIXED_POINT_TYPE:
+ case REAL_TYPE:
+ /* With these nodes, we can't determine type equivalence by
+ looking at what is stored in the nodes themselves, because
+ two nodes might have different TYPE_MAIN_VARIANTs but still
+ represent the same type. For example, wchar_t and int could
+ have the same properties (TYPE_PRECISION, TYPE_MIN_VALUE,
+ TYPE_MAX_VALUE, etc.), but have different TYPE_MAIN_VARIANTs
+ and are distinct types. On the other hand, int and the
+ following typedef
+
+ typedef int INT __attribute((may_alias));
+
+ have identical properties, different TYPE_MAIN_VARIANTs, but
+ represent the same type. The canonical type system keeps
+ track of equivalence in this case, so we fall back on it. */
+ return TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2);
+
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;
case OFFSET_TYPE:
- if (!comptypes (TYPE_OFFSET_BASETYPE (t1), TYPE_OFFSET_BASETYPE (t2),
- strict & ~COMPARE_REDECLARATION))
+ if (!cp_comptypes (TYPE_OFFSET_BASETYPE (t1), TYPE_OFFSET_BASETYPE (t2),
+ strict & ~COMPARE_REDECLARATION))
return false;
if (!same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
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;
}
return targetm.comp_type_attributes (t1, t2);
}
+extern int comptypes (tree, tree);
+
+/* Type comparison function that matches the signature of comptypes
+ from c-tree.h, which is used by the C front end and some of the
+ C/C++ common bits. */
+int
+comptypes (tree t1, tree t2)
+{
+ return cp_comptypes (t1, t2, COMPARE_STRICT);
+}
+
+/* Return true if T1 and T2 are related as allowed by STRICT. STRICT
+ is a bitwise-or of the COMPARE_* flags. */
+
+bool
+cp_comptypes (tree t1, tree t2, int strict)
+{
+ if (strict == COMPARE_STRICT)
+ {
+ if (t1 == t2)
+ return true;
+
+ if (t1 == error_mark_node || t2 == error_mark_node)
+ return false;
+
+ if (TYPE_STRUCTURAL_EQUALITY_P (t1) || TYPE_STRUCTURAL_EQUALITY_P (t2))
+ /* At least one of the types requires structural equality, so
+ perform a deep check. */
+ return structural_comptypes (t1, t2, strict);
+
+#ifdef ENABLE_CHECKING
+ if (USE_CANONICAL_TYPES)
+ {
+ 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.*/
+ 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. */
+ internal_error
+ ("same canonical type node for different types %T and %T",
+ t1, t2);
+
+ return result;
+ }
+#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 structural_comptypes (t1, t2, strict);
+}
+
/* Returns 1 if TYPE1 is at least as qualified as TYPE2. */
bool
-at_least_as_qualified_p (tree type1, tree type2)
+at_least_as_qualified_p (const_tree type1, const_tree type2)
{
int q1 = cp_type_quals (type1);
int q2 = cp_type_quals (type2);
more cv-qualified that TYPE1, and 0 otherwise. */
int
-comp_cv_qualification (tree type1, tree type2)
+comp_cv_qualification (const_tree type1, const_tree type2)
{
int q1 = cp_type_quals (type1);
int q2 = cp_type_quals (type2);
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'. */
+/* Subroutines of `cp_comptypes'. */
/* Return true if two parameter type lists PARMS1 and PARMS2 are
equivalent in the sense that functions with those parameter types
element by element. */
bool
-compparms (tree parms1, tree parms2)
+compparms (const_tree parms1, const_tree parms2)
{
- tree t1, t2;
+ const_tree t1, t2;
/* An unspecified parmlist matches any specified parmlist
whose argument types don't need default promotions. */
tree
cxx_sizeof_or_alignof_type (tree type, enum tree_code op, bool complain)
{
- enum tree_code type_code;
tree value;
- const char *op_name;
+ bool dependent_p;
gcc_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR);
if (type == error_mark_node)
return error_mark_node;
- if (dependent_type_p (type))
- {
- value = build_min (op, size_type_node, type);
- TREE_READONLY (value) = 1;
- return value;
- }
-
- op_name = operator_name_info[(int) op].name;
-
type = non_reference (type);
- type_code = TREE_CODE (type);
-
- if (type_code == METHOD_TYPE)
+ if (TREE_CODE (type) == METHOD_TYPE)
{
if (complain && (pedantic || warn_pointer_arith))
- pedwarn ("invalid application of %qs to a member function", op_name);
+ pedwarn ("invalid application of %qs to a member function",
+ operator_name_info[(int) op].name);
value = size_one_node;
}
- else
- value = c_sizeof_or_alignof_type (complete_type (type),
- op == SIZEOF_EXPR,
- complain);
- return value;
+ dependent_p = dependent_type_p (type);
+ if (!dependent_p)
+ complete_type (type);
+ if (dependent_p
+ /* VLA types will have a non-constant size. In the body of an
+ uninstantiated template, we don't need to try to compute the
+ value, because the sizeof expression is not an integral
+ constant expression in that case. And, if we do try to
+ compute the value, we'll likely end up with SAVE_EXPRs, which
+ the template substitution machinery does not expect to see. */
+ || (processing_template_decl
+ && COMPLETE_TYPE_P (type)
+ && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST))
+ {
+ value = build_min (op, size_type_node, type);
+ TREE_READONLY (value) = 1;
+ return value;
+ }
+
+ return c_sizeof_or_alignof_type (complete_type (type),
+ op == SIZEOF_EXPR,
+ complain);
}
/* Process a sizeof expression where the operand is an expression. */
cxx_alignof_expr (tree e)
{
tree t;
-
+
if (e == error_mark_node)
return error_mark_node;
{
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))
{
violates these rules. */
bool
-invalid_nonstatic_memfn_p (tree expr)
+invalid_nonstatic_memfn_p (const_tree expr)
{
if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE)
{
return false;
}
+/* If EXP is a reference to a bitfield, and the type of EXP does not
+ match the declared type of the bitfield, return the declared type
+ of the bitfield. Otherwise, return NULL_TREE. */
+
+tree
+is_bitfield_expr_with_lowered_type (const_tree exp)
+{
+ switch (TREE_CODE (exp))
+ {
+ case COND_EXPR:
+ if (!is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 1)
+ ? TREE_OPERAND (exp, 1)
+ : TREE_OPERAND (exp, 0)))
+ 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);
+ }
+
+ case NOP_EXPR:
+ case CONVERT_EXPR:
+ if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (exp, 0)))
+ == TYPE_MAIN_VARIANT (TREE_TYPE (exp)))
+ return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0));
+ /* Fallthrough. */
+
+ default:
+ return NULL_TREE;
+ }
+}
+
+/* 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 (const_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
in an rvalue context: the lvalue-to-rvalue, array-to-pointer, and
- function-to-pointer conversions.
+ function-to-pointer conversions. In addition, manifest constants
+ are replaced by their values, and bitfield references are converted
+ to their declared types.
- In addition manifest constants are replaced by their values. */
+ Although the returned value is being used as an rvalue, this
+ function does not wrap the returned expression in a
+ NON_LVALUE_EXPR; the caller is expected to be mindful of the fact
+ that the return value is no longer an lvalue. */
tree
decay_conversion (tree exp)
enum tree_code code;
type = TREE_TYPE (exp);
- code = TREE_CODE (type);
-
if (type == error_mark_node)
return error_mark_node;
}
exp = decl_constant_value (exp);
+ if (error_operand_p (exp))
+ return error_mark_node;
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
Leave such NOP_EXPRs, since RHS is being used in non-lvalue context. */
-
+ code = TREE_CODE (type);
if (code == VOID_TYPE)
{
error ("void value not ignored as it ought to be");
return cp_convert (ptrtype, adr);
}
- /* [basic.lval]: Class rvalues can have cv-qualified types; non-class
- rvalues always have cv-unqualified types. */
- if (! CLASS_TYPE_P (type))
- exp = cp_convert (TYPE_MAIN_VARIANT (type), exp);
+ /* If a bitfield is used in a context where integral promotion
+ applies, then the caller is expected to have used
+ default_conversion. That function promotes bitfields correctly
+ before calling this function. At this point, if we have a
+ bitfield referenced, we may assume that is not subject to
+ promotion, and that, therefore, the type of the resulting rvalue
+ is the declared type of the bitfield. */
+ exp = convert_bitfield_to_declared_type (exp);
+
+ /* We do not call rvalue() here because we do not want to wrap EXP
+ in a NON_LVALUE_EXPR. */
+
+ /* [basic.lval]
+
+ Non-class rvalues always have cv-unqualified types. */
+ type = TREE_TYPE (exp);
+ if (!CLASS_TYPE_P (type) && cp_type_quals (type))
+ exp = build_nop (TYPE_MAIN_VARIANT (type), exp);
return exp;
}
+/* Perform prepatory conversions, as part of the "usual arithmetic
+ conversions". In particular, as per [expr]:
+
+ Whenever an lvalue expression appears as an operand of an
+ operator that expects the rvalue for that operand, the
+ lvalue-to-rvalue, array-to-pointer, or function-to-pointer
+ standard conversions are applied to convert the expression to an
+ rvalue.
+
+ In addition, we perform integral promotions here, as those are
+ applied to both operands to a binary operator before determining
+ what additional conversions should apply. */
+
tree
default_conversion (tree exp)
{
- exp = decay_conversion (exp);
-
+ /* Perform the integral promotions first so that bitfield
+ expressions (which may promote to "int", even if the bitfield is
+ declared "unsigned") are promoted correctly. */
if (INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (exp)))
exp = perform_integral_promotions (exp);
+ /* Perform the other conversions. */
+ exp = decay_conversion (exp);
return exp;
}
tree type;
tree promoted_type;
- type = TREE_TYPE (expr);
+ /* [conv.prom]
+
+ If the bitfield has an enumerated type, it is treated as any
+ other value of that type for promotion purposes. */
+ type = is_bitfield_expr_with_lowered_type (expr);
+ if (!type || TREE_CODE (type) != ENUMERAL_TYPE)
+ type = TREE_TYPE (expr);
gcc_assert (INTEGRAL_OR_ENUMERATION_TYPE_P (type));
promoted_type = type_promotes_to (type);
if (type != promoted_type)
decay_conversion to one. */
int
-string_conv_p (tree totype, tree exp, int warn)
+string_conv_p (const_tree totype, const_tree exp, int warn)
{
tree t;
/* This warning is not very useful, as it complains about printf. */
if (warn)
- warning (OPT_Wwrite_strings, "deprecated conversion from string constant to %qT'", totype);
+ warning (OPT_Wwrite_strings,
+ "deprecated conversion from string constant to %qT",
+ totype);
return 1;
}
are equal, so we know what conditional expression this used to be. */
if (TREE_CODE (t) == MIN_EXPR || TREE_CODE (t) == MAX_EXPR)
{
+ tree op0 = TREE_OPERAND (t, 0);
+ tree op1 = TREE_OPERAND (t, 1);
+
/* The following code is incorrect if either operand side-effects. */
- gcc_assert (!TREE_SIDE_EFFECTS (TREE_OPERAND (t, 0))
- && !TREE_SIDE_EFFECTS (TREE_OPERAND (t, 1)));
+ gcc_assert (!TREE_SIDE_EFFECTS (op0)
+ && !TREE_SIDE_EFFECTS (op1));
return
build_conditional_expr (build_x_binary_op ((TREE_CODE (t) == MIN_EXPR
? LE_EXPR : GE_EXPR),
- TREE_OPERAND (t, 0),
- TREE_OPERAND (t, 1),
+ op0, TREE_CODE (op0),
+ op1, TREE_CODE (op1),
/*overloaded_p=*/NULL),
- build_unary_op (code, TREE_OPERAND (t, 0), 0),
- build_unary_op (code, TREE_OPERAND (t, 1), 0));
+ build_unary_op (code, op0, 0),
+ build_unary_op (code, op1, 0));
}
return
tree member_scope;
tree result = NULL_TREE;
- if (object == error_mark_node || member == error_mark_node)
+ if (error_operand_p (object) || error_operand_p (member))
return error_mark_node;
gcc_assert (DECL_P (member) || BASELINK_P (member));
warn_deprecated_use (member);
}
else
- member_scope = BINFO_TYPE (BASELINK_BINFO (member));
+ member_scope = BINFO_TYPE (BASELINK_ACCESS_BINFO (member));
/* If MEMBER is from an anonymous aggregate, MEMBER_SCOPE will
presently be the anonymous union. Go outwards until we find a
type related to OBJECT_TYPE. */
/* 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)
template, the program is ill-formed.
DR 228 removed the restriction that the template be a member
- template.
-
+ template.
+
DR 96, if accepted would add the further restriction that explicit
template arguments must be provided if the template keyword is
used, but, as of 2005-10-16, that DR is still in "drafting". If
orig_object, orig_name,
NULL_TREE);
}
-
+
return expr;
}
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;
}
+ warn_array_subscript_with_type_char (idx);
+
return build_indirect_ref (cp_build_binary_op (PLUS_EXPR, ar, ind),
"array indexing");
}
/* Start by extracting all the information from the PMF itself. */
e3 = pfn_from_ptrmemfunc (function);
- delta = build_ptrmemfunc_access_expr (function, delta_identifier);
+ delta = delta_from_ptrmemfunc (function);
idx = build1 (NOP_EXPR, vtable_index_type, e3);
switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
{
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;
e2 = build1 (NOP_EXPR, TREE_TYPE (e2),
build_unary_op (ADDR_EXPR, e2, /*noconvert=*/1));
- TREE_TYPE (e2) = TREE_TYPE (e3);
+ e2 = fold_convert (TREE_TYPE (e3), e2);
e1 = build_conditional_expr (e1, e2, e3);
/* Make sure this doesn't get evaluated first inside one of the
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 type = typetail ? TREE_VALUE (typetail) : 0;
tree val = TREE_VALUE (valtail);
- if (val == error_mark_node)
- return error_mark_node;
+ if (val == error_mark_node || type == 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_list;
+ return -1;
}
}
- return nreverse (result);
+ gcc_assert (i <= nargs);
+ return i;
}
\f
/* Build a binary-operation expression, after performing default
- conversions on the operands. CODE is the kind of expression to build. */
+ conversions on the operands. CODE is the kind of expression to
+ build. ARG1 and ARG2 are the arguments. ARG1_CODE and ARG2_CODE
+ are the tree codes which correspond to ARG1 and ARG2 when issuing
+ warnings about possibly misplaced parentheses. They may differ
+ from the TREE_CODE of ARG1 and ARG2 if the parser has done constant
+ folding (e.g., if the parser sees "a | 1 + 1", it may call this
+ routine with ARG2 being an INTEGER_CST and ARG2_CODE == PLUS_EXPR).
+ To avoid issuing any parentheses warnings, pass ARG1_CODE and/or
+ ARG2_CODE as ERROR_MARK. */
tree
-build_x_binary_op (enum tree_code code, tree arg1, tree arg2,
- bool *overloaded_p)
+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 orig_arg1;
tree orig_arg2;
expr = build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE,
overloaded_p);
+ /* 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
+ common idiom for I/O. */
+ if (warn_parentheses
+ && !processing_template_decl
+ && !error_operand_p (arg1)
+ && !error_operand_p (arg2)
+ && (code != LSHIFT_EXPR
+ || !CLASS_TYPE_P (TREE_TYPE (arg1))))
+ warn_about_parentheses (code, arg1_code, arg2_code);
+
if (processing_template_decl && expr != error_mark_node)
return build_min_non_dep (code, expr, orig_arg1, orig_arg2);
Also implies COMMON. */
int short_compare = 0;
- /* Nonzero if this is a right-shift operation, which can be computed on the
- original short and then promoted if the operand is a promoted short. */
- int short_shift = 0;
-
/* Nonzero means set RESULT_TYPE to the common type of the args. */
int common = 0;
switch (code)
{
- case PLUS_EXPR:
- /* Handle the pointer + int case. */
- if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
- return cp_pointer_int_sum (PLUS_EXPR, op0, op1);
- else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE)
- return cp_pointer_int_sum (PLUS_EXPR, op1, op0);
- else
- common = 1;
- break;
-
case MINUS_EXPR:
/* Subtraction of two similar pointers.
We must subtract them as integers, then divide by object size. */
&& same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type0),
TREE_TYPE (type1)))
return pointer_diff (op0, op1, common_type (type0, type1));
- /* Handle pointer minus int. Just like pointer plus int. */
- else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
- return cp_pointer_int_sum (MINUS_EXPR, op0, op1);
- else
- common = 1;
+ /* In all other cases except pointer - int, the usual arithmetic
+ rules aply. */
+ else if (!(code0 == POINTER_TYPE && code1 == INTEGER_TYPE))
+ {
+ common = 1;
+ break;
+ }
+ /* The pointer - int case is just like pointer + int; fall
+ through. */
+ case PLUS_EXPR:
+ if ((code0 == POINTER_TYPE || code1 == POINTER_TYPE)
+ && (code0 == INTEGER_TYPE || code1 == INTEGER_TYPE))
+ {
+ tree ptr_operand;
+ tree int_operand;
+ ptr_operand = ((code0 == POINTER_TYPE) ? op0 : op1);
+ int_operand = ((code0 == INTEGER_TYPE) ? op0 : op1);
+ if (processing_template_decl)
+ {
+ result_type = TREE_TYPE (ptr_operand);
+ break;
+ }
+ return cp_pointer_int_sum (code,
+ ptr_operand,
+ int_operand);
+ }
+ common = 1;
break;
case MULT_EXPR:
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
|| code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE))
{
- 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);
+ enum tree_code tcode0 = code0, tcode1 = code1;
+
+ warn_for_div_by_zero (op1);
- if (code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
- code0 = TREE_CODE (TREE_TYPE (TREE_TYPE (op0)));
- if (code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)
- code1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1)));
+ if (tcode0 == COMPLEX_TYPE || tcode0 == VECTOR_TYPE)
+ tcode0 = TREE_CODE (TREE_TYPE (TREE_TYPE (op0)));
+ if (tcode1 == COMPLEX_TYPE || tcode1 == VECTOR_TYPE)
+ tcode1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1)));
- if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))
+ if (!(tcode0 == INTEGER_TYPE && tcode1 == INTEGER_TYPE))
resultcode = RDIV_EXPR;
else
/* When dividing two signed integers, we have to promote to int.
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)
{
warning (0, "right shift count is negative");
else
{
- if (! integer_zerop (op1))
- short_shift = 1;
if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
warning (0, "right shift count >= width of type");
}
if (TREE_CODE (op1) == INTEGER_CST)
{
if (tree_int_cst_lt (op1, integer_zero_node))
- warning (0, "%s rotate count is negative",
- (code == LROTATE_EXPR) ? "left" : "right");
+ warning (0, (code == LROTATE_EXPR)
+ ? G_("left rotate count is negative")
+ : G_("right rotate count is negative"));
else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
- warning (0, "%s rotate count >= width of type",
- (code == LROTATE_EXPR) ? "left" : "right");
+ warning (0, (code == LROTATE_EXPR)
+ ? G_("left rotate count >= width of type")
+ : G_("right rotate count >= width of type"));
}
/* Convert the shift-count to an integer, regardless of
size of value being shifted. */
case EQ_EXPR:
case NE_EXPR:
if (code0 == REAL_TYPE || code1 == REAL_TYPE)
- warning (OPT_Wfloat_equal,
- "comparing floating point with == or != is unsafe");
+ warning (OPT_Wfloat_equal,
+ "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
"comparison");
else if ((code0 == POINTER_TYPE || TYPE_PTRMEM_P (type0))
&& null_ptr_cst_p (op1))
- result_type = type0;
+ {
+ if (TREE_CODE (op0) == ADDR_EXPR
+ && decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0)))
+ warning (OPT_Waddress, "the address of %qD will never be NULL",
+ TREE_OPERAND (op0, 0));
+ result_type = type0;
+ }
else if ((code1 == POINTER_TYPE || TYPE_PTRMEM_P (type1))
&& null_ptr_cst_p (op0))
- result_type = type1;
+ {
+ if (TREE_CODE (op1) == ADDR_EXPR
+ && decl_with_nonnull_addr_p (TREE_OPERAND (op1, 0)))
+ warning (OPT_Waddress, "the address of %qD will never be NULL",
+ TREE_OPERAND (op1, 0));
+ result_type = type1;
+ }
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
- error ("ISO C++ forbids comparison between pointer and integer");
+ pedwarn ("ISO C++ forbids comparison between pointer and integer");
}
else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
{
result_type = type1;
- error ("ISO C++ forbids comparison between pointer and integer");
+ pedwarn ("ISO C++ forbids comparison between pointer and integer");
}
else if (TYPE_PTRMEMFUNC_P (type0) && null_ptr_cst_p (op1))
{
- op0 = build_ptrmemfunc_access_expr (op0, pfn_identifier);
- op1 = cp_convert (TREE_TYPE (op0), integer_zero_node);
+ if (TARGET_PTRMEMFUNC_VBIT_LOCATION
+ == ptrmemfunc_vbit_in_delta)
+ {
+ tree pfn0 = pfn_from_ptrmemfunc (op0);
+ tree delta0 = delta_from_ptrmemfunc (op0);
+ tree e1 = cp_build_binary_op (EQ_EXPR,
+ pfn0,
+ fold_convert (TREE_TYPE (pfn0),
+ integer_zero_node));
+ tree e2 = cp_build_binary_op (BIT_AND_EXPR,
+ delta0,
+ integer_one_node);
+ e2 = cp_build_binary_op (EQ_EXPR, e2, integer_zero_node);
+ op0 = cp_build_binary_op (TRUTH_ANDIF_EXPR, e1, e2);
+ op1 = cp_convert (TREE_TYPE (op0), integer_one_node);
+ }
+ else
+ {
+ op0 = build_ptrmemfunc_access_expr (op0, pfn_identifier);
+ op1 = cp_convert (TREE_TYPE (op0), integer_zero_node);
+ }
result_type = TREE_TYPE (op0);
}
else if (TYPE_PTRMEMFUNC_P (type1) && null_ptr_cst_p (op0))
return cp_build_binary_op (code, op1, op0);
- else if (TYPE_PTRMEMFUNC_P (type0) && TYPE_PTRMEMFUNC_P (type1)
- && same_type_p (type0, type1))
+ else if (TYPE_PTRMEMFUNC_P (type0) && TYPE_PTRMEMFUNC_P (type1))
{
+ tree type;
/* E will be the final comparison. */
tree e;
/* E1 and E2 are for scratch. */
tree delta0;
tree delta1;
+ type = composite_pointer_type (type0, type1, op0, op1, "comparison");
+
+ if (!same_type_p (TREE_TYPE (op0), type))
+ op0 = cp_convert_and_check (type, op0);
+ if (!same_type_p (TREE_TYPE (op1), type))
+ op1 = cp_convert_and_check (type, op1);
+
+ if (op0 == error_mark_node || op1 == error_mark_node)
+ return error_mark_node;
+
if (TREE_SIDE_EFFECTS (op0))
op0 = save_expr (op0);
if (TREE_SIDE_EFFECTS (op1))
op1 = save_expr (op1);
- /* We generate:
-
- (op0.pfn == op1.pfn
- && (!op0.pfn || op0.delta == op1.delta))
-
- The reason for the `!op0.pfn' bit is that a NULL
- pointer-to-member is any member with a zero PFN; the
- DELTA field is unspecified. */
pfn0 = pfn_from_ptrmemfunc (op0);
pfn1 = pfn_from_ptrmemfunc (op1);
- delta0 = build_ptrmemfunc_access_expr (op0,
- delta_identifier);
- delta1 = build_ptrmemfunc_access_expr (op1,
- delta_identifier);
- e1 = cp_build_binary_op (EQ_EXPR, delta0, delta1);
- e2 = cp_build_binary_op (EQ_EXPR,
- pfn0,
- cp_convert (TREE_TYPE (pfn0),
- integer_zero_node));
- e1 = cp_build_binary_op (TRUTH_ORIF_EXPR, e1, e2);
+ delta0 = delta_from_ptrmemfunc (op0);
+ delta1 = delta_from_ptrmemfunc (op1);
+ if (TARGET_PTRMEMFUNC_VBIT_LOCATION
+ == ptrmemfunc_vbit_in_delta)
+ {
+ /* We generate:
+
+ (op0.pfn == op1.pfn
+ && ((op0.delta == op1.delta)
+ || (!op0.pfn && op0.delta & 1 == 0
+ && op1.delta & 1 == 0))
+
+ The reason for the `!op0.pfn' bit is that a NULL
+ pointer-to-member is any member with a zero PFN and
+ LSB of the DELTA field is 0. */
+
+ e1 = cp_build_binary_op (BIT_AND_EXPR,
+ delta0,
+ integer_one_node);
+ e1 = cp_build_binary_op (EQ_EXPR, e1, integer_zero_node);
+ e2 = cp_build_binary_op (BIT_AND_EXPR,
+ delta1,
+ integer_one_node);
+ e2 = cp_build_binary_op (EQ_EXPR, e2, integer_zero_node);
+ e1 = cp_build_binary_op (TRUTH_ANDIF_EXPR, e2, e1);
+ e2 = cp_build_binary_op (EQ_EXPR,
+ pfn0,
+ fold_convert (TREE_TYPE (pfn0),
+ integer_zero_node));
+ e2 = cp_build_binary_op (TRUTH_ANDIF_EXPR, e2, e1);
+ e1 = cp_build_binary_op (EQ_EXPR, delta0, delta1);
+ e1 = cp_build_binary_op (TRUTH_ORIF_EXPR, e1, e2);
+ }
+ else
+ {
+ /* We generate:
+
+ (op0.pfn == op1.pfn
+ && (!op0.pfn || op0.delta == op1.delta))
+
+ The reason for the `!op0.pfn' bit is that a NULL
+ pointer-to-member is any member with a zero PFN; the
+ DELTA field is unspecified. */
+
+ e1 = cp_build_binary_op (EQ_EXPR, delta0, delta1);
+ e2 = cp_build_binary_op (EQ_EXPR,
+ pfn0,
+ fold_convert (TREE_TYPE (pfn0),
+ integer_zero_node));
+ e1 = cp_build_binary_op (TRUTH_ORIF_EXPR, e1, e2);
+ }
e2 = build2 (EQ_EXPR, boolean_type_node, pfn0, pfn1);
e = cp_build_binary_op (TRUTH_ANDIF_EXPR, e2, e1);
if (code == EQ_EXPR)
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)
{
result_type = type;
}
- /* Shifts can be shortened if shifting right. */
-
- if (short_shift)
- {
- int unsigned_arg;
- tree arg0 = get_narrower (op0, &unsigned_arg);
-
- final_type = result_type;
-
- if (arg0 == op0 && final_type == TREE_TYPE (op0))
- unsigned_arg = TYPE_UNSIGNED (TREE_TYPE (op0));
-
- if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type)
- /* We can shorten only if the shift count is less than the
- number of bits in the smaller type size. */
- && compare_tree_int (op1, TYPE_PRECISION (TREE_TYPE (arg0))) < 0
- /* If arg is sign-extended and then unsigned-shifted,
- we can simulate this with a signed shift in arg's type
- only if the extended result is at least twice as wide
- as the arg. Otherwise, the shift could use up all the
- ones made by sign-extension and bring in zeros.
- We can't optimize that case at all, but in most machines
- it never happens because available widths are 2**N. */
- && (!TYPE_UNSIGNED (final_type)
- || unsigned_arg
- || (((unsigned) 2 * TYPE_PRECISION (TREE_TYPE (arg0)))
- <= TYPE_PRECISION (result_type))))
- {
- /* Do an unsigned shift if the operand was zero-extended. */
- result_type
- = c_common_signed_or_unsigned_type (unsigned_arg,
- TREE_TYPE (arg0));
- /* Convert value-to-be-shifted to that type. */
- if (TREE_TYPE (op0) != result_type)
- op0 = cp_convert (result_type, op0);
- converted = 1;
- }
- }
-
/* Comparison operations are shortened too but differently.
They identify themselves by setting short_compare = 1. */
&& TYPE_MAIN_VARIANT (TREE_TYPE (orig_op0))
!= TYPE_MAIN_VARIANT (TREE_TYPE (orig_op1)))
{
- warning (0, "comparison between types %q#T and %q#T",
+ warning (OPT_Wsign_compare, "comparison between types %q#T and %q#T",
TREE_TYPE (orig_op0), TREE_TYPE (orig_op1));
}
(result_type)))))
/* OK */;
else
- warning (0, "comparison between signed and unsigned integer expressions");
+ warning (OPT_Wsign_compare,
+ "comparison between signed and unsigned integer expressions");
/* Warn if two unsigned values are being compared in a size
larger than their original size, and one (and only one) is the
{
mask = (~ (HOST_WIDE_INT) 0) << bits;
if ((mask & constant) != mask)
- warning (0, "comparison of promoted ~unsigned with constant");
+ warning (OPT_Wsign_compare, "comparison of promoted ~unsigned with constant");
}
}
else if (unsignedp0 && unsignedp1
< TYPE_PRECISION (result_type))
&& (TYPE_PRECISION (TREE_TYPE (primop1))
< TYPE_PRECISION (result_type)))
- warning (0, "comparison of promoted ~unsigned with unsigned");
+ warning (OPT_Wsign_compare, "comparison of promoted ~unsigned with unsigned");
}
}
}
- /* 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;
result = fold_if_not_in_template (result);
if (final_type != 0)
result = cp_convert (final_type, result);
+
+ if (TREE_OVERFLOW_P (result)
+ && !TREE_OVERFLOW_P (op0)
+ && !TREE_OVERFLOW_P (op1))
+ overflow_warning (result);
+
return result;
}
\f
if (!noconvert)
arg = default_conversion (arg);
}
- else if (!(arg = build_expr_type_conversion (WANT_INT | WANT_ENUM,
+ else if (!(arg = build_expr_type_conversion (WANT_INT | WANT_ENUM
+ | WANT_VECTOR,
arg, true)))
errstring = "wrong type argument to bit-complement";
- else if (!noconvert)
+ else if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg)))
arg = perform_integral_promotions (arg);
break;
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. */
errstring ="no post-decrement operator for type";
break;
}
+ else if (arg == error_mark_node)
+ return error_mark_node;
/* Report something read-only. */
|| 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);
/* ARM $5.2.5 last annotation says this should be forbidden. */
if (TREE_CODE (argtype) == ENUMERAL_TYPE)
- pedwarn ("ISO C++ forbids %sing an enum",
- (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
- ? "increment" : "decrement");
+ pedwarn ((code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
+ ? G_("ISO C++ forbids incrementing an enum")
+ : G_("ISO C++ forbids decrementing an enum"));
/* Compute the increment. */
tree type = complete_type (TREE_TYPE (argtype));
if (!COMPLETE_OR_VOID_TYPE_P (type))
- error ("cannot %s a pointer to incomplete type %qT",
- ((code == PREINCREMENT_EXPR
- || code == POSTINCREMENT_EXPR)
- ? "increment" : "decrement"), TREE_TYPE (argtype));
+ error (((code == PREINCREMENT_EXPR
+ || code == POSTINCREMENT_EXPR))
+ ? G_("cannot increment a pointer to incomplete type %qT")
+ : G_("cannot decrement a pointer to incomplete type %qT"),
+ TREE_TYPE (argtype));
else if ((pedantic || warn_pointer_arith)
&& !TYPE_PTROB_P (argtype))
- pedwarn ("ISO C++ forbids %sing a pointer of type %qT",
- ((code == PREINCREMENT_EXPR
+ pedwarn ((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
- ? "increment" : "decrement"), argtype);
+ ? G_("ISO C++ forbids incrementing a pointer of type %qT")
+ : G_("ISO C++ forbids decrementing a pointer of type %qT"),
+ argtype);
inc = cxx_sizeof_nowarn (TREE_TYPE (argtype));
}
else
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:
- case FIX_FLOOR_EXPR:
- case FIX_ROUND_EXPR:
- case FIX_CEIL_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 (TREE_TYPE (arg) == boolean_type_node)
+ if (same_type_p (declared_type, boolean_type_node))
{
if (code == POSTDECREMENT_EXPR || code == PREDECREMENT_EXPR)
{
- error ("invalid use of %<--%> on bool variable %qD", arg);
+ error ("invalid use of Boolean expression as operand "
+ "to %<operator--%>");
return error_mark_node;
}
val = boolean_increment (code, arg);
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)
{
case CONVERT_EXPR:
case FLOAT_EXPR:
case FIX_TRUNC_EXPR:
- case FIX_FLOOR_EXPR:
- case FIX_ROUND_EXPR:
- case FIX_CEIL_EXPR:
if (! lvalue_p (arg) && pedantic)
pedwarn ("ISO C++ forbids taking the address of a cast to a non-lvalue expression");
break;
+ case BASELINK:
+ arg = BASELINK_FUNCTIONS (arg);
+ /* Fall through. */
+
case OVERLOAD:
arg = OVL_CURRENT (arg);
break;
if (TREE_CODE (argtype) != FUNCTION_TYPE
&& TREE_CODE (argtype) != METHOD_TYPE
&& TREE_CODE (arg) != OFFSET_REF
- /* Permit users to take the address of a compound-literal
- with sufficient simple elements. */
- && !(COMPOUND_LITERAL_P (arg) && TREE_STATIC (arg))
&& !lvalue_or_else (arg, lv_addressof))
return error_mark_node;
return val;
}
- /* If the user has taken the address of the compound literal,
- create a variable to contain the value of the literal and
- then return the address of that variable. */
- if (COMPOUND_LITERAL_P (arg))
- {
- tree var;
- gcc_assert (TREE_STATIC (arg));
- var = create_temporary_var (TREE_TYPE (arg));
- TREE_STATIC (var) = 1;
- set_compound_literal_name (var);
- initialize_artificial_var (var, arg);
- arg = pushdecl (var);
- /* Since each compound literal is unique, pushdecl should
- never find a pre-existing variable with the same
- name. */
- gcc_assert (arg == var);
- }
-
if (TREE_CODE (arg) != COMPONENT_REF)
{
val = build_address (arg);
("address of explicit register variable %qD requested", x);
return false;
}
- else
+ else if (extra_warnings)
warning
(OPT_Wextra, "address requested for %qD, which is declared %<register%>", x);
}
allow_inverse_p,
c_cast_p);
if (!integer_zerop (delta))
- expr = cp_build_binary_op (PLUS_EXPR,
- build_nop (ptrdiff_type_node, expr),
- delta);
+ {
+ tree cond, op1, op2;
+
+ cond = cp_build_binary_op (EQ_EXPR,
+ expr,
+ build_int_cst (TREE_TYPE (expr), -1));
+ op1 = build_nop (ptrdiff_type_node, expr);
+ op2 = cp_build_binary_op (PLUS_EXPR, op1, delta);
+
+ expr = fold_build3 (COND_EXPR, ptrdiff_type_node, cond, op1, op2);
+
+ }
+
return build_nop (type, expr);
}
else
}
/* 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;
intype = TREE_TYPE (expr);
+ /* Save casted types in the function's used types hash table. */
+ used_types_insert (type);
+
/* Determine what to do when casting away constness. */
if (c_cast_p)
{
t1 = intype;
t2 = type;
}
- if (can_convert (t1, t2))
+ if (can_convert (t1, t2) || can_convert (t2, t1))
{
if (!c_cast_p)
check_for_casting_away_constness (intype, type, diag_fn,
intype = TREE_TYPE (expr);
+ /* Save casted types in the function's used types hash table. */
+ used_types_insert (type);
+
/* [expr.reinterpret.cast]
An lvalue expression of type T1 can be cast to the type
"reference to T2" if an expression of type "pointer to T1" can be
"B" are related class types; the reinterpret_cast does not
adjust the pointer. */
if (TYPE_PTR_P (intype)
- && (comptypes (TREE_TYPE (intype), TREE_TYPE (type),
- COMPARE_BASE | COMPARE_DERIVED)))
+ && (cp_comptypes (TREE_TYPE (intype), TREE_TYPE (type),
+ COMPARE_BASE | COMPARE_DERIVED)))
warning (0, "casting %qT to %qT does not dereference pointer",
intype, type);
"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
{
return error_mark_node;
}
+ /* Save casted types in the function's used types hash table. */
+ used_types_insert (dst_type);
+
src_type = TREE_TYPE (expr);
/* Expressions do not really have reference types. */
if (TREE_CODE (src_type) == REFERENCE_TYPE)
bool plain_assign = (modifycode == NOP_EXPR);
/* Avoid duplicate error messages from operands that had errors. */
- if (lhs == error_mark_node || rhs == error_mark_node)
+ if (error_operand_p (lhs) || error_operand_p (rhs))
return error_mark_node;
/* Handle control structure constructs used as "lvalues". */
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
cond = build_conditional_expr
(TREE_OPERAND (lhs, 0),
- build_modify_expr (cp_convert (TREE_TYPE (lhs),
- TREE_OPERAND (lhs, 1)),
+ build_modify_expr (TREE_OPERAND (lhs, 1),
modifycode, rhs),
- build_modify_expr (cp_convert (TREE_TYPE (lhs),
- TREE_OPERAND (lhs, 2)),
+ build_modify_expr (TREE_OPERAND (lhs, 2),
modifycode, rhs));
if (cond == error_mark_node)
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
/* Allow array assignment in compiler-generated code. */
if (! DECL_ARTIFICIAL (current_function_decl))
- pedwarn ("ISO C++ forbids assignment of arrays");
+ {
+ /* This routine is used for both initialization and assignment.
+ Make sure the diagnostic message differentiates the context. */
+ if (modifycode == INIT_EXPR)
+ error ("array used as initializer");
+ else
+ error ("invalid array assignment");
+ return error_mark_node;
+ }
from_array = TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
? 1 + (modifycode != INIT_EXPR): 0;
- return build_vec_init (lhs, NULL_TREE, newrhs,
+ return build_vec_init (lhs, NULL_TREE, newrhs,
/*explicit_default_init_p=*/false,
from_array);
}
return build_modify_expr (lhs, modifycode, rhs);
}
-\f
+/* Helper function for get_delta_difference which assumes FROM is a base
+ class of TO. Returns a delta for the conversion of pointer-to-member
+ of FROM to pointer-to-member of TO. If the conversion is invalid,
+ returns zero. If FROM is not a base class of TO, returns NULL_TREE.
+ If C_CAST_P is true, this conversion is taking place as part of a C-style
+ cast. */
+
+static tree
+get_delta_difference_1 (tree from, tree to, bool c_cast_p)
+{
+ tree binfo;
+ base_kind kind;
+
+ binfo = lookup_base (to, from, c_cast_p ? ba_unique : ba_check, &kind);
+ if (kind == bk_inaccessible || kind == bk_ambig)
+ {
+ error (" in pointer to member function conversion");
+ return size_zero_node;
+ }
+ else if (binfo)
+ {
+ if (kind != bk_via_virtual)
+ return BINFO_OFFSET (binfo);
+ else
+ /* FROM is a virtual base class of TO. Issue an error or warning
+ depending on whether or not this is a reinterpret cast. */
+ {
+ error ("pointer to member conversion via virtual base %qT",
+ BINFO_TYPE (binfo_from_vbase (binfo)));
+
+ return size_zero_node;
+ }
+ }
+ else
+ return NULL_TREE;
+}
+
/* Get difference in deltas for different pointer to member function
types. Returns an integer constant of type PTRDIFF_TYPE_NODE. If
the conversion is invalid, the constant is zero. If
bool allow_inverse_p,
bool c_cast_p)
{
- tree binfo;
- base_kind kind;
tree result;
- /* Assume no conversion is required. */
- result = integer_zero_node;
- binfo = lookup_base (to, from, c_cast_p ? ba_unique : ba_check, &kind);
- if (kind == bk_inaccessible || kind == bk_ambig)
- error (" in pointer to member function conversion");
- else if (binfo)
- {
- if (kind != bk_via_virtual)
- result = BINFO_OFFSET (binfo);
- else
- {
- tree virt_binfo = binfo_from_vbase (binfo);
-
- /* This is a reinterpret cast, we choose to do nothing. */
- if (allow_inverse_p)
- warning (0, "pointer to member cast via virtual base %qT",
- BINFO_TYPE (virt_binfo));
- else
- error ("pointer to member conversion via virtual base %qT",
- BINFO_TYPE (virt_binfo));
- }
- }
- else if (same_type_ignoring_top_level_qualifiers_p (from, to))
- /* Pointer to member of incomplete class is permitted*/;
- else if (!allow_inverse_p)
- {
- error_not_base_type (from, to);
- error (" in pointer to member conversion");
- }
+ if (same_type_ignoring_top_level_qualifiers_p (from, to))
+ /* Pointer to member of incomplete class is permitted*/
+ result = size_zero_node;
else
- {
- binfo = lookup_base (from, to, c_cast_p ? ba_unique : ba_check, &kind);
- if (binfo)
- {
- if (kind != bk_via_virtual)
- result = size_diffop (size_zero_node, BINFO_OFFSET (binfo));
- else
- {
- /* This is a reinterpret cast, we choose to do nothing. */
- tree virt_binfo = binfo_from_vbase (binfo);
+ result = get_delta_difference_1 (from, to, c_cast_p);
- warning (0, "pointer to member cast via virtual base %qT",
- BINFO_TYPE (virt_binfo));
- }
- }
- }
+ if (!result)
+ {
+ if (!allow_inverse_p)
+ {
+ error_not_base_type (from, to);
+ error (" in pointer to member conversion");
+ result = size_zero_node;
+ }
+ else
+ {
+ result = get_delta_difference_1 (to, from, c_cast_p);
+
+ if (result)
+ result = size_diffop (size_zero_node, result);
+ else
+ {
+ error_not_base_type (from, to);
+ error (" in pointer to member conversion");
+ result = size_zero_node;
+ }
+ }
+ }
return fold_if_not_in_template (convert_to_integer (ptrdiff_type_node,
result));
/* Make sure DELTA has the type we want. */
delta = convert_and_check (delta_type_node, delta);
+ /* Convert to the correct target type if necessary. */
+ pfn = fold_convert (TREE_TYPE (pfn_field), pfn);
+
/* Finish creating the initializer. */
v = VEC_alloc(constructor_elt, gc, 2);
CONSTRUCTOR_APPEND_ELT(v, pfn_field, pfn);
return build_ptrmemfunc_access_expr (t, pfn_identifier);
}
+/* Return an expression for DELTA from the pointer-to-member function
+ given by T. */
+
+static tree
+delta_from_ptrmemfunc (tree t)
+{
+ if (TREE_CODE (t) == PTRMEM_CST)
+ {
+ tree delta;
+ tree pfn;
+
+ expand_ptrmemfunc_cst (t, &delta, &pfn);
+ if (delta)
+ return delta;
+ }
+
+ return build_ptrmemfunc_access_expr (t, delta_identifier);
+}
+
/* Convert value RHS to type TYPE as preparation for an assignment to
an lvalue of type TYPE. ERRTYPE is a string to use in error
messages: "assignment", "return", etc. If FNDECL is non-NULL, we
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)
"%s might be a candidate for a format attribute",
errtype);
}
-
+
+ /* 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_TYPE (rhs) != boolean_type_node)
+ {
+ warning (OPT_Wparentheses,
+ "suggest parentheses around assignment used as truth value");
+ TREE_NO_WARNING (rhs) = 1;
+ }
+
return perform_implicit_conversion (strip_top_quals (type), rhs);
}
&& codel != REFERENCE_TYPE)
rhs = TREE_OPERAND (rhs, 0);
- if (rhs == error_mark_node
+ if (type == error_mark_node
+ || rhs == error_mark_node
|| (TREE_CODE (rhs) == TREE_LIST && TREE_VALUE (rhs) == error_mark_node))
return error_mark_node;
}
}
+ while (TREE_CODE (whats_returned) == COMPONENT_REF
+ || TREE_CODE (whats_returned) == ARRAY_REF)
+ whats_returned = TREE_OPERAND (whats_returned, 0);
+
if (DECL_P (whats_returned)
&& DECL_NAME (whats_returned)
&& DECL_FUNCTION_SCOPE_P (whats_returned)
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;
+ if (check_for_bare_parameter_packs (retval))
+ retval = error_mark_node;
return retval;
}
return!). */
current_function_returns_null = 0;
/* And signal caller that TREE_NO_WARNING should be set on the
- RETURN_EXPR to avoid control reaches end of non-void function
- warnings in tree-cfg.c. */
+ RETURN_EXPR to avoid control reaches end of non-void function
+ warnings in tree-cfg.c. */
*no_warning = true;
}
/* Check for a return statement with a value in a function that
|| 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)))))
+ /* And the returned value must be non-volatile. */
+ && ! TYPE_VOLATILE (TREE_TYPE (retval)));
+
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;'. */
type or inheritance-related types, regardless of cv-quals. */
int
-ptr_reasonably_similar (tree to, tree from)
+ptr_reasonably_similar (const_tree to, const_tree from)
{
for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from))
{
return 0;
if (TREE_CODE (from) == OFFSET_TYPE
- && comptypes (TYPE_OFFSET_BASETYPE (to),
- TYPE_OFFSET_BASETYPE (from),
- COMPARE_BASE | COMPARE_DERIVED))
+ && cp_comptypes (TYPE_OFFSET_BASETYPE (to),
+ TYPE_OFFSET_BASETYPE (from),
+ COMPARE_BASE | COMPARE_DERIVED))
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 1;
if (TREE_CODE (to) != POINTER_TYPE)
- return comptypes
+ return cp_comptypes
(TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from),
COMPARE_BASE | COMPARE_DERIVED);
}
elements for an array type. */
int
-cp_type_quals (tree type)
+cp_type_quals (const_tree type)
{
- type = strip_array_types (type);
+ /* This CONST_CAST is okay because strip_array_types returns it's
+ argument unmodified and we assign it to a const_tree. */
+ type = strip_array_types (CONST_CAST_TREE(type));
if (type == error_mark_node)
return TYPE_UNQUALIFIED;
return TYPE_QUALS (type);
}
+/* Returns nonzero if the TYPE is const from a C++ perspective: look inside
+ arrays. */
+
+bool
+cp_type_readonly (const_tree type)
+{
+ /* This CONST_CAST is okay because strip_array_types returns it's
+ argument unmodified and we assign it to a const_tree. */
+ type = strip_array_types (CONST_CAST_TREE(type));
+ return TYPE_READONLY (type);
+}
+
/* Returns nonzero if the TYPE contains a mutable member. */
bool
-cp_has_mutable_p (tree type)
+cp_has_mutable_p (const_tree type)
{
- type = strip_array_types (type);
+ /* This CONST_CAST is okay because strip_array_types returns it's
+ argument unmodified and we assign it to a const_tree. */
+ type = strip_array_types (CONST_CAST_TREE(type));
return CLASS_TYPE_P (type) && CLASSTYPE_HAS_MUTABLE (type);
}
-/* Apply the TYPE_QUALS to the new DECL. */
+/* Set TREE_READONLY and TREE_VOLATILE on DECL as indicated by the
+ TYPE_QUALS. For a VAR_DECL, this may be an optimistic
+ approximation. In particular, consider:
+
+ int f();
+ struct S { int i; };
+ const S s = { f(); }
+
+ Here, we will make "s" as TREE_READONLY (because it is declared
+ "const") -- only to reverse ourselves upon seeing that the
+ initializer is non-constant. */
+
void
cp_apply_type_quals_to_decl (int type_quals, tree decl)
{
how the lvalue is being used and so selects the error message. */
int
-lvalue_or_else (tree ref, enum lvalue_use use)
+lvalue_or_else (const_tree ref, enum lvalue_use use)
{
int win = lvalue_p (ref);