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 8C4073858C50 for ; Thu, 9 Feb 2023 16:14:44 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 8C4073858C50 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=1675959284; h=from:from:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type; bh=CrAejOeuge2bLJsx6nj/8t8NvTuZOq0VfK2PHkJkf7k=; b=Ya2DeiaBrHnBqwGG4obuxJrwXNOsY97sf7+QZu+BKO2FE5jW8YMIYp9RY7PeZdIlm6TlkE a0kK8AQwVWrYb/dLbA0l8WECT076vaTHt7Ngx+/dmwVMl7xdUpCh2x3wOGkocgo1N4+ZS9 3MrL3wCeY/vwHahyAU61aRov8/PwWgY= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-388-3PErH_r0NGqpjROtcoXl_w-1; Thu, 09 Feb 2023 11:14:43 -0500 X-MC-Unique: 3PErH_r0NGqpjROtcoXl_w-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id A16E880D0E3 for ; Thu, 9 Feb 2023 16:14:42 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.192.223]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 5E155403D0C1; Thu, 9 Feb 2023 16:14:42 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.17.1/8.17.1) with ESMTPS id 319GEdU24060556 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Thu, 9 Feb 2023 17:14:40 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 319GEdTF4060555; Thu, 9 Feb 2023 17:14:39 +0100 Date: Thu, 9 Feb 2023 17:14:39 +0100 From: Jakub Jelinek To: Jason Merrill Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] c++: Don't defer local statics initialized with constant expressions [PR108702] Message-ID: Reply-To: Jakub Jelinek MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-Spam-Status: No, score=-3.5 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,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: Hi! The stmtexpr19.C testcase used to be rejected as it has a static variable in statement expression in constexpr context, but as that static variable is initialized by constant expression, when P2647R1 was implemented we agreed to make it valid. Now, as reported, the testcase compiles fine, but doesn't actually link because the static variable isn't defined anywhere, and with -flto ICEs because of this problem. This is because we never varpool_node::finalize_decl those vars, the constant expression in which the DECL_EXPR is present for the static VAR_DECL is folded (constant evaluated) into just the address of the VAR_DECL. Now, similar testcase included below (do we want to include it in the testsuite too?) works fine, because in cp_finish_decl -> make_rtl_for_nonlocal_decl we have since PR70353 fix: /* We defer emission of local statics until the corresponding DECL_EXPR is expanded. But with constexpr its function might never be expanded, so go ahead and tell cgraph about the variable now. */ defer_p = ((DECL_FUNCTION_SCOPE_P (decl) && !var_in_maybe_constexpr_fn (decl)) || DECL_VIRTUAL_P (decl)); and so don't defer them in constexpr/consteval functions. The following patch extends that and doesn't defer vars initialized by constant expressions either, because otherwise there is nothing to finalize those. It is true that e.g. with -O0 int foo (int x) { if (x) { static int y = 1; ++y; } if (0) { static int z = 1; ++z; } return sizeof (({ static int w = 1; w; })); } we used to emit just y and z and with the patch emit also w, but with optimizations that is optimized away properly. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? The testcase I was talking above that works because of the && !var_in_maybe_constexpr_fn (decl) case is: extern "C" void abort (); constexpr const int * foo () { static constexpr int a = 1; return &a; } consteval const int * bar () { static constexpr int a = 1; return &a; } [[gnu::noipa]] void baz (const int *x) { if (*x != 1) abort (); } int main () { constexpr const int *p = foo (); constexpr const int *q = bar (); baz (p); baz (q); if (p == q) abort (); } 2023-02-09 Jakub Jelinek PR c++/108702 * decl.cc (make_rtl_for_nonlocal_decl): Don't defer local statics initialized by constant expressions. * g++.dg/ext/stmtexpr19.C: Use dg-do link rather than dg-do compile. --- gcc/cp/decl.cc.jj 2023-01-24 11:10:13.151076134 +0100 +++ gcc/cp/decl.cc 2023-02-09 13:29:50.527083618 +0100 @@ -7731,9 +7731,12 @@ make_rtl_for_nonlocal_decl (tree decl, t /* We defer emission of local statics until the corresponding DECL_EXPR is expanded. But with constexpr its function might never - be expanded, so go ahead and tell cgraph about the variable now. */ + be expanded, so go ahead and tell cgraph about the variable now. + Also don't defer local statics initialized by constant expressions, + see PR108702. */ defer_p = ((DECL_FUNCTION_SCOPE_P (decl) - && !var_in_maybe_constexpr_fn (decl)) + && !var_in_maybe_constexpr_fn (decl) + && !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)) || DECL_VIRTUAL_P (decl)); /* Defer template instantiations. */ --- gcc/testsuite/g++.dg/ext/stmtexpr19.C.jj 2022-11-19 09:26:30.168061316 +0100 +++ gcc/testsuite/g++.dg/ext/stmtexpr19.C 2023-02-09 13:32:48.887453520 +0100 @@ -1,6 +1,6 @@ // PR c++/81073 // { dg-options "" } -// { dg-do compile { target c++11 } } +// { dg-do link { target c++11 } } struct test { const int *addr; }; Jakub