X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcp%2Ftypeck.c;h=a79f6e2dd46add26747ca47b18e042524cd313ae;hb=5b339181bd79211632e0da0c37f37c8ade7906a8;hp=b3c155a13c0e23b82be6f1fb331f528128c7d6bf;hpb=2840aae48b06eb49ec47d256709b91cf44948f4e;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index b3c155a13c0..a79f6e2dd46 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1,13 +1,14 @@ /* 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, @@ -16,9 +17,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 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 +. */ /* This file is part of the C++ front end. @@ -39,24 +39,26 @@ Boston, MA 02110-1301, USA. */ #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 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 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.) @@ -224,10 +226,12 @@ commonparms (tree p1, tree p2) /* Given a type, perhaps copied for a typedef, find the "original" version of it. */ -tree +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) @@ -237,7 +241,7 @@ original_type (tree t) break; t = x; } - return t; + return cp_build_qualified_type (t, quals); } /* T1 and T2 are arithmetic or enumeration types. Return the type @@ -253,12 +257,10 @@ type_after_usual_arithmetic_conversions (tree t1, tree t2) /* 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 @@ -320,12 +322,6 @@ type_after_usual_arithmetic_conversions (tree t1, tree t2) 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) @@ -728,7 +724,13 @@ merge_types (tree t1, tree t2) 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. @@ -752,9 +754,9 @@ common_type (tree t1, tree t2) 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)) @@ -923,11 +925,10 @@ comp_array_types (tree t1, tree t2, bool allow_redeclaration) 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 comptypes. */ -bool -comptypes (tree t1, tree t2, int strict) +static bool +structural_comptypes (tree t1, tree t2, int strict) { if (t1 == t2) return true; @@ -941,30 +942,10 @@ comptypes (tree t1, tree t2, int strict) /* 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); @@ -997,7 +978,9 @@ comptypes (tree t1, tree t2, int strict) 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)), @@ -1032,8 +1015,12 @@ comptypes (tree t1, tree t2, int strict) 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))) @@ -1056,7 +1043,9 @@ comptypes (tree t1, tree t2, int strict) 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; @@ -1086,6 +1075,18 @@ comptypes (tree t1, tree t2, int strict) 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; } @@ -1096,6 +1097,60 @@ comptypes (tree t1, tree t2, int strict) return targetm.comp_type_attributes (t1, t2); } +/* Return true if T1 and T2 are related as allowed by STRICT. STRICT + is a bitwise-or of the COMPARE_* flags. */ + +bool +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 @@ -1142,59 +1197,6 @@ comp_cv_qual_signature (tree type1, tree 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; -} /* Subroutines of `comptypes'. */ @@ -1232,54 +1234,57 @@ compparms (tree parms1, tree parms2) 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 or alignof expression where the operand is an - expression. */ +/* Process a sizeof expression where the operand is an expression. */ -tree -cxx_sizeof_or_alignof_expr (tree e, enum tree_code op) +static tree +cxx_sizeof_expr (tree e) { - const char *op_name = operator_name_info[(int) op].name; - if (e == error_mark_node) return error_mark_node; if (processing_template_decl) { - e = build_min (op, size_type_node, e); + e = build_min (SIZEOF_EXPR, size_type_node, e); TREE_SIDE_EFFECTS (e) = 0; TREE_READONLY (e) = 1; @@ -1290,13 +1295,13 @@ cxx_sizeof_or_alignof_expr (tree e, enum tree_code op) && TREE_CODE (TREE_OPERAND (e, 1)) == FIELD_DECL && DECL_C_BIT_FIELD (TREE_OPERAND (e, 1))) { - error ("invalid application of %qs to a bit-field", op_name); + error ("invalid application of % to a bit-field"); e = char_type_node; } else if (is_overloaded_fn (e)) { - pedwarn ("ISO C++ forbids applying %qs to an expression of " - "function type", op_name); + pedwarn ("ISO C++ forbids applying % to an expression of " + "function type"); e = char_type_node; } else if (type_unknown_p (e)) @@ -1307,9 +1312,74 @@ cxx_sizeof_or_alignof_expr (tree e, enum tree_code op) else e = TREE_TYPE (e); - return cxx_sizeof_or_alignof_type (e, op, true); + return cxx_sizeof_or_alignof_type (e, SIZEOF_EXPR, true); +} + +/* Implement the __alignof keyword: Return the minimum required + alignment of E, measured in bytes. For VAR_DECL's and + FIELD_DECL's return DECL_ALIGN (which can be set from an + "aligned" __attribute__ specification). */ + +static tree +cxx_alignof_expr (tree e) +{ + tree t; + + if (e == error_mark_node) + return error_mark_node; + + if (processing_template_decl) + { + e = build_min (ALIGNOF_EXPR, size_type_node, e); + TREE_SIDE_EFFECTS (e) = 0; + TREE_READONLY (e) = 1; + + return e; + } + + if (TREE_CODE (e) == VAR_DECL) + t = size_int (DECL_ALIGN_UNIT (e)); + else if (TREE_CODE (e) == COMPONENT_REF + && TREE_CODE (TREE_OPERAND (e, 1)) == FIELD_DECL + && DECL_C_BIT_FIELD (TREE_OPERAND (e, 1))) + { + error ("invalid application of %<__alignof%> to a bit-field"); + t = size_one_node; + } + else if (TREE_CODE (e) == COMPONENT_REF + && TREE_CODE (TREE_OPERAND (e, 1)) == FIELD_DECL) + t = size_int (DECL_ALIGN_UNIT (TREE_OPERAND (e, 1))); + else if (is_overloaded_fn (e)) + { + pedwarn ("ISO C++ forbids applying %<__alignof%> to an expression of " + "function type"); + if (TREE_CODE (e) == FUNCTION_DECL) + t = size_int (DECL_ALIGN_UNIT (e)); + else + t = size_one_node; + } + else if (type_unknown_p (e)) + { + cxx_incomplete_type_error (e, TREE_TYPE (e)); + t = size_one_node; + } + else + return cxx_sizeof_or_alignof_type (TREE_TYPE (e), ALIGNOF_EXPR, true); + + return fold_convert (size_type_node, t); } +/* Process a sizeof or alignof expression E with code OP where the operand + is an expression. */ + +tree +cxx_sizeof_or_alignof_expr (tree e, enum tree_code op) +{ + if (op == SIZEOF_EXPR) + return cxx_sizeof_expr (e); + else + return cxx_alignof_expr (e); +} /* EXPR is being used in a context that is not a function call. Enforce: @@ -1338,11 +1408,71 @@ invalid_nonstatic_memfn_p (tree expr) 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 (tree exp) +{ + 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; + } +} + +/* 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 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) @@ -1351,8 +1481,6 @@ 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; @@ -1363,10 +1491,12 @@ decay_conversion (tree exp) } 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"); @@ -1414,21 +1544,51 @@ decay_conversion (tree exp) 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; } @@ -1443,7 +1603,13 @@ perform_integral_promotions (tree expr) 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) @@ -1471,7 +1637,7 @@ string_conv_p (tree totype, tree exp, int warn) { tree t; - if (! flag_const_strings || TREE_CODE (totype) != POINTER_TYPE) + if (TREE_CODE (totype) != POINTER_TYPE) return 0; t = TREE_TYPE (totype); @@ -1498,8 +1664,10 @@ string_conv_p (tree totype, tree exp, int warn) } /* This warning is not very useful, as it complains about printf. */ - if (warn && warn_write_strings) - warning (0, "deprecated conversion from string constant to %qT'", totype); + if (warn) + warning (OPT_Wwrite_strings, + "deprecated conversion from string constant to %qT", + totype); return 1; } @@ -1520,17 +1688,20 @@ rationalize_conditional_expr (enum tree_code code, tree t) 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 @@ -1595,7 +1766,7 @@ build_class_member_access_expr (tree object, tree member, 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)); @@ -1645,7 +1816,7 @@ build_class_member_access_expr (tree object, tree member, /* 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) @@ -1828,7 +1999,7 @@ lookup_destructor (tree object, tree scope, tree dtor_name) tree dtor_type = TREE_OPERAND (dtor_name, 0); tree expr; - if (scope && !check_dtor_name (scope, dtor_name)) + if (scope && !check_dtor_name (scope, dtor_type)) { error ("qualified type %qT does not match destructor name ~%qT", scope, dtor_type); @@ -1862,8 +2033,8 @@ check_template_keyword (tree decl) 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 @@ -1986,16 +2157,11 @@ finish_class_member_access_expr (tree object, tree name, bool template_p) if (TREE_CODE (name) == SCOPE_REF) { - /* A qualified name. The qualifying class or namespace `S' has - already been looked up; it is either a TYPE or a - NAMESPACE_DECL. The member name is either an IDENTIFIER_NODE - or a BIT_NOT_EXPR. */ + /* A qualified name. The qualifying class or namespace `S' + has already been looked up; it is either a TYPE or a + NAMESPACE_DECL. */ scope = TREE_OPERAND (name, 0); name = TREE_OPERAND (name, 1); - gcc_assert (CLASS_TYPE_P (scope) - || TREE_CODE (scope) == NAMESPACE_DECL); - gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE - || TREE_CODE (name) == BIT_NOT_EXPR); /* If SCOPE is a namespace, then the qualified name does not name a member of OBJECT_TYPE. */ @@ -2006,6 +2172,10 @@ finish_class_member_access_expr (tree object, tree name, bool template_p) return error_mark_node; } + gcc_assert (CLASS_TYPE_P (scope)); + gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE + || TREE_CODE (name) == BIT_NOT_EXPR); + /* Find the base of OBJECT_TYPE corresponding to SCOPE. */ access_path = lookup_base (object_type, scope, ba_check, NULL); if (access_path == error_mark_node) @@ -2072,7 +2242,7 @@ finish_class_member_access_expr (tree object, tree name, bool template_p) orig_object, orig_name, NULL_TREE); } - + return expr; } @@ -2162,6 +2332,19 @@ build_indirect_ref (tree ptr, const char *errorstring) 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 @@ -2305,7 +2488,7 @@ build_array_ref (tree array, tree idx) while (TREE_CODE (foo) == COMPONENT_REF) foo = TREE_OPERAND (foo, 0); if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo)) - warning (0, "subscripting array declared %"); + warning (OPT_Wextra, "subscripting array declared %"); } type = TREE_TYPE (TREE_TYPE (array)); @@ -2347,6 +2530,8 @@ build_array_ref (tree array, tree idx) 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"); } @@ -2437,8 +2622,8 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function) 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; @@ -2449,7 +2634,8 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function) 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; @@ -2478,10 +2664,12 @@ tree 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. */ @@ -2547,22 +2735,29 @@ build_function_call (tree function, tree params) /* 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); } /* Convert the actual parameter expressions in the list VALUES @@ -2570,23 +2765,26 @@ build_function_call (tree function, tree params) 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; @@ -2614,8 +2812,8 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags) 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) { @@ -2626,11 +2824,7 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags) } 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. @@ -2649,7 +2843,7 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags) } if (val == error_mark_node) - return error_mark_node; + return -1; if (type != 0) { @@ -2674,9 +2868,9 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags) } if (parmval == error_mark_node) - return error_mark_node; + return -1; - result = tree_cons (NULL_TREE, parmval, result); + argarray[i] = parmval; } else { @@ -2689,7 +2883,7 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags) else val = convert_arg_to_ellipsis (val); - result = tree_cons (NULL_TREE, val, result); + argarray[i] = val; } if (typetail) @@ -2698,8 +2892,14 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags) 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) @@ -2710,9 +2910,9 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags) 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) @@ -2728,19 +2928,28 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags) } else error ("too few arguments to function"); - return error_mark_list; + return -1; } } - return nreverse (result); + gcc_assert (i <= nargs); + return i; } /* 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; @@ -2764,6 +2973,17 @@ build_x_binary_op (enum tree_code code, tree arg1, tree arg2, expr = build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE, overloaded_p); + /* Check for cases such as x+y<", op0); - else if (TREE_CODE (op1) == REAL_CST && real_zerop (op1)) - warning (0, "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. @@ -2983,16 +3214,15 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, 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 (0, "division by zero in %<%E %% 0%>", op0); - else if (code1 == REAL_TYPE && real_zerop (op1)) - warning (0, "division by zero in %<%E %% 0.%>", op0); + warn_for_div_by_zero (op1); if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { @@ -3072,11 +3302,13 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, 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. */ @@ -3087,8 +3319,12 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, case EQ_EXPR: case NE_EXPR: - if (warn_float_equal && (code0 == REAL_TYPE || code1 == REAL_TYPE)) - warning (0, "comparing floating point with == or != is unsafe"); + if (code0 == REAL_TYPE || code1 == REAL_TYPE) + 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_Waddress, "comparison with string literal results in unspecified behaviour"); build_type = boolean_type_node; if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE @@ -3102,10 +3338,22 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, "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; @@ -3118,8 +3366,28 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, } 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 = build_ptrmemfunc_access_expr (op0, + delta_identifier); + 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)) @@ -3142,26 +3410,61 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, 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); + 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) @@ -3194,6 +3497,10 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, case GE_EXPR: case LT_EXPR: case GT_EXPR: + if (TREE_CODE (orig_op0) == STRING_CST + || TREE_CODE (orig_op1) == STRING_CST) + warning (OPT_Waddress, "comparison with string literal results in unspecified behaviour"); + build_type = boolean_type_node; if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE) && (code1 == INTEGER_TYPE || code1 == REAL_TYPE)) @@ -3253,7 +3560,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, || !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; @@ -3275,9 +3582,17 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, /* 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) { @@ -3524,36 +3839,34 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, } } - /* 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; @@ -3566,6 +3879,12 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, 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; } @@ -3688,7 +4007,7 @@ build_x_unary_op (enum tree_code code, tree xarg) } else { - error ("parenthesis around %qE cannot be used to form a" + error ("parentheses around %qE cannot be used to form a" " pointer-to-member-function", xarg); PTRMEM_OK_P (xarg) = 1; @@ -3842,10 +4161,11 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) 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; @@ -3917,8 +4237,11 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) 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. */ @@ -3943,21 +4266,23 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) || 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. */ @@ -3966,16 +4291,18 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) 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 @@ -3983,44 +4310,6 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) 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) @@ -4028,7 +4317,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) 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) { @@ -4108,10 +4397,12 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) is used here to remove this const from the diagnostics and the created OFFSET_REF. */ tree base = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg, 0))); - tree name = DECL_NAME (get_first_fn (TREE_OPERAND (arg, 1))); + tree fn = get_first_fn (TREE_OPERAND (arg, 1)); + mark_used (fn); if (! flag_ms_extensions) { + tree name = DECL_NAME (fn); if (current_class_type && TREE_OPERAND (arg, 0) == current_class_ref) /* An expression like &memfn. */ @@ -4125,7 +4416,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) " Say %<&%T::%D%>", base, name); } - arg = build_offset_ref (base, name, /*address_p=*/true); + arg = build_offset_ref (base, fn, /*address_p=*/true); } offset_ref: @@ -4144,13 +4435,14 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) 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; @@ -4182,75 +4474,72 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) break; } - /* Allow the address of a constructor if all the elements - are constant. */ - if (TREE_CODE (arg) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (arg) - && TREE_CONSTANT (arg)) - ; /* Anything not already handled and not a true memory reference is an error. */ - else if (TREE_CODE (argtype) != FUNCTION_TYPE - && TREE_CODE (argtype) != METHOD_TYPE - && TREE_CODE (arg) != OFFSET_REF - && !lvalue_or_else (arg, lv_addressof)) + if (TREE_CODE (argtype) != FUNCTION_TYPE + && TREE_CODE (argtype) != METHOD_TYPE + && TREE_CODE (arg) != OFFSET_REF + && !lvalue_or_else (arg, lv_addressof)) return error_mark_node; if (argtype != error_mark_node) argtype = build_pointer_type (argtype); - { - tree addr; + /* In a template, we are processing a non-dependent expression + so we can just form an ADDR_EXPR with the correct type. */ + if (processing_template_decl) + { + val = build_address (arg); + if (TREE_CODE (arg) == OFFSET_REF) + PTRMEM_OK_P (val) = PTRMEM_OK_P (arg); + return val; + } - if (TREE_CODE (arg) != COMPONENT_REF - /* Inside a template, we are processing a non-dependent - expression so we can just form an ADDR_EXPR with the - correct type. */ - || processing_template_decl) - { - addr = build_address (arg); - if (TREE_CODE (arg) == OFFSET_REF) - PTRMEM_OK_P (addr) = PTRMEM_OK_P (arg); - } - else if (TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK) - { - tree fn = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1)); - - /* We can only get here with a single static member - function. */ - gcc_assert (TREE_CODE (fn) == FUNCTION_DECL - && DECL_STATIC_FUNCTION_P (fn)); - mark_used (fn); - addr = build_address (fn); - if (TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0))) - /* Do not lose object's side effects. */ - addr = build2 (COMPOUND_EXPR, TREE_TYPE (addr), - TREE_OPERAND (arg, 0), addr); - } - else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1))) - { - error ("attempt to take address of bit-field structure member %qD", - TREE_OPERAND (arg, 1)); - return error_mark_node; - } - else - { - tree object = TREE_OPERAND (arg, 0); - tree field = TREE_OPERAND (arg, 1); - gcc_assert (same_type_ignoring_top_level_qualifiers_p - (TREE_TYPE (object), decl_type_context (field))); - addr = build_address (arg); - } + if (TREE_CODE (arg) != COMPONENT_REF) + { + val = build_address (arg); + if (TREE_CODE (arg) == OFFSET_REF) + PTRMEM_OK_P (val) = PTRMEM_OK_P (arg); + } + else if (TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK) + { + tree fn = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1)); + + /* We can only get here with a single static member + function. */ + gcc_assert (TREE_CODE (fn) == FUNCTION_DECL + && DECL_STATIC_FUNCTION_P (fn)); + mark_used (fn); + val = build_address (fn); + if (TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0))) + /* Do not lose object's side effects. */ + val = build2 (COMPOUND_EXPR, TREE_TYPE (val), + TREE_OPERAND (arg, 0), val); + } + else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1))) + { + error ("attempt to take address of bit-field structure member %qD", + TREE_OPERAND (arg, 1)); + return error_mark_node; + } + else + { + tree object = TREE_OPERAND (arg, 0); + tree field = TREE_OPERAND (arg, 1); + gcc_assert (same_type_ignoring_top_level_qualifiers_p + (TREE_TYPE (object), decl_type_context (field))); + val = build_address (arg); + } - if (TREE_CODE (argtype) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE) - { - build_ptrmemfunc_type (argtype); - addr = build_ptrmemfunc (argtype, addr, 0, - /*c_cast_p=*/false); - } + if (TREE_CODE (argtype) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE) + { + build_ptrmemfunc_type (argtype); + val = build_ptrmemfunc (argtype, val, 0, + /*c_cast_p=*/false); + } - return addr; - } + return val; default: break; @@ -4313,7 +4602,7 @@ unary_complex_lvalue (enum tree_code code, tree arg) } if (code != ADDR_EXPR) - return 0; + return NULL_TREE; /* Handle (a = b) used as an "lvalue" for `&'. */ if (TREE_CODE (arg) == MODIFY_EXPR @@ -4354,7 +4643,7 @@ unary_complex_lvalue (enum tree_code code, tree arg) } /* Don't let anything else be handled specially. */ - return 0; + return NULL_TREE; } /* Mark EXP saying that we need to be able to take the @@ -4410,7 +4699,7 @@ cxx_mark_addressable (tree exp) } else if (extra_warnings) warning - (0, "address requested for %qD, which is declared %", x); + (OPT_Wextra, "address requested for %qD, which is declared %", x); } TREE_ADDRESSABLE (x) = 1; return true; @@ -4588,8 +4877,8 @@ convert_ptrmem (tree type, tree expr, bool allow_inverse_p, } /* 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) @@ -4597,11 +4886,9 @@ 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), @@ -4611,8 +4898,6 @@ ignore_overflows (tree expr, tree orig) /* 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; @@ -4640,6 +4925,9 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, 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) { @@ -4928,6 +5216,9 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, 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 @@ -5011,6 +5302,8 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, else if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype)) || (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype))) { + tree sexpr = expr; + if (!c_cast_p) check_for_casting_away_constness (intype, type, error, "reinterpret_cast"); @@ -5025,6 +5318,12 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, "target type", intype, type); + /* 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); + if (warn_strict_aliasing <= 2) + strict_aliasing_warning (intype, type, sexpr); + return fold_if_not_in_template (build_nop (type, expr)); } else if ((TYPE_PTRFN_P (type) && TYPE_PTROBV_P (intype)) @@ -5040,7 +5339,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, } 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 { @@ -5116,6 +5415,9 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain, 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) @@ -5331,7 +5633,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) 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". */ @@ -5396,6 +5698,12 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) 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 @@ -5405,11 +5713,9 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) 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) @@ -5509,7 +5815,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) 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 @@ -5557,11 +5863,19 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) /* 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); } @@ -5841,7 +6155,7 @@ build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p) } if (type_unknown_p (pfn)) - return instantiate_type (type, pfn, tf_error | tf_warning); + return instantiate_type (type, pfn, tf_warning_or_error); fn = TREE_OPERAND (pfn, 0); gcc_assert (TREE_CODE (fn) == FUNCTION_DECL @@ -5927,7 +6241,7 @@ expand_ptrmemfunc_cst (tree cst, tree *delta, tree *pfn) /* Return an expression for PFN from the pointer-to-member function given by T. */ -tree +static tree pfn_from_ptrmemfunc (tree t) { if (TREE_CODE (t) == PTRMEM_CST) @@ -5964,7 +6278,7 @@ convert_for_assignment (tree type, tree rhs, 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) @@ -6032,7 +6346,7 @@ convert_for_assignment (tree type, tree rhs, overloaded function. Call instantiate_type to get error messages. */ if (rhstype == unknown_type_node) - instantiate_type (type, rhs, tf_error | tf_warning); + instantiate_type (type, rhs, tf_warning_or_error); else if (fndecl) error ("cannot convert %qT to %qT for argument %qP to %qD", rhstype, type, parmnum, fndecl); @@ -6051,7 +6365,20 @@ convert_for_assignment (tree type, tree rhs, "%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); } @@ -6086,7 +6413,8 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags, && 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; @@ -6185,6 +6513,10 @@ maybe_warn_about_returning_address_of_local (tree retval) } } + 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) @@ -6216,6 +6548,7 @@ check_return_expr (tree retval, bool *no_warning) promotions. */ tree valtype; int fn_returns_value_p; + bool named_return_value_okay_p; *no_warning = false; @@ -6247,6 +6580,7 @@ check_return_expr (tree retval, bool *no_warning) if (processing_template_decl) { current_function_returns_value = 1; + check_for_bare_parameter_packs (retval); return retval; } @@ -6270,8 +6604,8 @@ check_return_expr (tree retval, bool *no_warning) 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 @@ -6314,7 +6648,7 @@ check_return_expr (tree retval, bool *no_warning) || 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, "% must not return NULL unless it is " "declared % (or -fcheck-new is in effect)"); @@ -6341,7 +6675,7 @@ check_return_expr (tree retval, bool *no_warning) } if (warn) - warning (0, "% should return a reference to %<*this%>"); + warning (OPT_Weffc__, "% should return a reference to %<*this%>"); } /* The fabled Named Return Value optimization, as per [class.copy]/15: @@ -6363,20 +6697,27 @@ check_return_expr (tree retval, bool *no_warning) 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; @@ -6395,18 +6736,29 @@ check_return_expr (tree retval, bool *no_warning) { /* 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;'. */ @@ -6515,7 +6867,7 @@ ptr_reasonably_similar (tree to, tree from) 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 @@ -6566,6 +6918,16 @@ cp_type_quals (tree 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