From patchwork Tue May 24 19:50:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 54350 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 1F5F93857B94 for ; Tue, 24 May 2022 19:52:58 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1F5F93857B94 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1653421978; bh=2rrznz2DHKbFQCghhsYSxy0eR2/G1SI7/gHf9XB+P2A=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=WKVi9xDY+yI3DGm/sA0R0hmB23ULFeaLLXtphsVUcc91bH+F1MEMd57VT3o6YvCpI YZ1Lq+NhWpIxvdOrLyV6zmZQwo8o+C7pKYoKrTkxmnwECgmZHzC1NexKLGVZlFxJWl rYjfed0pTfnf7A+fr3zLER/8VNh0IwrRR2ypaxuk= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id DD2CA3857B9F for ; Tue, 24 May 2022 19:51:06 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org DD2CA3857B9F Received: from mail-qk1-f199.google.com (mail-qk1-f199.google.com [209.85.222.199]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-564-q5nMtqvdOVSJ0WdjegPW0Q-1; Tue, 24 May 2022 15:51:05 -0400 X-MC-Unique: q5nMtqvdOVSJ0WdjegPW0Q-1 Received: by mail-qk1-f199.google.com with SMTP id o13-20020a05620a0d4d00b0069f47054e58so14213074qkl.13 for ; Tue, 24 May 2022 12:51:05 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=2rrznz2DHKbFQCghhsYSxy0eR2/G1SI7/gHf9XB+P2A=; b=1+9rJYHzQ02U7F66qr0++y20x6Q8zJjc/qcYnLrIpr77JjVCZb1JwF8j2nn256Hi7E qp/GnyFH2J6LZS1f1Wt3C0M/Y4ekAxLpLP6FQFHys0QmV1X/ngpbDmufKdbkxpDHOLm8 vN0P9JrVKmKIJ9Z3N2jmO+GX0q57UZ/lqd7qWrgyrMoLEo0zpBz1F7rS4imcknoLcbKb hb2kYKIWtYo7JXxP2OG0/sUXlCIUKjlEvE29cfCSWLdUNSXcJEzb9rI6OEVZpJPTe+rX nF1G5MXIkT1+zPaMG6yXptCiRXWyexO0Mpjs+g5sxiDgzGx9ti0oVYvF/pP6YsgL5gab 725g== X-Gm-Message-State: AOAM53278zEIAzoMVb3aDn1VXcPTqbVfiKe9gxiq9vWVU8p8AoF6iQn6 C+YpgsoRoG1Srb0ViBerft2knSOHqj1+ZCjYsokLXkJQBUjR6uCWrJREJr3Q1W2OikrMtD/jWHr vwRfLMtcnmg6A7tOJrJ6jDoK6jLOq22Eqd/TJ4f4WdKPOnF8ZKfse+TT60swcRDtLtw== X-Received: by 2002:a37:9b55:0:b0:6a3:4ac4:1594 with SMTP id d82-20020a379b55000000b006a34ac41594mr13860297qke.164.1653421863911; Tue, 24 May 2022 12:51:03 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzz+TBoXcdP+Opd+6cZZZBi9Vot9PclQZhcdwL/aJ9TgtQVFHoeht24qVTXxmQD4aZYGS+tFg== X-Received: by 2002:a37:9b55:0:b0:6a3:4ac4:1594 with SMTP id d82-20020a379b55000000b006a34ac41594mr13860260qke.164.1653421863026; Tue, 24 May 2022 12:51:03 -0700 (PDT) Received: from barrymore.redhat.com (130-44-159-43.s15913.c3-0.arl-cbr1.sbo-arl.ma.cable.rcncustomer.com. [130.44.159.43]) by smtp.gmail.com with ESMTPSA id f4-20020ac87f04000000b002f39b99f66bsm240643qtk.5.2022.05.24.12.51.02 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 24 May 2022 12:51:02 -0700 (PDT) To: gcc-patches@gcc.gnu.org Subject: [pushed] c++: discarded-value and constexpr Date: Tue, 24 May 2022 15:50:59 -0400 Message-Id: <20220524195059.991193-1-jason@redhat.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-13.5 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jason Merrill via Gcc-patches From: Jason Merrill Reply-To: Jason Merrill Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" I've been thinking for a while that the 'lval' parameter needed a third value for discarded-value expressions; most importantly, cxx_eval_store_expression does extra work for an lvalue result, and we also don't want to do the l->r conversion. Mostly this is pretty mechanical. Apart from the _store_ fix, I also use vc_discard for substatements of a STATEMENT_LIST other than a stmt-expr result, and avoid building _REFs to be ignored in a few other places. Tested x86_64-pc-linux-gnu, applying to trunk. gcc/cp/ChangeLog: * constexpr.cc (enum value_cat): New. Change all 'lval' parameters from int to value_cat. Change most false to vc_prvalue, most true to vc_glvalue, cases where the return value is ignored to vc_discard. (cxx_eval_statement_list): Only vc_prvalue for stmt-expr result. (cxx_eval_store_expression): Only build _REF for vc_glvalue. (cxx_eval_array_reference, cxx_eval_component_reference) (cxx_eval_indirect_ref, cxx_eval_constant_expression): Likewise. --- gcc/cp/constexpr.cc | 198 ++++++++++++++++++++++++-------------------- 1 file changed, 108 insertions(+), 90 deletions(-) base-commit: 2540e2c604142889308857657d3510874955336a diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index 0f1a43982d0..a015bc7c818 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -1210,9 +1210,6 @@ uid_sensitive_constexpr_evaluation_checker::evaluation_restricted_p () const static GTY (()) hash_table *constexpr_call_table; -static tree cxx_eval_constant_expression (const constexpr_ctx *, tree, - bool, bool *, bool *, tree * = NULL); - /* Compute a hash value for a constexpr call representation. */ inline hashval_t @@ -1346,13 +1343,25 @@ get_nth_callarg (tree t, int n) } } +/* Whether our evaluation wants a prvalue (e.g. CONSTRUCTOR or _CST), + a glvalue (e.g. VAR_DECL or _REF), or nothing. */ + +enum value_cat { + vc_prvalue = 0, + vc_glvalue = 1, + vc_discard = 2 +}; + +static tree cxx_eval_constant_expression (const constexpr_ctx *, tree, + value_cat, bool *, bool *, tree * = NULL); + /* Attempt to evaluate T which represents a call to a builtin function. We assume here that all builtin functions evaluate to scalar types represented by _CST nodes. */ static tree cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, - bool lval, + value_cat lval, bool *non_constant_p, bool *overflow_p) { const int nargs = call_expr_nargs (t); @@ -1458,7 +1467,7 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, || potential_constant_expression (arg)) { bool dummy1 = false, dummy2 = false; - arg = cxx_eval_constant_expression (&new_ctx, arg, false, + arg = cxx_eval_constant_expression (&new_ctx, arg, vc_prvalue, &dummy1, &dummy2); } @@ -1703,7 +1712,7 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun, /* Normally we would strip a TARGET_EXPR in an initialization context such as this, but here we do the elision differently: we keep the TARGET_EXPR, and use its CONSTRUCTOR as the value of the parm. */ - arg = cxx_eval_constant_expression (ctx, x, /*lval=*/false, + arg = cxx_eval_constant_expression (ctx, x, vc_prvalue, non_constant_p, overflow_p); /* Don't VERIFY_CONSTANT here. */ if (*non_constant_p && ctx->quiet) @@ -1807,7 +1816,7 @@ cx_error_context (void) static tree cxx_eval_internal_function (const constexpr_ctx *ctx, tree t, - bool lval, + value_cat lval, bool *non_constant_p, bool *overflow_p) { enum tree_code opcode = ERROR_MARK; @@ -1832,12 +1841,13 @@ cxx_eval_internal_function (const constexpr_ctx *ctx, tree t, case IFN_LAUNDER: return cxx_eval_constant_expression (ctx, CALL_EXPR_ARG (t, 0), - false, non_constant_p, overflow_p); + vc_prvalue, non_constant_p, + overflow_p); case IFN_VEC_CONVERT: { tree arg = cxx_eval_constant_expression (ctx, CALL_EXPR_ARG (t, 0), - false, non_constant_p, + vc_prvalue, non_constant_p, overflow_p); if (TREE_CODE (arg) == VECTOR_CST) if (tree r = fold_const_call (CFN_VEC_CONVERT, TREE_TYPE (t), arg)) @@ -2103,7 +2113,7 @@ cxx_eval_dynamic_cast_fn (const constexpr_ctx *ctx, tree call, } /* Evaluate the object so that we know its dynamic type. */ - obj = cxx_eval_constant_expression (ctx, obj, /*lval*/false, non_constant_p, + obj = cxx_eval_constant_expression (ctx, obj, vc_prvalue, non_constant_p, overflow_p); if (*non_constant_p) return call; @@ -2138,7 +2148,7 @@ cxx_eval_dynamic_cast_fn (const constexpr_ctx *ctx, tree call, considered to be a most derived object that has the type of the constructor or destructor's class. */ tree vtable = build_vfield_ref (obj, objtype); - vtable = cxx_eval_constant_expression (ctx, vtable, /*lval*/false, + vtable = cxx_eval_constant_expression (ctx, vtable, vc_prvalue, non_constant_p, overflow_p); if (*non_constant_p) return call; @@ -2301,7 +2311,7 @@ replace_decl (tree *tp, tree decl, tree replacement) static tree cxx_eval_thunk_call (const constexpr_ctx *ctx, tree t, tree thunk_fndecl, - bool lval, + value_cat lval, bool *non_constant_p, bool *overflow_p) { tree function = THUNK_TARGET (thunk_fndecl); @@ -2362,7 +2372,7 @@ cxx_set_object_constness (const constexpr_ctx *ctx, tree object, { /* Subobjects might not be stored in ctx->global->values but we can get its CONSTRUCTOR by evaluating *this. */ - tree e = cxx_eval_constant_expression (ctx, object, /*lval*/false, + tree e = cxx_eval_constant_expression (ctx, object, vc_prvalue, non_constant_p, overflow_p); if (TREE_CODE (e) == CONSTRUCTOR && !*non_constant_p) TREE_READONLY (e) = readonly_p; @@ -2375,7 +2385,7 @@ cxx_set_object_constness (const constexpr_ctx *ctx, tree object, static tree cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, - bool lval, + value_cat lval, bool *non_constant_p, bool *overflow_p) { /* Handle concept checks separately. */ @@ -2395,9 +2405,8 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, if (TREE_CODE (fun) != FUNCTION_DECL) { /* Might be a constexpr function pointer. */ - fun = cxx_eval_constant_expression (ctx, fun, - /*lval*/false, non_constant_p, - overflow_p); + fun = cxx_eval_constant_expression (ctx, fun, vc_prvalue, + non_constant_p, overflow_p); STRIP_NOPS (fun); if (TREE_CODE (fun) == ADDR_EXPR) fun = TREE_OPERAND (fun, 0); @@ -2463,7 +2472,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, for (int i = 0; i < nargs; ++i) { tree arg = CALL_EXPR_ARG (t, i); - arg = cxx_eval_constant_expression (ctx, arg, false, + arg = cxx_eval_constant_expression (ctx, arg, vc_prvalue, non_constant_p, overflow_p); VERIFY_CONSTANT (arg); if (i == 0) @@ -2571,7 +2580,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, for (int i = 0; i < nargs; ++i) { tree arg = CALL_EXPR_ARG (t, i); - arg = cxx_eval_constant_expression (ctx, arg, false, + arg = cxx_eval_constant_expression (ctx, arg, vc_prvalue, non_constant_p, overflow_p); if (i == 1) arg1 = arg; @@ -2852,7 +2861,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, tree jump_target = NULL_TREE; cxx_eval_constant_expression (&ctx_with_save_exprs, body, - lval, non_constant_p, overflow_p, + vc_discard, non_constant_p, overflow_p, &jump_target); if (DECL_CONSTRUCTOR_P (fun)) @@ -3213,7 +3222,7 @@ cxx_eval_unary_expression (const constexpr_ctx *ctx, tree t, { tree r; tree orig_arg = TREE_OPERAND (t, 0); - tree arg = cxx_eval_constant_expression (ctx, orig_arg, /*lval*/false, + tree arg = cxx_eval_constant_expression (ctx, orig_arg, vc_prvalue, non_constant_p, overflow_p); VERIFY_CONSTANT (arg); location_t loc = EXPR_LOCATION (t); @@ -3259,8 +3268,8 @@ cxx_fold_pointer_plus_expression (const constexpr_ctx *ctx, tree t, t = fold_convert_loc (loc, ssizetype, TREE_OPERAND (lhs, 1)); tree nelts = array_type_nelts_top (TREE_TYPE (TREE_OPERAND (lhs, 0))); - nelts = cxx_eval_constant_expression (ctx, nelts, false, non_constant_p, - overflow_p); + nelts = cxx_eval_constant_expression (ctx, nelts, vc_prvalue, + non_constant_p, overflow_p); if (*non_constant_p) return NULL_TREE; /* Don't fold an out-of-bound access. */ @@ -3281,7 +3290,7 @@ cxx_fold_pointer_plus_expression (const constexpr_ctx *ctx, tree t, t, NULL_TREE, NULL_TREE); t = cp_build_addr_expr (t, tf_warning_or_error); t = cp_fold_convert (orig_type, t); - return cxx_eval_constant_expression (ctx, t, /*lval*/false, + return cxx_eval_constant_expression (ctx, t, vc_prvalue, non_constant_p, overflow_p); } @@ -3325,20 +3334,20 @@ cxx_maybe_fold_addr_pointer_plus (tree t) static tree cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t, - bool lval, + value_cat lval, bool *non_constant_p, bool *overflow_p) { tree r = NULL_TREE; tree orig_lhs = TREE_OPERAND (t, 0); tree orig_rhs = TREE_OPERAND (t, 1); tree lhs, rhs; - lhs = cxx_eval_constant_expression (ctx, orig_lhs, /*lval*/false, + lhs = cxx_eval_constant_expression (ctx, orig_lhs, vc_prvalue, non_constant_p, overflow_p); /* Don't VERIFY_CONSTANT here, it's unnecessary and will break pointer subtraction. */ if (*non_constant_p) return t; - rhs = cxx_eval_constant_expression (ctx, orig_rhs, /*lval*/false, + rhs = cxx_eval_constant_expression (ctx, orig_rhs, vc_prvalue, non_constant_p, overflow_p); if (*non_constant_p) return t; @@ -3457,12 +3466,12 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t, static tree cxx_eval_conditional_expression (const constexpr_ctx *ctx, tree t, - bool lval, + value_cat lval, bool *non_constant_p, bool *overflow_p, tree *jump_target) { tree val = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), - /*lval*/false, + vc_prvalue, non_constant_p, overflow_p); VERIFY_CONSTANT (val); if (TREE_CODE (t) == IF_STMT && IF_STMT_CONSTEVAL_P (t)) @@ -3504,15 +3513,15 @@ cxx_eval_vector_conditional_expression (const constexpr_ctx *ctx, tree t, bool *non_constant_p, bool *overflow_p) { tree arg1 = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), - /*lval*/false, + vc_prvalue, non_constant_p, overflow_p); VERIFY_CONSTANT (arg1); tree arg2 = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), - /*lval*/false, + vc_prvalue, non_constant_p, overflow_p); VERIFY_CONSTANT (arg2); tree arg3 = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 2), - /*lval*/false, + vc_prvalue, non_constant_p, overflow_p); VERIFY_CONSTANT (arg3); location_t loc = EXPR_LOCATION (t); @@ -3844,7 +3853,7 @@ get_array_or_vector_nelts (const constexpr_ctx *ctx, tree type, gcc_unreachable (); /* For VLAs, the number of elements won't be an integer constant. */ - nelts = cxx_eval_constant_expression (ctx, nelts, false, + nelts = cxx_eval_constant_expression (ctx, nelts, vc_prvalue, non_constant_p, overflow_p); return nelts; } @@ -3881,7 +3890,7 @@ eval_and_check_array_index (const constexpr_ctx *ctx, location_t loc = cp_expr_loc_or_input_loc (t); tree ary = TREE_OPERAND (t, 0); t = TREE_OPERAND (t, 1); - tree index = cxx_eval_constant_expression (ctx, t, false, + tree index = cxx_eval_constant_expression (ctx, t, vc_prvalue, non_constant_p, overflow_p); VERIFY_CONSTANT (index); @@ -3913,7 +3922,7 @@ eval_and_check_array_index (const constexpr_ctx *ctx, static tree cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, - bool lval, + value_cat lval, bool *non_constant_p, bool *overflow_p) { tree oldary = TREE_OPERAND (t, 0); @@ -3936,6 +3945,8 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, if (lval && ary == oldary && index == oldidx) return t; + else if (lval == vc_discard) + return t; else if (lval) return build4 (ARRAY_REF, TREE_TYPE (t), ary, index, NULL, NULL); @@ -4043,7 +4054,7 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, static tree cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, - bool lval, + value_cat lval, bool *non_constant_p, bool *overflow_p) { unsigned HOST_WIDE_INT i; @@ -4067,6 +4078,8 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, whole = cplus_expand_constant (whole); if (whole == orig_whole) return t; + if (lval == vc_discard) + return t; if (lval) return fold_build3 (COMPONENT_REF, TREE_TYPE (t), whole, part, NULL_TREE); @@ -4152,7 +4165,7 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, static tree cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t, - bool lval, + value_cat lval, bool *non_constant_p, bool *overflow_p) { tree orig_whole = TREE_OPERAND (t, 0); @@ -4449,7 +4462,7 @@ cxx_eval_bit_cast (const constexpr_ctx *ctx, tree t, bool *non_constant_p, return t; } - tree op = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), false, + tree op = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), vc_prvalue, non_constant_p, overflow_p); if (*non_constant_p) return t; @@ -4569,14 +4582,14 @@ cxx_eval_logical_expression (const constexpr_ctx *ctx, tree t, { tree r; tree lhs = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), - /*lval*/false, non_constant_p, + vc_prvalue, non_constant_p, overflow_p); VERIFY_CONSTANT (lhs); if (tree_int_cst_equal (lhs, bailout_value)) return lhs; gcc_assert (tree_int_cst_equal (lhs, continue_value)); r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), - /*lval*/false, non_constant_p, + vc_prvalue, non_constant_p, overflow_p); VERIFY_CONSTANT (r); return r; @@ -4725,7 +4738,7 @@ verify_ctor_sanity (const constexpr_ctx *ctx, tree type) static tree cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t, - bool lval, + value_cat lval, bool *non_constant_p, bool *overflow_p) { vec *v = CONSTRUCTOR_ELTS (t); @@ -4858,7 +4871,7 @@ cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t, static tree cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init, - bool value_init, bool lval, + bool value_init, value_cat lval, bool *non_constant_p, bool *overflow_p) { tree elttype = TREE_TYPE (atype); @@ -5000,7 +5013,7 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init, static tree cxx_eval_vec_init (const constexpr_ctx *ctx, tree t, - bool lval, + value_cat lval, bool *non_constant_p, bool *overflow_p) { tree atype = TREE_TYPE (t); @@ -5070,7 +5083,7 @@ cxx_union_active_member (const constexpr_ctx *ctx, tree t) constexpr_ctx new_ctx = *ctx; new_ctx.quiet = true; bool non_constant_p = false, overflow_p = false; - tree ctor = cxx_eval_constant_expression (&new_ctx, t, false, + tree ctor = cxx_eval_constant_expression (&new_ctx, t, vc_prvalue, &non_constant_p, &overflow_p); if (TREE_CODE (ctor) == CONSTRUCTOR @@ -5306,7 +5319,7 @@ cxx_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type, static tree cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, - bool lval, + value_cat lval, bool *non_constant_p, bool *overflow_p) { tree orig_op0 = TREE_OPERAND (t, 0); @@ -5330,7 +5343,7 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, { /* If that didn't work, evaluate the operand first. */ tree op0 = cxx_eval_constant_expression (ctx, orig_op0, - /*lval*/false, non_constant_p, + vc_prvalue, non_constant_p, overflow_p); /* Don't VERIFY_CONSTANT here. */ if (*non_constant_p) @@ -5366,7 +5379,7 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, return t; } - if (lval && op0 != orig_op0) + if (lval == vc_glvalue && op0 != orig_op0) return build1 (INDIRECT_REF, TREE_TYPE (t), op0); if (!lval) VERIFY_CONSTANT (t); @@ -5462,7 +5475,7 @@ non_const_var_error (location_t loc, tree r) static tree cxx_eval_trinary_expression (const constexpr_ctx *ctx, tree t, - bool lval, + value_cat lval, bool *non_constant_p, bool *overflow_p) { int i; @@ -5594,7 +5607,7 @@ modifying_const_object_p (tree_code code, tree obj, bool mutable_p) static tree cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, - bool lval, + value_cat lval, bool *non_constant_p, bool *overflow_p) { constexpr_ctx new_ctx = *ctx; @@ -5617,19 +5630,19 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, stored in, so that any side-effects happen first. */ if (!SCALAR_TYPE_P (type)) new_ctx.ctor = new_ctx.object = NULL_TREE; - init = cxx_eval_constant_expression (&new_ctx, init, false, + init = cxx_eval_constant_expression (&new_ctx, init, vc_prvalue, non_constant_p, overflow_p); if (*non_constant_p) return t; } bool evaluated = false; - if (lval) + if (lval == vc_glvalue) { /* If we want to return a reference to the target, we need to evaluate it as a whole; otherwise, only evaluate the innermost piece to avoid building up unnecessary *_REFs. */ - target = cxx_eval_constant_expression (ctx, target, true, + target = cxx_eval_constant_expression (ctx, target, lval, non_constant_p, overflow_p); evaluated = true; if (*non_constant_p) @@ -5681,7 +5694,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, object = probe; else { - probe = cxx_eval_constant_expression (ctx, probe, true, + probe = cxx_eval_constant_expression (ctx, probe, vc_glvalue, non_constant_p, overflow_p); evaluated = true; if (*non_constant_p) @@ -5893,7 +5906,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, if (TREE_CODE (init) == TARGET_EXPR) if (tree tinit = TARGET_EXPR_INITIAL (init)) init = tinit; - init = cxx_eval_constant_expression (&new_ctx, init, false, + init = cxx_eval_constant_expression (&new_ctx, init, vc_prvalue, non_constant_p, overflow_p); /* The hash table might have moved since the get earlier, and the initializer might have mutated the underlying CONSTRUCTORs, so we must @@ -5992,7 +6005,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, static tree cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t, - bool lval, + value_cat lval, bool *non_constant_p, bool *overflow_p) { enum tree_code code = TREE_CODE (t); @@ -6006,12 +6019,12 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t, offset = fold_simple (offset); /* The operand as an lvalue. */ - op = cxx_eval_constant_expression (ctx, op, true, + op = cxx_eval_constant_expression (ctx, op, vc_glvalue, non_constant_p, overflow_p); /* The operand as an rvalue. */ tree val - = cxx_eval_constant_expression (ctx, op, false, + = cxx_eval_constant_expression (ctx, op, vc_prvalue, non_constant_p, overflow_p); /* Don't VERIFY_CONSTANT if this might be dealing with a pointer to a local array in a constexpr function. */ @@ -6160,8 +6173,10 @@ cxx_eval_statement_list (const constexpr_ctx *ctx, tree t, local_target = NULL_TREE; jump_target = &local_target; } - for (tree stmt : tsi_range (t)) + for (tree_stmt_iterator i = tsi_start (t); !tsi_end_p (i); ++i) { + tree stmt = *i; + /* We've found a continue, so skip everything until we reach the label its jumping to. */ if (continues (jump_target)) @@ -6174,7 +6189,13 @@ cxx_eval_statement_list (const constexpr_ctx *ctx, tree t, } if (TREE_CODE (stmt) == DEBUG_BEGIN_STMT) continue; - r = cxx_eval_constant_expression (ctx, stmt, false, + + value_cat lval = vc_discard; + /* The result of a statement-expression is not wrapped in EXPR_STMT. */ + if (tsi_one_before_end_p (i) && TREE_CODE (stmt) != EXPR_STMT) + lval = vc_prvalue; + + r = cxx_eval_constant_expression (ctx, stmt, lval, non_constant_p, overflow_p, jump_target); if (*non_constant_p) @@ -6228,7 +6249,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, break; case FOR_STMT: if (FOR_INIT_STMT (t)) - cxx_eval_constant_expression (ctx, FOR_INIT_STMT (t), /*lval*/false, + cxx_eval_constant_expression (ctx, FOR_INIT_STMT (t), vc_discard, non_constant_p, overflow_p, jump_target); if (*non_constant_p) return NULL_TREE; @@ -6247,7 +6268,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, if (count != -1) { if (body) - cxx_eval_constant_expression (&new_ctx, body, /*lval*/false, + cxx_eval_constant_expression (&new_ctx, body, vc_discard, non_constant_p, overflow_p, jump_target); if (breaks (jump_target)) @@ -6260,7 +6281,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, *jump_target = NULL_TREE; if (expr) - cxx_eval_constant_expression (&new_ctx, expr, /*lval*/false, + cxx_eval_constant_expression (&new_ctx, expr, vc_prvalue, non_constant_p, overflow_p, jump_target); } @@ -6268,7 +6289,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, if (cond) { tree res - = cxx_eval_constant_expression (&new_ctx, cond, /*lval*/false, + = cxx_eval_constant_expression (&new_ctx, cond, vc_prvalue, non_constant_p, overflow_p, jump_target); if (res) @@ -6322,7 +6343,7 @@ cxx_eval_switch_expr (const constexpr_ctx *ctx, tree t, { tree cond = TREE_CODE (t) == SWITCH_STMT ? SWITCH_STMT_COND (t) : SWITCH_COND (t); - cond = cxx_eval_constant_expression (ctx, cond, false, + cond = cxx_eval_constant_expression (ctx, cond, vc_prvalue, non_constant_p, overflow_p); VERIFY_CONSTANT (cond); *jump_target = cond; @@ -6332,7 +6353,7 @@ cxx_eval_switch_expr (const constexpr_ctx *ctx, tree t, constexpr_ctx new_ctx = *ctx; constexpr_switch_state css = css_default_not_seen; new_ctx.css_state = &css; - cxx_eval_constant_expression (&new_ctx, body, false, + cxx_eval_constant_expression (&new_ctx, body, vc_discard, non_constant_p, overflow_p, jump_target); if (switches (jump_target) && css == css_default_seen) { @@ -6340,7 +6361,7 @@ cxx_eval_switch_expr (const constexpr_ctx *ctx, tree t, this time instructing label_matches to return true for default: label on switches (jump_target). */ css = css_default_processing; - cxx_eval_constant_expression (&new_ctx, body, false, + cxx_eval_constant_expression (&new_ctx, body, vc_discard, non_constant_p, overflow_p, jump_target); } if (breaks (jump_target) || switches (jump_target)) @@ -6351,7 +6372,7 @@ cxx_eval_switch_expr (const constexpr_ctx *ctx, tree t, /* Find the object of TYPE under initialization in CTX. */ static tree -lookup_placeholder (const constexpr_ctx *ctx, bool lval, tree type) +lookup_placeholder (const constexpr_ctx *ctx, value_cat lval, tree type) { if (!ctx) return NULL_TREE; @@ -6478,12 +6499,12 @@ build_new_constexpr_heap_type (const constexpr_ctx *ctx, tree elt_type, tree op1 = TREE_OPERAND (arg_size, 1); if (integer_zerop (op0)) arg_size - = cxx_eval_constant_expression (ctx, op1, false, non_constant_p, - overflow_p); + = cxx_eval_constant_expression (ctx, op1, vc_prvalue, + non_constant_p, overflow_p); else if (integer_zerop (op1)) arg_size - = cxx_eval_constant_expression (ctx, op0, false, non_constant_p, - overflow_p); + = cxx_eval_constant_expression (ctx, op0, vc_prvalue, + non_constant_p, overflow_p); else arg_size = NULL_TREE; } @@ -6513,7 +6534,7 @@ build_new_constexpr_heap_type (const constexpr_ctx *ctx, tree elt_type, static tree cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, - bool lval, + value_cat lval, bool *non_constant_p, bool *overflow_p, tree *jump_target /* = NULL */) { @@ -6760,8 +6781,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, if (tree init = DECL_INITIAL (r)) { - init = cxx_eval_constant_expression (ctx, init, - false, + init = cxx_eval_constant_expression (ctx, init, vc_prvalue, non_constant_p, overflow_p); /* Don't share a CONSTRUCTOR that might be changed. */ init = unshare_constructor (init); @@ -6821,10 +6841,9 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, ctx->global->values.put (new_ctx.object, new_ctx.ctor); ctx = &new_ctx; } - /* Pass false for 'lval' because this indicates + /* Pass vc_prvalue because this indicates initialization of a temporary. */ - r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), - false, + r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), vc_prvalue, non_constant_p, overflow_p); if (*non_constant_p) break; @@ -6880,7 +6899,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, r = *p; else { - r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), false, + r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), vc_prvalue, non_constant_p, overflow_p); if (*non_constant_p) break; @@ -6922,7 +6941,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, tree cleanup; /* Evaluate the cleanups. */ FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup) - cxx_eval_constant_expression (ctx, cleanup, false, + cxx_eval_constant_expression (ctx, cleanup, vc_discard, non_constant_p, overflow_p); } break; @@ -6933,7 +6952,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, jump_target); if (!*non_constant_p) /* Also evaluate the cleanup. */ - cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), true, + cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), vc_discard, non_constant_p, overflow_p); break; @@ -6945,7 +6964,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, { iloc_sentinel ils (loc); /* Also evaluate the cleanup. */ - cxx_eval_constant_expression (ctx, CLEANUP_EXPR (t), true, + cxx_eval_constant_expression (ctx, CLEANUP_EXPR (t), vc_discard, non_constant_p, overflow_p); } break; @@ -6962,8 +6981,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case ADDR_EXPR: { tree oldop = TREE_OPERAND (t, 0); - tree op = cxx_eval_constant_expression (ctx, oldop, - /*lval*/true, + tree op = cxx_eval_constant_expression (ctx, oldop, vc_glvalue, non_constant_p, overflow_p); /* Don't VERIFY_CONSTANT here. */ if (*non_constant_p) @@ -6987,7 +7005,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, non_constant_p, overflow_p); if (r == error_mark_node) ; - else if (r == TREE_OPERAND (t, 0)) + else if (r == TREE_OPERAND (t, 0) || lval == vc_discard) r = t; else r = fold_build1 (TREE_CODE (t), TREE_TYPE (t), r); @@ -7039,8 +7057,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, else { /* Check that the LHS is constant and then discard it. */ - cxx_eval_constant_expression (ctx, op0, - true, non_constant_p, overflow_p, + cxx_eval_constant_expression (ctx, op0, vc_discard, + non_constant_p, overflow_p, jump_target); if (*non_constant_p) return t; @@ -7461,7 +7479,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case EXIT_EXPR: { tree cond = TREE_OPERAND (t, 0); - cond = cxx_eval_constant_expression (ctx, cond, /*lval*/false, + cond = cxx_eval_constant_expression (ctx, cond, vc_prvalue, non_constant_p, overflow_p); VERIFY_CONSTANT (cond); if (integer_nonzerop (cond)) @@ -7820,8 +7838,8 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, if (manifestly_const_eval) instantiate_constexpr_fns (r); - r = cxx_eval_constant_expression (&ctx, r, - false, &non_constant_p, &overflow_p); + r = cxx_eval_constant_expression (&ctx, r, vc_prvalue, + &non_constant_p, &overflow_p); if (!constexpr_dtor) verify_constant (r, allow_non_constant, &non_constant_p, &overflow_p); @@ -7832,7 +7850,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, tree cleanup; /* Evaluate the cleanups. */ FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup) - cxx_eval_constant_expression (&ctx, cleanup, false, + cxx_eval_constant_expression (&ctx, cleanup, vc_discard, &non_constant_p, &overflow_p); /* Mutable logic is a bit tricky: we want to allow initialization of