From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-1.mimecast.com (us-smtp-1.mimecast.com [207.211.31.81]) by sourceware.org (Postfix) with ESMTP id 77D7D3858D35 for ; Tue, 14 Jul 2020 08:50:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 77D7D3858D35 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-95-cZEvc1qBPKO7_H7QRrfiWQ-1; Tue, 14 Jul 2020 04:50:47 -0400 X-MC-Unique: cZEvc1qBPKO7_H7QRrfiWQ-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 8827D100AA27 for ; Tue, 14 Jul 2020 08:50:46 +0000 (UTC) Received: from tucnak.zalov.cz (ovpn-112-218.ams2.redhat.com [10.36.112.218]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 0B2B35C6DD; Tue, 14 Jul 2020 08:50:45 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.15.2/8.15.2) with ESMTP id 06E8ogLK031465; Tue, 14 Jul 2020 10:50:43 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.15.2/8.15.2/Submit) id 06E8ogLu031464; Tue, 14 Jul 2020 10:50:42 +0200 Date: Tue, 14 Jul 2020 10:50:42 +0200 From: Jakub Jelinek To: Jason Merrill Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] c++: Use error_at rather than warning_at for missing return in constexpr functions [PR96182] Message-ID: <20200714085042.GM2363@tucnak> Reply-To: Jakub Jelinek MIME-Version: 1.0 User-Agent: Mutt/1.11.3 (2019-02-01) X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 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=-7.9 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_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-List-Received-Date: Tue, 14 Jul 2020 08:50:51 -0000 Hi! For C++11 we already emit an error if a constexpr function doesn't contain a return statement, because in C++11 that is the only thing it needs to contain, but for C++14 we would normally issue a -Wreturn-type warning. As mentioned by Jonathan, such constexpr functions are invalid, no diagnostics required, because there doesn't exist any arguments for which it would result in valid constant expression. This raises it to an error in such cases. The !LAMBDA_TYPE_P case is to avoid error on g++.dg/pr81194.C where the user didn't write constexpr anywhere and the operator() is compiler generated. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2020-07-14 Jakub Jelinek PR c++/96182 * decl.c (finish_function): In constexpr functions other than lambdas use for C++14 and later error instead of warning if no return statement is present and diagnose it regardless of warn_return_type. * g++.dg/cpp1y/constexpr-96182.C: New test. * g++.dg/other/error35.C (S::g()): Add return statement. * g++.dg/cpp1y/pr63996.C (foo): Likewise. * g++.dg/cpp1y/constexpr-return2.C (f): Likewise. * g++.dg/cpp1y/var-templ44.C (make_array): Add throw 1. --- gcc/cp/decl.c.jj 2020-07-13 19:09:27.258953908 +0200 +++ gcc/cp/decl.c 2020-07-13 22:25:42.437062842 +0200 @@ -17164,7 +17164,10 @@ finish_function (bool inline_p) BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl; /* Complain if there's just no return statement. */ - if (warn_return_type + if ((warn_return_type + || (cxx_dialect >= cxx14 + && DECL_DECLARED_CONSTEXPR_P (fndecl) + && !LAMBDA_TYPE_P (CP_DECL_CONTEXT (fndecl)))) && !VOID_TYPE_P (TREE_TYPE (fntype)) && !dependent_type_p (TREE_TYPE (fntype)) && !current_function_returns_value && !current_function_returns_null @@ -17196,8 +17199,14 @@ finish_function (bool inline_p) global_dc->option_state)) add_return_star_this_fixit (&richloc, fndecl); } - if (warning_at (&richloc, OPT_Wreturn_type, - "no return statement in function returning non-void")) + if (cxx_dialect >= cxx14 + && DECL_DECLARED_CONSTEXPR_P (fndecl) + && !LAMBDA_TYPE_P (CP_DECL_CONTEXT (fndecl))) + error_at (&richloc, "no return statement in % function " + "returning non-void"); + else if (warning_at (&richloc, OPT_Wreturn_type, + "no return statement in function returning " + "non-void")) TREE_NO_WARNING (fndecl) = 1; } --- gcc/testsuite/g++.dg/other/error35.C.jj 2020-01-12 11:54:37.214401324 +0100 +++ gcc/testsuite/g++.dg/other/error35.C 2020-07-13 22:35:55.359228614 +0200 @@ -9,6 +9,6 @@ template struct S { enum S::E; template enum S::E : int { b }; template -constexpr int S::g() const { b; } // { dg-error "not declared" } +constexpr int S::g() const { b; if (false) return 0; } // { dg-error "not declared" } static_assert(S().g() == 1, ""); // { dg-error "" } // { dg-message "in .constexpr. expansion of" "" { target *-*-* } .-1 } --- gcc/testsuite/g++.dg/cpp1y/pr63996.C.jj 2020-01-12 11:54:37.000000000 +0100 +++ gcc/testsuite/g++.dg/cpp1y/pr63996.C 2020-07-13 22:17:39.034004329 +0200 @@ -5,6 +5,7 @@ constexpr int foo (int i) { int a[i] = { }; // { dg-error "7:ISO C\\+\\+ forbids variable length array .a" } + if (i == 23) return 0; } constexpr int j = foo (1); // { dg-error "flows off the end|in .constexpr. expansion of" } --- gcc/testsuite/g++.dg/cpp1y/constexpr-96182.C.jj 2020-07-13 19:16:42.742936492 +0200 +++ gcc/testsuite/g++.dg/cpp1y/constexpr-96182.C 2020-07-13 19:16:12.264357640 +0200 @@ -0,0 +1,6 @@ +// PR c++/96182 +// { dg-do compile { target c++11 } } + +constexpr int foo () {} // { dg-error "no return statement in 'constexpr' function returning non-void" "" { target c++14 } } +// { dg-error "body of 'constexpr' function 'constexpr int foo\\\(\\\)' not a return-statement" "" { target c++11_only } .-1 } +// { dg-warning "no return statement in function returning non-void" "" { target c++11_only } .-2 } --- gcc/testsuite/g++.dg/cpp1y/constexpr-return2.C.jj 2020-01-12 11:54:37.115402818 +0100 +++ gcc/testsuite/g++.dg/cpp1y/constexpr-return2.C 2020-07-13 22:17:03.582513397 +0200 @@ -3,6 +3,7 @@ constexpr int f (int i) { + if (i == -1) return 0; } constexpr int i = f(42); // { dg-error "flows off the end|in .constexpr. expansion of " } --- gcc/testsuite/g++.dg/cpp1y/var-templ44.C.jj 2020-01-12 11:54:37.123402697 +0100 +++ gcc/testsuite/g++.dg/cpp1y/var-templ44.C 2020-07-13 22:35:03.322980157 +0200 @@ -26,5 +26,6 @@ constexpr auto make_array() -> array, common_type_t<>, _Dest>, sizeof...(_Types)> { static_assert(__or_<__not_>, __and_<>>::value, ""); // { dg-error "static assert" } + throw 1; } auto d = make_array(); Jakub