X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcp%2Ftypeck.c;h=a4bbd4eb1373391d546997f4afc874038f1dde52;hb=fe5f0da48681bc0b6f8174cbe11e83745cc84ca2;hp=36f306558d30d156a2267909af4945f720743d72;hpb=7feec18988e4d3b2b4076b77ceb4405ec57cd9d8;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 36f306558d3..a4bbd4eb137 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1,6 +1,6 @@ /* Build expressions with type checking for C++ compiler. Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) @@ -31,23 +31,20 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "tree.h" -#include "rtl.h" -#include "expr.h" #include "cp-tree.h" -#include "tm_p.h" #include "flags.h" #include "output.h" -#include "toplev.h" #include "diagnostic.h" #include "intl.h" #include "target.h" #include "convert.h" -#include "c-common.h" +#include "c-family/c-common.h" +#include "c-family/c-objc.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 convert_for_assignment (tree, tree, impl_conv_rhs, tree, int, tsubst_flags_t, int); static tree cp_pointer_int_sum (enum tree_code, tree, tree); static tree rationalize_conditional_expr (enum tree_code, tree, @@ -56,21 +53,22 @@ static int comp_ptr_ttypes_real (tree, tree, int); static bool comp_except_types (tree, tree, bool); 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 tree get_delta_difference (tree, tree, bool, bool, tsubst_flags_t); 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 void warn_args_num (location_t, tree, bool); static int convert_arguments (tree, VEC(tree,gc) **, tree, int, tsubst_flags_t); /* Do `exp = require_complete_type (exp);' to make sure exp does not have an incomplete type. (That includes void types.) - Returns the error_mark_node if the VALUE does not have + Returns error_mark_node if the VALUE does not have complete type when this function returns. */ tree -require_complete_type (tree value) +require_complete_type_sfinae (tree value, tsubst_flags_t complain) { tree type; @@ -89,12 +87,18 @@ require_complete_type (tree value) if (COMPLETE_TYPE_P (type)) return value; - if (complete_type_or_else (type, value)) + if (complete_type_or_maybe_complain (type, value, complain)) return value; else return error_mark_node; } +tree +require_complete_type (tree value) +{ + return require_complete_type_sfinae (value, tf_warning_or_error); +} + /* Try to complete TYPE, if it is incomplete. For example, if TYPE is a template instantiation, do the instantiation. Returns TYPE, whether or not it could be completed, unless something goes @@ -137,7 +141,7 @@ complete_type (tree type) Returns NULL_TREE if the type cannot be made complete. */ tree -complete_type_or_else (tree type, tree value) +complete_type_or_maybe_complain (tree type, tree value, tsubst_flags_t complain) { type = complete_type (type); if (type == error_mark_node) @@ -145,13 +149,20 @@ complete_type_or_else (tree type, tree value) return NULL_TREE; else if (!COMPLETE_TYPE_P (type)) { - cxx_incomplete_type_diagnostic (value, type, DK_ERROR); + if (complain & tf_error) + cxx_incomplete_type_diagnostic (value, type, DK_ERROR); return NULL_TREE; } else return type; } +tree +complete_type_or_else (tree type, tree value) +{ + return complete_type_or_maybe_complain (type, value, tf_warning_or_error); +} + /* Return truthvalue of whether type of EXP is instantiated. */ int @@ -260,6 +271,7 @@ cp_common_type (tree t1, tree t2) enum tree_code code2 = TREE_CODE (t2); tree attributes; + /* In what follows, we slightly generalize the rules given in [expr] so as to deal with `long long' and `complex'. First, merge the attributes. */ @@ -352,6 +364,17 @@ cp_common_type (tree t1, tree t2) : long_long_integer_type_node); return build_type_attribute_variant (t, attributes); } + if (int128_integer_type_node != NULL_TREE + && (same_type_p (TYPE_MAIN_VARIANT (t1), + int128_integer_type_node) + || same_type_p (TYPE_MAIN_VARIANT (t2), + int128_integer_type_node))) + { + tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2)) + ? int128_unsigned_type_node + : int128_integer_type_node); + return build_type_attribute_variant (t, attributes); + } /* Go through the same procedure, but for longs. */ if (same_type_p (TYPE_MAIN_VARIANT (t1), long_unsigned_type_node) @@ -420,6 +443,35 @@ type_after_usual_arithmetic_conversions (tree t1, tree t2) return cp_common_type (t1, t2); } +static void +composite_pointer_error (diagnostic_t kind, tree t1, tree t2, + composite_pointer_operation operation) +{ + switch (operation) + { + case CPO_COMPARISON: + emit_diagnostic (kind, input_location, 0, + "comparison between " + "distinct pointer types %qT and %qT lacks a cast", + t1, t2); + break; + case CPO_CONVERSION: + emit_diagnostic (kind, input_location, 0, + "conversion between " + "distinct pointer types %qT and %qT lacks a cast", + t1, t2); + break; + case CPO_CONDITIONAL_EXPR: + emit_diagnostic (kind, input_location, 0, + "conditional expression between " + "distinct pointer types %qT and %qT lacks a cast", + t1, t2); + break; + default: + gcc_unreachable (); + } +} + /* Subroutine of composite_pointer_type to implement the recursive case. See that function for documentation of the parameters. */ @@ -463,28 +515,8 @@ composite_pointer_type_r (tree t1, tree t2, else { if (complain & tf_error) - { - switch (operation) - { - case CPO_COMPARISON: - permerror (input_location, "comparison between " - "distinct pointer types %qT and %qT lacks a cast", - t1, t2); - break; - case CPO_CONVERSION: - permerror (input_location, "conversion between " - "distinct pointer types %qT and %qT lacks a cast", - t1, t2); - break; - case CPO_CONDITIONAL_EXPR: - permerror (input_location, "conditional expression between " - "distinct pointer types %qT and %qT lacks a cast", - t1, t2); - break; - default: - gcc_unreachable (); - } - } + composite_pointer_error (DK_PERMERROR, t1, t2, operation); + result_type = void_type_node; } result_type = cp_build_qualified_type (result_type, @@ -497,28 +529,7 @@ composite_pointer_type_r (tree t1, tree t2, if (!same_type_p (TYPE_PTRMEM_CLASS_TYPE (t1), TYPE_PTRMEM_CLASS_TYPE (t2)) && (complain & tf_error)) - { - switch (operation) - { - case CPO_COMPARISON: - permerror (input_location, "comparison between " - "distinct pointer types %qT and %qT lacks a cast", - t1, t2); - break; - case CPO_CONVERSION: - permerror (input_location, "conversion between " - "distinct pointer types %qT and %qT lacks a cast", - t1, t2); - break; - case CPO_CONDITIONAL_EXPR: - permerror (input_location, "conditional expression between " - "distinct pointer types %qT and %qT lacks a cast", - t1, t2); - break; - default: - gcc_unreachable (); - } - } + composite_pointer_error (DK_PERMERROR, t1, t2, operation); result_type = build_ptrmem_type (TYPE_PTRMEM_CLASS_TYPE (t1), result_type); } @@ -615,8 +626,8 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2, if (c_dialect_objc () && TREE_CODE (t1) == POINTER_TYPE && TREE_CODE (t2) == POINTER_TYPE) { - if (objc_compare_types (t1, t2, -3, NULL_TREE)) - return t1; + if (objc_have_common_type (t1, t2, -3, NULL_TREE)) + return objc_common_type (t1, t2); } /* [expr.eq] permits the application of a pointer conversion to @@ -632,30 +643,14 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2, if (DERIVED_FROM_P (class1, class2)) t2 = (build_pointer_type - (cp_build_qualified_type (class1, TYPE_QUALS (class2)))); + (cp_build_qualified_type (class1, cp_type_quals (class2)))); else if (DERIVED_FROM_P (class2, class1)) t1 = (build_pointer_type - (cp_build_qualified_type (class2, TYPE_QUALS (class1)))); + (cp_build_qualified_type (class2, cp_type_quals (class1)))); else { if (complain & tf_error) - switch (operation) - { - case CPO_COMPARISON: - error ("comparison between distinct " - "pointer types %qT and %qT lacks a cast", t1, t2); - break; - case CPO_CONVERSION: - error ("conversion between distinct " - "pointer types %qT and %qT lacks a cast", t1, t2); - break; - case CPO_CONDITIONAL_EXPR: - error ("conditional expression between distinct " - "pointer types %qT and %qT lacks a cast", t1, t2); - break; - default: - gcc_unreachable (); - } + composite_pointer_error (DK_ERROR, t1, t2, operation); return error_mark_node; } } @@ -809,6 +804,7 @@ merge_types (tree t1, tree t2) tree valtype = merge_types (TREE_TYPE (t1), TREE_TYPE (t2)); tree p1 = TYPE_ARG_TYPES (t1); tree p2 = TYPE_ARG_TYPES (t2); + tree parms; tree rval, raises; /* Save space: see if the result is identical to one of the args. */ @@ -819,22 +815,17 @@ merge_types (tree t1, tree t2) /* Simple way if one arg fails to specify argument types. */ if (p1 == NULL_TREE || TREE_VALUE (p1) == void_type_node) - { - rval = build_function_type (valtype, p2); - if ((raises = TYPE_RAISES_EXCEPTIONS (t2))) - rval = build_exception_variant (rval, raises); - return cp_build_type_attribute_variant (rval, attributes); - } - raises = TYPE_RAISES_EXCEPTIONS (t1); - if (p2 == NULL_TREE || TREE_VALUE (p2) == void_type_node) - { - rval = build_function_type (valtype, p1); - if (raises) - rval = build_exception_variant (rval, raises); - return cp_build_type_attribute_variant (rval, attributes); - } + parms = p2; + else if (p2 == NULL_TREE || TREE_VALUE (p2) == void_type_node) + parms = p1; + else + parms = commonparms (p1, p2); - rval = build_function_type (valtype, commonparms (p1, p2)); + rval = build_function_type (valtype, parms); + gcc_assert (type_memfn_quals (t1) == type_memfn_quals (t2)); + rval = apply_memfn_quals (rval, type_memfn_quals (t1)); + raises = merge_exception_specifiers (TYPE_RAISES_EXCEPTIONS (t1), + TYPE_RAISES_EXCEPTIONS (t2)); t1 = build_exception_variant (rval, raises); break; } @@ -844,7 +835,8 @@ merge_types (tree t1, tree t2) /* Get this value the long way, since TYPE_METHOD_BASETYPE is just the main variant of this. */ tree basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t2))); - tree raises = TYPE_RAISES_EXCEPTIONS (t1); + tree raises = merge_exception_specifiers (TYPE_RAISES_EXCEPTIONS (t1), + TYPE_RAISES_EXCEPTIONS (t2)); tree t3; /* If this was a member function type, get back to the @@ -878,6 +870,19 @@ merge_types (tree t1, tree t2) return cp_build_type_attribute_variant (t1, attributes); } +/* Return the ARRAY_TYPE type without its domain. */ + +tree +strip_array_domain (tree type) +{ + tree t2; + gcc_assert (TREE_CODE (type) == ARRAY_TYPE); + if (TYPE_DOMAIN (type) == NULL_TREE) + return type; + t2 = build_cplus_array_type (TREE_TYPE (type), NULL_TREE); + return cp_build_type_attribute_variant (t2, TYPE_ATTRIBUTES (type)); +} + /* Wrapper around cp_common_type that is used by c-common.c and other front end optimizations that remove promotions. @@ -962,13 +967,14 @@ comp_except_types (tree a, tree b, bool exact) } /* Return true if TYPE1 and TYPE2 are equivalent exception specifiers. - If EXACT is false, T2 can be stricter than T1 (according to 15.4/7), - otherwise it must be exact. Exception lists are unordered, but - we've already filtered out duplicates. Most lists will be in order, - we should try to make use of that. */ + If EXACT is ce_derived, T2 can be stricter than T1 (according to 15.4/5). + If EXACT is ce_normal, the compatibility rules in 15.4/3 apply. + If EXACT is ce_exact, the specs must be exactly the same. Exception lists + are unordered, but we've already filtered out duplicates. Most lists will + be in order, we should try to make use of that. */ bool -comp_except_specs (const_tree t1, const_tree t2, bool exact) +comp_except_specs (const_tree t1, const_tree t2, int exact) { const_tree probe; const_tree base; @@ -977,14 +983,42 @@ comp_except_specs (const_tree t1, const_tree t2, bool exact) if (t1 == t2) return true; + /* First handle noexcept. */ + if (exact < ce_exact) + { + /* noexcept(false) is compatible with any throwing dynamic-exc-spec + and stricter than any spec. */ + if (t1 == noexcept_false_spec) + return !nothrow_spec_p (t2) || exact == ce_derived; + /* Even a derived noexcept(false) is compatible with a throwing + dynamic spec. */ + if (t2 == noexcept_false_spec) + return !nothrow_spec_p (t1); + + /* Otherwise, if we aren't looking for an exact match, noexcept is + equivalent to throw(). */ + if (t1 == noexcept_true_spec) + t1 = empty_except_spec; + if (t2 == noexcept_true_spec) + t2 = empty_except_spec; + } + + /* If any noexcept is left, it is only comparable to itself; + either we're looking for an exact match or we're redeclaring a + template with dependent noexcept. */ + if ((t1 && TREE_PURPOSE (t1)) + || (t2 && TREE_PURPOSE (t2))) + return (t1 && t2 + && cp_tree_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2))); + if (t1 == NULL_TREE) /* T1 is ... */ - return t2 == NULL_TREE || !exact; + return t2 == NULL_TREE || exact == ce_derived; if (!TREE_VALUE (t1)) /* t1 is EMPTY */ return t2 != NULL_TREE && !TREE_VALUE (t2); if (t2 == NULL_TREE) /* T2 is ... */ return false; if (TREE_VALUE (t1) && !TREE_VALUE (t2)) /* T2 is EMPTY, T1 is not */ - return !exact; + return exact == ce_derived; /* Neither set is ... or EMPTY, make sure each part of T2 is in T1. Count how many we find, to determine exactness. For exact matching and @@ -999,7 +1033,7 @@ comp_except_specs (const_tree t1, const_tree t2, bool exact) if (comp_except_types (a, b, exact)) { - if (probe == base && exact) + if (probe == base && exact > ce_derived) base = TREE_CHAIN (probe); length++; break; @@ -1008,7 +1042,7 @@ comp_except_specs (const_tree t1, const_tree t2, bool exact) if (probe == NULL_TREE) return false; } - return !exact || base == NULL_TREE || length == list_length (t1); + return exact == ce_derived || base == NULL_TREE || length == list_length (t1); } /* Compare the array types T1 and T2. ALLOW_REDECLARATION is true if @@ -1081,98 +1115,30 @@ comp_array_types (const_tree t1, const_tree t2, bool allow_redeclaration) static bool comp_template_parms_position (tree t1, tree t2) { + tree index1, index2; gcc_assert (t1 && t2 && TREE_CODE (t1) == TREE_CODE (t2) && (TREE_CODE (t1) == BOUND_TEMPLATE_TEMPLATE_PARM || TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM || TREE_CODE (t1) == TEMPLATE_TYPE_PARM)); - if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2) - || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2) - || (TEMPLATE_TYPE_PARAMETER_PACK (t1) - != TEMPLATE_TYPE_PARAMETER_PACK (t2))) - return false; - - return true; -} - -/* Subroutine of incompatible_dependent_types_p. - Return the template parameter of the dependent type T. - If T is a typedef, return the template parameters of - the _decl_ of the typedef. T must be a dependent type. */ - -static tree -get_template_parms_of_dependent_type (tree t) -{ - tree tinfo = NULL_TREE, tparms = NULL_TREE; - - /* If T1 is a typedef or whatever has a template info associated - to its context, get the template parameters from that context. */ - if (typedef_variant_p (t) - && DECL_CONTEXT (TYPE_NAME (t)) - && !NAMESPACE_SCOPE_P (TYPE_NAME (t))) - tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t))); - else if (TYPE_CONTEXT (t) - && !NAMESPACE_SCOPE_P (t)) - tinfo = get_template_info (TYPE_CONTEXT (t)); - - if (tinfo) - tparms = DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo)); - /* If T is a template type parameter, get the template parameter - set it is part of. */ - else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM - && DECL_CONTEXT (TYPE_NAME (t))) - tparms = DECL_TEMPLATE_PARMS (DECL_CONTEXT (TYPE_NAME (t))); - /* If T is a TYPENAME_TYPE which context is a template type - parameter, get the template parameters from that context. */ - else if (TYPE_CONTEXT (t) - && TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM) - tparms = get_template_parms_of_dependent_type (TYPE_CONTEXT (t)); - - return tparms; -} - -/* Subroutine of structural_comptypes. - Compare the dependent types T1 and T2. - Return TRUE if we are sure they can't be equal, FALSE otherwise. - The whole point of this function is to support cases where either T1 or - T2 is a typedef. In those cases, we need to compare the template parameters - of the _decl_ of the typedef. If those don't match then we know T1 - and T2 cannot be equal. */ + index1 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t1)); + index2 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t2)); -static bool -incompatible_dependent_types_p (tree t1, tree t2) -{ - tree tparms1 = NULL_TREE, tparms2 = NULL_TREE; - - if (!uses_template_parms (t1) || !uses_template_parms (t2)) + /* If T1 and T2 belong to template parm lists of different size, + let's assume they are different. */ + if (TEMPLATE_PARM_NUM_SIBLINGS (index1) + != TEMPLATE_PARM_NUM_SIBLINGS (index2)) return false; - if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM) - { - /* If T1 and T2 don't have the same relative position in their - template parameters set, they can't be equal. */ - if (!comp_template_parms_position (t1, t2)) - return true; - } - - /* Either T1 or T2 must be a typedef. */ - if (!typedef_variant_p (t1) && !typedef_variant_p (t2)) + /* Then compare their relative position. */ + if (TEMPLATE_PARM_IDX (index1) != TEMPLATE_PARM_IDX (index2) + || TEMPLATE_PARM_LEVEL (index1) != TEMPLATE_PARM_LEVEL (index2) + || (TEMPLATE_PARM_PARAMETER_PACK (index1) + != TEMPLATE_PARM_PARAMETER_PACK (index2))) return false; - /* So if we reach this point, it means either T1 or T2 is a typedef variant. - Let's compare their template parameters. */ - - tparms1 = get_template_parms_of_dependent_type (t1); - tparms2 = get_template_parms_of_dependent_type (t2); - - if (tparms1 == NULL_TREE - || tparms2 == NULL_TREE - || tparms1 == tparms2) - return false; - - /* And now compare the mighty template parms! */ - return !comp_template_parms (tparms1, tparms2); + return true; } /* Subroutine in comptypes. */ @@ -1209,7 +1175,10 @@ structural_comptypes (tree t1, tree t2, int strict) /* Qualifiers must match. For array types, we will check when we recur on the array element types. */ if (TREE_CODE (t1) != ARRAY_TYPE - && TYPE_QUALS (t1) != TYPE_QUALS (t2)) + && cp_type_quals (t1) != cp_type_quals (t2)) + return false; + if (TREE_CODE (t1) == FUNCTION_TYPE + && type_memfn_quals (t1) != type_memfn_quals (t2)) return false; if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2)) return false; @@ -1222,11 +1191,6 @@ structural_comptypes (tree t1, tree t2, int strict) && TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)) return true; - /* If T1 and T2 are dependent typedefs then check upfront that - the template parameters of their typedef DECLs match before - going down checking their subtypes. */ - if (incompatible_dependent_types_p (t1, t2)) - return false; /* Compare the types. Break out if they could be the same. */ switch (TREE_CODE (t1)) @@ -1319,8 +1283,10 @@ structural_comptypes (tree t1, tree t2, int strict) break; case TEMPLATE_TYPE_PARM: - /* If incompatible_dependent_types_p called earlier didn't decide - T1 and T2 were different, they might be equal. */ + /* If T1 and T2 don't have the same relative position in their + template parameters set, they can't be equal. */ + if (!comp_template_parms_position (t1, t2)) + return false; break; case TYPENAME_TYPE: @@ -1429,6 +1395,18 @@ comptypes (tree t1, tree t2, int strict) return structural_comptypes (t1, t2, strict); } +/* Returns nonzero iff TYPE1 and TYPE2 are the same type, ignoring + top-level qualifiers. */ + +bool +same_type_ignoring_top_level_qualifiers_p (tree type1, tree type2) +{ + if (type1 == error_mark_node || type2 == error_mark_node) + return false; + + return same_type_p (TYPE_MAIN_VARIANT (type1), TYPE_MAIN_VARIANT (type2)); +} + /* Returns 1 if TYPE1 is at least as qualified as TYPE2. */ bool @@ -1587,6 +1565,15 @@ cxx_sizeof_expr (tree e, tsubst_flags_t complain) return e; } + /* To get the size of a static data member declared as an array of + unknown bound, we need to instantiate it. */ + if (TREE_CODE (e) == VAR_DECL + && VAR_HAD_UNKNOWN_BOUND (e) + && DECL_TEMPLATE_INSTANTIATION (e)) + instantiate_decl (e, /*defer_ok*/true, /*expl_inst_mem*/false); + + e = mark_type_use (e); + if (TREE_CODE (e) == COMPONENT_REF && TREE_CODE (TREE_OPERAND (e, 1)) == FIELD_DECL && DECL_C_BIT_FIELD (TREE_OPERAND (e, 1))) @@ -1642,6 +1629,8 @@ cxx_alignof_expr (tree e, tsubst_flags_t complain) return e; } + e = mark_type_use (e); + if (TREE_CODE (e) == VAR_DECL) t = size_int (DECL_ALIGN_UNIT (e)); else if (TREE_CODE (e) == COMPONENT_REF @@ -1791,7 +1780,9 @@ unlowered_expr_type (const_tree exp) in an rvalue context: the lvalue-to-rvalue, array-to-pointer, and function-to-pointer conversions. In addition, manifest constants are replaced by their values, and bitfield references are converted - to their declared types. + to their declared types. Note that this function does not perform the + lvalue-to-rvalue conversion for class types. If you need that conversion + to for class types, then you probably need to use force_rvalue. Although the returned value is being used as an rvalue, this function does not wrap the returned expression in a @@ -1808,6 +1799,8 @@ decay_conversion (tree exp) if (type == error_mark_node) return error_mark_node; + exp = mark_rvalue_use (exp); + exp = resolve_nondeduced_context (exp); if (type_unknown_p (exp)) { @@ -1815,10 +1808,16 @@ decay_conversion (tree exp) return error_mark_node; } + /* FIXME remove? at least need to remember that this isn't really a + constant expression if EXP isn't decl_constant_var_p, like with + C_MAYBE_CONST_EXPR. */ exp = decl_constant_value (exp); if (error_operand_p (exp)) return error_mark_node; + if (NULLPTR_TYPE_P (type)) + return nullptr_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); @@ -1830,7 +1829,7 @@ decay_conversion (tree exp) if (invalid_nonstatic_memfn_p (exp, tf_warning_or_error)) return error_mark_node; if (code == FUNCTION_TYPE || is_overloaded_fn (exp)) - return cp_build_unary_op (ADDR_EXPR, exp, 0, tf_warning_or_error); + return cp_build_addr_expr (exp, tf_warning_or_error); if (code == ARRAY_TYPE) { tree adr; @@ -1865,7 +1864,7 @@ decay_conversion (tree exp) } /* This way is better for a COMPONENT_REF since it can simplify the offset for a component. */ - adr = cp_build_unary_op (ADDR_EXPR, exp, 1, tf_warning_or_error); + adr = cp_build_addr_expr (exp, tf_warning_or_error); return cp_convert (ptrtype, adr); } @@ -1932,6 +1931,8 @@ perform_integral_promotions (tree expr) tree type; tree promoted_type; + expr = mark_rvalue_use (expr); + /* [conv.prom] If the bitfield has an enumerated type, it is treated as any @@ -1973,7 +1974,7 @@ string_conv_p (const_tree totype, const_tree exp, int warn) else { /* Is this a string constant which has decayed to 'const char *'? */ - t = build_pointer_type (build_qualified_type (t, TYPE_QUAL_CONST)); + t = build_pointer_type (cp_build_qualified_type (t, TYPE_QUAL_CONST)); if (!same_type_p (TREE_TYPE (exp), t)) return 0; STRIP_NOPS (exp); @@ -2045,7 +2046,7 @@ lookup_anon_field (tree t, tree type) { tree field; - for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field)) + for (field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field)) { if (TREE_STATIC (field)) continue; @@ -2103,7 +2104,7 @@ build_class_member_access_expr (tree object, tree member, complete type). */ object_type = TREE_TYPE (object); if (!currently_open_class (object_type) - && !complete_type_or_else (object_type, object)) + && !complete_type_or_maybe_complain (object_type, object, complain)) return error_mark_node; if (!CLASS_TYPE_P (object_type)) { @@ -2159,6 +2160,7 @@ build_class_member_access_expr (tree object, tree member, { /* A static data member. */ result = member; + mark_exp_read (object); /* If OBJECT has side-effects, they are supposed to occur. */ if (TREE_SIDE_EFFECTS (object)) result = build2 (COMPOUND_EXPR, TREE_TYPE (result), object, result); @@ -2472,13 +2474,17 @@ finish_class_member_access_expr (tree object, tree name, bool template_p, return build_min_nt (COMPONENT_REF, object, name, NULL_TREE); object = build_non_dependent_expr (object); } - + else if (c_dialect_objc () + && TREE_CODE (name) == IDENTIFIER_NODE + && (expr = objc_maybe_build_component_ref (object, name))) + return expr; + /* [expr.ref] The type of the first expression shall be "class object" (of a complete type). */ if (!currently_open_class (object_type) - && !complete_type_or_else (object_type, object)) + && !complete_type_or_maybe_complain (object_type, object, complain)) return error_mark_node; if (!CLASS_TYPE_P (object_type)) { @@ -2806,13 +2812,15 @@ cp_build_indirect_ref (tree ptr, ref_operator errorstring, LOC is the location to use in building the array reference. */ tree -build_array_ref (location_t loc, tree array, tree idx) +cp_build_array_ref (location_t loc, tree array, tree idx, + tsubst_flags_t complain) { tree ret; if (idx == 0) { - error_at (loc, "subscript missing in array reference"); + if (complain & tf_error) + error_at (loc, "subscript missing in array reference"); return error_mark_node; } @@ -2826,7 +2834,8 @@ build_array_ref (location_t loc, tree array, tree idx) { case COMPOUND_EXPR: { - tree value = build_array_ref (loc, TREE_OPERAND (array, 1), idx); + tree value = cp_build_array_ref (loc, TREE_OPERAND (array, 1), idx, + complain); ret = build2 (COMPOUND_EXPR, TREE_TYPE (value), TREE_OPERAND (array, 0), value); SET_EXPR_LOCATION (ret, loc); @@ -2836,8 +2845,10 @@ build_array_ref (location_t loc, tree array, tree idx) case COND_EXPR: ret = build_conditional_expr (TREE_OPERAND (array, 0), - build_array_ref (loc, TREE_OPERAND (array, 1), idx), - build_array_ref (loc, TREE_OPERAND (array, 2), idx), + cp_build_array_ref (loc, TREE_OPERAND (array, 1), idx, + complain), + cp_build_array_ref (loc, TREE_OPERAND (array, 2), idx, + complain), tf_warning_or_error); protected_set_expr_location (ret, loc); return ret; @@ -2854,7 +2865,8 @@ build_array_ref (location_t loc, tree array, tree idx) if (!INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (idx))) { - error_at (loc, "array subscript is not an integer"); + if (complain & tf_error) + error_at (loc, "array subscript is not an integer"); return error_mark_node; } @@ -2890,7 +2902,7 @@ build_array_ref (location_t loc, tree array, tree idx) return error_mark_node; } - if (!lvalue_p (array)) + if (!lvalue_p (array) && (complain & tf_error)) pedwarn (loc, OPT_pedantic, "ISO C++ forbids subscripting non-lvalue array"); @@ -2902,7 +2914,8 @@ build_array_ref (location_t loc, tree array, tree idx) tree foo = array; while (TREE_CODE (foo) == COMPONENT_REF) foo = TREE_OPERAND (foo, 0); - if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo)) + if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo) + && (complain & tf_warning)) warning_at (loc, OPT_Wextra, "subscripting array declared %"); } @@ -2917,7 +2930,8 @@ build_array_ref (location_t loc, tree array, tree idx) |= (CP_TYPE_VOLATILE_P (type) | TREE_SIDE_EFFECTS (array)); TREE_THIS_VOLATILE (rval) |= (CP_TYPE_VOLATILE_P (type) | TREE_THIS_VOLATILE (array)); - ret = require_complete_type (fold_if_not_in_template (rval)); + ret = require_complete_type_sfinae (fold_if_not_in_template (rval), + complain); protected_set_expr_location (ret, loc); return ret; } @@ -2939,12 +2953,14 @@ build_array_ref (location_t loc, tree array, tree idx) if (TREE_CODE (TREE_TYPE (ar)) != POINTER_TYPE) { - error_at (loc, "subscripted value is neither array nor pointer"); + if (complain & tf_error) + error_at (loc, "subscripted value is neither array nor pointer"); return error_mark_node; } if (TREE_CODE (TREE_TYPE (ind)) != INTEGER_TYPE) { - error_at (loc, "array subscript is not an integer"); + if (complain & tf_error) + error_at (loc, "array subscript is not an integer"); return error_mark_node; } @@ -2952,13 +2968,21 @@ build_array_ref (location_t loc, tree array, tree idx) ret = cp_build_indirect_ref (cp_build_binary_op (input_location, PLUS_EXPR, ar, ind, - tf_warning_or_error), + complain), RO_ARRAY_INDEXING, - tf_warning_or_error); + complain); protected_set_expr_location (ret, loc); return ret; } } + +/* Entry point for Obj-C++. */ + +tree +build_array_ref (location_t loc, tree array, tree idx) +{ + return cp_build_array_ref (loc, array, idx, tf_warning_or_error); +} /* Resolve a pointer to member function. INSTANCE is the object instance to use, if the member points to a virtual member. @@ -3079,8 +3103,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function) vtable entry is treated as a function pointer. */ if (TARGET_VTABLE_USES_DESCRIPTORS) e2 = build1 (NOP_EXPR, TREE_TYPE (e2), - cp_build_unary_op (ADDR_EXPR, e2, /*noconvert=*/1, - tf_warning_or_error)); + cp_build_addr_expr (e2, tf_warning_or_error)); e2 = fold_convert (TREE_TYPE (e3), e2); e1 = build_conditional_expr (e1, e2, e3, tf_warning_or_error); @@ -3138,6 +3161,25 @@ cp_build_function_call (tree function, tree params, tsubst_flags_t complain) return ret; } +/* Build a function call using varargs. */ + +tree +cp_build_function_call_nary (tree function, tsubst_flags_t complain, ...) +{ + VEC(tree,gc) *vec; + va_list args; + tree ret, t; + + vec = make_tree_vector (); + va_start (args, complain); + for (t = va_arg (args, tree); t != NULL_TREE; t = va_arg (args, tree)) + VEC_safe_push (tree, gc, vec, t); + va_end (args); + ret = cp_build_function_call_vec (function, &vec, complain); + release_tree_vector (vec); + return ret; +} + /* Build a function call using a vector of arguments. PARAMS may be NULL if there are no parameters. This changes the contents of PARAMS. */ @@ -3243,6 +3285,53 @@ cp_build_function_call_vec (tree function, VEC(tree,gc) **params, return ret; } +/* Subroutine of convert_arguments. + Warn about wrong number of args are genereted. */ + +static void +warn_args_num (location_t loc, tree fndecl, bool too_many_p) +{ + if (fndecl) + { + if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE) + { + if (DECL_NAME (fndecl) == NULL_TREE + || IDENTIFIER_HAS_TYPE_VALUE (DECL_NAME (fndecl))) + error_at (loc, + too_many_p + ? G_("too many arguments to constructor %q#D") + : G_("too few arguments to constructor %q#D"), + fndecl); + else + error_at (loc, + too_many_p + ? G_("too many arguments to member function %q#D") + : G_("too few arguments to member function %q#D"), + fndecl); + } + else + error_at (loc, + too_many_p + ? G_("too many arguments to function %q#D") + : G_("too few arguments to function %q#D"), + fndecl); + inform (DECL_SOURCE_LOCATION (fndecl), + "declared here"); + } + else + { + if (c_dialect_objc () && objc_message_selector ()) + error_at (loc, + too_many_p + ? G_("too many arguments to method %q#D") + : G_("too few arguments to method %q#D"), + objc_message_selector ()); + else + error_at (loc, too_many_p ? G_("too many arguments to function") + : G_("too few arguments to function")); + } +} + /* Convert the actual parameter expressions in the list VALUES to the types in the list TYPELIST. The converted expressions are stored back in the VALUES vector. @@ -3264,26 +3353,11 @@ convert_arguments (tree typelist, VEC(tree,gc) **values, tree fndecl, int flags, tsubst_flags_t complain) { tree typetail; - const char *called_thing = 0; unsigned int i; /* Argument passing is always copy-initialization. */ flags |= LOOKUP_ONLYCONVERTING; - if (fndecl) - { - if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE) - { - if (DECL_NAME (fndecl) == NULL_TREE - || IDENTIFIER_HAS_TYPE_VALUE (DECL_NAME (fndecl))) - called_thing = "constructor"; - else - called_thing = "member function"; - } - else - called_thing = "function"; - } - for (i = 0, typetail = typelist; i < VEC_length (tree, *values); i++) @@ -3298,14 +3372,7 @@ convert_arguments (tree typelist, VEC(tree,gc) **values, tree fndecl, { if (complain & tf_error) { - if (fndecl) - { - error ("too many arguments to %s %q+#D", - called_thing, fndecl); - error ("at this point in file"); - } - else - error ("too many arguments to function"); + warn_args_num (input_location, fndecl, /*too_many_p=*/true); return i; } else @@ -3351,7 +3418,7 @@ convert_arguments (tree typelist, VEC(tree,gc) **values, tree fndecl, { parmval = convert_for_initialization (NULL_TREE, type, val, flags, - "argument passing", fndecl, i, complain); + ICR_ARGPASS, fndecl, i, complain); parmval = convert_for_arg_passing (type, parmval); } @@ -3367,7 +3434,7 @@ convert_arguments (tree typelist, VEC(tree,gc) **values, tree fndecl, /* Don't do ellipsis conversion for __built_in_constant_p as this will result in spurious errors for non-trivial types. */ - val = require_complete_type (val); + val = require_complete_type_sfinae (val, complain); else val = convert_arg_to_ellipsis (val); @@ -3410,16 +3477,7 @@ convert_arguments (tree typelist, VEC(tree,gc) **values, tree fndecl, else { if (complain & tf_error) - { - if (fndecl) - { - error ("too few arguments to %s %q+#D", - called_thing, fndecl); - error ("at this point in file"); - } - else - error ("too few arguments to function"); - } + warn_args_num (input_location, fndecl, /*too_many_p=*/false); return -1; } } @@ -3932,6 +3990,9 @@ cp_build_binary_op (location_t location, } result_type = type1; } + else if (null_ptr_cst_p (op0) && null_ptr_cst_p (op1)) + /* One of the operands must be of nullptr_t type. */ + result_type = TREE_TYPE (nullptr_node); else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) { result_type = type0; @@ -3958,8 +4019,7 @@ cp_build_binary_op (location_t location, tree e1 = cp_build_binary_op (location, EQ_EXPR, pfn0, - fold_convert (TREE_TYPE (pfn0), - integer_zero_node), + build_zero_cst (TREE_TYPE (pfn0)), complain); tree e2 = cp_build_binary_op (location, BIT_AND_EXPR, @@ -4049,8 +4109,7 @@ cp_build_binary_op (location_t location, complain); e2 = cp_build_binary_op (location, EQ_EXPR, pfn0, - fold_convert (TREE_TYPE (pfn0), - integer_zero_node), + build_zero_cst (TREE_TYPE (pfn0)), complain); e2 = cp_build_binary_op (location, TRUTH_ANDIF_EXPR, e2, e1, complain); @@ -4075,8 +4134,7 @@ cp_build_binary_op (location_t location, e2 = cp_build_binary_op (location, EQ_EXPR, pfn0, - fold_convert (TREE_TYPE (pfn0), - integer_zero_node), + build_zero_cst (TREE_TYPE (pfn0)), complain); e1 = cp_build_binary_op (location, TRUTH_ORIF_EXPR, e1, e2, complain); @@ -4123,18 +4181,21 @@ cp_build_binary_op (location_t location, } build_type = boolean_type_node; - if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE) - && (code1 == INTEGER_TYPE || code1 == REAL_TYPE)) + if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE + || code0 == ENUMERAL_TYPE) + && (code1 == INTEGER_TYPE || code1 == REAL_TYPE + || code1 == ENUMERAL_TYPE)) short_compare = 1; else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) result_type = composite_pointer_type (type0, type1, op0, op1, CPO_COMPARISON, complain); - else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST - && integer_zerop (op1)) + else if (code0 == POINTER_TYPE && null_ptr_cst_p (op1)) result_type = type0; - else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST - && integer_zerop (op0)) + else if (code1 == POINTER_TYPE && null_ptr_cst_p (op0)) result_type = type1; + else if (null_ptr_cst_p (op0) && null_ptr_cst_p (op1)) + /* One of the operands must be of nullptr_t type. */ + result_type = TREE_TYPE (nullptr_node); else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) { result_type = type0; @@ -4199,7 +4260,14 @@ cp_build_binary_op (location_t location, if (!result_type && arithmetic_types_p && (shorten || common || short_compare)) - result_type = cp_common_type (type0, type1); + { + result_type = cp_common_type (type0, type1); + do_warn_double_promotion (result_type, type0, type1, + "implicit conversion from %qT to %qT " + "to match other operand of binary " + "expression", + location); + } if (!result_type) { @@ -4226,7 +4294,83 @@ cp_build_binary_op (location_t location, if (arithmetic_types_p) { - int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE); + bool first_complex = (code0 == COMPLEX_TYPE); + bool second_complex = (code1 == COMPLEX_TYPE); + int none_complex = (!first_complex && !second_complex); + + /* Adapted from patch for c/24581. */ + if (first_complex != second_complex + && (code == PLUS_EXPR + || code == MINUS_EXPR + || code == MULT_EXPR + || (code == TRUNC_DIV_EXPR && first_complex)) + && TREE_CODE (TREE_TYPE (result_type)) == REAL_TYPE + && flag_signed_zeros) + { + /* An operation on mixed real/complex operands must be + handled specially, but the language-independent code can + more easily optimize the plain complex arithmetic if + -fno-signed-zeros. */ + tree real_type = TREE_TYPE (result_type); + tree real, imag; + if (first_complex) + { + if (TREE_TYPE (op0) != result_type) + op0 = cp_convert_and_check (result_type, op0); + if (TREE_TYPE (op1) != real_type) + op1 = cp_convert_and_check (real_type, op1); + } + else + { + if (TREE_TYPE (op0) != real_type) + op0 = cp_convert_and_check (real_type, op0); + if (TREE_TYPE (op1) != result_type) + op1 = cp_convert_and_check (result_type, op1); + } + if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK) + return error_mark_node; + if (first_complex) + { + op0 = save_expr (op0); + real = cp_build_unary_op (REALPART_EXPR, op0, 1, complain); + imag = cp_build_unary_op (IMAGPART_EXPR, op0, 1, complain); + switch (code) + { + case MULT_EXPR: + case TRUNC_DIV_EXPR: + imag = build2 (resultcode, real_type, imag, op1); + /* Fall through. */ + case PLUS_EXPR: + case MINUS_EXPR: + real = build2 (resultcode, real_type, real, op1); + break; + default: + gcc_unreachable(); + } + } + else + { + op1 = save_expr (op1); + real = cp_build_unary_op (REALPART_EXPR, op1, 1, complain); + imag = cp_build_unary_op (IMAGPART_EXPR, op1, 1, complain); + switch (code) + { + case MULT_EXPR: + imag = build2 (resultcode, real_type, op0, imag); + /* Fall through. */ + case PLUS_EXPR: + real = build2 (resultcode, real_type, op0, real); + break; + case MINUS_EXPR: + real = build2 (resultcode, real_type, op0, real); + imag = build1 (NEGATE_EXPR, real_type, imag); + break; + default: + gcc_unreachable(); + } + } + return build2 (COMPLEX_EXPR, result_type, real, imag); + } /* For certain operations (which identify themselves by shorten != 0) if both args were extended from the same smaller type, @@ -4465,9 +4609,8 @@ build_x_unary_op (enum tree_code code, tree xarg, tsubst_flags_t complain) PTRMEM_OK_P (xarg) = ptrmem; } } - else if (TREE_CODE (xarg) == TARGET_EXPR && (complain & tf_warning)) - warning (0, "taking address of temporary"); - exp = cp_build_unary_op (ADDR_EXPR, xarg, 0, complain); + + exp = cp_build_addr_expr_strict (xarg, complain); } if (processing_template_decl && exp != error_mark_node) @@ -4544,6 +4687,287 @@ build_nop (tree type, tree expr) return build1 (NOP_EXPR, type, expr); } +/* Take the address of ARG, whatever that means under C++ semantics. + If STRICT_LVALUE is true, require an lvalue; otherwise, allow xvalues + and class rvalues as well. + + Nothing should call this function directly; instead, callers should use + cp_build_addr_expr or cp_build_addr_expr_strict. */ + +static tree +cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain) +{ + tree argtype; + tree val; + + if (!arg || error_operand_p (arg)) + return error_mark_node; + + arg = mark_lvalue_use (arg); + argtype = lvalue_type (arg); + + gcc_assert (TREE_CODE (arg) != IDENTIFIER_NODE + || !IDENTIFIER_OPNAME_P (arg)); + + if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg) + && !really_overloaded_fn (TREE_OPERAND (arg, 1))) + { + /* They're trying to take the address of a unique non-static + member function. This is ill-formed (except in MS-land), + but let's try to DTRT. + Note: We only handle unique functions here because we don't + want to complain if there's a static overload; non-unique + cases will be handled by instantiate_type. But we need to + handle this case here to allow casts on the resulting PMF. + We could defer this in non-MS mode, but it's easier to give + a useful error here. */ + + /* Inside constant member functions, the `this' pointer + contains an extra const qualifier. TYPE_MAIN_VARIANT + is used here to remove this const from the diagnostics + and the created OFFSET_REF. */ + tree base = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg, 0))); + tree fn = get_first_fn (TREE_OPERAND (arg, 1)); + mark_used (fn); + + if (! flag_ms_extensions) + { + tree name = DECL_NAME (fn); + if (!(complain & tf_error)) + return error_mark_node; + else if (current_class_type + && TREE_OPERAND (arg, 0) == current_class_ref) + /* An expression like &memfn. */ + permerror (input_location, "ISO C++ forbids taking the address of an unqualified" + " or parenthesized non-static member function to form" + " a pointer to member function. Say %<&%T::%D%>", + base, name); + else + permerror (input_location, "ISO C++ forbids taking the address of a bound member" + " function to form a pointer to member function." + " Say %<&%T::%D%>", + base, name); + } + arg = build_offset_ref (base, fn, /*address_p=*/true); + } + + /* Uninstantiated types are all functions. Taking the + address of a function is a no-op, so just return the + argument. */ + if (type_unknown_p (arg)) + return build1 (ADDR_EXPR, unknown_type_node, arg); + + if (TREE_CODE (arg) == OFFSET_REF) + /* We want a pointer to member; bypass all the code for actually taking + the address of something. */ + goto offset_ref; + + /* Anything not already handled and not a true memory reference + is an error. */ + if (TREE_CODE (argtype) != FUNCTION_TYPE + && TREE_CODE (argtype) != METHOD_TYPE) + { + cp_lvalue_kind kind = lvalue_kind (arg); + if (kind == clk_none) + { + if (complain & tf_error) + lvalue_error (lv_addressof); + return error_mark_node; + } + if (strict_lvalue && (kind & (clk_rvalueref|clk_class))) + { + if (!(complain & tf_error)) + return error_mark_node; + if (kind & clk_class) + /* Make this a permerror because we used to accept it. */ + permerror (input_location, "taking address of temporary"); + else + error ("taking address of xvalue (rvalue reference)"); + } + } + + if (TREE_CODE (argtype) == REFERENCE_TYPE) + { + tree type = build_pointer_type (TREE_TYPE (argtype)); + arg = build1 (CONVERT_EXPR, type, arg); + return arg; + } + else if (pedantic && DECL_MAIN_P (arg)) + { + /* ARM $3.4 */ + /* Apparently a lot of autoconf scripts for C++ packages do this, + so only complain if -pedantic. */ + if (complain & (flag_pedantic_errors ? tf_error : tf_warning)) + pedwarn (input_location, OPT_pedantic, + "ISO C++ forbids taking address of function %<::main%>"); + else if (flag_pedantic_errors) + return error_mark_node; + } + + /* Let &* cancel out to simplify resulting code. */ + if (TREE_CODE (arg) == INDIRECT_REF) + { + /* We don't need to have `current_class_ptr' wrapped in a + NON_LVALUE_EXPR node. */ + if (arg == current_class_ref) + return current_class_ptr; + + arg = TREE_OPERAND (arg, 0); + if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE) + { + tree type = build_pointer_type (TREE_TYPE (TREE_TYPE (arg))); + arg = build1 (CONVERT_EXPR, type, arg); + } + else + /* Don't let this be an lvalue. */ + arg = rvalue (arg); + return arg; + } + + /* ??? Cope with user tricks that amount to offsetof. */ + if (TREE_CODE (argtype) != FUNCTION_TYPE + && TREE_CODE (argtype) != METHOD_TYPE + && argtype != unknown_type_node + && (val = get_base_address (arg)) + && COMPLETE_TYPE_P (TREE_TYPE (val)) + && TREE_CODE (val) == INDIRECT_REF + && TREE_CONSTANT (TREE_OPERAND (val, 0))) + { + tree type = build_pointer_type (argtype); + tree op0 = fold_convert (type, TREE_OPERAND (val, 0)); + tree op1 = fold_convert (sizetype, fold_offsetof (arg, val)); + return fold_build2 (POINTER_PLUS_EXPR, type, op0, op1); + } + + /* Handle complex lvalues (when permitted) + by reduction to simpler cases. */ + val = unary_complex_lvalue (ADDR_EXPR, arg); + if (val != 0) + return val; + + switch (TREE_CODE (arg)) + { + CASE_CONVERT: + case FLOAT_EXPR: + case FIX_TRUNC_EXPR: + /* Even if we're not being pedantic, we cannot allow this + extension when we're instantiating in a SFINAE + context. */ + if (! lvalue_p (arg) && complain == tf_none) + { + if (complain & tf_error) + permerror (input_location, "ISO C++ forbids taking the address of a cast to a non-lvalue expression"); + else + return error_mark_node; + } + break; + + case BASELINK: + arg = BASELINK_FUNCTIONS (arg); + /* Fall through. */ + + case OVERLOAD: + arg = OVL_CURRENT (arg); + break; + + case OFFSET_REF: + offset_ref: + /* Turn a reference to a non-static data member into a + pointer-to-member. */ + { + tree type; + tree t; + + gcc_assert (PTRMEM_OK_P (arg)); + + t = TREE_OPERAND (arg, 1); + if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE) + { + if (complain & tf_error) + error ("cannot create pointer to reference member %qD", t); + return error_mark_node; + } + + type = build_ptrmem_type (context_for_name_lookup (t), + TREE_TYPE (t)); + t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1)); + return t; + } + + default: + break; + } + + if (argtype != error_mark_node) + argtype = build_pointer_type (argtype); + + /* In a template, we are processing a non-dependent expression + so we can just form an ADDR_EXPR with the correct type. */ + if (processing_template_decl || TREE_CODE (arg) != COMPONENT_REF) + { + val = build_address (arg); + if (TREE_CODE (arg) == OFFSET_REF) + PTRMEM_OK_P (val) = PTRMEM_OK_P (arg); + } + else if (TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK) + { + tree fn = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1)); + + /* We can only get here with a single static member + function. */ + gcc_assert (TREE_CODE (fn) == FUNCTION_DECL + && DECL_STATIC_FUNCTION_P (fn)); + mark_used (fn); + val = build_address (fn); + if (TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0))) + /* Do not lose object's side effects. */ + val = build2 (COMPOUND_EXPR, TREE_TYPE (val), + TREE_OPERAND (arg, 0), val); + } + else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1))) + { + if (complain & tf_error) + error ("attempt to take address of bit-field structure member %qD", + TREE_OPERAND (arg, 1)); + return error_mark_node; + } + else + { + tree object = TREE_OPERAND (arg, 0); + tree field = TREE_OPERAND (arg, 1); + gcc_assert (same_type_ignoring_top_level_qualifiers_p + (TREE_TYPE (object), decl_type_context (field))); + val = build_address (arg); + } + + if (TREE_CODE (argtype) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE) + { + build_ptrmemfunc_type (argtype); + val = build_ptrmemfunc (argtype, val, 0, + /*c_cast_p=*/false, + tf_warning_or_error); + } + + return val; +} + +/* Take the address of ARG if it has one, even if it's an rvalue. */ + +tree +cp_build_addr_expr (tree arg, tsubst_flags_t complain) +{ + return cp_build_addr_expr_1 (arg, 0, complain); +} + +/* Take the address of ARG, but only if it's an lvalue. */ + +tree +cp_build_addr_expr_strict (tree arg, tsubst_flags_t complain) +{ + return cp_build_addr_expr_1 (arg, 1, complain); +} + /* C++: Must handle pointers to members. Perhaps type instantiation should be extended to handle conversion @@ -4564,7 +4988,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert, tree val; const char *invalid_op_diag; - if (error_operand_p (arg)) + if (!arg || error_operand_p (arg)) return error_mark_node; if ((invalid_op_diag @@ -4611,7 +5035,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert, arg = default_conversion (arg); } else if (!(arg = build_expr_type_conversion (WANT_INT | WANT_ENUM - | WANT_VECTOR, + | WANT_VECTOR_OR_COMPLEX, arg, true))) errstring = _("wrong type argument to bit-complement"); else if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) @@ -4646,26 +5070,12 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert, break; case REALPART_EXPR: - if (TREE_CODE (arg) == COMPLEX_CST) - return TREE_REALPART (arg); - else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) - { - arg = build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg); - return fold_if_not_in_template (arg); - } - else - return arg; - case IMAGPART_EXPR: - if (TREE_CODE (arg) == COMPLEX_CST) - return TREE_IMAGPART (arg); - else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) - { - arg = build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg); - return fold_if_not_in_template (arg); - } + arg = build_real_imag_expr (input_location, code, arg); + if (arg == error_mark_node) + return arg; else - return cp_convert (TREE_TYPE (arg), integer_zero_node); + return fold_if_not_in_template (arg); case PREINCREMENT_EXPR: case POSTINCREMENT_EXPR: @@ -4678,6 +5088,8 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert, if (val != 0) return val; + arg = mark_lvalue_use (arg); + /* Increment or decrement the real part of the value, and don't change the imaginary part. */ if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) @@ -4779,6 +5191,13 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert, inc = cp_convert (argtype, inc); + /* If 'arg' is an Objective-C PROPERTY_REF expression, then we + need to ask Objective-C to build the increment or decrement + expression for it. */ + if (objc_is_property_ref (arg)) + return objc_build_incr_expr_for_property_ref (input_location, code, + arg, inc); + /* Complain about anything else that is not a true lvalue. */ if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) @@ -4808,221 +5227,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert, case ADDR_EXPR: /* Note that this operation never does default_conversion regardless of NOCONVERT. */ - - argtype = lvalue_type (arg); - - if (TREE_CODE (arg) == OFFSET_REF) - goto offset_ref; - - if (TREE_CODE (argtype) == REFERENCE_TYPE) - { - tree type = build_pointer_type (TREE_TYPE (argtype)); - arg = build1 (CONVERT_EXPR, type, arg); - return arg; - } - else if (pedantic && DECL_MAIN_P (arg)) - { - /* ARM $3.4 */ - /* Apparently a lot of autoconf scripts for C++ packages do this, - so only complain if -pedantic. */ - if (complain & (flag_pedantic_errors ? tf_error : tf_warning)) - pedwarn (input_location, OPT_pedantic, - "ISO C++ forbids taking address of function %<::main%>"); - else if (flag_pedantic_errors) - return error_mark_node; - } - - /* Let &* cancel out to simplify resulting code. */ - if (TREE_CODE (arg) == INDIRECT_REF) - { - /* We don't need to have `current_class_ptr' wrapped in a - NON_LVALUE_EXPR node. */ - if (arg == current_class_ref) - return current_class_ptr; - - arg = TREE_OPERAND (arg, 0); - if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE) - { - tree type = build_pointer_type (TREE_TYPE (TREE_TYPE (arg))); - arg = build1 (CONVERT_EXPR, type, arg); - } - else - /* Don't let this be an lvalue. */ - arg = rvalue (arg); - return arg; - } - - /* Uninstantiated types are all functions. Taking the - address of a function is a no-op, so just return the - argument. */ - - gcc_assert (TREE_CODE (arg) != IDENTIFIER_NODE - || !IDENTIFIER_OPNAME_P (arg)); - - if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg) - && !really_overloaded_fn (TREE_OPERAND (arg, 1))) - { - /* They're trying to take the address of a unique non-static - member function. This is ill-formed (except in MS-land), - but let's try to DTRT. - Note: We only handle unique functions here because we don't - want to complain if there's a static overload; non-unique - cases will be handled by instantiate_type. But we need to - handle this case here to allow casts on the resulting PMF. - We could defer this in non-MS mode, but it's easier to give - a useful error here. */ - - /* Inside constant member functions, the `this' pointer - contains an extra const qualifier. TYPE_MAIN_VARIANT - is used here to remove this const from the diagnostics - and the created OFFSET_REF. */ - tree base = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg, 0))); - tree fn = get_first_fn (TREE_OPERAND (arg, 1)); - mark_used (fn); - - if (! flag_ms_extensions) - { - tree name = DECL_NAME (fn); - if (!(complain & tf_error)) - return error_mark_node; - else if (current_class_type - && TREE_OPERAND (arg, 0) == current_class_ref) - /* An expression like &memfn. */ - permerror (input_location, "ISO C++ forbids taking the address of an unqualified" - " or parenthesized non-static member function to form" - " a pointer to member function. Say %<&%T::%D%>", - base, name); - else - permerror (input_location, "ISO C++ forbids taking the address of a bound member" - " function to form a pointer to member function." - " Say %<&%T::%D%>", - base, name); - } - arg = build_offset_ref (base, fn, /*address_p=*/true); - } - - offset_ref: - if (type_unknown_p (arg)) - return build1 (ADDR_EXPR, unknown_type_node, arg); - - /* Handle complex lvalues (when permitted) - by reduction to simpler cases. */ - val = unary_complex_lvalue (code, arg); - if (val != 0) - return val; - - switch (TREE_CODE (arg)) - { - CASE_CONVERT: - case FLOAT_EXPR: - case FIX_TRUNC_EXPR: - /* Even if we're not being pedantic, we cannot allow this - extension when we're instantiating in a SFINAE - context. */ - if (! lvalue_p (arg) && complain == tf_none) - { - if (complain & tf_error) - permerror (input_location, "ISO C++ forbids taking the address of a cast to a non-lvalue expression"); - else - return error_mark_node; - } - break; - - case BASELINK: - arg = BASELINK_FUNCTIONS (arg); - /* Fall through. */ - - case OVERLOAD: - arg = OVL_CURRENT (arg); - break; - - case OFFSET_REF: - /* Turn a reference to a non-static data member into a - pointer-to-member. */ - { - tree type; - tree t; - - if (!PTRMEM_OK_P (arg)) - return cp_build_unary_op (code, arg, 0, complain); - - t = TREE_OPERAND (arg, 1); - if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE) - { - if (complain & tf_error) - error ("cannot create pointer to reference member %qD", t); - return error_mark_node; - } - - type = build_ptrmem_type (context_for_name_lookup (t), - TREE_TYPE (t)); - t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1)); - return t; - } - - default: - break; - } - - /* Anything not already handled and not a true memory reference - is an error. */ - if (TREE_CODE (argtype) != FUNCTION_TYPE - && TREE_CODE (argtype) != METHOD_TYPE - && TREE_CODE (arg) != OFFSET_REF - && !lvalue_or_else (arg, lv_addressof, complain)) - return error_mark_node; - - if (argtype != error_mark_node) - argtype = build_pointer_type (argtype); - - /* In a template, we are processing a non-dependent expression - so we can just form an ADDR_EXPR with the correct type. */ - if (processing_template_decl || TREE_CODE (arg) != COMPONENT_REF) - { - val = build_address (arg); - if (TREE_CODE (arg) == OFFSET_REF) - PTRMEM_OK_P (val) = PTRMEM_OK_P (arg); - } - else if (TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK) - { - tree fn = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1)); - - /* We can only get here with a single static member - function. */ - gcc_assert (TREE_CODE (fn) == FUNCTION_DECL - && DECL_STATIC_FUNCTION_P (fn)); - mark_used (fn); - val = build_address (fn); - if (TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0))) - /* Do not lose object's side effects. */ - val = build2 (COMPOUND_EXPR, TREE_TYPE (val), - TREE_OPERAND (arg, 0), val); - } - else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1))) - { - if (complain & tf_error) - error ("attempt to take address of bit-field structure member %qD", - TREE_OPERAND (arg, 1)); - return error_mark_node; - } - else - { - tree object = TREE_OPERAND (arg, 0); - tree field = TREE_OPERAND (arg, 1); - gcc_assert (same_type_ignoring_top_level_qualifiers_p - (TREE_TYPE (object), decl_type_context (field))); - val = build_address (arg); - } - - if (TREE_CODE (argtype) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE) - { - build_ptrmemfunc_type (argtype); - val = build_ptrmemfunc (argtype, val, 0, - /*c_cast_p=*/false); - } - - return val; + return cp_build_addr_expr (arg, complain); default: break; @@ -5253,18 +5458,36 @@ build_x_conditional_expr (tree ifexp, tree op1, tree op2, /* Given a list of expressions, return a compound expression that performs them all and returns the value of the last of them. */ -tree build_x_compound_expr_from_list (tree list, const char *msg) +tree +build_x_compound_expr_from_list (tree list, expr_list_kind exp, + tsubst_flags_t complain) { tree expr = TREE_VALUE (list); if (TREE_CHAIN (list)) { - if (msg) - permerror (input_location, "%s expression list treated as compound expression", msg); + if (complain & tf_error) + switch (exp) + { + case ELK_INIT: + permerror (input_location, "expression list treated as compound " + "expression in initializer"); + break; + case ELK_MEM_INIT: + permerror (input_location, "expression list treated as compound " + "expression in mem-initializer"); + break; + case ELK_FUNC_CAST: + permerror (input_location, "expression list treated as compound " + "expression in functional cast"); + break; + default: + gcc_unreachable (); + } for (list = TREE_CHAIN (list); list; list = TREE_CHAIN (list)) expr = build_x_compound_expr (expr, TREE_VALUE (list), - tf_warning_or_error); + complain); } return expr; @@ -5340,7 +5563,7 @@ build_compound_expr (location_t loc ATTRIBUTE_UNUSED, tree lhs, tree rhs) tree cp_build_compound_expr (tree lhs, tree rhs, tsubst_flags_t complain) { - lhs = convert_to_void (lhs, "left-hand operand of comma", complain); + lhs = convert_to_void (lhs, ICV_LEFT_OF_COMMA, complain); if (lhs == error_mark_node || rhs == error_mark_node) return error_mark_node; @@ -5418,7 +5641,7 @@ check_for_casting_away_constness (tree src_type, tree dest_type, tree convert_ptrmem (tree type, tree expr, bool allow_inverse_p, - bool c_cast_p) + bool c_cast_p, tsubst_flags_t complain) { if (TYPE_PTRMEM_P (type)) { @@ -5429,7 +5652,10 @@ convert_ptrmem (tree type, tree expr, bool allow_inverse_p, delta = get_delta_difference (TYPE_PTRMEM_CLASS_TYPE (TREE_TYPE (expr)), TYPE_PTRMEM_CLASS_TYPE (type), allow_inverse_p, - c_cast_p); + c_cast_p, complain); + if (delta == error_mark_node) + return error_mark_node; + if (!integer_zerop (delta)) { tree cond, op1, op2; @@ -5453,34 +5679,7 @@ convert_ptrmem (tree type, tree expr, bool allow_inverse_p, } else return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, - allow_inverse_p, c_cast_p); -} - -/* If EXPR is an INTEGER_CST and ORIG is an arithmetic constant, return - a version of EXPR that has TREE_OVERFLOW set if it is set in ORIG. - Otherwise, return EXPR unchanged. */ - -static tree -ignore_overflows (tree expr, tree orig) -{ - if (TREE_CODE (expr) == INTEGER_CST - && CONSTANT_CLASS_P (orig) - && TREE_CODE (orig) != STRING_CST - && TREE_OVERFLOW (expr) != TREE_OVERFLOW (orig)) - { - if (!TREE_OVERFLOW (orig)) - /* Ensure constant sharing. */ - expr = build_int_cst_wide (TREE_TYPE (expr), - TREE_INT_CST_LOW (expr), - TREE_INT_CST_HIGH (expr)); - else - { - /* Avoid clobbering a shared constant. */ - expr = copy_node (expr); - TREE_OVERFLOW (expr) = TREE_OVERFLOW (orig); - } - } - return expr; + allow_inverse_p, c_cast_p, complain); } /* Perform a static_cast from EXPR to TYPE. When C_CAST_P is true, @@ -5496,7 +5695,6 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, { tree intype; tree result; - tree orig; /* Assume the cast is valid. */ *valid_p = true; @@ -5553,8 +5751,14 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, expr = build_base_path (MINUS_EXPR, build_address (expr), base, /*nonnull=*/false); /* Convert the pointer to a reference -- but then remember that - there are no expressions with reference type in C++. */ - return convert_from_reference (cp_fold_convert (type, expr)); + there are no expressions with reference type in C++. + + We call rvalue so that there's an actual tree code + (NON_LVALUE_EXPR) for the static_cast; otherwise, if the operand + is a variable with the same type, the conversion would get folded + away, leaving just the variable and causing lvalue_kind to give + the wrong answer. */ + return convert_from_reference (rvalue (cp_fold_convert (type, expr))); } /* "An lvalue of type cv1 T1 can be cast to type rvalue reference to @@ -5569,8 +5773,6 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, return convert_from_reference (expr); } - orig = expr; - /* Resolve overloaded address here rather than once in implicit_conversion and again in the inverse code below. */ if (TYPE_PTRMEMFUNC_P (type) && type_unknown_p (expr)) @@ -5591,9 +5793,6 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, { result = convert_from_reference (result); - /* Ignore any integer overflow caused by the cast. */ - result = ignore_overflows (result, orig); - /* [expr.static.cast] If T is a reference type, the result is an lvalue; otherwise, @@ -5607,7 +5806,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, Any expression can be explicitly converted to type cv void. */ if (TREE_CODE (type) == VOID_TYPE) - return convert_to_void (expr, /*implicit=*/NULL, complain); + return convert_to_void (expr, ICV_CAST, complain); /* [expr.static.cast] @@ -5633,13 +5832,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, || SCALAR_FLOAT_TYPE_P (type)) && (INTEGRAL_OR_ENUMERATION_TYPE_P (intype) || SCALAR_FLOAT_TYPE_P (intype))) - { - expr = ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL); - - /* Ignore any integer overflow caused by the cast. */ - expr = ignore_overflows (expr, orig); - return expr; - } + return ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL); if (TYPE_PTR_P (type) && TYPE_PTR_P (intype) && CLASS_TYPE_P (TREE_TYPE (type)) @@ -5656,7 +5849,8 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype), c_cast_p ? ba_unique : ba_check, NULL); - return build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false); + expr = build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false); + return cp_fold_convert(type, expr); } if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype)) @@ -5689,7 +5883,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, if (!c_cast_p) check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR); return convert_ptrmem (type, expr, /*allow_inverse_p=*/1, - c_cast_p); + c_cast_p, tf_warning_or_error); } } @@ -5832,7 +6026,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, warning (0, "casting %qT to %qT does not dereference pointer", intype, type); - expr = cp_build_unary_op (ADDR_EXPR, expr, 0, complain); + expr = cp_build_addr_expr (expr, complain); if (warn_strict_aliasing > 2) strict_aliasing_warning (TREE_TYPE (expr), type, expr); @@ -5877,8 +6071,11 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, /* [expr.reinterpret.cast] A pointer can be converted to any integral type large enough to - hold it. */ - if (CP_INTEGRAL_TYPE_P (type) && TYPE_PTR_P (intype)) + hold it. ... A value of type std::nullptr_t can be converted to + an integral type; the conversion has the same meaning and + validity as a conversion of (void*)0 to the integral type. */ + if (CP_INTEGRAL_TYPE_P (type) + && (TYPE_PTR_P (intype) || NULLPTR_TYPE_P (intype))) { if (TYPE_PRECISION (type) < TYPE_PRECISION (intype)) { @@ -5888,6 +6085,8 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, else return error_mark_node; } + if (NULLPTR_TYPE_P (intype)) + return build_int_cst (type, 0); } /* [expr.reinterpret.cast] A value of integral or enumeration type can be explicitly @@ -6065,8 +6264,8 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain, } if (reference_type) { - expr = cp_build_unary_op (ADDR_EXPR, expr, 0, - complain? tf_warning_or_error : tf_none); + expr = cp_build_addr_expr (expr, + complain ? tf_warning_or_error : tf_none); expr = build_nop (reference_type, expr); return convert_from_reference (expr); } @@ -6182,6 +6381,15 @@ cp_build_c_cast (tree type, tree expr, tsubst_flags_t complain) return error_mark_node; } + if (TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE + /* Casting to an integer of smaller size is an error detected elsewhere. */ + && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (value)) + /* Don't warn about converting any constant. */ + && !TREE_CONSTANT (value)) + warning_at (input_location, OPT_Wint_to_pointer_cast, + "cast to pointer from integer of different size"); + /* A C-style cast can be a const_cast. */ result = build_const_cast_1 (type, value, /*complain=*/false, &valid_p); @@ -6387,12 +6595,19 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, } else { - lhs = require_complete_type (lhs); + lhs = require_complete_type_sfinae (lhs, complain); if (lhs == error_mark_node) return error_mark_node; if (modifycode == NOP_EXPR) { + if (c_dialect_objc ()) + { + result = objc_maybe_build_modify_expr (lhs, rhs); + if (result) + return result; + } + /* `operator=' is not an inheritable operator. */ if (! MAYBE_CLASS_TYPE_P (lhstype)) /* Do the default thing. */; @@ -6431,6 +6646,12 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, /* Now it looks like a plain assignment. */ modifycode = NOP_EXPR; + if (c_dialect_objc ()) + { + result = objc_maybe_build_modify_expr (lhs, newrhs); + if (result) + return result; + } } gcc_assert (TREE_CODE (lhstype) != REFERENCE_TYPE); gcc_assert (TREE_CODE (TREE_TYPE (newrhs)) != REFERENCE_TYPE); @@ -6473,6 +6694,12 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, if (BRACE_ENCLOSED_INITIALIZER_P (newrhs)) { + if (modifycode != INIT_EXPR) + { + if (complain & tf_error) + error ("assigning to an array from an initializer list"); + return error_mark_node; + } if (check_array_initializer (lhs, lhstype, newrhs)) return error_mark_node; newrhs = digest_init (lhstype, newrhs); @@ -6514,10 +6741,10 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, /* Calls with INIT_EXPR are all direct-initialization, so don't set LOOKUP_ONLYCONVERTING. */ newrhs = convert_for_initialization (lhs, olhstype, newrhs, LOOKUP_NORMAL, - "initialization", NULL_TREE, 0, + ICR_INIT, NULL_TREE, 0, complain); else - newrhs = convert_for_assignment (olhstype, newrhs, "assignment", + newrhs = convert_for_assignment (olhstype, newrhs, ICR_ASSIGN, NULL_TREE, 0, complain, LOOKUP_IMPLICIT); if (!same_type_p (lhstype, olhstype)) @@ -6584,20 +6811,32 @@ build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, /* 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, + of FROM to pointer-to-member of TO. If the conversion is invalid and + tf_error is not set in COMPLAIN returns error_mark_node, otherwise 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. */ + 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) +get_delta_difference_1 (tree from, tree to, bool c_cast_p, + tsubst_flags_t complain) { tree binfo; base_kind kind; + base_access access = c_cast_p ? ba_unique : ba_check; + + /* Note: ba_quiet does not distinguish between access control and + ambiguity. */ + if (!(complain & tf_error)) + access |= ba_quiet; + + binfo = lookup_base (to, from, access, &kind); - binfo = lookup_base (to, from, c_cast_p ? ba_unique : ba_check, &kind); if (kind == bk_inaccessible || kind == bk_ambig) { + if (!(complain & tf_error)) + return error_mark_node; + error (" in pointer to member function conversion"); return size_zero_node; } @@ -6609,22 +6848,26 @@ get_delta_difference_1 (tree from, tree to, bool c_cast_p) /* FROM is a virtual base class of TO. Issue an error or warning depending on whether or not this is a reinterpret cast. */ { + if (!(complain & tf_error)) + return error_mark_node; + error ("pointer to member conversion via virtual base %qT", BINFO_TYPE (binfo_from_vbase (binfo))); return size_zero_node; } } - else - return NULL_TREE; + 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 - ALLOW_INVERSE_P is true, then allow reverse conversions as well. - If C_CAST_P is true this conversion is taking place as part of a - C-style cast. + types. If the conversion is invalid and tf_error is not set in + COMPLAIN, returns error_mark_node, otherwise returns an integer + constant of type PTRDIFF_TYPE_NODE and its value is zero if the + conversion is invalid. If ALLOW_INVERSE_P is true, then allow reverse + conversions as well. If C_CAST_P is true this conversion is taking + place as part of a C-style cast. Note that the naming of FROM and TO is kind of backwards; the return value is what we add to a TO in order to get a FROM. They are named @@ -6634,7 +6877,7 @@ get_delta_difference_1 (tree from, tree to, bool c_cast_p) static tree get_delta_difference (tree from, tree to, bool allow_inverse_p, - bool c_cast_p) + bool c_cast_p, tsubst_flags_t complain) { tree result; @@ -6642,25 +6885,37 @@ get_delta_difference (tree from, tree to, /* Pointer to member of incomplete class is permitted*/ result = size_zero_node; else - result = get_delta_difference_1 (from, to, c_cast_p); + result = get_delta_difference_1 (from, to, c_cast_p, complain); + + if (result == error_mark_node) + return error_mark_node; if (!result) { if (!allow_inverse_p) { + if (!(complain & tf_error)) + return error_mark_node; + error_not_base_type (from, to); error (" in pointer to member conversion"); - result = size_zero_node; + result = size_zero_node; } else { - result = get_delta_difference_1 (to, from, c_cast_p); + result = get_delta_difference_1 (to, from, c_cast_p, complain); + + if (result == error_mark_node) + return error_mark_node; if (result) result = size_diffop_loc (input_location, - size_zero_node, result); + size_zero_node, result); else { + if (!(complain & tf_error)) + return error_mark_node; + error_not_base_type (from, to); error (" in pointer to member conversion"); result = size_zero_node; @@ -6685,7 +6940,7 @@ build_ptrmemfunc1 (tree type, tree delta, tree pfn) /* Pull the FIELD_DECLs out of the type. */ pfn_field = TYPE_FIELDS (type); - delta_field = TREE_CHAIN (pfn_field); + delta_field = DECL_CHAIN (pfn_field); /* Make sure DELTA has the type we want. */ delta = convert_and_check (delta_type_node, delta); @@ -6719,7 +6974,8 @@ build_ptrmemfunc1 (tree type, tree delta, tree pfn) Return error_mark_node, if something goes wrong. */ tree -build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p) +build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p, + tsubst_flags_t complain) { tree fn; tree pfn_type; @@ -6746,7 +7002,9 @@ build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p) n = get_delta_difference (TYPE_PTRMEMFUNC_OBJECT_TYPE (pfn_type), TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type), force, - c_cast_p); + c_cast_p, complain); + if (n == error_mark_node) + return error_mark_node; /* We don't have to do any conversion to convert a pointer-to-member to its own type. But, we don't want to @@ -6786,7 +7044,7 @@ build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p) } /* Handle null pointer to member function conversions. */ - if (integer_zerop (pfn)) + if (null_ptr_cst_p (pfn)) { pfn = build_c_cast (input_location, type, integer_zero_node); return build_ptrmemfunc1 (to_type, @@ -6829,7 +7087,7 @@ expand_ptrmemfunc_cst (tree cst, tree *delta, tree *pfn) /* First, calculate the adjustment to the function's class. */ *delta = get_delta_difference (fn_class, ptr_class, /*force=*/0, - /*c_cast_p=*/0); + /*c_cast_p=*/0, tf_warning_or_error); if (!DECL_VIRTUAL_P (fn)) *pfn = convert (TYPE_PTRMEMFUNC_FN_TYPE (type), build_addr_func (fn)); @@ -6917,14 +7175,15 @@ delta_from_ptrmemfunc (tree t) } /* 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 - are doing the conversion in order to pass the PARMNUMth argument of - FNDECL. */ + an lvalue of type TYPE. ERRTYPE indicates what kind of error the + implicit conversion is. If FNDECL is non-NULL, we are doing the + conversion in order to pass the PARMNUMth argument of FNDECL. + If FNDECL is NULL, we are doing the conversion in function pointer + argument passing, conversion in initialization, etc. */ static tree convert_for_assignment (tree type, tree rhs, - const char *errtype, tree fndecl, int parmnum, + impl_conv_rhs errtype, tree fndecl, int parmnum, tsubst_flags_t complain, int flags) { tree rhstype; @@ -6939,7 +7198,10 @@ convert_for_assignment (tree type, tree rhs, if (TREE_CODE (type) == VECTOR_TYPE && coder == VECTOR_TYPE && vector_types_convertible_p (type, rhstype, true)) - return convert (type, rhs); + { + rhs = mark_rvalue_use (rhs); + return convert (type, rhs); + } if (rhs == error_mark_node || rhstype == error_mark_node) return error_mark_node; @@ -6961,27 +7223,32 @@ convert_for_assignment (tree type, tree rhs, if (c_dialect_objc ()) { int parmno; + tree selector; tree rname = fndecl; - if (!strcmp (errtype, "assignment")) - parmno = -1; - else if (!strcmp (errtype, "initialization")) - parmno = -2; - else - { - tree selector = objc_message_selector (); - - parmno = parmnum; - - if (selector && parmno > 1) - { - rname = selector; - parmno -= 1; - } + switch (errtype) + { + case ICR_ASSIGN: + parmno = -1; + break; + case ICR_INIT: + parmno = -2; + break; + default: + selector = objc_message_selector (); + parmno = parmnum; + if (selector && parmno > 1) + { + rname = selector; + parmno -= 1; + } } if (objc_compare_types (type, rhstype, parmno, rname)) - return convert (type, rhs); + { + rhs = mark_rvalue_use (rhs); + return convert (type, rhs); + } } /* [expr.ass] @@ -7014,8 +7281,35 @@ convert_for_assignment (tree type, tree rhs, error ("cannot convert %qT to %qT for argument %qP to %qD", rhstype, type, parmnum, fndecl); else - error ("cannot convert %qT to %qT in %s", rhstype, type, - errtype); + switch (errtype) + { + case ICR_DEFAULT_ARGUMENT: + error ("cannot convert %qT to %qT in default argument", + rhstype, type); + break; + case ICR_ARGPASS: + error ("cannot convert %qT to %qT in argument passing", + rhstype, type); + break; + case ICR_CONVERTING: + error ("cannot convert %qT to %qT", + rhstype, type); + break; + case ICR_INIT: + error ("cannot convert %qT to %qT in initialization", + rhstype, type); + break; + case ICR_RETURN: + error ("cannot convert %qT to %qT in return", + rhstype, type); + break; + case ICR_ASSIGN: + error ("cannot convert %qT to %qT in assignment", + rhstype, type); + break; + default: + gcc_unreachable(); + } } return error_mark_node; } @@ -7027,9 +7321,42 @@ convert_for_assignment (tree type, tree rhs, && coder == codel && check_missing_format_attribute (type, rhstype) && (complain & tf_warning)) - warning (OPT_Wmissing_format_attribute, - "%s might be a candidate for a format attribute", - errtype); + switch (errtype) + { + case ICR_ARGPASS: + case ICR_DEFAULT_ARGUMENT: + if (fndecl) + warning (OPT_Wmissing_format_attribute, + "parameter %qP of %qD might be a candidate " + "for a format attribute", parmnum, fndecl); + else + warning (OPT_Wmissing_format_attribute, + "parameter might be a candidate " + "for a format attribute"); + break; + case ICR_CONVERTING: + warning (OPT_Wmissing_format_attribute, + "target of conversion might be might be a candidate " + "for a format attribute"); + break; + case ICR_INIT: + warning (OPT_Wmissing_format_attribute, + "target of initialization might be a candidate " + "for a format attribute"); + break; + case ICR_RETURN: + warning (OPT_Wmissing_format_attribute, + "return type might be a candidate " + "for a format attribute"); + break; + case ICR_ASSIGN: + warning (OPT_Wmissing_format_attribute, + "left-hand side of assignment might be a candidate " + "for a format attribute"); + break; + default: + gcc_unreachable(); + } } /* If -Wparentheses, warn about a = b = c when a has type bool and b @@ -7041,8 +7368,7 @@ convert_for_assignment (tree type, tree rhs, && TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE && (complain & tf_warning)) { - location_t loc = EXPR_HAS_LOCATION (rhs) - ? EXPR_LOCATION (rhs) : input_location; + location_t loc = EXPR_LOC_OR_HERE (rhs); warning_at (loc, OPT_Wparentheses, "suggest parentheses around assignment used as truth value"); @@ -7055,7 +7381,7 @@ convert_for_assignment (tree type, tree rhs, /* Convert RHS to be of type TYPE. If EXP is nonzero, it is the target of the initialization. - ERRTYPE is a string to use in error messages. + ERRTYPE indicates what kind of error the implicit conversion is. Two major differences between the behavior of `convert_for_assignment' and `convert_for_initialization' @@ -7071,7 +7397,7 @@ convert_for_assignment (tree type, tree rhs, tree convert_for_initialization (tree exp, tree type, tree rhs, int flags, - const char *errtype, tree fndecl, int parmnum, + impl_conv_rhs errtype, tree fndecl, int parmnum, tsubst_flags_t complain) { enum tree_code codel = TREE_CODE (type); @@ -7129,7 +7455,7 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags, } if (exp != 0) - exp = require_complete_type (exp); + exp = require_complete_type_sfinae (exp, complain); if (exp == error_mark_node) return error_mark_node; @@ -7453,7 +7779,7 @@ check_return_expr (tree retval, bool *no_warning) 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) + && !CP_TYPE_VOLATILE_P (TREE_TYPE (retval)) /* The return type must be a class type. */ && CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))) flags = flags | LOOKUP_PREFER_RVALUE; @@ -7462,7 +7788,7 @@ check_return_expr (tree retval, bool *no_warning) 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, flags, "return", NULL_TREE, 0, + (NULL_TREE, functype, retval, flags, ICR_RETURN, NULL_TREE, 0, tf_warning_or_error); retval = convert (valtype, retval); @@ -7515,15 +7841,10 @@ comp_ptr_ttypes_real (tree to, tree from, int constp) so the usual checks are not appropriate. */ if (TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE) { - /* In Objective-C++, some types may have been 'volatilized' by - the compiler for EH; when comparing them here, the volatile - qualification must be ignored. */ - bool objc_quals_match = objc_type_quals_match (to, from); - - if (!at_least_as_qualified_p (to, from) && !objc_quals_match) + if (!at_least_as_qualified_p (to, from)) return 0; - if (!at_least_as_qualified_p (from, to) && !objc_quals_match) + if (!at_least_as_qualified_p (from, to)) { if (constp == 0) return 0; @@ -7667,24 +7988,50 @@ comp_ptr_ttypes_const (tree to, tree from) int cp_type_quals (const_tree type) { + int quals; /* This CONST_CAST is okay because strip_array_types returns its argument unmodified and we assign it to a const_tree. */ - type = strip_array_types (CONST_CAST_TREE(type)); - if (type == error_mark_node) + type = strip_array_types (CONST_CAST_TREE (type)); + if (type == error_mark_node + /* Quals on a FUNCTION_TYPE are memfn quals. */ + || TREE_CODE (type) == FUNCTION_TYPE) return TYPE_UNQUALIFIED; - return TYPE_QUALS (type); + quals = TYPE_QUALS (type); + /* METHOD and REFERENCE_TYPEs should never have quals. */ + gcc_assert ((TREE_CODE (type) != METHOD_TYPE + && TREE_CODE (type) != REFERENCE_TYPE) + || ((quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE)) + == TYPE_UNQUALIFIED)); + return quals; } -/* Returns nonzero if the TYPE is const from a C++ perspective: look inside - arrays. */ +/* Returns the function-cv-quals for TYPE, which must be a FUNCTION_TYPE or + METHOD_TYPE. */ -bool -cp_type_readonly (const_tree type) +int +type_memfn_quals (const_tree type) { - /* This CONST_CAST is okay because strip_array_types returns its - argument unmodified and we assign it to a const_tree. */ - type = strip_array_types (CONST_CAST_TREE(type)); - return TYPE_READONLY (type); + if (TREE_CODE (type) == FUNCTION_TYPE) + return TYPE_QUALS (type); + else if (TREE_CODE (type) == METHOD_TYPE) + return cp_type_quals (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type)))); + else + gcc_unreachable (); +} + +/* Returns the FUNCTION_TYPE TYPE with its function-cv-quals changed to + MEMFN_QUALS. */ + +tree +apply_memfn_quals (tree type, cp_cv_quals memfn_quals) +{ + /* Could handle METHOD_TYPE here if necessary. */ + gcc_assert (TREE_CODE (type) == FUNCTION_TYPE); + if (TYPE_QUALS (type) == memfn_quals) + return type; + /* This should really have a different TYPE_MAIN_VARIANT, but that gets + complex. */ + return build_qualified_type (type, memfn_quals); } /* Returns nonzero if TYPE is const or volatile. */ @@ -7731,23 +8078,8 @@ cp_apply_type_quals_to_decl (int type_quals, tree decl) if (TREE_CODE (decl) == TYPE_DECL) return; - if (TREE_CODE (type) == FUNCTION_TYPE - && type_quals != TYPE_UNQUALIFIED) - { - /* This was an error in C++98 (cv-qualifiers cannot be added to - a function type), but DR 295 makes the code well-formed by - dropping the extra qualifiers. */ - if (pedantic) - { - tree bad_type = build_qualified_type (type, type_quals); - pedwarn (input_location, OPT_pedantic, - "ignoring %qV qualifiers added to function type %qT", - bad_type, type); - } - - TREE_TYPE (decl) = TYPE_MAIN_VARIANT (type); - return; - } + gcc_assert (!(TREE_CODE (type) == FUNCTION_TYPE + && type_quals != TYPE_UNQUALIFIED)); /* Avoid setting TREE_READONLY incorrectly. */ if (/* If the object has a constructor, the constructor may modify @@ -7897,10 +8229,24 @@ non_reference (tree t) int lvalue_or_else (tree ref, enum lvalue_use use, tsubst_flags_t complain) { - int win = lvalue_p (ref); - - if (!win && (complain & tf_error)) - lvalue_error (use); + cp_lvalue_kind kind = lvalue_kind (ref); - return win; + if (kind == clk_none) + { + if (complain & tf_error) + lvalue_error (use); + return 0; + } + else if (kind & (clk_rvalueref|clk_class)) + { + if (!(complain & tf_error)) + return 0; + if (kind & clk_class) + /* Make this a permerror because we used to accept it. */ + permerror (input_location, "using temporary as lvalue"); + else + error ("using xvalue (rvalue reference) as lvalue"); + } + return 1; } +