From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: 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 943B03857B80 for ; Wed, 12 Oct 2022 15:38:06 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 943B03857B80 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1665589086; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=K/U6EQ6mJI4Kn1OdUK97OPdbIsV5TRVWJ7ciHzYIdt4=; b=YecPNeRWCCueS77m46H2ZOnkCawF6Vdwti3KOgCIQTH1gk5EMTaEzCKmBVa99rtslLJ4F4 H0bayz3EwBp/pLKBc/qlpdHNWouSWe40t1zjO452w7vlewROZR2Q2uKcaAt0kGM3xO+stp msJYRO3R78PAX0WMBUrY3p7uSP5LnmY= Received: from mail-qk1-f200.google.com (mail-qk1-f200.google.com [209.85.222.200]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-616-RZ7O6AySMRSSpJsAbLXF8Q-1; Wed, 12 Oct 2022 11:37:56 -0400 X-MC-Unique: RZ7O6AySMRSSpJsAbLXF8Q-1 Received: by mail-qk1-f200.google.com with SMTP id n13-20020a05620a294d00b006cf933c40feso14710188qkp.20 for ; Wed, 12 Oct 2022 08:37:56 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=K/U6EQ6mJI4Kn1OdUK97OPdbIsV5TRVWJ7ciHzYIdt4=; b=0ciXbfWHcOBQ0QjAqpxeR8Oa4EWBf9A9iqjUOYjt48GavPBF2HZTg6CUT0na5EST5W eiHu5UnKkOOGAqnFg7AtMEQ4CU52xyKmlTEaWhBLkf3gVOMWajo+BUvSzk2MkRuAeLsc I9aR+Y/iUaW/rLQgNG+wHSQnyzc/cZsdhO28NHDt/vTBcDZvf/kOTEBu7jJ67fyjTJSM MWvk1qJcjc9FgdFmx4chDLsgh+eBGh8QRggHoz0HFbOJWw9GKYZdE0DnuR7+uIDpCdJT PnklIKE/OAzC7WJWHJmj+f+ZGnrH7FelNnLL7Q5DRJv8Rig59eH/KyKZCgrBN5KU8WCJ Im7w== X-Gm-Message-State: ACrzQf1Ryxm8cjgm5HGUWZp1b0R+dFEKYIbUi2e5L402crrdQJfSaURm UAJGvj6Mto/kNjZOIDS5U4TKPUOoxQCvhsrIa5NyFXo91Lx0EPUPejKxZ4flC6mDbz24W5EsHV8 21us1uJaewfJ+Y7OTIw3sFM1ai5uX5gVvatFILPAfZIXjCD1hMX6KjCnyJreGOGdT0A== X-Received: by 2002:a05:620a:c99:b0:6ed:5fdd:2717 with SMTP id q25-20020a05620a0c9900b006ed5fdd2717mr9899433qki.665.1665589075178; Wed, 12 Oct 2022 08:37:55 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5jPtaH9pXPCLYBC97JZCcDkCY9zn8frduPc4HwzTP5d4tm10kVMSVqEpPenCcv5CQcNoPLXQ== X-Received: by 2002:a05:620a:c99:b0:6ed:5fdd:2717 with SMTP id q25-20020a05620a0c9900b006ed5fdd2717mr9899388qki.665.1665589074475; Wed, 12 Oct 2022 08:37:54 -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 bq8-20020a05620a468800b006ee0b144730sm6623445qkb.69.2022.10.12.08.37.53 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 12 Oct 2022 08:37:53 -0700 (PDT) From: Jason Merrill To: gcc-patches@gcc.gnu.org Subject: [pushed] c++: defer all consteval in default args [DR2631] Date: Wed, 12 Oct 2022 11:37:52 -0400 Message-Id: <20221012153752.427563-1-jason@redhat.com> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-12.8 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_NONE,SPF_HELO_NONE,SPF_NONE,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Tested x86_64-pc-linux-gnu, applying to trunk. -- >8 -- The proposed resolution of CWG2631 extends our current handling of source_location::current to all consteval functions: default arguments are not evaluated until they're used in a call, the same should apply to evaluation of immediate invocations. And similarly for default member initializers. Previously we folded source_location::current in cp_fold_r; now we fold all consteval calls in default arguments/member initializers in bot_replace. DR 2631 gcc/cp/ChangeLog: * cp-tree.h (source_location_current_p): Remove. * name-lookup.h (struct cp_binding_level): Remove immediate_fn_ctx_p. * call.cc (in_immediate_context): All default args and DMI are potentially immediate context. (immediate_invocation_p): Don't treat source_location specially. (struct in_consteval_if_p_temp_override): Move to cp-tree.h. * constexpr.cc (get_nth_callarg): Move to cp-tree.h. * cp-gimplify.cc (cp_fold_r): Don't fold consteval. * name-lookup.cc (begin_scope): Don't set immediate_fn_ctx_p. * parser.cc (cp_parser_lambda_declarator_opt): Likewise. (cp_parser_direct_declarator): Likewise. * pt.cc (tsubst_default_argument): Open sk_function_parms level. * tree.cc (source_location_current_p): Remove. (bot_replace): Fold consteval here. (break_out_target_exprs): Handle errors. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/consteval-defarg3.C: New test. --- gcc/cp/cp-tree.h | 32 +++++++++++- gcc/cp/name-lookup.h | 5 +- gcc/cp/call.cc | 36 +++++-------- gcc/cp/constexpr.cc | 20 ------- gcc/cp/cp-gimplify.cc | 7 --- gcc/cp/name-lookup.cc | 2 - gcc/cp/parser.cc | 24 --------- gcc/cp/pt.cc | 3 ++ gcc/cp/tree.cc | 52 +++++++++---------- .../g++.dg/cpp2a/consteval-defarg3.C | 23 ++++++++ 10 files changed, 94 insertions(+), 110 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/consteval-defarg3.C diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index ab6f85a2490..80037fabb41 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2030,6 +2030,18 @@ make_temp_override (T& var, type_identity_t overrider) return { var, overrider }; } +/* temp_override for in_consteval_if_p, which can't use make_temp_override + because it is a bitfield. */ + +struct in_consteval_if_p_temp_override { + bool save_in_consteval_if_p; + in_consteval_if_p_temp_override () + : save_in_consteval_if_p (in_consteval_if_p) {} + void reset () { in_consteval_if_p = save_in_consteval_if_p; } + ~in_consteval_if_p_temp_override () + { reset (); } +}; + /* The cached class binding level, from the most recently exited class, or NULL if none. */ @@ -4201,6 +4213,25 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) for ((arg) = first_aggr_init_expr_arg ((call), &(iter)); (arg); \ (arg) = next_aggr_init_expr_arg (&(iter))) +/* We have an expression tree T that represents a call, either CALL_EXPR + or AGGR_INIT_EXPR. Return a reference to the Nth argument. */ + +static inline tree& +get_nth_callarg (tree t, int n) +{ + switch (TREE_CODE (t)) + { + case CALL_EXPR: + return CALL_EXPR_ARG (t, n); + + case AGGR_INIT_EXPR: + return AGGR_INIT_EXPR_ARG (t, n); + + default: + gcc_unreachable (); + } +} + /* VEC_INIT_EXPR accessors. */ #define VEC_INIT_EXPR_SLOT(NODE) TREE_OPERAND (VEC_INIT_EXPR_CHECK (NODE), 0) #define VEC_INIT_EXPR_INIT(NODE) TREE_OPERAND (VEC_INIT_EXPR_CHECK (NODE), 1) @@ -7880,7 +7911,6 @@ extern tree bind_template_template_parm (tree, tree); extern tree array_type_nelts_total (tree); extern tree array_type_nelts_top (tree); extern bool array_of_unknown_bound_p (const_tree); -extern bool source_location_current_p (tree); extern tree break_out_target_exprs (tree, bool = false); extern tree build_ctor_subob_ref (tree, tree, tree); extern tree replace_placeholders (tree, tree, bool * = NULL); diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h index 7201ae8ead8..9e3b69865a6 100644 --- a/gcc/cp/name-lookup.h +++ b/gcc/cp/name-lookup.h @@ -307,13 +307,10 @@ struct GTY(()) cp_binding_level { 'this_entity'. */ unsigned defining_class_p : 1; - /* true for SK_FUNCTION_PARMS of immediate functions. */ - unsigned immediate_fn_ctx_p : 1; - /* True for SK_FUNCTION_PARMS of a requires-expression. */ unsigned requires_expression: 1; - /* 21 bits left to fill a 32-bit word. */ + /* 22 bits left to fill a 32-bit word. */ }; /* The binding level currently in effect. */ diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 70ec964a219..2fa33c5c604 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -9301,7 +9301,8 @@ build_trivial_dtor_call (tree instance, bool no_ptr_deref) } /* Return true if in an immediate function context, or an unevaluated operand, - or a subexpression of an immediate invocation. */ + or a default argument/member initializer, or a subexpression of an immediate + invocation. */ bool in_immediate_context () @@ -9309,8 +9310,11 @@ in_immediate_context () return (cp_unevaluated_operand != 0 || (current_function_decl != NULL_TREE && DECL_IMMEDIATE_FUNCTION_P (current_function_decl)) - || (current_binding_level->kind == sk_function_parms - && current_binding_level->immediate_fn_ctx_p) + /* DR 2631: default args and DMI aren't immediately evaluated. + Return true here so immediate_invocation_p returns false. */ + || current_binding_level->kind == sk_function_parms + || current_binding_level->kind == sk_template_parms + || parsing_nsdmi () || in_consteval_if_p); } @@ -9318,29 +9322,13 @@ in_immediate_context () is an immediate invocation. */ static bool -immediate_invocation_p (tree fn, int nargs) +immediate_invocation_p (tree fn) { return (TREE_CODE (fn) == FUNCTION_DECL && DECL_IMMEDIATE_FUNCTION_P (fn) - && !in_immediate_context () - /* As an exception, we defer std::source_location::current () - invocations until genericization because LWG3396 mandates - special behavior for it. */ - && (nargs > 1 || !source_location_current_p (fn))); + && !in_immediate_context ()); } -/* temp_override for in_consteval_if_p, which can't use make_temp_override - because it is a bitfield. */ - -struct in_consteval_if_p_temp_override { - bool save_in_consteval_if_p; - in_consteval_if_p_temp_override () - : save_in_consteval_if_p (in_consteval_if_p) {} - void reset () { in_consteval_if_p = save_in_consteval_if_p; } - ~in_consteval_if_p_temp_override () - { reset (); } -}; - /* Subroutine of the various build_*_call functions. Overload resolution has chosen a winning candidate CAND; build up a CALL_EXPR accordingly. ARGS is a TREE_LIST of the unconverted arguments to the call. FLAGS is a @@ -9398,7 +9386,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) SET_EXPR_LOCATION (expr, input_location); if (TREE_THIS_VOLATILE (fn) && cfun) current_function_returns_abnormally = 1; - if (immediate_invocation_p (fn, vec_safe_length (args))) + if (immediate_invocation_p (fn)) { tree obj_arg = NULL_TREE, exprimm = expr; if (DECL_CONSTRUCTOR_P (fn)) @@ -9543,7 +9531,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) in_consteval_if_p_temp_override icip; /* If the call is immediate function invocation, make sure taking address of immediate functions is allowed in its arguments. */ - if (immediate_invocation_p (STRIP_TEMPLATE (fn), nargs)) + if (immediate_invocation_p (STRIP_TEMPLATE (fn))) in_consteval_if_p = true; /* The implicit parameters to a constructor are not considered by overload @@ -10072,7 +10060,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) if (TREE_CODE (fn) == ADDR_EXPR) { tree fndecl = STRIP_TEMPLATE (TREE_OPERAND (fn, 0)); - if (immediate_invocation_p (fndecl, nargs)) + if (immediate_invocation_p (fndecl)) { tree obj_arg = NULL_TREE; /* Undo convert_from_reference called by build_cxx_call. */ diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index 06dcd71c926..2038f43425b 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -1324,26 +1324,6 @@ save_fundef_copy (tree fun, tree copy) *slot = copy; } -/* We have an expression tree T that represents a call, either CALL_EXPR - or AGGR_INIT_EXPR. Return the Nth argument. */ - -static inline tree -get_nth_callarg (tree t, int n) -{ - switch (TREE_CODE (t)) - { - case CALL_EXPR: - return CALL_EXPR_ARG (t, n); - - case AGGR_INIT_EXPR: - return AGGR_INIT_EXPR_ARG (t, n); - - default: - gcc_unreachable (); - return NULL; - } -} - /* Whether our evaluation wants a prvalue (e.g. CONSTRUCTOR or _CST), a glvalue (e.g. VAR_DECL or _REF), or nothing. */ diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc index d0e12c9ee17..a937060b029 100644 --- a/gcc/cp/cp-gimplify.cc +++ b/gcc/cp/cp-gimplify.cc @@ -1010,13 +1010,6 @@ cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data_) } break; - case CALL_EXPR: - if (tree fndecl = cp_get_callee_fndecl_nofold (stmt)) - if (DECL_IMMEDIATE_FUNCTION_P (fndecl) - && source_location_current_p (fndecl)) - *stmt_p = stmt = cxx_constant_value (stmt); - break; - default: break; } diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc index 25657cfd4c6..14e937d81cb 100644 --- a/gcc/cp/name-lookup.cc +++ b/gcc/cp/name-lookup.cc @@ -4302,8 +4302,6 @@ begin_scope (scope_kind kind, tree entity) case sk_function_parms: scope->keep = keep_next_level_flag; - if (entity) - scope->immediate_fn_ctx_p = DECL_IMMEDIATE_FUNCTION_P (entity); break; case sk_namespace: diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index dc3d17c416c..4e3ed660e68 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -11519,31 +11519,11 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) opening parenthesis if present. */ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) { - bool is_consteval = false; - /* For C++20, before parsing the parameter list check if there is - a consteval specifier in the corresponding decl-specifier-seq. */ - if (cxx_dialect >= cxx20) - { - for (size_t n = cp_parser_skip_balanced_tokens (parser, 1); - cp_lexer_nth_token_is (parser->lexer, n, CPP_KEYWORD); n++) - { - if (cp_lexer_peek_nth_token (parser->lexer, n)->keyword - == RID_CONSTEVAL) - { - is_consteval = true; - break; - } - } - } - matching_parens parens; parens.consume_open (parser); begin_scope (sk_function_parms, /*entity=*/NULL_TREE); - if (is_consteval) - current_binding_level->immediate_fn_ctx_p = true; - /* Parse parameters. */ param_list = cp_parser_parameter_declaration_clause @@ -23186,10 +23166,6 @@ cp_parser_direct_declarator (cp_parser* parser, begin_scope (sk_function_parms, NULL_TREE); - /* Signal we are in the immediate function context. */ - if (flags & CP_PARSER_FLAGS_CONSTEVAL) - current_binding_level->immediate_fn_ctx_p = true; - /* Parse the parameter-declaration-clause. */ params = cp_parser_parameter_declaration_clause (parser, flags); diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index b80e7ff1845..ec337e2349e 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -13933,6 +13933,8 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg, push_to_top_level (); push_access_scope (fn); push_deferring_access_checks (dk_no_deferred); + /* So in_immediate_context knows this is a default argument. */ + begin_scope (sk_function_parms, fn); start_lambda_scope (parm); /* The default argument expression may cause implicitly defined @@ -13956,6 +13958,7 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg, inform (input_location, " when instantiating default argument for call to %qD", fn); + leave_scope (); pop_deferring_access_checks (); pop_access_scope (fn); pop_from_top_level (); diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index 3532e44279f..45348c58bb6 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -3125,32 +3125,6 @@ array_type_nelts_total (tree type) return sz; } -/* Return true if FNDECL is std::source_location::current () method. */ - -bool -source_location_current_p (tree fndecl) -{ - gcc_checking_assert (TREE_CODE (fndecl) == FUNCTION_DECL - && DECL_IMMEDIATE_FUNCTION_P (fndecl)); - if (DECL_NAME (fndecl) == NULL_TREE - || TREE_CODE (TREE_TYPE (fndecl)) != FUNCTION_TYPE - || TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != RECORD_TYPE - || DECL_CONTEXT (fndecl) != TREE_TYPE (TREE_TYPE (fndecl)) - || !id_equal (DECL_NAME (fndecl), "current")) - return false; - - tree source_location = DECL_CONTEXT (fndecl); - if (TYPE_NAME (source_location) == NULL_TREE - || TREE_CODE (TYPE_NAME (source_location)) != TYPE_DECL - || TYPE_IDENTIFIER (source_location) == NULL_TREE - || !id_equal (TYPE_IDENTIFIER (source_location), - "source_location") - || !decl_in_std_namespace_p (TYPE_NAME (source_location))) - return false; - - return true; -} - struct bot_data { splay_tree target_remap; @@ -3298,7 +3272,7 @@ bot_manip (tree* tp, int* walk_subtrees, void* data_) variables. */ static tree -bot_replace (tree* t, int* /*walk_subtrees*/, void* data_) +bot_replace (tree* t, int* walk_subtrees, void* data_) { bot_data &data = *(bot_data*)data_; splay_tree target_remap = data.target_remap; @@ -3328,6 +3302,27 @@ bot_replace (tree* t, int* /*walk_subtrees*/, void* data_) /*check_access=*/false, /*nonnull=*/true, tf_warning_or_error); } + else if (cxx_dialect >= cxx20 + && (TREE_CODE (*t) == CALL_EXPR + || TREE_CODE (*t) == AGGR_INIT_EXPR) + && !in_immediate_context ()) + { + /* Expand immediate invocations. */ + if (tree fndecl = cp_get_callee_fndecl_nofold (*t)) + if (DECL_IMMEDIATE_FUNCTION_P (fndecl)) + { + /* Make in_immediate_context true within the args. */ + in_consteval_if_p_temp_override ito; + in_consteval_if_p = true; + int nargs = call_expr_nargs (*t); + for (int i = 0; i < nargs; ++i) + cp_walk_tree (&get_nth_callarg (*t, i), bot_replace, data_, NULL); + *t = cxx_constant_value (*t); + if (*t == error_mark_node) + return error_mark_node; + *walk_subtrees = 0; + } + } return NULL_TREE; } @@ -3353,7 +3348,8 @@ break_out_target_exprs (tree t, bool clear_location /* = false */) 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 (cp_walk_tree (&t, bot_replace, &data, NULL) == error_mark_node) + t = error_mark_node; if (!--target_remap_count) { diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval-defarg3.C b/gcc/testsuite/g++.dg/cpp2a/consteval-defarg3.C new file mode 100644 index 00000000000..316219c6547 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/consteval-defarg3.C @@ -0,0 +1,23 @@ +// DR 2631: default args and DMI aren't immediately evaluated +// { dg-do compile { target c++20 } } +// { dg-final { scan-assembler-not "foober" } } + +consteval int foober(); + +int g(int = foober()); +struct A { int i = foober(); }; +template struct B { }; +struct C +{ + consteval C(int = foober()) { } +}; +int h(C = C()); + +consteval int foober() { return 42; } + +int main() { + A a; + B<> b; + g(); + h(); +} base-commit: 11c72f20d4d7ba1862a257cef05dc3a5e84a276d -- 2.31.1