From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-1.mimecast.com (us-smtp-2.mimecast.com [207.211.31.81]) by sourceware.org (Postfix) with ESMTP id 088363851C01 for ; Fri, 31 Jul 2020 20:28:46 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 088363851C01 Received: from mail-qv1-f71.google.com (mail-qv1-f71.google.com [209.85.219.71]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-77-HcLKiDjVNF-Hi-v1wPtHoA-1; Fri, 31 Jul 2020 16:28:43 -0400 X-MC-Unique: HcLKiDjVNF-Hi-v1wPtHoA-1 Received: by mail-qv1-f71.google.com with SMTP id y7so18442376qvj.11 for ; Fri, 31 Jul 2020 13:28:43 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=lcoBJ03d6iuGNn8QPM9z9Mgw5N6Py8KtQw/lUUksKWA=; b=I4mvHzB2wQPWUisnMEuBNvyS1lVQPL900XxFZ0nl04odIFeAZ0Ug9IcuG2cxxWWZ4w uWkQS65EX/1/X/hhOQETcgP+dNCmtSCSTGvc0FzVzsvjWv7pEurfUwtO8OQePBbYhDQm jhkC3t6ji5nNsqo3Dc4MjaUwYiYSlSkMJ/i5gcxa0fuu8ZeBcVeOa1OKzDC1+WAFc3xG 6D5WitdM3XCg1pejA6zj+kmBsLyKQ2puDTMiX9MAgIVPfp6c7G8InKHzjcYzxB5uxArI sqYBynSY1V8/YlspDzn6qOLCDcLSS6h1inx9MgqHY6KyUjB+5C34/r0xtCJQ4I8msdhp sV+Q== X-Gm-Message-State: AOAM530nbuz2YfC8EMzRVY/T0AA5C3Tuo0U2L8dbYf3xKXB8kuqoAyji z1cckD/1OA5oeCHDEfFiv/gMVEOO+WjfbYa117DxYXVyL36JaY9TjadVPEUdhF+FmTLJVk5Btvx V1Wj+0PGD+GJDczINCA== X-Received: by 2002:ac8:3a26:: with SMTP id w35mr5663649qte.124.1596227322480; Fri, 31 Jul 2020 13:28:42 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwdMOQIrZ26qq7qbbgdrVnujxxRTydzsssvwux483RPlkMQb3nP1ZyrKdXDvb88FEWh8jiStw== X-Received: by 2002:ac8:3a26:: with SMTP id w35mr5663628qte.124.1596227322092; Fri, 31 Jul 2020 13:28:42 -0700 (PDT) Received: from [192.168.1.148] (209-6-216-142.s141.c3-0.smr-cbr1.sbo-smr.ma.cable.rcncustomer.com. [209.6.216.142]) by smtp.gmail.com with ESMTPSA id f189sm8819065qke.15.2020.07.31.13.28.41 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 31 Jul 2020 13:28:41 -0700 (PDT) Subject: Re: [PATCH] c++: Use error_at rather than warning_at for missing return in constexpr functions [PR96182] To: Jakub Jelinek Cc: gcc-patches@gcc.gnu.org References: <20200714085042.GM2363@tucnak> <66e1b57c-2f31-def5-fb6b-ca9a5abecf91@redhat.com> <20200731075211.GD2363@tucnak> From: Jason Merrill Message-ID: Date: Fri, 31 Jul 2020 16:28:40 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.6.0 MIME-Version: 1.0 In-Reply-To: <20200731075211.GD2363@tucnak> Content-Language: en-US X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, NICE_REPLY_A, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, 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: Fri, 31 Jul 2020 20:28:47 -0000 On 7/31/20 3:52 AM, Jakub Jelinek wrote: > On Wed, Jul 29, 2020 at 03:30:07PM -0400, Jason Merrill via Gcc-patches wrote: >> On 7/14/20 4:50 AM, Jakub Jelinek wrote: >>> 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. >> >> We set DECL_DECLARED_CONSTEXPR_P on lambdas earlier in finish_function if >> suitable; can we move this diagnostic up before that? > > That works too. Bootstrapped/regtested on x86_64-linux and i686-linux, ok > for trunk then? OK. > 2020-07-31 Jakub Jelinek > > PR c++/96182 > * decl.c (finish_function): In constexpr functions use for C++14 and > later error instead of warning if no return statement is present and > diagnose it regardless of warn_return_type. Move the warn_return_type > diagnostics earlier in the function. > > * 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-29 11:57:23.340517489 +0200 > +++ gcc/cp/decl.c 2020-07-30 20:44:33.634951396 +0200 > @@ -17112,6 +17112,51 @@ finish_function (bool inline_p) > DECL_ATTRIBUTES (fndecl))) > omp_declare_variant_finalize (fndecl, attr); > > + /* Complain if there's just no return statement. */ > + if ((warn_return_type > + || (cxx_dialect >= cxx14 > + && DECL_DECLARED_CONSTEXPR_P (fndecl))) > + && !VOID_TYPE_P (TREE_TYPE (fntype)) > + && !dependent_type_p (TREE_TYPE (fntype)) > + && !current_function_returns_value && !current_function_returns_null > + /* Don't complain if we abort or throw. */ > + && !current_function_returns_abnormally > + /* Don't complain if there's an infinite loop. */ > + && !current_function_infinite_loop > + /* Don't complain if we are declared noreturn. */ > + && !TREE_THIS_VOLATILE (fndecl) > + && !DECL_NAME (DECL_RESULT (fndecl)) > + && !TREE_NO_WARNING (fndecl) > + /* Structor return values (if any) are set by the compiler. */ > + && !DECL_CONSTRUCTOR_P (fndecl) > + && !DECL_DESTRUCTOR_P (fndecl) > + && targetm.warn_func_return (fndecl)) > + { > + gcc_rich_location richloc (input_location); > + /* Potentially add a "return *this;" fix-it hint for > + assignment operators. */ > + if (IDENTIFIER_ASSIGN_OP_P (DECL_NAME (fndecl))) > + { > + tree valtype = TREE_TYPE (DECL_RESULT (fndecl)); > + if (TREE_CODE (valtype) == REFERENCE_TYPE > + && current_class_ref > + && same_type_ignoring_top_level_qualifiers_p > + (TREE_TYPE (valtype), TREE_TYPE (current_class_ref)) > + && global_dc->option_enabled (OPT_Wreturn_type, > + global_dc->lang_mask, > + global_dc->option_state)) > + add_return_star_this_fixit (&richloc, fndecl); > + } > + if (cxx_dialect >= cxx14 > + && DECL_DECLARED_CONSTEXPR_P (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; > + } > + > /* Lambda closure members are implicitly constexpr if possible. */ > if (cxx_dialect >= cxx17 > && LAMBDA_TYPE_P (CP_DECL_CONTEXT (fndecl))) > @@ -17163,44 +17208,6 @@ finish_function (bool inline_p) > to the FUNCTION_DECL node itself. */ > BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl; > > - /* Complain if there's just no return statement. */ > - if (warn_return_type > - && !VOID_TYPE_P (TREE_TYPE (fntype)) > - && !dependent_type_p (TREE_TYPE (fntype)) > - && !current_function_returns_value && !current_function_returns_null > - /* Don't complain if we abort or throw. */ > - && !current_function_returns_abnormally > - /* Don't complain if there's an infinite loop. */ > - && !current_function_infinite_loop > - /* Don't complain if we are declared noreturn. */ > - && !TREE_THIS_VOLATILE (fndecl) > - && !DECL_NAME (DECL_RESULT (fndecl)) > - && !TREE_NO_WARNING (fndecl) > - /* Structor return values (if any) are set by the compiler. */ > - && !DECL_CONSTRUCTOR_P (fndecl) > - && !DECL_DESTRUCTOR_P (fndecl) > - && targetm.warn_func_return (fndecl)) > - { > - gcc_rich_location richloc (input_location); > - /* Potentially add a "return *this;" fix-it hint for > - assignment operators. */ > - if (IDENTIFIER_ASSIGN_OP_P (DECL_NAME (fndecl))) > - { > - tree valtype = TREE_TYPE (DECL_RESULT (fndecl)); > - if (TREE_CODE (valtype) == REFERENCE_TYPE > - && current_class_ref > - && same_type_ignoring_top_level_qualifiers_p > - (TREE_TYPE (valtype), TREE_TYPE (current_class_ref)) > - && global_dc->option_enabled (OPT_Wreturn_type, > - global_dc->lang_mask, > - 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")) > - TREE_NO_WARNING (fndecl) = 1; > - } > - > /* Store the end of the function, so that we get good line number > info for the epilogue. */ > cfun->function_end_locus = input_location; > --- 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 >