X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gcc%2Fcp%2Ftree.c;h=620e2c2699cb3a6de9de2b9dbcedfcc5783c06e4;hb=4f75f97bf61a610f21023b731159489e6d23f0fe;hp=c60d54ab01fb498d1b030a0f2fd5a51db01c3598;hpb=04757a2a49bd21c71af386a64591f77c165a0d93;p=gcc.git diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index c60d54ab01f..620e2c2699c 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1,5 +1,5 @@ /* Language-dependent node constructors for parse phase of GNU compiler. - Copyright (C) 1987-2017 Free Software Foundation, Inc. + Copyright (C) 1987-2019 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. @@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see #include "stringpool.h" #include "attribs.h" #include "flags.h" +#include "selftest.h" static tree bot_manip (tree *, int *, void *); static tree bot_replace (tree *, int *, void *); @@ -42,7 +43,6 @@ static hashval_t list_hash_pieces (tree, tree, tree); static tree build_target_expr (tree, tree, tsubst_flags_t); static tree count_trees_r (tree *, int *, void *); static tree verify_stmt_tree_r (tree *, int *, void *); -static tree build_local_temp (tree); static tree handle_init_priority_attribute (tree *, tree, tree, int, bool *); static tree handle_abi_tag_attribute (tree *, tree, tree, int, bool *); @@ -64,7 +64,7 @@ lvalue_kind (const_tree ref) return lvalue_kind (TREE_OPERAND (ref, 0)); if (TREE_TYPE (ref) - && TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE) + && TYPE_REF_P (TREE_TYPE (ref))) { /* unnamed rvalue references are rvalues */ if (TYPE_REF_IS_RVALUE (TREE_TYPE (ref)) @@ -82,10 +82,15 @@ lvalue_kind (const_tree ref) if (ref == current_class_ptr) return clk_none; + /* Expressions with cv void type are prvalues. */ + if (TREE_TYPE (ref) && VOID_TYPE_P (TREE_TYPE (ref))) + return clk_none; + switch (TREE_CODE (ref)) { case SAVE_EXPR: return clk_none; + /* preincrements and predecrements are valid lvals, provided what they refer to are valid lvals. */ case PREINCREMENT_EXPR: @@ -93,8 +98,25 @@ lvalue_kind (const_tree ref) case TRY_CATCH_EXPR: case REALPART_EXPR: case IMAGPART_EXPR: + case VIEW_CONVERT_EXPR: return lvalue_kind (TREE_OPERAND (ref, 0)); + case ARRAY_REF: + { + tree op1 = TREE_OPERAND (ref, 0); + if (TREE_CODE (TREE_TYPE (op1)) == ARRAY_TYPE) + { + op1_lvalue_kind = lvalue_kind (op1); + if (op1_lvalue_kind == clk_class) + /* in the case of an array operand, the result is an lvalue if + that operand is an lvalue and an xvalue otherwise */ + op1_lvalue_kind = clk_rvalueref; + return op1_lvalue_kind; + } + else + return clk_ordinary; + } + case MEMBER_REF: case DOTSTAR_EXPR: if (TREE_CODE (ref) == MEMBER_REF) @@ -103,6 +125,11 @@ lvalue_kind (const_tree ref) op1_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 0)); if (TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (ref, 1)))) op1_lvalue_kind = clk_none; + else if (op1_lvalue_kind == clk_class) + /* The result of a .* expression whose second operand is a pointer to a + data member is an lvalue if the first operand is an lvalue and an + xvalue otherwise. */ + op1_lvalue_kind = clk_rvalueref; return op1_lvalue_kind; case COMPONENT_REF: @@ -118,6 +145,11 @@ lvalue_kind (const_tree ref) return lvalue_kind (TREE_OPERAND (ref, 1)); } op1_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 0)); + if (op1_lvalue_kind == clk_class) + /* If E1 is an lvalue, then E1.E2 is an lvalue; + otherwise E1.E2 is an xvalue. */ + op1_lvalue_kind = clk_rvalueref; + /* Look at the member designator. */ if (!op1_lvalue_kind) ; @@ -164,8 +196,6 @@ lvalue_kind (const_tree ref) /* FALLTHRU */ case INDIRECT_REF: case ARROW_EXPR: - case ARRAY_REF: - case ARRAY_NOTATION_REF: case PARM_DECL: case RESULT_DECL: case PLACEHOLDER_EXPR: @@ -194,10 +224,34 @@ lvalue_kind (const_tree ref) break; case COND_EXPR: - op1_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 1) - ? TREE_OPERAND (ref, 1) - : TREE_OPERAND (ref, 0)); - op2_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 2)); + if (processing_template_decl) + { + /* Within templates, a REFERENCE_TYPE will indicate whether + the COND_EXPR result is an ordinary lvalue or rvalueref. + Since REFERENCE_TYPEs are handled above, if we reach this + point, we know we got a plain rvalue. Unless we have a + type-dependent expr, that is, but we shouldn't be testing + lvalueness if we can't even tell the types yet! */ + gcc_assert (!type_dependent_expression_p (CONST_CAST_TREE (ref))); + goto default_; + } + { + tree op1 = TREE_OPERAND (ref, 1); + if (!op1) op1 = TREE_OPERAND (ref, 0); + tree op2 = TREE_OPERAND (ref, 2); + op1_lvalue_kind = lvalue_kind (op1); + op2_lvalue_kind = lvalue_kind (op2); + if (!op1_lvalue_kind != !op2_lvalue_kind) + { + /* The second or the third operand (but not both) is a + throw-expression; the result is of the type + and value category of the other. */ + if (op1_lvalue_kind && TREE_CODE (op2) == THROW_EXPR) + op2_lvalue_kind = op1_lvalue_kind; + else if (op2_lvalue_kind && TREE_CODE (op1) == THROW_EXPR) + op1_lvalue_kind = op2_lvalue_kind; + } + } break; case MODOP_EXPR: @@ -239,15 +293,23 @@ lvalue_kind (const_tree ref) return lvalue_kind (BASELINK_FUNCTIONS (CONST_CAST_TREE (ref))); case NON_DEPENDENT_EXPR: + case PAREN_EXPR: return lvalue_kind (TREE_OPERAND (ref, 0)); + case TEMPLATE_PARM_INDEX: + if (CLASS_TYPE_P (TREE_TYPE (ref))) + /* A template parameter object is an lvalue. */ + return clk_ordinary; + return clk_none; + default: + default_: if (!TREE_TYPE (ref)) return clk_none; if (CLASS_TYPE_P (TREE_TYPE (ref)) || TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE) return clk_class; - break; + return clk_none; } /* If one operand is not an lvalue at all, then this expression is @@ -331,6 +393,7 @@ bitfield_p (const_tree ref) tree cp_stabilize_reference (tree ref) { + STRIP_ANY_LOCATION_WRAPPER (ref); switch (TREE_CODE (ref)) { case NON_DEPENDENT_EXPR: @@ -375,10 +438,18 @@ cp_stabilize_reference (tree ref) bool builtin_valid_in_constant_expr_p (const_tree decl) { - if (!(TREE_CODE (decl) == FUNCTION_DECL - && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)) - /* Not a built-in. */ + STRIP_ANY_LOCATION_WRAPPER (decl); + if (TREE_CODE (decl) != FUNCTION_DECL) + /* Not a function. */ return false; + if (DECL_BUILT_IN_CLASS (decl) != BUILT_IN_NORMAL) + { + if (fndecl_built_in_p (decl, CP_BUILT_IN_IS_CONSTANT_EVALUATED, + BUILT_IN_FRONTEND)) + return true; + /* Not a built-in. */ + return false; + } switch (DECL_FUNCTION_CODE (decl)) { /* These always have constant results like the corresponding @@ -421,6 +492,14 @@ build_target_expr (tree decl, tree value, tsubst_flags_t complain) || useless_type_conversion_p (TREE_TYPE (decl), TREE_TYPE (value))); + /* Set TREE_READONLY for optimization, such as gimplify_init_constructor + moving a constant aggregate into .rodata. */ + if (CP_TYPE_CONST_NON_VOLATILE_P (type) + && !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type) + && !VOID_TYPE_P (TREE_TYPE (value)) + && reduced_constant_expression_p (value)) + TREE_READONLY (decl) = true; + if (complain & tf_no_cleanup) /* The caller is building a new-expr and does not need a cleanup. */ t = NULL_TREE; @@ -431,8 +510,8 @@ build_target_expr (tree decl, tree value, tsubst_flags_t complain) return error_mark_node; } t = build4 (TARGET_EXPR, type, decl, value, t, NULL_TREE); - if (EXPR_HAS_LOCATION (value)) - SET_EXPR_LOCATION (t, EXPR_LOCATION (value)); + if (location_t eloc = cp_expr_location (value)) + SET_EXPR_LOCATION (t, eloc); /* We always set TREE_SIDE_EFFECTS so that expand_expr does not ignore the TARGET_EXPR. If there really turn out to be no side-effects, then the optimizer should be able to get rid of @@ -445,7 +524,7 @@ build_target_expr (tree decl, tree value, tsubst_flags_t complain) /* Return an undeclared local temporary of type TYPE for use in building a TARGET_EXPR. */ -static tree +tree build_local_temp (tree type) { tree slot = build_decl (input_location, @@ -521,6 +600,8 @@ build_aggr_init_expr (tree type, tree init) tree rval; int is_ctor; + gcc_assert (!VOID_TYPE_P (type)); + /* Don't build AGGR_INIT_EXPR in a template. */ if (processing_template_decl) return init; @@ -588,9 +669,21 @@ build_aggr_init_expr (tree type, tree init) tree build_cplus_new (tree type, tree init, tsubst_flags_t complain) { + /* This function should cope with what build_special_member_call + can produce. When performing parenthesized aggregate initialization, + it can produce a { }. */ + if (BRACE_ENCLOSED_INITIALIZER_P (init)) + { + gcc_assert (cxx_dialect >= cxx2a); + return finish_compound_literal (type, init, complain); + } + tree rval = build_aggr_init_expr (type, init); tree slot; + if (init == error_mark_node) + return error_mark_node; + if (!complete_type_or_maybe_complain (type, init, complain)) return error_mark_node; @@ -630,7 +723,6 @@ static tree build_vec_init_elt (tree type, tree init, tsubst_flags_t complain) { tree inner_type = strip_array_types (type); - vec *argvec; if (integer_zerop (array_type_nelts_total (type)) || !CLASS_TYPE_P (inner_type)) @@ -643,7 +735,7 @@ build_vec_init_elt (tree type, tree init, tsubst_flags_t complain) || (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (init)))); - argvec = make_tree_vector (); + releasing_vec argvec; if (init) { tree init_type = strip_array_types (TREE_TYPE (init)); @@ -655,7 +747,6 @@ build_vec_init_elt (tree type, tree init, tsubst_flags_t complain) init = build_special_member_call (NULL_TREE, complete_ctor_identifier, &argvec, inner_type, LOOKUP_NORMAL, complain); - release_tree_vector (argvec); /* For a trivial constructor, build_over_call creates a TARGET_EXPR. But we don't want one here because we aren't creating a temporary. */ @@ -1030,14 +1121,18 @@ build_array_of_n_type (tree elt, int n) return build_cplus_array_type (elt, build_index_type (size_int (n - 1))); } -/* True iff T is an N3639 array of runtime bound (VLA). These were - approved for C++14 but then removed. */ +/* True iff T is an N3639 array of runtime bound (VLA). These were approved + for C++14 but then removed. This should only be used for N3639 + specifically; code wondering more generally if something is a VLA should use + vla_type_p. */ bool array_of_runtime_bound_p (tree t) { if (!t || TREE_CODE (t) != ARRAY_TYPE) return false; + if (variably_modified_type_p (TREE_TYPE (t), NULL_TREE)) + return false; tree dom = TYPE_DOMAIN (t); if (!dom) return false; @@ -1046,6 +1141,23 @@ array_of_runtime_bound_p (tree t) || (!value_dependent_expression_p (max) && !TREE_CONSTANT (max))); } +/* True iff T is a variable length array. */ + +bool +vla_type_p (tree t) +{ + for (; t && TREE_CODE (t) == ARRAY_TYPE; + t = TREE_TYPE (t)) + if (tree dom = TYPE_DOMAIN (t)) + { + tree max = TYPE_MAX_VALUE (dom); + if (!potential_rvalue_constant_expression (max) + || (!value_dependent_expression_p (max) && !TREE_CONSTANT (max))) + return true; + } + return false; +} + /* Return a reference type node referring to TO_TYPE. If RVAL is true, return an rvalue reference type, otherwise return an lvalue reference type. If a type node exists, reuse it, otherwise create @@ -1055,7 +1167,10 @@ cp_build_reference_type (tree to_type, bool rval) { tree lvalue_ref, t; - if (TREE_CODE (to_type) == REFERENCE_TYPE) + if (to_type == error_mark_node) + return error_mark_node; + + if (TYPE_REF_P (to_type)) { rval = rval && TYPE_REF_IS_RVALUE (to_type); to_type = TREE_TYPE (to_type); @@ -1103,7 +1218,7 @@ tree move (tree expr) { tree type = TREE_TYPE (expr); - gcc_assert (TREE_CODE (type) != REFERENCE_TYPE); + gcc_assert (!TYPE_REF_P (type)); type = cp_build_reference_type (type, /*rval*/true); return build_static_cast (type, expr, tf_warning_or_error); } @@ -1215,11 +1330,10 @@ cp_build_qualified_type_real (tree type, [dcl.ref], [dcl.fct]. This used to be an error, but as of DR 295 (in CD1) we always ignore extra cv-quals on functions. */ if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE) - && (TREE_CODE (type) == REFERENCE_TYPE - || TREE_CODE (type) == FUNCTION_TYPE - || TREE_CODE (type) == METHOD_TYPE)) + && (TYPE_REF_P (type) + || FUNC_OR_METHOD_TYPE_P (type))) { - if (TREE_CODE (type) == REFERENCE_TYPE) + if (TYPE_REF_P (type)) bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE); type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE); } @@ -1233,7 +1347,7 @@ cp_build_qualified_type_real (tree type, if ((type_quals & TYPE_QUAL_RESTRICT) && TREE_CODE (type) != TEMPLATE_TYPE_PARM && TREE_CODE (type) != TYPENAME_TYPE - && !POINTER_TYPE_P (type)) + && !INDIRECT_TYPE_P (type)) { bad_quals |= TYPE_QUAL_RESTRICT; type_quals &= ~TYPE_QUAL_RESTRICT; @@ -1254,15 +1368,6 @@ cp_build_qualified_type_real (tree type, /* Retrieve (or create) the appropriately qualified variant. */ result = build_qualified_type (type, type_quals); - /* Preserve exception specs and ref-qualifier since build_qualified_type - doesn't know about them. */ - if (TREE_CODE (result) == FUNCTION_TYPE - || TREE_CODE (result) == METHOD_TYPE) - { - result = build_exception_variant (result, TYPE_RAISES_EXCEPTIONS (type)); - result = build_ref_qualified_type (result, type_memfn_rqual (type)); - } - return result; } @@ -1334,7 +1439,10 @@ apply_identity_attributes (tree result, tree attribs, bool *remove_attributes) return cp_build_type_attribute_variant (result, new_attribs); } -/* Builds a qualified variant of T that is not a typedef variant. +/* Builds a qualified variant of T that is either not a typedef variant + (the default behavior) or not a typedef variant of a user-facing type + (if FLAGS contains STF_USER_FACING). + E.g. consider the following declarations: typedef const int ConstInt; typedef ConstInt* PtrConstInt; @@ -1359,7 +1467,7 @@ apply_identity_attributes (tree result, tree attribs, bool *remove_attributes) stripped. */ tree -strip_typedefs (tree t, bool *remove_attributes) +strip_typedefs (tree t, bool *remove_attributes, unsigned int flags) { tree result = NULL, type = NULL, t0 = NULL; @@ -1369,19 +1477,18 @@ strip_typedefs (tree t, bool *remove_attributes) if (TREE_CODE (t) == TREE_LIST) { bool changed = false; - vec *vec = make_tree_vector (); + releasing_vec vec; tree r = t; for (; t; t = TREE_CHAIN (t)) { gcc_assert (!TREE_PURPOSE (t)); - tree elt = strip_typedefs (TREE_VALUE (t), remove_attributes); + tree elt = strip_typedefs (TREE_VALUE (t), remove_attributes, flags); if (elt != TREE_VALUE (t)) changed = true; vec_safe_push (vec, elt); } if (changed) r = build_tree_list_vec (vec); - release_tree_vector (vec); return r; } @@ -1390,7 +1497,8 @@ strip_typedefs (tree t, bool *remove_attributes) if (t == TYPE_CANONICAL (t)) return t; - if (dependent_alias_template_spec_p (t)) + if (!(flags & STF_STRIP_DEPENDENT) + && dependent_alias_template_spec_p (t, nt_opaque)) /* DR 1558: However, if the template-id is dependent, subsequent template argument substitution still applies to the template-id. */ return t; @@ -1398,28 +1506,29 @@ strip_typedefs (tree t, bool *remove_attributes) switch (TREE_CODE (t)) { case POINTER_TYPE: - type = strip_typedefs (TREE_TYPE (t), remove_attributes); + type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags); result = build_pointer_type (type); break; case REFERENCE_TYPE: - type = strip_typedefs (TREE_TYPE (t), remove_attributes); + type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags); result = cp_build_reference_type (type, TYPE_REF_IS_RVALUE (t)); break; case OFFSET_TYPE: - t0 = strip_typedefs (TYPE_OFFSET_BASETYPE (t), remove_attributes); - type = strip_typedefs (TREE_TYPE (t), remove_attributes); + t0 = strip_typedefs (TYPE_OFFSET_BASETYPE (t), remove_attributes, flags); + type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags); result = build_offset_type (t0, type); break; case RECORD_TYPE: if (TYPE_PTRMEMFUNC_P (t)) { - t0 = strip_typedefs (TYPE_PTRMEMFUNC_FN_TYPE (t), remove_attributes); + t0 = strip_typedefs (TYPE_PTRMEMFUNC_FN_TYPE (t), + remove_attributes, flags); result = build_ptrmemfunc_type (t0); } break; case ARRAY_TYPE: - type = strip_typedefs (TREE_TYPE (t), remove_attributes); - t0 = strip_typedefs (TYPE_DOMAIN (t), remove_attributes); + type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags); + t0 = strip_typedefs (TYPE_DOMAIN (t), remove_attributes, flags); result = build_cplus_array_type (type, t0); break; case FUNCTION_TYPE: @@ -1438,7 +1547,7 @@ strip_typedefs (tree t, bool *remove_attributes) && (TYPE_ATTRIBUTES (t) || TYPE_USER_ALIGN (t))) is_variant = true; - type = strip_typedefs (TREE_TYPE (t), remove_attributes); + type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags); tree canon_spec = (flag_noexcept_type ? canonical_eh_spec (TYPE_RAISES_EXCEPTIONS (t)) : NULL_TREE); @@ -1452,7 +1561,7 @@ strip_typedefs (tree t, bool *remove_attributes) if (arg_node == void_list_node) break; arg_type = strip_typedefs (TREE_VALUE (arg_node), - remove_attributes); + remove_attributes, flags); gcc_assert (arg_type); if (arg_type == TREE_VALUE (arg_node) && !changed) continue; @@ -1490,22 +1599,16 @@ strip_typedefs (tree t, bool *remove_attributes) result = build_method_type_directly (class_type, type, TREE_CHAIN (arg_types)); - result - = build_ref_qualified_type (result, type_memfn_rqual (t)); } else { - result = build_function_type (type, - arg_types); - result = apply_memfn_quals (result, - type_memfn_quals (t), - type_memfn_rqual (t)); + result = build_function_type (type, arg_types); + result = apply_memfn_quals (result, type_memfn_quals (t)); } - if (canon_spec) - result = build_exception_variant (result, canon_spec); - if (TYPE_HAS_LATE_RETURN_TYPE (t)) - TYPE_HAS_LATE_RETURN_TYPE (result) = 1; + result = build_cp_fntype_variant (result, + type_memfn_rqual (t), canon_spec, + TYPE_HAS_LATE_RETURN_TYPE (t)); } break; case TYPENAME_TYPE: @@ -1522,9 +1625,10 @@ strip_typedefs (tree t, bool *remove_attributes) tree arg = TREE_VEC_ELT (args, i); tree strip_arg; if (TYPE_P (arg)) - strip_arg = strip_typedefs (arg, remove_attributes); + strip_arg = strip_typedefs (arg, remove_attributes, flags); else - strip_arg = strip_typedefs_expr (arg, remove_attributes); + strip_arg = strip_typedefs_expr (arg, remove_attributes, + flags); TREE_VEC_ELT (new_args, i) = strip_arg; if (strip_arg != arg) changed = true; @@ -1540,7 +1644,7 @@ strip_typedefs (tree t, bool *remove_attributes) else ggc_free (new_args); } - tree ctx = strip_typedefs (TYPE_CONTEXT (t), remove_attributes); + tree ctx = strip_typedefs (TYPE_CONTEXT (t), remove_attributes, flags); if (!changed && ctx == TYPE_CONTEXT (t) && !typedef_variant_p (t)) return t; tree name = fullname; @@ -1553,7 +1657,7 @@ strip_typedefs (tree t, bool *remove_attributes) break; case DECLTYPE_TYPE: result = strip_typedefs_expr (DECLTYPE_TYPE_EXPR (t), - remove_attributes); + remove_attributes, flags); if (result == DECLTYPE_TYPE_EXPR (t)) result = NULL_TREE; else @@ -1563,7 +1667,8 @@ strip_typedefs (tree t, bool *remove_attributes) tf_none)); break; case UNDERLYING_TYPE: - type = strip_typedefs (UNDERLYING_TYPE_TYPE (t), remove_attributes); + type = strip_typedefs (UNDERLYING_TYPE_TYPE (t), + remove_attributes, flags); result = finish_underlying_type (type); break; default: @@ -1574,15 +1679,24 @@ strip_typedefs (tree t, bool *remove_attributes) { if (typedef_variant_p (t)) { - /* Explicitly get the underlying type, as TYPE_MAIN_VARIANT doesn't - strip typedefs with attributes. */ - result = TYPE_MAIN_VARIANT (DECL_ORIGINAL_TYPE (TYPE_NAME (t))); - result = strip_typedefs (result); + if ((flags & STF_USER_VISIBLE) + && !user_facing_original_type_p (t)) + return t; + /* If T is a non-template alias or typedef, we can assume that + instantiating its definition will hit any substitution failure, + so we don't need to retain it here as well. */ + if (!alias_template_specialization_p (t, nt_opaque)) + flags |= STF_STRIP_DEPENDENT; + result = strip_typedefs (DECL_ORIGINAL_TYPE (TYPE_NAME (t)), + remove_attributes, flags); } else result = TYPE_MAIN_VARIANT (t); } - gcc_assert (!typedef_variant_p (result)); + /*gcc_assert (!typedef_variant_p (result) + || dependent_alias_template_spec_p (result, nt_opaque) + || ((flags & STF_USER_VISIBLE) + && !user_facing_original_type_p (result)));*/ if (COMPLETE_TYPE_P (result) && !COMPLETE_TYPE_P (t)) /* If RESULT is complete and T isn't, it's likely the case that T @@ -1631,7 +1745,7 @@ strip_typedefs (tree t, bool *remove_attributes) sizeof(TT) is replaced by sizeof(T). */ tree -strip_typedefs_expr (tree t, bool *remove_attributes) +strip_typedefs_expr (tree t, bool *remove_attributes, unsigned int flags) { unsigned i,n; tree r, type, *ops; @@ -1640,13 +1754,15 @@ strip_typedefs_expr (tree t, bool *remove_attributes) if (t == NULL_TREE || t == error_mark_node) return t; + STRIP_ANY_LOCATION_WRAPPER (t); + if (DECL_P (t) || CONSTANT_CLASS_P (t)) return t; /* Some expressions have type operands, so let's handle types here rather than check TYPE_P in multiple places below. */ if (TYPE_P (t)) - return strip_typedefs (t, remove_attributes); + return strip_typedefs (t, remove_attributes, flags); code = TREE_CODE (t); switch (code) @@ -1660,8 +1776,10 @@ strip_typedefs_expr (tree t, bool *remove_attributes) case TRAIT_EXPR: { - tree type1 = strip_typedefs (TRAIT_EXPR_TYPE1 (t), remove_attributes); - tree type2 = strip_typedefs (TRAIT_EXPR_TYPE2 (t), remove_attributes); + tree type1 = strip_typedefs (TRAIT_EXPR_TYPE1 (t), + remove_attributes, flags); + tree type2 = strip_typedefs (TRAIT_EXPR_TYPE2 (t), + remove_attributes, flags); if (type1 == TRAIT_EXPR_TYPE1 (t) && type2 == TRAIT_EXPR_TYPE2 (t)) return t; @@ -1673,14 +1791,15 @@ strip_typedefs_expr (tree t, bool *remove_attributes) case TREE_LIST: { - vec *vec = make_tree_vector (); + releasing_vec vec; bool changed = false; tree it; for (it = t; it; it = TREE_CHAIN (it)) { - tree val = strip_typedefs_expr (TREE_VALUE (t), remove_attributes); + tree val = strip_typedefs_expr (TREE_VALUE (it), + remove_attributes, flags); vec_safe_push (vec, val); - if (val != TREE_VALUE (t)) + if (val != TREE_VALUE (it)) changed = true; gcc_assert (TREE_PURPOSE (it) == NULL_TREE); } @@ -1692,20 +1811,19 @@ strip_typedefs_expr (tree t, bool *remove_attributes) } else r = t; - release_tree_vector (vec); return r; } case TREE_VEC: { bool changed = false; - vec *vec = make_tree_vector (); + releasing_vec vec; n = TREE_VEC_LENGTH (t); vec_safe_reserve (vec, n); for (i = 0; i < n; ++i) { tree op = strip_typedefs_expr (TREE_VEC_ELT (t, i), - remove_attributes); + remove_attributes, flags); vec->quick_push (op); if (op != TREE_VEC_ELT (t, i)) changed = true; @@ -1720,7 +1838,6 @@ strip_typedefs_expr (tree t, bool *remove_attributes) } else r = t; - release_tree_vector (vec); return r; } @@ -1730,18 +1847,19 @@ strip_typedefs_expr (tree t, bool *remove_attributes) vec *vec = vec_safe_copy (CONSTRUCTOR_ELTS (t)); n = CONSTRUCTOR_NELTS (t); - type = strip_typedefs (TREE_TYPE (t), remove_attributes); + type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags); for (i = 0; i < n; ++i) { constructor_elt *e = &(*vec)[i]; - tree op = strip_typedefs_expr (e->value, remove_attributes); + tree op = strip_typedefs_expr (e->value, remove_attributes, flags); if (op != e->value) { changed = true; e->value = op; } gcc_checking_assert - (e->index == strip_typedefs_expr (e->index, remove_attributes)); + (e->index == strip_typedefs_expr (e->index, remove_attributes, + flags)); } if (!changed && type == TREE_TYPE (t)) @@ -1759,7 +1877,10 @@ strip_typedefs_expr (tree t, bool *remove_attributes) } case LAMBDA_EXPR: - error ("lambda-expression in a constant expression"); + return t; + + case STATEMENT_LIST: + error ("statement-expression in a constant expression"); return error_mark_node; default: @@ -1768,7 +1889,7 @@ strip_typedefs_expr (tree t, bool *remove_attributes) gcc_assert (EXPR_P (t)); - n = TREE_OPERAND_LENGTH (t); + n = cp_tree_operand_length (t); ops = XALLOCAVEC (tree, n); type = TREE_TYPE (t); @@ -1782,12 +1903,13 @@ strip_typedefs_expr (tree t, bool *remove_attributes) case REINTERPRET_CAST_EXPR: case CAST_EXPR: case NEW_EXPR: - type = strip_typedefs (type, remove_attributes); + type = strip_typedefs (type, remove_attributes, flags); /* fallthrough */ default: for (i = 0; i < n; ++i) - ops[i] = strip_typedefs_expr (TREE_OPERAND (t, i), remove_attributes); + ops[i] = strip_typedefs_expr (TREE_OPERAND (t, i), + remove_attributes, flags); break; } @@ -2044,17 +2166,19 @@ build_qualified_name (tree type, tree scope, tree name, bool template_p) return t; } -/* Like check_qualified_type, but also check ref-qualifier and exception - specification. */ +/* Like check_qualified_type, but also check ref-qualifier, exception + specification, and whether the return type was specified after the + parameters. */ static bool cp_check_qualified_type (const_tree cand, const_tree base, int type_quals, - cp_ref_qualifier rqual, tree raises) + cp_ref_qualifier rqual, tree raises, bool late) { return (TYPE_QUALS (cand) == type_quals && check_base_type (cand, base) && comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (cand), ce_exact) + && TYPE_HAS_LATE_RETURN_TYPE (cand) == late && type_memfn_rqual (cand) == rqual); } @@ -2063,155 +2187,69 @@ cp_check_qualified_type (const_tree cand, const_tree base, int type_quals, tree build_ref_qualified_type (tree type, cp_ref_qualifier rqual) { - tree t; - - if (rqual == type_memfn_rqual (type)) - return type; - - int type_quals = TYPE_QUALS (type); tree raises = TYPE_RAISES_EXCEPTIONS (type); - for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) - if (cp_check_qualified_type (t, type, type_quals, rqual, raises)) - return t; - - t = build_variant_type_copy (type); - switch (rqual) - { - case REF_QUAL_RVALUE: - FUNCTION_RVALUE_QUALIFIED (t) = 1; - FUNCTION_REF_QUALIFIED (t) = 1; - break; - case REF_QUAL_LVALUE: - FUNCTION_RVALUE_QUALIFIED (t) = 0; - FUNCTION_REF_QUALIFIED (t) = 1; - break; - default: - FUNCTION_REF_QUALIFIED (t) = 0; - break; - } - - if (TYPE_STRUCTURAL_EQUALITY_P (type)) - /* Propagate structural equality. */ - SET_TYPE_STRUCTURAL_EQUALITY (t); - else if (TYPE_CANONICAL (type) != type) - /* Build the underlying canonical type, since it is different - from TYPE. */ - TYPE_CANONICAL (t) = build_ref_qualified_type (TYPE_CANONICAL (type), - rqual); - else - /* T is its own canonical type. */ - TYPE_CANONICAL (t) = t; - - return t; + bool late = TYPE_HAS_LATE_RETURN_TYPE (type); + return build_cp_fntype_variant (type, rqual, raises, late); } -/* Cache of free ovl nodes. Uses OVL_FUNCTION for chaining. */ -static GTY((deletable)) tree ovl_cache; - /* Make a raw overload node containing FN. */ tree ovl_make (tree fn, tree next) { - tree result = ovl_cache; - - if (result) - { - ovl_cache = OVL_FUNCTION (result); - /* Zap the flags. */ - memset (result, 0, sizeof (tree_base)); - TREE_SET_CODE (result, OVERLOAD); - } - else - result = make_node (OVERLOAD); + tree result = make_node (OVERLOAD); if (TREE_CODE (fn) == OVERLOAD) OVL_NESTED_P (result) = true; TREE_TYPE (result) = (next || TREE_CODE (fn) == TEMPLATE_DECL ? unknown_type_node : TREE_TYPE (fn)); + if (next && TREE_CODE (next) == OVERLOAD && OVL_DEDUP_P (next)) + OVL_DEDUP_P (result) = true; OVL_FUNCTION (result) = fn; OVL_CHAIN (result) = next; return result; } -static tree -ovl_copy (tree ovl) -{ - tree result = ovl_cache; - - if (result) - { - ovl_cache = OVL_FUNCTION (result); - /* Zap the flags. */ - memset (result, 0, sizeof (tree_base)); - TREE_SET_CODE (result, OVERLOAD); - } - else - result = make_node (OVERLOAD); - - gcc_checking_assert (!OVL_NESTED_P (ovl) && OVL_USED_P (ovl)); - TREE_TYPE (result) = TREE_TYPE (ovl); - OVL_FUNCTION (result) = OVL_FUNCTION (ovl); - OVL_CHAIN (result) = OVL_CHAIN (ovl); - OVL_HIDDEN_P (result) = OVL_HIDDEN_P (ovl); - OVL_USING_P (result) = OVL_USING_P (ovl); - OVL_LOOKUP_P (result) = OVL_LOOKUP_P (ovl); - - return result; -} - /* Add FN to the (potentially NULL) overload set OVL. USING_P is true, if FN is via a using declaration. We also pay attention to - DECL_HIDDEN. Overloads are ordered as hidden, using, regular. */ + DECL_HIDDEN. We keep the hidden decls first, but remaining ones + are unordered. */ tree ovl_insert (tree fn, tree maybe_ovl, bool using_p) { - bool copying = false; /* Checking use only. */ - bool hidden_p = DECL_HIDDEN_P (fn); - int weight = (hidden_p << 1) | (using_p << 0); - - tree result = NULL_TREE; + tree result = maybe_ovl; tree insert_after = NULL_TREE; - /* Find insertion point. */ - while (maybe_ovl && TREE_CODE (maybe_ovl) == OVERLOAD - && (weight < ((OVL_HIDDEN_P (maybe_ovl) << 1) - | (OVL_USING_P (maybe_ovl) << 0)))) + /* Skip hidden. */ + for (; maybe_ovl && TREE_CODE (maybe_ovl) == OVERLOAD + && OVL_HIDDEN_P (maybe_ovl); + maybe_ovl = OVL_CHAIN (maybe_ovl)) { - gcc_checking_assert (!OVL_LOOKUP_P (maybe_ovl) - && (!copying || OVL_USED_P (maybe_ovl))); - if (OVL_USED_P (maybe_ovl)) - { - copying = true; - maybe_ovl = ovl_copy (maybe_ovl); - if (insert_after) - OVL_CHAIN (insert_after) = maybe_ovl; - } - if (!result) - result = maybe_ovl; + gcc_checking_assert (!OVL_LOOKUP_P (maybe_ovl)); insert_after = maybe_ovl; - maybe_ovl = OVL_CHAIN (maybe_ovl); } - tree trail = fn; + bool hidden_p = DECL_HIDDEN_P (fn); if (maybe_ovl || using_p || hidden_p || TREE_CODE (fn) == TEMPLATE_DECL) { - trail = ovl_make (fn, maybe_ovl); + maybe_ovl = ovl_make (fn, maybe_ovl); if (hidden_p) - OVL_HIDDEN_P (trail) = true; + OVL_HIDDEN_P (maybe_ovl) = true; if (using_p) - OVL_USING_P (trail) = true; + OVL_DEDUP_P (maybe_ovl) = OVL_USING_P (maybe_ovl) = true; } + else + maybe_ovl = fn; if (insert_after) { - OVL_CHAIN (insert_after) = trail; + OVL_CHAIN (insert_after) = maybe_ovl; TREE_TYPE (insert_after) = unknown_type_node; } else - result = trail; + result = maybe_ovl; return result; } @@ -2242,25 +2280,27 @@ ovl_skip_hidden (tree ovl) tree ovl_iterator::reveal_node (tree overload, tree node) { - /* We cannot have returned NODE as part of a lookup overload, so it - cannot be USED. */ - gcc_checking_assert (!OVL_USED_P (node)); + /* We cannot have returned NODE as part of a lookup overload, so we + don't have to worry about preserving that. */ OVL_HIDDEN_P (node) = false; if (tree chain = OVL_CHAIN (node)) - if (TREE_CODE (chain) == OVERLOAD - && (OVL_USING_P (chain) || OVL_HIDDEN_P (chain))) + if (TREE_CODE (chain) == OVERLOAD) { - /* The node needs moving, and the simplest way is to remove it - and reinsert. */ - overload = remove_node (overload, node); - overload = ovl_insert (OVL_FUNCTION (node), overload); + if (OVL_HIDDEN_P (chain)) + { + /* The node needs moving, and the simplest way is to remove it + and reinsert. */ + overload = remove_node (overload, node); + overload = ovl_insert (OVL_FUNCTION (node), overload); + } + else if (OVL_DEDUP_P (chain)) + OVL_DEDUP_P (node) = true; } return overload; } -/* NODE is on the overloads of OVL. Remove it. If a predecessor is - OVL_USED_P we must copy OVL nodes, because those are immutable. +/* NODE is on the overloads of OVL. Remove it. The removed node is unaltered and may continue to be iterated from (i.e. it is safe to remove a node from an overload one is currently iterating over). */ @@ -2268,20 +2308,11 @@ ovl_iterator::reveal_node (tree overload, tree node) tree ovl_iterator::remove_node (tree overload, tree node) { - bool copying = false; /* Checking use only. */ - tree *slot = &overload; while (*slot != node) { tree probe = *slot; - gcc_checking_assert (!OVL_LOOKUP_P (probe) - && (!copying || OVL_USED_P (probe))); - if (OVL_USED_P (probe)) - { - copying = true; - probe = ovl_copy (probe); - *slot = probe; - } + gcc_checking_assert (!OVL_LOOKUP_P (probe)); slot = &OVL_CHAIN (probe); } @@ -2316,6 +2347,9 @@ lookup_mark (tree ovl, bool val) tree lookup_add (tree fns, tree lookup) { + if (fns == error_mark_node || lookup == error_mark_node) + return error_mark_node; + if (lookup || TREE_CODE (fns) == TEMPLATE_DECL) { lookup = ovl_make (fns, lookup); @@ -2354,7 +2388,8 @@ lookup_maybe_add (tree fns, tree lookup, bool deduping) for (; fns != probe; fns = OVL_CHAIN (fns)) { lookup = lookup_add (OVL_FUNCTION (fns), lookup); - /* Propagate OVL_USING, but OVL_HIDDEN doesn't matter. */ + /* Propagate OVL_USING, but OVL_HIDDEN & + OVL_DEDUP_P don't matter. */ if (OVL_USING_P (fns)) OVL_USING_P (lookup) = true; } @@ -2371,48 +2406,6 @@ lookup_maybe_add (tree fns, tree lookup, bool deduping) return lookup; } -/* Regular overload OVL is part of a kept lookup. Mark the nodes on - it as immutable. */ - -static void -ovl_used (tree ovl) -{ - for (; - ovl && TREE_CODE (ovl) == OVERLOAD - && !OVL_USED_P (ovl); - ovl = OVL_CHAIN (ovl)) - { - gcc_checking_assert (!OVL_LOOKUP_P (ovl)); - OVL_USED_P (ovl) = true; - } -} - -/* If KEEP is true, preserve the contents of a lookup so that it is - available for a later instantiation. Otherwise release the LOOKUP - nodes for reuse. */ - -void -lookup_keep (tree lookup, bool keep) -{ - for (; - lookup && TREE_CODE (lookup) == OVERLOAD - && OVL_LOOKUP_P (lookup) && !OVL_USED_P (lookup); - lookup = OVL_CHAIN (lookup)) - if (keep) - { - OVL_USED_P (lookup) = true; - ovl_used (OVL_FUNCTION (lookup)); - } - else - { - OVL_FUNCTION (lookup) = ovl_cache; - ovl_cache = lookup; - } - - if (keep) - ovl_used (lookup); -} - /* Returns nonzero if X is an expression for a (possibly overloaded) function. If "f" is a function or function template, "f", "c->f", "c.f", "C::f", and "f" will all be considered possibly @@ -2423,6 +2416,8 @@ lookup_keep (tree lookup, bool keep) int is_overloaded_fn (tree x) { + STRIP_ANY_LOCATION_WRAPPER (x); + /* A baselink is also considered an overloaded function. */ if (TREE_CODE (x) == OFFSET_REF || TREE_CODE (x) == COMPONENT_REF) @@ -2435,8 +2430,7 @@ is_overloaded_fn (tree x) || (TREE_CODE (x) == OVERLOAD && !OVL_SINGLE_P (x))) return 2; - return (TREE_CODE (x) == FUNCTION_DECL - || TREE_CODE (x) == OVERLOAD); + return OVL_P (x); } /* X is the CALL_EXPR_FN of a CALL_EXPR. If X represents a dependent name @@ -2450,7 +2444,7 @@ dependent_name (tree x) return x; if (TREE_CODE (x) == TEMPLATE_ID_EXPR) x = TREE_OPERAND (x, 0); - if (TREE_CODE (x) == OVERLOAD || TREE_CODE (x) == FUNCTION_DECL) + if (OVL_P (x)) return OVL_NAME (x); return NULL_TREE; } @@ -2465,11 +2459,14 @@ really_overloaded_fn (tree x) return is_overloaded_fn (x) == 2; } -/* Get the overload set FROM refers to. */ +/* Get the overload set FROM refers to. Returns NULL if it's not an + overload set. */ tree -get_fns (tree from) +maybe_get_fns (tree from) { + STRIP_ANY_LOCATION_WRAPPER (from); + /* A baselink is also considered an overloaded function. */ if (TREE_CODE (from) == OFFSET_REF || TREE_CODE (from) == COMPONENT_REF) @@ -2478,9 +2475,22 @@ get_fns (tree from) from = BASELINK_FUNCTIONS (from); if (TREE_CODE (from) == TEMPLATE_ID_EXPR) from = TREE_OPERAND (from, 0); - gcc_assert (TREE_CODE (from) == OVERLOAD - || TREE_CODE (from) == FUNCTION_DECL); - return from; + + if (OVL_P (from)) + return from; + + return NULL; +} + +/* FROM refers to an overload set. Return that set (or die). */ + +tree +get_fns (tree from) +{ + tree res = maybe_get_fns (from); + + gcc_assert (res); + return res; } /* Return the first function of the overload set FROM refers to. */ @@ -2581,6 +2591,7 @@ canonical_eh_spec (tree raises) if (raises == NULL_TREE) return raises; else if (DEFERRED_NOEXCEPT_SPEC_P (raises) + || UNPARSED_NOEXCEPT_SPEC_P (raises) || uses_template_parms (raises) || uses_template_parms (TREE_PURPOSE (raises))) /* Keep a dependent or deferred exception specification. */ @@ -2593,42 +2604,50 @@ canonical_eh_spec (tree raises) return NULL_TREE; } -/* Build the FUNCTION_TYPE or METHOD_TYPE which may throw exceptions - listed in RAISES. */ - tree -build_exception_variant (tree type, tree raises) +build_cp_fntype_variant (tree type, cp_ref_qualifier rqual, + tree raises, bool late) { - tree v; - int type_quals; + cp_cv_quals type_quals = TYPE_QUALS (type); - if (comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (type), ce_exact)) + if (cp_check_qualified_type (type, type, type_quals, rqual, raises, late)) return type; - type_quals = TYPE_QUALS (type); - cp_ref_qualifier rqual = type_memfn_rqual (type); - for (v = TYPE_MAIN_VARIANT (type); v; v = TYPE_NEXT_VARIANT (v)) - if (cp_check_qualified_type (v, type, type_quals, rqual, raises)) + tree v = TYPE_MAIN_VARIANT (type); + for (; v; v = TYPE_NEXT_VARIANT (v)) + if (cp_check_qualified_type (v, type, type_quals, rqual, raises, late)) return v; /* Need to build a new variant. */ v = build_variant_type_copy (type); TYPE_RAISES_EXCEPTIONS (v) = raises; - - if (!flag_noexcept_type) - /* The exception-specification is not part of the canonical type. */ - return v; + TYPE_HAS_LATE_RETURN_TYPE (v) = late; + switch (rqual) + { + case REF_QUAL_RVALUE: + FUNCTION_RVALUE_QUALIFIED (v) = 1; + FUNCTION_REF_QUALIFIED (v) = 1; + break; + case REF_QUAL_LVALUE: + FUNCTION_RVALUE_QUALIFIED (v) = 0; + FUNCTION_REF_QUALIFIED (v) = 1; + break; + default: + FUNCTION_REF_QUALIFIED (v) = 0; + break; + } /* Canonicalize the exception specification. */ - tree cr = canonical_eh_spec (raises); + tree cr = flag_noexcept_type ? canonical_eh_spec (raises) : NULL_TREE; if (TYPE_STRUCTURAL_EQUALITY_P (type)) /* Propagate structural equality. */ SET_TYPE_STRUCTURAL_EQUALITY (v); - else if (TYPE_CANONICAL (type) != type || cr != raises) + else if (TYPE_CANONICAL (type) != type || cr != raises || late) /* Build the underlying canonical type, since it is different from TYPE. */ - TYPE_CANONICAL (v) = build_exception_variant (TYPE_CANONICAL (type), cr); + TYPE_CANONICAL (v) = build_cp_fntype_variant (TYPE_CANONICAL (type), + rqual, cr, false); else /* T is its own canonical type. */ TYPE_CANONICAL (v) = v; @@ -2636,6 +2655,17 @@ build_exception_variant (tree type, tree raises) return v; } +/* Build the FUNCTION_TYPE or METHOD_TYPE which may throw exceptions + listed in RAISES. */ + +tree +build_exception_variant (tree type, tree raises) +{ + cp_ref_qualifier rqual = type_memfn_rqual (type); + bool late = TYPE_HAS_LATE_RETURN_TYPE (type); + return build_cp_fntype_variant (type, rqual, raises, late); +} + /* Given a TEMPLATE_TEMPLATE_PARM node T, create a new BOUND_TEMPLATE_TEMPLATE_PARM bound with NEWARGS as its template arguments. */ @@ -2733,7 +2763,18 @@ no_linkage_check (tree t, bool relaxed_p) { tree r; - /* There's no point in checking linkage on template functions; we + /* Lambda types that don't have mangling scope have no linkage. We + check CLASSTYPE_LAMBDA_EXPR for error_mark_node because + when we get here from pushtag none of the lambda information is + set up yet, so we want to assume that the lambda has linkage and + fix it up later if not. We need to check this even in templates so + that we properly handle a lambda-expression in the signature. */ + if (LAMBDA_TYPE_P (t) + && CLASSTYPE_LAMBDA_EXPR (t) != error_mark_node + && LAMBDA_TYPE_EXTRA_SCOPE (t) == NULL_TREE) + return t; + + /* Otherwise there's no point in checking linkage on template functions; we can't know their complete types. */ if (processing_template_decl) return NULL_TREE; @@ -2743,15 +2784,6 @@ no_linkage_check (tree t, bool relaxed_p) case RECORD_TYPE: if (TYPE_PTRMEMFUNC_P (t)) goto ptrmem; - /* Lambda types that don't have mangling scope have no linkage. We - check CLASSTYPE_LAMBDA_EXPR for error_mark_node because - when we get here from pushtag none of the lambda information is - set up yet, so we want to assume that the lambda has linkage and - fix it up later if not. */ - if (CLASSTYPE_LAMBDA_EXPR (t) - && CLASSTYPE_LAMBDA_EXPR (t) != error_mark_node - && LAMBDA_TYPE_EXTRA_SCOPE (t) == NULL_TREE) - return t; /* Fall through. */ case UNION_TYPE: if (!CLASS_TYPE_P (t)) @@ -2826,7 +2858,6 @@ extern int depth_reached; void cxx_print_statistics (void) { - print_class_statistics (); print_template_statistics (); if (GATHER_STATISTICS) fprintf (stderr, "maximum template instantiation depth reached: %d\n", @@ -2865,12 +2896,19 @@ array_type_nelts_total (tree type) return sz; } +struct bot_data +{ + splay_tree target_remap; + bool clear_location; +}; + /* Called from break_out_target_exprs via mapcar. */ static tree -bot_manip (tree* tp, int* walk_subtrees, void* data) +bot_manip (tree* tp, int* walk_subtrees, void* data_) { - splay_tree target_remap = ((splay_tree) data); + bot_data &data = *(bot_data*)data_; + splay_tree target_remap = data.target_remap; tree t = *tp; if (!TYPE_P (t) && TREE_CONSTANT (t) && !TREE_SIDE_EFFECTS (t)) @@ -2892,6 +2930,8 @@ bot_manip (tree* tp, int* walk_subtrees, void* data) { u = build_cplus_new (TREE_TYPE (t), TREE_OPERAND (t, 1), tf_warning_or_error); + if (u == error_mark_node) + return u; if (AGGR_INIT_ZERO_FIRST (TREE_OPERAND (t, 1))) AGGR_INIT_ZERO_FIRST (TREE_OPERAND (u, 1)) = true; } @@ -2908,7 +2948,10 @@ bot_manip (tree* tp, int* walk_subtrees, void* data) (splay_tree_key) TREE_OPERAND (t, 0), (splay_tree_value) TREE_OPERAND (u, 0)); - TREE_OPERAND (u, 1) = break_out_target_exprs (TREE_OPERAND (u, 1)); + TREE_OPERAND (u, 1) = break_out_target_exprs (TREE_OPERAND (u, 1), + data.clear_location); + if (TREE_OPERAND (u, 1) == error_mark_node) + return error_mark_node; /* Replace the old expression with the new version. */ *tp = u; @@ -2944,23 +2987,11 @@ bot_manip (tree* tp, int* walk_subtrees, void* data) /* Make a copy of this node. */ t = copy_tree_r (tp, walk_subtrees, NULL); - if (TREE_CODE (*tp) == CALL_EXPR) - { + if (TREE_CODE (*tp) == CALL_EXPR || TREE_CODE (*tp) == AGGR_INIT_EXPR) + if (!processing_template_decl) set_flags_from_callee (*tp); - - /* builtin_LINE and builtin_FILE get the location where the default - argument is expanded, not where the call was written. */ - tree callee = get_callee_fndecl (*tp); - if (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL) - switch (DECL_FUNCTION_CODE (callee)) - { - case BUILT_IN_FILE: - case BUILT_IN_LINE: - SET_EXPR_LOCATION (*tp, input_location); - default: - break; - } - } + if (data.clear_location && EXPR_HAS_LOCATION (*tp)) + SET_EXPR_LOCATION (*tp, input_location); return t; } @@ -2969,9 +3000,10 @@ bot_manip (tree* tp, int* walk_subtrees, void* data) variables. */ static tree -bot_replace (tree* t, int* /*walk_subtrees*/, void* data) +bot_replace (tree* t, int* /*walk_subtrees*/, void* data_) { - splay_tree target_remap = ((splay_tree) data); + bot_data &data = *(bot_data*)data_; + splay_tree target_remap = data.target_remap; if (VAR_P (*t)) { @@ -3009,10 +3041,13 @@ bot_replace (tree* t, int* /*walk_subtrees*/, void* data) /* When we parse a default argument expression, we may create temporary variables via TARGET_EXPRs. When we actually use the default-argument expression, we make a copy of the expression - and replace the temporaries with appropriate local versions. */ + and replace the temporaries with appropriate local versions. + + If CLEAR_LOCATION is true, override any EXPR_LOCATION with + input_location. */ tree -break_out_target_exprs (tree t) +break_out_target_exprs (tree t, bool clear_location /* = false */) { static int target_remap_count; static splay_tree target_remap; @@ -3021,8 +3056,10 @@ break_out_target_exprs (tree t) target_remap = splay_tree_new (splay_tree_compare_pointers, /*splay_tree_delete_key_fn=*/NULL, /*splay_tree_delete_value_fn=*/NULL); - cp_walk_tree (&t, bot_manip, target_remap, NULL); - cp_walk_tree (&t, bot_replace, target_remap, NULL); + bot_data data = { target_remap, clear_location }; + if (cp_walk_tree (&t, bot_manip, &data, NULL) == error_mark_node) + t = error_mark_node; + cp_walk_tree (&t, bot_replace, &data, NULL); if (!--target_remap_count) { @@ -3069,6 +3106,7 @@ build_ctor_subob_ref (tree index, tree type, tree obj) struct replace_placeholders_t { tree obj; /* The object to be substituted for a PLACEHOLDER_EXPR. */ + tree exp; /* The outermost exp. */ bool seen; /* Whether we've encountered a PLACEHOLDER_EXPR. */ hash_set *pset; /* To avoid walking same trees multiple times. */ }; @@ -3082,7 +3120,7 @@ replace_placeholders_r (tree* t, int* walk_subtrees, void* data_) replace_placeholders_t *d = static_cast(data_); tree obj = d->obj; - if (TREE_CONSTANT (*t)) + if (TYPE_P (*t) || TREE_CONSTANT (*t)) { *walk_subtrees = false; return NULL_TREE; @@ -3096,8 +3134,8 @@ replace_placeholders_r (tree* t, int* walk_subtrees, void* data_) for (; !same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (*t), TREE_TYPE (x)); x = TREE_OPERAND (x, 0)) - gcc_assert (TREE_CODE (x) == COMPONENT_REF); - *t = x; + gcc_assert (handled_component_p (x)); + *t = unshare_expr (x); *walk_subtrees = false; d->seen = true; } @@ -3107,12 +3145,27 @@ replace_placeholders_r (tree* t, int* walk_subtrees, void* data_) { constructor_elt *ce; vec *v = CONSTRUCTOR_ELTS (*t); + /* Don't walk into CONSTRUCTOR_PLACEHOLDER_BOUNDARY ctors + other than the d->exp one, those have PLACEHOLDER_EXPRs + related to another object. */ + if ((CONSTRUCTOR_PLACEHOLDER_BOUNDARY (*t) + && *t != d->exp) + || d->pset->add (*t)) + { + *walk_subtrees = false; + return NULL_TREE; + } for (unsigned i = 0; vec_safe_iterate (v, i, &ce); ++i) { tree *valp = &ce->value; tree type = TREE_TYPE (*valp); tree subob = obj; + /* Elements with RANGE_EXPR index shouldn't have any + placeholders in them. */ + if (ce->index && TREE_CODE (ce->index) == RANGE_EXPR) + continue; + if (TREE_CODE (*valp) == CONSTRUCTOR && AGGREGATE_TYPE_P (type)) { @@ -3126,7 +3179,7 @@ replace_placeholders_r (tree* t, int* walk_subtrees, void* data_) valp = &TARGET_EXPR_INITIAL (*valp); } d->obj = subob; - cp_walk_tree (valp, replace_placeholders_r, data_, d->pset); + cp_walk_tree (valp, replace_placeholders_r, data_, NULL); d->obj = obj; } *walk_subtrees = false; @@ -3134,6 +3187,8 @@ replace_placeholders_r (tree* t, int* walk_subtrees, void* data_) } default: + if (d->pset->add (*t)) + *walk_subtrees = false; break; } @@ -3158,16 +3213,57 @@ replace_placeholders (tree exp, tree obj, bool *seen_p) return exp; tree *tp = &exp; - hash_set pset; - replace_placeholders_t data = { obj, false, &pset }; if (TREE_CODE (exp) == TARGET_EXPR) tp = &TARGET_EXPR_INITIAL (exp); - cp_walk_tree (tp, replace_placeholders_r, &data, &pset); + hash_set pset; + replace_placeholders_t data = { obj, *tp, false, &pset }; + cp_walk_tree (tp, replace_placeholders_r, &data, NULL); if (seen_p) *seen_p = data.seen; return exp; } +/* Callback function for find_placeholders. */ + +static tree +find_placeholders_r (tree *t, int *walk_subtrees, void *) +{ + if (TYPE_P (*t) || TREE_CONSTANT (*t)) + { + *walk_subtrees = false; + return NULL_TREE; + } + + switch (TREE_CODE (*t)) + { + case PLACEHOLDER_EXPR: + return *t; + + case CONSTRUCTOR: + if (CONSTRUCTOR_PLACEHOLDER_BOUNDARY (*t)) + *walk_subtrees = false; + break; + + default: + break; + } + + return NULL_TREE; +} + +/* Return true if EXP contains a PLACEHOLDER_EXPR. Don't walk into + ctors with CONSTRUCTOR_PLACEHOLDER_BOUNDARY flag set. */ + +bool +find_placeholders (tree exp) +{ + /* This is only relevant for C++14. */ + if (cxx_dialect < cxx14) + return false; + + return cp_walk_tree_without_duplicates (&exp, find_placeholders_r, NULL); +} + /* Similar to `build_nt', but for template definitions of dependent expressions */ @@ -3188,12 +3284,7 @@ build_min_nt_loc (location_t loc, enum tree_code code, ...) length = TREE_CODE_LENGTH (code); for (i = 0; i < length; i++) - { - tree x = va_arg (p, tree); - TREE_OPERAND (t, i) = x; - if (x && TREE_CODE (x) == OVERLOAD) - lookup_keep (x, true); - } + TREE_OPERAND (t, i) = va_arg (p, tree); va_end (p); return t; @@ -3221,16 +3312,12 @@ build_min (enum tree_code code, tree tt, ...) { tree x = va_arg (p, tree); TREE_OPERAND (t, i) = x; - if (x) - { - if (!TYPE_P (x) && TREE_SIDE_EFFECTS (x)) - TREE_SIDE_EFFECTS (t) = 1; - if (TREE_CODE (x) == OVERLOAD) - lookup_keep (x, true); - } + if (x && !TYPE_P (x) && TREE_SIDE_EFFECTS (x)) + TREE_SIDE_EFFECTS (t) = 1; } va_end (p); + return t; } @@ -3259,12 +3346,7 @@ build_min_non_dep (enum tree_code code, tree non_dep, ...) TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (non_dep); for (i = 0; i < length; i++) - { - tree x = va_arg (p, tree); - TREE_OPERAND (t, i) = x; - if (x && TREE_CODE (x) == OVERLOAD) - lookup_keep (x, true); - } + TREE_OPERAND (t, i) = va_arg (p, tree); if (code == COMPOUND_EXPR && TREE_CODE (non_dep) != COMPOUND_EXPR) /* This should not be considered a COMPOUND_EXPR, because it @@ -3287,11 +3369,8 @@ build_min_nt_call_vec (tree fn, vec *args) CALL_EXPR_FN (ret) = fn; CALL_EXPR_STATIC_CHAIN (ret) = NULL_TREE; FOR_EACH_VEC_SAFE_ELT (args, ix, t) - { - CALL_EXPR_ARG (ret, ix) = t; - if (TREE_CODE (t) == OVERLOAD) - lookup_keep (t, true); - } + CALL_EXPR_ARG (ret, ix) = t; + return ret; } @@ -3324,7 +3403,6 @@ build_min_non_dep_op_overload (enum tree_code op, va_list p; int nargs, expected_nargs; tree fn, call; - vec *args; non_dep = extract_call_expr (non_dep); @@ -3338,7 +3416,7 @@ build_min_non_dep_op_overload (enum tree_code op, expected_nargs += 1; gcc_assert (nargs == expected_nargs); - args = make_tree_vector (); + releasing_vec args; va_start (p, overload); if (TREE_CODE (TREE_TYPE (overload)) == FUNCTION_TYPE) @@ -3368,7 +3446,6 @@ build_min_non_dep_op_overload (enum tree_code op, va_end (p); call = build_min_non_dep_call_vec (non_dep, fn, args); - release_tree_vector (args); tree call_expr = extract_call_expr (call); KOENIG_LOOKUP_P (call_expr) = KOENIG_LOOKUP_P (non_dep); @@ -3494,6 +3571,10 @@ cp_tree_equal (tree t1, tree t2) if (code1 != code2) return false; + if (CONSTANT_CLASS_P (t1) + && !same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))) + return false; + switch (code1) { case VOID_CST: @@ -3625,6 +3706,8 @@ cp_tree_equal (tree t1, tree t2) case TEMPLATE_DECL: case IDENTIFIER_NODE: case SSA_NAME: + case USING_DECL: + case DEFERRED_PARSE: return false; case BASELINK: @@ -3751,6 +3834,10 @@ cp_tree_equal (tree t1, tree t2) DEFERRED_NOEXCEPT_ARGS (t2))); break; + case LAMBDA_EXPR: + /* Two lambda-expressions are never considered equivalent. */ + return false; + default: break; } @@ -3936,15 +4023,28 @@ maybe_warn_parm_abi (tree t, location_t loc) || !deleted_copy_types->contains (t)) return; - warning_at (loc, OPT_Wabi, "the calling convention for %qT changes in " - "-fabi-version=12 (GCC 8)", t); - static bool explained = false; - if (!explained) + if ((flag_abi_version == 12 || warn_abi_version == 12) + && classtype_has_non_deleted_move_ctor (t)) { - inform (loc, " because all of its copy and move constructors " - "are deleted"); - explained = true; + bool w; + auto_diagnostic_group d; + if (flag_abi_version > 12) + w = warning_at (loc, OPT_Wabi, "%<-fabi-version=13%> (GCC 8.2) fixes " + "the calling convention for %qT, which was " + "accidentally changed in 8.1", t); + else + w = warning_at (loc, OPT_Wabi, "%<-fabi-version=12%> (GCC 8.1) accident" + "ally changes the calling convention for %qT", t); + if (w) + inform (location_of (t), " declared here"); + return; } + + auto_diagnostic_group d; + if (warning_at (loc, OPT_Wabi, "the calling convention for %qT changes in " + "%<-fabi-version=13%> (GCC 8.2)", t)) + inform (location_of (t), " because all of its copy and move " + "constructors are deleted"); } /* Returns true iff copying an object of type T (including via move @@ -3979,6 +4079,7 @@ type_has_nontrivial_copy_init (const_tree type) bool saw_copy = false; bool saw_non_deleted = false; + bool saw_non_deleted_move = false; if (CLASSTYPE_LAZY_MOVE_CTOR (t)) saw_copy = saw_non_deleted = true; @@ -4010,19 +4111,27 @@ type_has_nontrivial_copy_init (const_tree type) break; } } + else if (move_fn_p (fn)) + if (!DECL_DELETED_FN (fn)) + saw_non_deleted_move = true; } gcc_assert (saw_copy); - if (saw_copy && !saw_non_deleted) - { - if (warn_abi && abi_version_crosses (12)) - remember_deleted_copy (t); - if (abi_version_at_least (12)) - return true; - } - - return false; + /* ABI v12 buggily ignored move constructors. */ + bool v11nontriv = false; + bool v12nontriv = !saw_non_deleted; + bool v13nontriv = !saw_non_deleted && !saw_non_deleted_move; + bool nontriv = (abi_version_at_least (13) ? v13nontriv + : flag_abi_version == 12 ? v12nontriv + : v11nontriv); + bool warn_nontriv = (warn_abi_version >= 13 ? v13nontriv + : warn_abi_version == 12 ? v12nontriv + : v11nontriv); + if (nontriv != warn_nontriv) + remember_deleted_copy (t); + + return nontriv; } else return 0; @@ -4045,7 +4154,8 @@ trivially_copyable_p (const_tree t) && !TYPE_HAS_COMPLEX_MOVE_ASSIGN (t) && TYPE_HAS_TRIVIAL_DESTRUCTOR (t)); else - return !CP_TYPE_VOLATILE_P (t) && scalarish_type_p (t); + /* CWG 2094 makes volatile-qualified scalars trivially copyable again. */ + return scalarish_type_p (t); } /* Returns 1 iff type T is a trivial type, as defined in [basic.types] and @@ -4292,18 +4402,82 @@ zero_init_p (const_tree t) return 1; } +/* True IFF T is a C++20 structural type (P1907R1) that can be used as a + non-type template parameter. If EXPLAIN, explain why not. */ + +bool +structural_type_p (tree t, bool explain) +{ + t = strip_array_types (t); + if (INTEGRAL_OR_ENUMERATION_TYPE_P (t)) + return true; + if (NULLPTR_TYPE_P (t)) + return true; + if (TYPE_PTR_P (t) || TYPE_PTRMEM_P (t)) + return true; + if (TYPE_REF_P (t) && !TYPE_REF_IS_RVALUE (t)) + return true; + if (!CLASS_TYPE_P (t)) + return false; + if (TREE_CODE (t) == UNION_TYPE) + { + if (explain) + inform (location_of (t), "%qT is a union", t); + return false; + } + if (!literal_type_p (t)) + { + if (explain) + explain_non_literal_class (t); + return false; + } + if (CLASSTYPE_HAS_MUTABLE (t)) + { + if (explain) + inform (location_of (t), "%qT has a mutable member", t); + return false; + } + for (tree m = next_initializable_field (TYPE_FIELDS (t)); m; + m = next_initializable_field (DECL_CHAIN (m))) + { + if (TREE_PRIVATE (m) || TREE_PROTECTED (m)) + { + if (explain) + inform (location_of (m), "%qD is not public", m); + return false; + } + if (!structural_type_p (TREE_TYPE (m))) + { + if (explain) + { + inform (location_of (m), "%qD has a non-structural type", m); + structural_type_p (TREE_TYPE (m), true); + } + return false; + } + } + return true; +} + /* Handle the C++17 [[nodiscard]] attribute, which is similar to the GNU warn_unused_result attribute. */ static tree -handle_nodiscard_attribute (tree *node, tree name, tree /*args*/, +handle_nodiscard_attribute (tree *node, tree name, tree args, int /*flags*/, bool *no_add_attrs) { + if (args && TREE_CODE (TREE_VALUE (args)) != STRING_CST) + { + error ("%qE attribute argument must be a string constant", name); + *no_add_attrs = true; + } if (TREE_CODE (*node) == FUNCTION_DECL) { - if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (*node)))) - warning (OPT_Wattributes, "%qE attribute applied to %qD with void " - "return type", name, *node); + if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (*node))) + && !DECL_CONSTRUCTOR_P (*node)) + warning_at (DECL_SOURCE_LOCATION (*node), + OPT_Wattributes, "%qE attribute applied to %qD with void " + "return type", name, *node); } else if (OVERLOAD_TYPE_P (*node)) /* OK */; @@ -4316,28 +4490,87 @@ handle_nodiscard_attribute (tree *node, tree name, tree /*args*/, return NULL_TREE; } +/* Handle a C++2a "no_unique_address" attribute; arguments as in + struct attribute_spec.handler. */ +static tree +handle_no_unique_addr_attribute (tree* node, + tree name, + tree /*args*/, + int /*flags*/, + bool* no_add_attrs) +{ + if (TREE_CODE (*node) != FIELD_DECL) + { + warning (OPT_Wattributes, "%qE attribute can only be applied to " + "non-static data members", name); + *no_add_attrs = true; + } + else if (DECL_C_BIT_FIELD (*node)) + { + warning (OPT_Wattributes, "%qE attribute cannot be applied to " + "a bit-field", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* The C++20 [[likely]] and [[unlikely]] attributes on labels map to the GNU + hot/cold attributes. */ + +static tree +handle_likeliness_attribute (tree *node, tree name, tree args, + int flags, bool *no_add_attrs) +{ + *no_add_attrs = true; + if (TREE_CODE (*node) == LABEL_DECL + || TREE_CODE (*node) == FUNCTION_DECL) + { + if (args) + warning (OPT_Wattributes, "%qE attribute takes no arguments", name); + tree bname = (is_attribute_p ("likely", name) + ? get_identifier ("hot") : get_identifier ("cold")); + if (TREE_CODE (*node) == FUNCTION_DECL) + warning (OPT_Wattributes, "ISO C++ %qE attribute does not apply to " + "functions; treating as %<[[gnu::%E]]%>", name, bname); + tree battr = build_tree_list (bname, NULL_TREE); + decl_attributes (node, battr, flags); + return NULL_TREE; + } + else + return error_mark_node; +} + /* Table of valid C++ attributes. */ const struct attribute_spec cxx_attribute_table[] = { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity } */ - { "init_priority", 1, 1, true, false, false, - handle_init_priority_attribute, false }, - { "abi_tag", 1, -1, false, false, false, - handle_abi_tag_attribute, true }, - { NULL, 0, 0, false, false, false, NULL, false } + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, + affects_type_identity, handler, exclude } */ + { "init_priority", 1, 1, true, false, false, false, + handle_init_priority_attribute, NULL }, + { "abi_tag", 1, -1, false, false, false, true, + handle_abi_tag_attribute, NULL }, + { NULL, 0, 0, false, false, false, false, NULL, NULL } }; /* Table of C++ standard attributes. */ const struct attribute_spec std_attribute_table[] = { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, - affects_type_identity } */ - { "maybe_unused", 0, 0, false, false, false, - handle_unused_attribute, false }, - { "nodiscard", 0, 0, false, false, false, - handle_nodiscard_attribute, false }, - { NULL, 0, 0, false, false, false, NULL, false } + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, + affects_type_identity, handler, exclude } */ + { "maybe_unused", 0, 0, false, false, false, false, + handle_unused_attribute, NULL }, + { "nodiscard", 0, 1, false, false, false, false, + handle_nodiscard_attribute, NULL }, + { "no_unique_address", 0, 0, true, false, false, false, + handle_no_unique_addr_attribute, NULL }, + { "likely", 0, 0, false, false, false, false, + handle_likeliness_attribute, attr_cold_hot_exclusions }, + { "unlikely", 0, 0, false, false, false, false, + handle_likeliness_attribute, attr_cold_hot_exclusions }, + { "noreturn", 0, 0, true, false, false, false, + handle_noreturn_attribute, attr_noreturn_exclusions }, + { NULL, 0, 0, false, false, false, false, NULL, NULL } }; /* Handle an "init_priority" attribute; arguments as in @@ -4361,7 +4594,7 @@ handle_init_priority_attribute (tree* node, if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST) { - error ("requested init_priority is not an integer constant"); + error ("requested % is not an integer constant"); cxx_constant_value (initp_expr); *no_add_attrs = true; return NULL_TREE; @@ -4391,7 +4624,8 @@ handle_init_priority_attribute (tree* node, if (pri > MAX_INIT_PRIORITY || pri <= 0) { - error ("requested init_priority is out of range"); + error ("requested % %i is out of range [0, %i]", + pri, MAX_INIT_PRIORITY); *no_add_attrs = true; return NULL_TREE; } @@ -4401,7 +4635,8 @@ handle_init_priority_attribute (tree* node, if (pri <= MAX_RESERVED_INIT_PRIORITY) { warning - (0, "requested init_priority is reserved for internal use"); + (0, "requested % %i is reserved for internal use", + pri); } if (SUPPORTS_INIT_PRIORITY) @@ -4604,14 +4839,8 @@ cp_build_type_attribute_variant (tree type, tree attributes) tree new_type; new_type = build_type_attribute_variant (type, attributes); - if (TREE_CODE (new_type) == FUNCTION_TYPE - || TREE_CODE (new_type) == METHOD_TYPE) - { - new_type = build_exception_variant (new_type, - TYPE_RAISES_EXCEPTIONS (type)); - new_type = build_ref_qualified_type (new_type, - type_memfn_rqual (type)); - } + if (FUNC_OR_METHOD_TYPE_P (new_type)) + gcc_checking_assert (cxx_type_hash_eq (type, new_type)); /* Making a new main variant of a class type is broken. */ gcc_assert (!CLASS_TYPE_P (type) || new_type == type); @@ -4625,11 +4854,12 @@ cp_build_type_attribute_variant (tree type, tree attributes) bool cxx_type_hash_eq (const_tree typea, const_tree typeb) { - gcc_assert (TREE_CODE (typea) == FUNCTION_TYPE - || TREE_CODE (typea) == METHOD_TYPE); + gcc_assert (FUNC_OR_METHOD_TYPE_P (typea)); if (type_memfn_rqual (typea) != type_memfn_rqual (typeb)) return false; + if (TYPE_HAS_LATE_RETURN_TYPE (typea) != TYPE_HAS_LATE_RETURN_TYPE (typeb)) + return false; return comp_except_specs (TYPE_RAISES_EXCEPTIONS (typea), TYPE_RAISES_EXCEPTIONS (typeb), ce_exact); } @@ -4641,11 +4871,10 @@ tree cxx_copy_lang_qualifiers (const_tree typea, const_tree typeb) { tree type = CONST_CAST_TREE (typea); - if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE) - { - type = build_exception_variant (type, TYPE_RAISES_EXCEPTIONS (typeb)); - type = build_ref_qualified_type (type, type_memfn_rqual (typeb)); - } + if (FUNC_OR_METHOD_TYPE_P (type)) + type = build_cp_fntype_variant (type, type_memfn_rqual (typeb), + TYPE_RAISES_EXCEPTIONS (typeb), + TYPE_HAS_LATE_RETURN_TYPE (typeb)); return type; } @@ -4672,7 +4901,7 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, result = NULL_TREE; switch (code) { - case DEFAULT_ARG: + case DEFERRED_PARSE: case TEMPLATE_TEMPLATE_PARM: case BOUND_TEMPLATE_TEMPLATE_PARM: case UNBOUND_CLASS_TEMPLATE: @@ -4766,7 +4995,19 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, break; case DECLTYPE_TYPE: - WALK_SUBTREE (DECLTYPE_TYPE_EXPR (*tp)); + ++cp_unevaluated_operand; + /* We can't use WALK_SUBTREE here because of the goto. */ + result = cp_walk_tree (&DECLTYPE_TYPE_EXPR (*tp), func, data, pset); + --cp_unevaluated_operand; + *walk_subtrees_p = 0; + break; + + case ALIGNOF_EXPR: + case SIZEOF_EXPR: + case NOEXCEPT_EXPR: + ++cp_unevaluated_operand; + result = cp_walk_tree (&TREE_OPERAND (*tp, 0), func, data, pset); + --cp_unevaluated_operand; *walk_subtrees_p = 0; break; @@ -4783,10 +5024,12 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, /* User variables should be mentioned in BIND_EXPR_VARS and their initializers and sizes walked when walking the containing BIND_EXPR. Compiler temporaries are - handled here. */ + handled here. And also normal variables in templates, + since do_poplevel doesn't build a BIND_EXPR then. */ if (VAR_P (TREE_OPERAND (*tp, 0)) - && DECL_ARTIFICIAL (TREE_OPERAND (*tp, 0)) - && !TREE_STATIC (TREE_OPERAND (*tp, 0))) + && (processing_template_decl + || (DECL_ARTIFICIAL (TREE_OPERAND (*tp, 0)) + && !TREE_STATIC (TREE_OPERAND (*tp, 0))))) { tree decl = TREE_OPERAND (*tp, 0); WALK_SUBTREE (DECL_INITIAL (decl)); @@ -4795,6 +5038,14 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, } break; + case LAMBDA_EXPR: + /* Don't walk into the body of the lambda, but the capture initializers + are part of the enclosing context. */ + for (tree cap = LAMBDA_EXPR_CAPTURE_LIST (*tp); cap; + cap = TREE_CHAIN (cap)) + WALK_SUBTREE (TREE_VALUE (cap)); + break; + default: return NULL_TREE; } @@ -4817,6 +5068,11 @@ cp_save_expr (tree expr) tree codes. */ if (processing_template_decl) return expr; + + /* TARGET_EXPRs are only expanded once. */ + if (TREE_CODE (expr) == TARGET_EXPR) + return expr; + return save_expr (expr); } @@ -4867,7 +5123,35 @@ special_function_p (const_tree decl) return sfk_conversion; if (deduction_guide_p (decl)) return sfk_deduction_guide; + if (DECL_OVERLOADED_OPERATOR_CODE_RAW (decl) >= OVL_OP_EQ_EXPR + && DECL_OVERLOADED_OPERATOR_CODE_RAW (decl) <= OVL_OP_SPACESHIP_EXPR) + return sfk_comparison; + + return sfk_none; +} +/* As above, but only if DECL is a special member function as per 11.3.3 + [special]: default/copy/move ctor, copy/move assignment, or destructor. */ + +special_function_kind +special_memfn_p (const_tree decl) +{ + switch (special_function_kind sfk = special_function_p (decl)) + { + case sfk_constructor: + if (!default_ctor_p (decl)) + break; + gcc_fallthrough(); + case sfk_copy_constructor: + case sfk_copy_assignment: + case sfk_move_assignment: + case sfk_move_constructor: + case sfk_destructor: + return sfk; + + default: + break; + } return sfk_none; } @@ -4879,6 +5163,7 @@ char_type_p (tree type) return (same_type_p (type, char_type_node) || same_type_p (type, unsigned_char_type_node) || same_type_p (type, signed_char_type_node) + || same_type_p (type, char8_type_node) || same_type_p (type, char16_type_node) || same_type_p (type, char32_type_node) || same_type_p (type, wchar_type_node)); @@ -4915,10 +5200,9 @@ decl_linkage (tree decl) /* maybe_thunk_body clears TREE_PUBLIC on the maybe-in-charge 'tor variants, check one of the "clones" for the real linkage. */ - if ((DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl) - || DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)) + if (DECL_MAYBE_IN_CHARGE_CDTOR_P (decl) && DECL_CHAIN (decl) - && DECL_CLONED_FUNCTION (DECL_CHAIN (decl))) + && DECL_CLONED_FUNCTION_P (DECL_CHAIN (decl))) return decl_linkage (DECL_CHAIN (decl)); if (TREE_CODE (decl) == NAMESPACE_DECL) @@ -4994,7 +5278,7 @@ stabilize_expr (tree exp, tree* initp) } /* There are no expressions with REFERENCE_TYPE, but there can be call arguments with such a type; just treat it as a pointer. */ - else if (TREE_CODE (TREE_TYPE (exp)) == REFERENCE_TYPE + else if (TYPE_REF_P (TREE_TYPE (exp)) || SCALAR_TYPE_P (TREE_TYPE (exp)) || !glvalue_p (exp)) { @@ -5155,7 +5439,7 @@ stabilize_init (tree init, tree *initp) { tree type = TREE_TYPE (ce->value); tree subinit; - if (TREE_CODE (type) == REFERENCE_TYPE + if (TYPE_REF_P (type) || SCALAR_TYPE_P (type)) ce->value = stabilize_expr (ce->value, &subinit); else if (!stabilize_init (ce->value, &subinit)) @@ -5227,8 +5511,7 @@ cp_fix_function_decl_p (tree decl) void cp_free_lang_data (tree t) { - if (TREE_CODE (t) == METHOD_TYPE - || TREE_CODE (t) == FUNCTION_TYPE) + if (FUNC_OR_METHOD_TYPE_P (t)) { /* Default args are not interesting anymore. */ tree argtypes = TYPE_ARG_TYPES (t); @@ -5247,6 +5530,8 @@ cp_free_lang_data (tree t) DECL_EXTERNAL (t) = 1; TREE_STATIC (t) = 0; } + if (TREE_CODE (t) == FUNCTION_DECL) + discard_operator_bindings (t); if (TREE_CODE (t) == NAMESPACE_DECL) /* We do not need the leftover chaining of namespaces from the binding level. */ @@ -5302,13 +5587,35 @@ cp_tree_code_length (enum tree_code code) } } +/* Like EXPR_LOCATION, but also handle some tcc_exceptional that have + locations. */ + +location_t +cp_expr_location (const_tree t_) +{ + tree t = CONST_CAST_TREE (t_); + if (t == NULL_TREE) + return UNKNOWN_LOCATION; + switch (TREE_CODE (t)) + { + case LAMBDA_EXPR: + return LAMBDA_EXPR_LOCATION (t); + case STATIC_ASSERT: + return STATIC_ASSERT_SOURCE_LOCATION (t); + case TRAIT_EXPR: + return TRAIT_EXPR_LOCATION (t); + default: + return EXPR_LOCATION (t); + } +} + /* Implement -Wzero_as_null_pointer_constant. Return true if the conditions for the warning hold, false otherwise. */ bool maybe_warn_zero_as_null_pointer_constant (tree expr, location_t loc) { if (c_inhibit_evaluation_warnings == 0 - && !NULLPTR_TYPE_P (TREE_TYPE (expr))) + && !null_node_p (expr) && !NULLPTR_TYPE_P (TREE_TYPE (expr))) { warning_at (loc, OPT_Wzero_as_null_pointer_constant, "zero as null pointer constant"); @@ -5317,6 +5624,68 @@ maybe_warn_zero_as_null_pointer_constant (tree expr, location_t loc) return false; } +/* Given an initializer INIT for a TYPE, return true if INIT is zero + so that it can be replaced by value initialization. This function + distinguishes betwen empty strings as initializers for arrays and + for pointers (which make it return false). */ + +bool +type_initializer_zero_p (tree type, tree init) +{ + if (type == error_mark_node || init == error_mark_node) + return false; + + STRIP_NOPS (init); + + if (POINTER_TYPE_P (type)) + return TREE_CODE (init) != STRING_CST && initializer_zerop (init); + + if (TREE_CODE (init) != CONSTRUCTOR) + return initializer_zerop (init); + + if (TREE_CODE (type) == ARRAY_TYPE) + { + tree elt_type = TREE_TYPE (type); + elt_type = TYPE_MAIN_VARIANT (elt_type); + if (elt_type == char_type_node) + return initializer_zerop (init); + + tree elt_init; + unsigned HOST_WIDE_INT i; + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), i, elt_init) + if (!type_initializer_zero_p (elt_type, elt_init)) + return false; + return true; + } + + if (TREE_CODE (type) != RECORD_TYPE) + return initializer_zerop (init); + + if (TYPE_NON_AGGREGATE_CLASS (type)) + return false; + + tree fld = TYPE_FIELDS (type); + + tree fld_init; + unsigned HOST_WIDE_INT i; + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), i, fld_init) + { + fld = next_initializable_field (fld); + if (!fld) + return true; + + tree fldtype = TREE_TYPE (fld); + if (!type_initializer_zero_p (fldtype, fld_init)) + return false; + + fld = DECL_CHAIN (fld); + if (!fld) + break; + } + + return true; +} + #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007) /* Complain that some language-specific thing hanging off a tree node has been accessed improperly. */ @@ -5324,9 +5693,77 @@ maybe_warn_zero_as_null_pointer_constant (tree expr, location_t loc) void lang_check_failed (const char* file, int line, const char* function) { - internal_error ("lang_* check: failed in %s, at %s:%d", + internal_error ("% check: failed in %s, at %s:%d", function, trim_filename (file), line); } #endif /* ENABLE_TREE_CHECKING */ +#if CHECKING_P + +namespace selftest { + +/* Verify that lvalue_kind () works, for various expressions, + and that location wrappers don't affect the results. */ + +static void +test_lvalue_kind () +{ + location_t loc = BUILTINS_LOCATION; + + /* Verify constants and parameters, without and with + location wrappers. */ + tree int_cst = build_int_cst (integer_type_node, 42); + ASSERT_EQ (clk_none, lvalue_kind (int_cst)); + + tree wrapped_int_cst = maybe_wrap_with_location (int_cst, loc); + ASSERT_TRUE (location_wrapper_p (wrapped_int_cst)); + ASSERT_EQ (clk_none, lvalue_kind (wrapped_int_cst)); + + tree string_lit = build_string (4, "foo"); + TREE_TYPE (string_lit) = char_array_type_node; + string_lit = fix_string_type (string_lit); + ASSERT_EQ (clk_ordinary, lvalue_kind (string_lit)); + + tree wrapped_string_lit = maybe_wrap_with_location (string_lit, loc); + ASSERT_TRUE (location_wrapper_p (wrapped_string_lit)); + ASSERT_EQ (clk_ordinary, lvalue_kind (wrapped_string_lit)); + + tree parm = build_decl (UNKNOWN_LOCATION, PARM_DECL, + get_identifier ("some_parm"), + integer_type_node); + ASSERT_EQ (clk_ordinary, lvalue_kind (parm)); + + tree wrapped_parm = maybe_wrap_with_location (parm, loc); + ASSERT_TRUE (location_wrapper_p (wrapped_parm)); + ASSERT_EQ (clk_ordinary, lvalue_kind (wrapped_parm)); + + /* Verify that lvalue_kind of std::move on a parm isn't + affected by location wrappers. */ + tree rvalue_ref_of_parm = move (parm); + ASSERT_EQ (clk_rvalueref, lvalue_kind (rvalue_ref_of_parm)); + tree rvalue_ref_of_wrapped_parm = move (wrapped_parm); + ASSERT_EQ (clk_rvalueref, lvalue_kind (rvalue_ref_of_wrapped_parm)); + + /* Verify lvalue_p. */ + ASSERT_FALSE (lvalue_p (int_cst)); + ASSERT_FALSE (lvalue_p (wrapped_int_cst)); + ASSERT_TRUE (lvalue_p (parm)); + ASSERT_TRUE (lvalue_p (wrapped_parm)); + ASSERT_FALSE (lvalue_p (rvalue_ref_of_parm)); + ASSERT_FALSE (lvalue_p (rvalue_ref_of_wrapped_parm)); +} + +/* Run all of the selftests within this file. */ + +void +cp_tree_c_tests () +{ + test_lvalue_kind (); +} + +} // namespace selftest + +#endif /* #if CHECKING_P */ + + #include "gt-cp-tree.h"