Mercurial > hg > CbC > CbC_gcc
diff gcc/cp/tree.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
line wrap: on
line diff
--- a/gcc/cp/tree.c Fri Oct 27 22:46:09 2017 +0900 +++ b/gcc/cp/tree.c Thu Oct 25 07:37:49 2018 +0900 @@ -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-2018 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. @@ -35,6 +35,7 @@ #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 *); @@ -64,7 +65,7 @@ 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)) @@ -86,6 +87,7 @@ { 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 +95,25 @@ 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 +122,11 @@ 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 +142,11 @@ 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 +193,6 @@ /* FALLTHRU */ case INDIRECT_REF: case ARROW_EXPR: - case ARRAY_REF: - case ARRAY_NOTATION_REF: case PARM_DECL: case RESULT_DECL: case PLACEHOLDER_EXPR: @@ -194,6 +221,17 @@ break; case COND_EXPR: + 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_; + } op1_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 1) ? TREE_OPERAND (ref, 1) : TREE_OPERAND (ref, 0)); @@ -239,15 +277,17 @@ return lvalue_kind (BASELINK_FUNCTIONS (CONST_CAST_TREE (ref))); case NON_DEPENDENT_EXPR: + case PAREN_EXPR: return lvalue_kind (TREE_OPERAND (ref, 0)); 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 @@ -375,10 +415,17 @@ 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. */ + 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 +468,14 @@ || 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 +486,8 @@ 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 @@ -591,6 +646,9 @@ 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; @@ -1030,14 +1088,18 @@ 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 +1108,23 @@ || (!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 +1134,10 @@ { 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 +1185,7 @@ 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); } @@ -1208,18 +1290,18 @@ tree t = PACK_EXPANSION_PATTERN (type); t = cp_build_qualified_type_real (t, type_quals, complain); - return make_pack_expansion (t); + return make_pack_expansion (t, complain); } /* A reference or method type shall not be cv-qualified. [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 + && (TYPE_REF_P (type) || TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_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 +1315,7 @@ 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 +1336,6 @@ /* 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; } @@ -1490,22 +1563,16 @@ 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: @@ -1678,9 +1745,9 @@ 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); vec_safe_push (vec, val); - if (val != TREE_VALUE (t)) + if (val != TREE_VALUE (it)) changed = true; gcc_assert (TREE_PURPOSE (it) == NULL_TREE); } @@ -1762,13 +1829,17 @@ error ("lambda-expression in a constant expression"); return error_mark_node; + case STATEMENT_LIST: + error ("statement-expression in a constant expression"); + return error_mark_node; + default: break; } gcc_assert (EXPR_P (t)); - n = TREE_OPERAND_LENGTH (t); + n = cp_tree_operand_length (t); ops = XALLOCAVEC (tree, n); type = TREE_TYPE (t); @@ -2044,17 +2115,19 @@ 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,67 +2136,17 @@ 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; @@ -2138,17 +2161,7 @@ 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); + tree result = make_node (OVERLOAD); gcc_checking_assert (!OVL_NESTED_P (ovl) && OVL_USED_P (ovl)); TREE_TYPE (result) = TREE_TYPE (ovl); @@ -2387,30 +2400,22 @@ } } -/* 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. */ +/* Preserve the contents of a lookup so that it is available for a + later instantiation. */ void -lookup_keep (tree lookup, bool keep) +lookup_keep (tree lookup) { 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); + { + OVL_USED_P (lookup) = true; + ovl_used (OVL_FUNCTION (lookup)); + } + + ovl_used (lookup); } /* Returns nonzero if X is an expression for a (possibly overloaded) @@ -2465,10 +2470,11 @@ 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) { /* A baselink is also considered an overloaded function. */ if (TREE_CODE (from) == OFFSET_REF @@ -2478,9 +2484,23 @@ 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 (TREE_CODE (from) == OVERLOAD + || TREE_CODE (from) == FUNCTION_DECL) + 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. */ @@ -2593,47 +2613,66 @@ return NULL_TREE; } +tree +build_cp_fntype_variant (tree type, cp_ref_qualifier rqual, + tree raises, bool late) +{ + cp_cv_quals type_quals = TYPE_QUALS (type); + + if (cp_check_qualified_type (type, type, type_quals, rqual, raises, late)) + return type; + + 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; + 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 = 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 || late) + /* Build the underlying canonical type, since it is different + from TYPE. */ + TYPE_CANONICAL (v) = build_cp_fntype_variant (TYPE_CANONICAL (type), + rqual, cr, false); + else + /* T is its own canonical type. */ + TYPE_CANONICAL (v) = v; + + return v; +} + /* Build the FUNCTION_TYPE or METHOD_TYPE which may throw exceptions listed in RAISES. */ tree build_exception_variant (tree type, tree raises) { - tree v; - int type_quals; - - if (comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (type), ce_exact)) - 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)) - 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; - - /* Canonicalize the exception specification. */ - tree cr = canonical_eh_spec (raises); - - if (TYPE_STRUCTURAL_EQUALITY_P (type)) - /* Propagate structural equality. */ - SET_TYPE_STRUCTURAL_EQUALITY (v); - else if (TYPE_CANONICAL (type) != type || cr != raises) - /* Build the underlying canonical type, since it is different - from TYPE. */ - TYPE_CANONICAL (v) = build_exception_variant (TYPE_CANONICAL (type), cr); - else - /* T is its own canonical type. */ - TYPE_CANONICAL (v) = v; - - return v; + 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 @@ -2826,7 +2865,6 @@ 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 +2903,19 @@ 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 +2937,8 @@ { 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 +2955,10 @@ (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 +2994,11 @@ /* 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 +3007,10 @@ 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 +3048,13 @@ /* 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 +3063,10 @@ 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 +3113,7 @@ 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<tree> *pset; /* To avoid walking same trees multiple times. */ }; @@ -3082,7 +3127,7 @@ replace_placeholders_t *d = static_cast<replace_placeholders_t*>(data_); tree obj = d->obj; - if (TREE_CONSTANT (*t)) + if (TYPE_P (*t) || TREE_CONSTANT (*t)) { *walk_subtrees = false; return NULL_TREE; @@ -3096,8 +3141,8 @@ 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,6 +3152,16 @@ { constructor_elt *ce; vec<constructor_elt,va_gc> *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; @@ -3126,7 +3181,7 @@ 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 +3189,8 @@ } default: + if (d->pset->add (*t)) + *walk_subtrees = false; break; } @@ -3158,16 +3215,57 @@ return exp; tree *tp = &exp; - hash_set<tree> 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<tree> 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 +3286,7 @@ 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 +3314,12 @@ { 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 +3348,7 @@ 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 +3371,8 @@ 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; } @@ -3494,6 +3575,10 @@ 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: @@ -3751,6 +3836,14 @@ 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))); + return false; + default: break; } @@ -3841,7 +3934,7 @@ build_dummy_object (tree type) { tree decl = build1 (CONVERT_EXPR, build_pointer_type (type), void_node); - return cp_build_indirect_ref (decl, RO_NULL, tf_warning_or_error); + return cp_build_fold_indirect_ref (decl); } /* We've gotten a reference to a member of TYPE. Return *this if appropriate, @@ -3936,15 +4029,28 @@ || !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 +4085,7 @@ 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 +4117,27 @@ 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; @@ -4316,28 +4431,55 @@ 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; +} + /* 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, 0, false, false, false, false, + handle_nodiscard_attribute, NULL }, + { "no_unique_address", 0, 0, true, false, false, false, + handle_no_unique_addr_attribute, NULL }, + { NULL, 0, 0, false, false, false, false, NULL, NULL } }; /* Handle an "init_priority" attribute; arguments as in @@ -4606,12 +4748,7 @@ 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)); - } + 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); @@ -4630,6 +4767,8 @@ 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); } @@ -4642,10 +4781,9 @@ { 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)); - } + type = build_cp_fntype_variant (type, type_memfn_rqual (typeb), + TYPE_RAISES_EXCEPTIONS (typeb), + TYPE_HAS_LATE_RETURN_TYPE (typeb)); return type; } @@ -4766,7 +4904,19 @@ 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 +4933,12 @@ /* 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)); @@ -4817,6 +4969,11 @@ 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); } @@ -4847,7 +5004,8 @@ return sfk_move_constructor; if (DECL_CONSTRUCTOR_P (decl)) return sfk_constructor; - if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR) + if (DECL_ASSIGNMENT_OPERATOR_P (decl) + && DECL_OVERLOADED_OPERATOR_IS (decl, NOP_EXPR)) { if (copy_fn_p (decl)) return sfk_copy_assignment; @@ -4914,10 +5072,9 @@ /* 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) @@ -4993,7 +5150,7 @@ } /* 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)) { @@ -5010,7 +5167,7 @@ exp = cp_build_addr_expr (exp, tf_warning_or_error); init_expr = get_target_expr (exp); exp = TARGET_EXPR_SLOT (init_expr); - exp = cp_build_indirect_ref (exp, RO_NULL, tf_warning_or_error); + exp = cp_build_fold_indirect_ref (exp); if (xval) exp = move (exp); } @@ -5154,7 +5311,7 @@ { 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)) @@ -5301,13 +5458,33 @@ } } +/* 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); + 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"); @@ -5328,4 +5505,64 @@ } #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)); +} + +/* 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"