From patchwork Tue Dec 1 17:38:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 1408975 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gcc.gnu.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=T6TF8V0T; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Clq8J3mLnz9s1l for ; Wed, 2 Dec 2020 04:38:39 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 5B30C3857C7F; Tue, 1 Dec 2020 17:38:36 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 5B30C3857C7F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1606844316; bh=mAYcnSlWAP981HnBW2J7R2FsK6HYa2Yad16WsCQMTn0=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=T6TF8V0T8X7BgGYonbCT9avDuYEy+/S8noqYodQChdcPedZq4dk3xuZ2Sml0ZjpBQ Pn0SYACFXCa0PsK8dGJrgcDagiczM9YbK2/t96SgFSymI7FXYMfz+l3AI8BZiNG2Uq O8T4QV5faAK/U/ohwG1yxWiosXKWxbYC364l/oZY= 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 [216.205.24.124]) by sourceware.org (Postfix) with ESMTP id 6F58E3857C4F for ; Tue, 1 Dec 2020 17:38:34 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 6F58E3857C4F Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-323-6ZonKnInNFSPNuGeKA5tjg-1; Tue, 01 Dec 2020 12:38:32 -0500 X-MC-Unique: 6ZonKnInNFSPNuGeKA5tjg-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 76CCD42390 for ; Tue, 1 Dec 2020 17:38:31 +0000 (UTC) Received: from pdp-11.redhat.com (ovpn-118-89.rdu2.redhat.com [10.10.118.89]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1DDEF60BFA; Tue, 1 Dec 2020 17:38:30 +0000 (UTC) To: GCC Patches , Jason Merrill Subject: [PATCH] c++: Fix ICE with inline variable in template [PR97975] Date: Tue, 1 Dec 2020 12:38:20 -0500 Message-Id: <20201201173820.1908090-1-polacek@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-15.0 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, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) 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: Marek Polacek via Gcc-patches From: Marek Polacek Reply-To: Marek Polacek Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" In this test, we have static inline const int c = b; in a class template, and we call store_init_value as usual. There, the value is IMPLICIT_CONV_EXPR(b) which is is_nondependent_static_init_expression but isn't is_nondependent_constant_expression (they only differ in STRICT). We call fold_non_dependent_expr, but that just returns the expression because it only instantiates is_nondependent_constant_expression expressions. Since we're not checking the initializer of a constexpr variable, we go on to call maybe_constant_init, whereupon we crash because it tries to evaluate all is_nondependent_static_init_expression expressions, which our value is, but it still contains a template code. I think the fix is to call fold_non_dependent_init instead of maybe_constant_init, and only call fold_non_dependent_expr on the "this is a constexpr variable" path so as to avoid instantiating twice in a row. Outside a template this should also avoid evaluating the value twice. Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/10? gcc/cp/ChangeLog: PR c++/97975 * constexpr.c (fold_non_dependent_init): Add a tree parameter. Use it. * cp-tree.h (fold_non_dependent_init): Add a tree parameter with a default value. * typeck2.c (store_init_value): Call fold_non_dependent_expr only when checking the initializer for constexpr variables. Call fold_non_dependent_init instead of maybe_constant_init. gcc/testsuite/ChangeLog: PR c++/97975 * g++.dg/cpp1z/inline-var8.C: New test. --- gcc/cp/constexpr.c | 7 ++++--- gcc/cp/cp-tree.h | 2 +- gcc/cp/typeck2.c | 7 +++++-- gcc/testsuite/g++.dg/cpp1z/inline-var8.C | 17 +++++++++++++++++ 4 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1z/inline-var8.C base-commit: 855bb43f6d0bee5a74b5d3739456ca34b4609a50 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 054ee524c7a..9a1a1db1267 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -7271,7 +7271,8 @@ maybe_fold_non_dependent_expr (tree expr, tree fold_non_dependent_init (tree t, tsubst_flags_t complain /*=tf_warning_or_error*/, - bool manifestly_const_eval /*=false*/) + bool manifestly_const_eval /*=false*/, + tree object /* = NULL_TREE */) { if (t == NULL_TREE) return NULL_TREE; @@ -7279,7 +7280,7 @@ fold_non_dependent_init (tree t, if (processing_template_decl) { t = fold_non_dependent_expr_template (t, complain, - manifestly_const_eval, NULL_TREE); + manifestly_const_eval, object); /* maybe_constant_init does this stripping, so do it here too. */ if (TREE_CODE (t) == TARGET_EXPR) { @@ -7290,7 +7291,7 @@ fold_non_dependent_init (tree t, return t; } - return maybe_constant_init (t, NULL_TREE, manifestly_const_eval); + return maybe_constant_init (t, object, manifestly_const_eval); } /* Like maybe_constant_value, but returns a CONSTRUCTOR directly, rather diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 021de76e142..41516deeafa 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7953,7 +7953,7 @@ extern tree maybe_fold_non_dependent_expr (tree, tsubst_flags_t = tf_warning_or_error); extern tree fold_non_dependent_init (tree, tsubst_flags_t = tf_warning_or_error, - bool = false); + bool = false, tree = NULL_TREE); extern tree fold_simple (tree); extern bool reduced_constant_expression_p (tree); extern bool is_instantiation_of_constexpr (tree); diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 721987e8502..575c609a365 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -744,11 +744,13 @@ store_init_value (tree decl, tree init, vec** cleanups, int flags) { bool const_init; tree oldval = value; - value = fold_non_dependent_expr (value, tf_warning_or_error, true, decl); if (DECL_DECLARED_CONSTEXPR_P (decl) || (DECL_IN_AGGR_P (decl) && DECL_INITIALIZED_IN_CLASS_P (decl))) { + value = fold_non_dependent_expr (value, tf_warning_or_error, + /*manifestly_const_eval=*/true, + decl); /* Diagnose a non-constant initializer for constexpr variable or non-inline in-class-initialized static data member. */ if (!require_constant_expression (value)) @@ -762,7 +764,8 @@ store_init_value (tree decl, tree init, vec** cleanups, int flags) value = cxx_constant_init (value, decl); } else - value = maybe_constant_init (value, decl, true); + value = fold_non_dependent_init (value, tf_warning_or_error, + /*manifestly_const_eval=*/true, decl); if (TREE_CODE (value) == CONSTRUCTOR && cp_has_mutable_p (type)) /* Poison this CONSTRUCTOR so it can't be copied to another constexpr variable. */ diff --git a/gcc/testsuite/g++.dg/cpp1z/inline-var8.C b/gcc/testsuite/g++.dg/cpp1z/inline-var8.C new file mode 100644 index 00000000000..8db3c19374d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/inline-var8.C @@ -0,0 +1,17 @@ +// PR c++/97975 +// { dg-do compile { target c++17 } } + +template +class A +{ + static const float b; + static inline const int c = b; +}; + +A a; + +struct B +{ + static const float b; + static inline const int c = b; +};