From e4511ca2e9ecdb51d41b64452398f8e2df575668 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 22 Jun 2018 17:57:01 -0400 Subject: [PATCH] Avoid taking the address of something just because it's in parens. * constexpr.c (same_type_ignoring_tlq_and_bounds_p): New. (cxx_fold_indirect_ref): Use it. (cxx_eval_constant_expression) [VIEW_CONVERT_EXPR]: Use it. * cp-tree.h (REF_PARENTHESIZED_P): Allow VIEW_CONVERT_EXPR. * semantics.c (force_paren_expr): Use VIEW_CONVERT_EXPR instead of static_cast to reference type. (maybe_undo_parenthesized_ref): Handle VIEW_CONVERT_EXPR. From-SVN: r261971 --- gcc/cp/ChangeLog | 11 +++++++++++ gcc/cp/constexpr.c | 33 +++++++++++++++++++++++---------- gcc/cp/cp-tree.h | 4 ++-- gcc/cp/semantics.c | 20 +++++--------------- 4 files changed, 41 insertions(+), 27 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f0e44532348..8c7b19b1754 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2018-06-22 Jason Merrill + + Avoid taking the address of something just because it's in parens. + * constexpr.c (same_type_ignoring_tlq_and_bounds_p): New. + (cxx_fold_indirect_ref): Use it. + (cxx_eval_constant_expression) [VIEW_CONVERT_EXPR]: Use it. + * cp-tree.h (REF_PARENTHESIZED_P): Allow VIEW_CONVERT_EXPR. + * semantics.c (force_paren_expr): Use VIEW_CONVERT_EXPR instead of + static_cast to reference type. + (maybe_undo_parenthesized_ref): Handle VIEW_CONVERT_EXPR. + 2018-06-21 Jason Merrill * pt.c (tsubst) [TEMPLATE_TYPE_PARM]: Use TEMPLATE_PARM_DESCENDANTS. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 44f3093ab47..dea2a4e57b3 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -3076,6 +3076,23 @@ cxx_eval_vec_init (const constexpr_ctx *ctx, tree t, return r; } +/* Like same_type_ignoring_top_level_qualifiers_p, but also handle the case + where the desired type is an array of unknown bounds because the variable + has had its bounds deduced since the wrapping expression was created. */ + +static bool +same_type_ignoring_tlq_and_bounds_p (tree type1, tree type2) +{ + while (TREE_CODE (type1) == ARRAY_TYPE + && TREE_CODE (type2) == ARRAY_TYPE + && (!TYPE_DOMAIN (type1) || !TYPE_DOMAIN (type2))) + { + type1 = TREE_TYPE (type1); + type2 = TREE_TYPE (type2); + } + return same_type_ignoring_top_level_qualifiers_p (type1, type2); +} + /* A less strict version of fold_indirect_ref_1, which requires cv-quals to match. We want to be less strict for simple *& folding; if we have a non-const temporary that we access through a const pointer, that should @@ -3108,15 +3125,7 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base) if (TREE_CODE (op) == CONST_DECL) return DECL_INITIAL (op); /* *&p => p; make sure to handle *&"str"[cst] here. */ - if (same_type_ignoring_top_level_qualifiers_p (optype, type) - /* Also handle the case where the desired type is an array of unknown - bounds because the variable has had its bounds deduced since the - ADDR_EXPR was created. */ - || (TREE_CODE (type) == ARRAY_TYPE - && TREE_CODE (optype) == ARRAY_TYPE - && TYPE_DOMAIN (type) == NULL_TREE - && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (optype), - TREE_TYPE (type)))) + if (same_type_ignoring_tlq_and_bounds_p (optype, type)) { tree fop = fold_read_from_constant_string (op); if (fop) @@ -4676,7 +4685,11 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, conversion. */ return fold (t); - if (tcode == UNARY_PLUS_EXPR) + /* Handle an array's bounds having been deduced after we built + the wrapping expression. */ + if (same_type_ignoring_tlq_and_bounds_p (type, TREE_TYPE (op))) + r = op; + else if (tcode == UNARY_PLUS_EXPR) r = fold_convert (TREE_TYPE (t), op); else r = fold_build1 (tcode, type, op); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 0994377e5d7..f16f00c40de 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -399,7 +399,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; TARGET_EXPR_DIRECT_INIT_P (in TARGET_EXPR) FNDECL_USED_AUTO (in FUNCTION_DECL) DECLTYPE_FOR_LAMBDA_PROXY (in DECLTYPE_TYPE) - REF_PARENTHESIZED_P (in COMPONENT_REF, INDIRECT_REF, SCOPE_REF) + REF_PARENTHESIZED_P (in COMPONENT_REF, INDIRECT_REF, SCOPE_REF, VIEW_CONVERT_EXPR) AGGR_INIT_ZERO_FIRST (in AGGR_INIT_EXPR) CONSTRUCTOR_MUTABLE_POISON (in CONSTRUCTOR) OVL_HIDDEN_P (in OVERLOAD) @@ -3676,7 +3676,7 @@ struct GTY(()) lang_decl { of the time in C++14 mode. */ #define REF_PARENTHESIZED_P(NODE) \ - TREE_LANG_FLAG_2 (TREE_CHECK3 ((NODE), COMPONENT_REF, INDIRECT_REF, SCOPE_REF)) + TREE_LANG_FLAG_2 (TREE_CHECK4 ((NODE), COMPONENT_REF, INDIRECT_REF, SCOPE_REF, VIEW_CONVERT_EXPR)) /* Nonzero if this AGGR_INIT_EXPR provides for initialization via a constructor call, rather than an ordinary function call. */ diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index bad712ee6e8..da75f30885f 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1720,23 +1720,10 @@ force_paren_expr (tree expr) REF_PARENTHESIZED_P (expr) = true; else if (processing_template_decl) expr = build1 (PAREN_EXPR, TREE_TYPE (expr), expr); - else if (VAR_P (expr) && DECL_HARD_REGISTER (expr)) - /* We can't bind a hard register variable to a reference. */; else { - cp_lvalue_kind kind = lvalue_kind (expr); - if ((kind & ~clk_class) != clk_none) - { - tree type = unlowered_expr_type (expr); - bool rval = !!(kind & clk_rvalueref); - type = cp_build_reference_type (type, rval); - /* This inhibits warnings in, eg, cxx_mark_addressable - (c++/60955). */ - warning_sentinel s (extra_warnings); - expr = build_static_cast (type, expr, tf_error); - if (expr != error_mark_node) - REF_PARENTHESIZED_P (expr) = true; - } + expr = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (expr), expr); + REF_PARENTHESIZED_P (expr) = true; } return expr; @@ -1765,6 +1752,9 @@ maybe_undo_parenthesized_ref (tree t) } else if (TREE_CODE (t) == PAREN_EXPR) t = TREE_OPERAND (t, 0); + else if (TREE_CODE (t) == VIEW_CONVERT_EXPR + && REF_PARENTHESIZED_P (t)) + t = TREE_OPERAND (t, 0); return t; } -- 2.30.2