Mercurial > hg > CbC > CbC_gcc
diff gcc/cp/tree.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
line wrap: on
line diff
--- a/gcc/cp/tree.c Thu Oct 25 07:37:49 2018 +0900 +++ b/gcc/cp/tree.c Thu Feb 13 11:34:05 2020 +0900 @@ -1,5 +1,5 @@ /* Language-dependent node constructors for parse phase of GNU compiler. - Copyright (C) 1987-2018 Free Software Foundation, Inc. + Copyright (C) 1987-2020 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. @@ -43,7 +43,6 @@ 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 *); @@ -83,6 +82,10 @@ 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: @@ -232,10 +235,23 @@ gcc_assert (!type_dependent_expression_p (CONST_CAST_TREE (ref))); goto default_; } - 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)); + { + 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: @@ -280,6 +296,12 @@ 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)) @@ -371,6 +393,7 @@ tree cp_stabilize_reference (tree ref) { + STRIP_ANY_LOCATION_WRAPPER (ref); switch (TREE_CODE (ref)) { case NON_DEPENDENT_EXPR: @@ -402,7 +425,8 @@ /* This inhibits warnings in, eg, cxx_mark_addressable (c++/60955). */ warning_sentinel s (extra_warnings); - ref = build_static_cast (type, ref, tf_error); + ref = build_static_cast (input_location, type, ref, + tf_error); } } @@ -415,13 +439,16 @@ bool builtin_valid_in_constant_expr_p (const_tree decl) { + 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)) + BUILT_IN_FRONTEND) + || fndecl_built_in_p (decl, CP_BUILT_IN_SOURCE_LOCATION, + BUILT_IN_FRONTEND)) return true; /* Not a built-in. */ return false; @@ -500,7 +527,7 @@ /* 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, @@ -512,6 +539,17 @@ return slot; } +/* Return whether DECL is such a local temporary (or one from + create_tmp_var_raw). */ + +bool +is_local_temp (tree decl) +{ + return (VAR_P (decl) && DECL_ARTIFICIAL (decl) + && !TREE_STATIC (decl) + && DECL_FUNCTION_SCOPE_P (decl)); +} + /* Set various status flags when building an AGGR_INIT_EXPR object T. */ static void @@ -576,6 +614,8 @@ 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; @@ -643,6 +683,15 @@ 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; @@ -688,7 +737,6 @@ build_vec_init_elt (tree type, tree init, tsubst_flags_t complain) { tree inner_type = strip_array_types (type); - vec<tree, va_gc> *argvec; if (integer_zerop (array_type_nelts_total (type)) || !CLASS_TYPE_P (inner_type)) @@ -701,7 +749,7 @@ || (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)); @@ -713,7 +761,6 @@ 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. */ @@ -1088,6 +1135,15 @@ return build_cplus_array_type (elt, build_index_type (size_int (n - 1))); } +/* True iff T is an array of unknown bound. */ + +bool +array_of_unknown_bound_p (const_tree t) +{ + return (TREE_CODE (t) == ARRAY_TYPE + && !TYPE_DOMAIN (t)); +} + /* 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 @@ -1187,7 +1243,8 @@ tree type = TREE_TYPE (expr); gcc_assert (!TYPE_REF_P (type)); type = cp_build_reference_type (type, /*rval*/true); - return build_static_cast (type, expr, tf_warning_or_error); + return build_static_cast (input_location, type, expr, + tf_warning_or_error); } /* Used by the C++ front end to build qualified array types. However, @@ -1298,8 +1355,7 @@ (in CD1) we always ignore extra cv-quals on functions. */ if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE) && (TYPE_REF_P (type) - || TREE_CODE (type) == FUNCTION_TYPE - || TREE_CODE (type) == METHOD_TYPE)) + || FUNC_OR_METHOD_TYPE_P (type))) { if (TYPE_REF_P (type)) bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE); @@ -1407,7 +1463,10 @@ 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; @@ -1432,7 +1491,7 @@ 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; @@ -1442,19 +1501,18 @@ if (TREE_CODE (t) == TREE_LIST) { bool changed = false; - vec<tree,va_gc> *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; } @@ -1463,7 +1521,8 @@ 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; @@ -1471,28 +1530,29 @@ 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: @@ -1511,7 +1571,7 @@ && (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); @@ -1525,7 +1585,7 @@ 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; @@ -1589,9 +1649,10 @@ 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; @@ -1607,7 +1668,7 @@ 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; @@ -1620,7 +1681,7 @@ 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 @@ -1630,7 +1691,8 @@ 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: @@ -1641,15 +1703,24 @@ { 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 @@ -1698,7 +1769,7 @@ 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; @@ -1707,13 +1778,15 @@ 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) @@ -1727,8 +1800,10 @@ 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; @@ -1740,12 +1815,13 @@ case TREE_LIST: { - vec<tree, va_gc> *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 (it), remove_attributes); + tree val = strip_typedefs_expr (TREE_VALUE (it), + remove_attributes, flags); vec_safe_push (vec, val); if (val != TREE_VALUE (it)) changed = true; @@ -1759,20 +1835,19 @@ } else r = t; - release_tree_vector (vec); return r; } case TREE_VEC: { bool changed = false; - vec<tree, va_gc> *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; @@ -1787,7 +1862,6 @@ } else r = t; - release_tree_vector (vec); return r; } @@ -1797,18 +1871,19 @@ vec<constructor_elt, va_gc> *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)) @@ -1826,8 +1901,7 @@ } case LAMBDA_EXPR: - error ("lambda-expression in a constant expression"); - return error_mark_node; + return t; case STATEMENT_LIST: error ("statement-expression in a constant expression"); @@ -1853,12 +1927,13 @@ 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; } @@ -2153,78 +2228,52 @@ 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 = 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; } @@ -2255,25 +2304,27 @@ 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). */ @@ -2281,20 +2332,11 @@ 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); } @@ -2329,6 +2371,9 @@ 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); @@ -2367,7 +2412,8 @@ 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; } @@ -2384,40 +2430,6 @@ 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; - } -} - -/* Preserve the contents of a lookup so that it is available for a - later instantiation. */ - -void -lookup_keep (tree lookup) -{ - for (; - lookup && TREE_CODE (lookup) == OVERLOAD - && OVL_LOOKUP_P (lookup) && !OVL_USED_P (lookup); - lookup = OVL_CHAIN (lookup)) - { - OVL_USED_P (lookup) = true; - ovl_used (OVL_FUNCTION (lookup)); - } - - 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<int>" will all be considered possibly @@ -2428,6 +2440,8 @@ 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) @@ -2440,8 +2454,7 @@ || (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 @@ -2455,7 +2468,7 @@ 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; } @@ -2476,6 +2489,8 @@ tree 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) @@ -2485,8 +2500,7 @@ if (TREE_CODE (from) == TEMPLATE_ID_EXPR) from = TREE_OPERAND (from, 0); - if (TREE_CODE (from) == OVERLOAD - || TREE_CODE (from) == FUNCTION_DECL) + if (OVL_P (from)) return from; return NULL; @@ -2601,6 +2615,7 @@ 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. */ @@ -2772,7 +2787,18 @@ { 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; @@ -2782,15 +2808,6 @@ 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)) @@ -3168,6 +3185,11 @@ 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)) { @@ -3343,6 +3365,7 @@ non_dep = TREE_OPERAND (non_dep, 0); t = make_node (code); + SET_EXPR_LOCATION (t, cp_expr_loc_or_input_loc (non_dep)); length = TREE_CODE_LENGTH (code); TREE_TYPE (t) = unlowered_expr_type (non_dep); TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (non_dep); @@ -3405,7 +3428,6 @@ va_list p; int nargs, expected_nargs; tree fn, call; - vec<tree, va_gc> *args; non_dep = extract_call_expr (non_dep); @@ -3419,7 +3441,7 @@ 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) @@ -3449,7 +3471,6 @@ 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); @@ -3710,6 +3731,8 @@ case TEMPLATE_DECL: case IDENTIFIER_NODE: case SSA_NAME: + case USING_DECL: + case DEFERRED_PARSE: return false; case BASELINK: @@ -3836,12 +3859,8 @@ DEFERRED_NOEXCEPT_ARGS (t2))); break; - case USING_DECL: - if (DECL_DEPENDENT_P (t1) && DECL_DEPENDENT_P (t2)) - return (cp_tree_equal (USING_DECL_SCOPE (t1), - USING_DECL_SCOPE (t2)) - && cp_tree_equal (DECL_NAME (t1), - DECL_NAME (t2))); + case LAMBDA_EXPR: + /* Two lambda-expressions are never considered equivalent. */ return false; default: @@ -4035,11 +4054,11 @@ 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); + 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" + 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"); @@ -4048,7 +4067,7 @@ auto_diagnostic_group d; if (warning_at (loc, OPT_Wabi, "the calling convention for %qT changes in " - "-fabi-version=13 (GCC 8.2)", t)) + "%<-fabi-version=13%> (GCC 8.2)", t)) inform (location_of (t), " because all of its copy and move " "constructors are deleted"); } @@ -4160,7 +4179,8 @@ && !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 @@ -4407,18 +4427,88 @@ 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) + { + if (DECL_FIELD_IS_BASE (m)) + inform (location_of (m), "base class %qT is not public", + TREE_TYPE (m)); + else + 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 */; @@ -4456,6 +4546,32 @@ 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[] = { @@ -4475,10 +4591,16 @@ affects_type_identity, handler, exclude } */ { "maybe_unused", 0, 0, false, false, false, false, handle_unused_attribute, NULL }, - { "nodiscard", 0, 0, false, false, false, false, + { "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 } }; @@ -4503,7 +4625,7 @@ if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST) { - error ("requested init_priority is not an integer constant"); + error ("requested %<init_priority%> is not an integer constant"); cxx_constant_value (initp_expr); *no_add_attrs = true; return NULL_TREE; @@ -4533,7 +4655,8 @@ if (pri > MAX_INIT_PRIORITY || pri <= 0) { - error ("requested init_priority is out of range"); + error ("requested %<init_priority%> %i is out of range [0, %i]", + pri, MAX_INIT_PRIORITY); *no_add_attrs = true; return NULL_TREE; } @@ -4543,7 +4666,8 @@ if (pri <= MAX_RESERVED_INIT_PRIORITY) { warning - (0, "requested init_priority is reserved for internal use"); + (0, "requested %<init_priority%> %i is reserved for internal use", + pri); } if (SUPPORTS_INIT_PRIORITY) @@ -4746,8 +4870,7 @@ tree new_type; new_type = build_type_attribute_variant (type, attributes); - if (TREE_CODE (new_type) == FUNCTION_TYPE - || TREE_CODE (new_type) == METHOD_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. */ @@ -4762,8 +4885,7 @@ 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; @@ -4780,7 +4902,7 @@ 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) + 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)); @@ -4805,12 +4927,17 @@ } \ while (0) + if (TYPE_P (*tp)) + /* Walk into template args without looking through typedefs. */ + if (tree ti = TYPE_TEMPLATE_INFO_MAYBE_ALIAS (*tp)) + WALK_SUBTREE (TI_ARGS (ti)); + /* Not one of the easy cases. We must explicitly go through the children. */ result = NULL_TREE; switch (code) { - case DEFAULT_ARG: + case DEFERRED_PARSE: case TEMPLATE_TEMPLATE_PARM: case BOUND_TEMPLATE_TEMPLATE_PARM: case UNBOUND_CLASS_TEMPLATE: @@ -4897,6 +5024,11 @@ *walk_subtrees_p = 0; break; + case CONSTRUCTOR: + if (COMPOUND_LITERAL_P (*tp)) + WALK_SUBTREE (TREE_TYPE (*tp)); + break; + case TRAIT_EXPR: WALK_SUBTREE (TRAIT_EXPR_TYPE1 (*tp)); WALK_SUBTREE (TRAIT_EXPR_TYPE2 (*tp)); @@ -4947,6 +5079,45 @@ } 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; + + case CO_YIELD_EXPR: + if (TREE_OPERAND (*tp, 1)) + /* Operand 1 is the tree for the relevant co_await which has any + interesting sub-trees. */ + WALK_SUBTREE (TREE_OPERAND (*tp, 1)); + break; + + case CO_AWAIT_EXPR: + if (TREE_OPERAND (*tp, 1)) + /* Operand 1 is frame variable. */ + WALK_SUBTREE (TREE_OPERAND (*tp, 1)); + if (TREE_OPERAND (*tp, 2)) + /* Operand 2 has the initialiser, and we need to walk any subtrees + there. */ + WALK_SUBTREE (TREE_OPERAND (*tp, 2)); + break; + + case CO_RETURN_EXPR: + if (TREE_OPERAND (*tp, 0)) + { + if (VOID_TYPE_P (TREE_OPERAND (*tp, 0))) + /* For void expressions, operand 1 is a trivial call, and any + interesting subtrees will be part of operand 0. */ + WALK_SUBTREE (TREE_OPERAND (*tp, 0)); + else if (TREE_OPERAND (*tp, 1)) + /* Interesting sub-trees will be in the return_value () call + arguments. */ + WALK_SUBTREE (TREE_OPERAND (*tp, 1)); + } + break; + default: return NULL_TREE; } @@ -5024,7 +5195,35 @@ 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; } @@ -5036,6 +5235,7 @@ 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)); @@ -5383,8 +5583,7 @@ 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); @@ -5403,6 +5602,8 @@ 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. */ @@ -5473,6 +5674,8 @@ 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); } @@ -5493,6 +5696,68 @@ 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. */ @@ -5500,7 +5765,7 @@ void lang_check_failed (const char* file, int line, const char* function) { - internal_error ("lang_* check: failed in %s, at %s:%d", + internal_error ("%<lang_*%> check: failed in %s, at %s:%d", function, trim_filename (file), line); } #endif /* ENABLE_TREE_CHECKING */ @@ -5550,6 +5815,14 @@ 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. */