public inbox for gcc-cvs@sourceware.org help / color / mirror / Atom feed
From: Jakub Jelinek <jakub@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org Subject: [gcc r12-4731] c++: Reject addresses of immediate functions in constexpr vars inside of immediate functions or cons Date: Wed, 27 Oct 2021 07:28:50 +0000 (GMT) [thread overview] Message-ID: <20211027072850.356B53858C27@sourceware.org> (raw) https://gcc.gnu.org/g:7473b8a90490e1dcd8fd5f7a92307d79fd2a5f8e commit r12-4731-g7473b8a90490e1dcd8fd5f7a92307d79fd2a5f8e Author: Jakub Jelinek <jakub@redhat.com> Date: Wed Oct 27 09:08:19 2021 +0200 c++: Reject addresses of immediate functions in constexpr vars inside of immediate functions or consteval if [PR102753] Another thing that wasn't in the previous patch, but I'm wondering whether we don't handle it incorrectly. constexpr.c has: /* Check that immediate invocation does not return an expression referencing any immediate function decls. They need to be allowed while parsing immediate functions, but can't leak outside of them. */ if (is_consteval && t != r && (current_function_decl == NULL_TREE || !DECL_IMMEDIATE_FUNCTION_P (current_function_decl))) as condition for the discovery of embedded immediate FUNCTION_DECLs (or now PTRMEM_CSTs). If I remove the && (current... ..._decl)) then g++.dg/cpp2a/consteval7.C's struct S { int b; int (*c) (); }; consteval S baz () { return { 5, foo }; } consteval int qux () { S s = baz (); return s.b + s.c (); } consteval int quux () { constexpr S s = baz (); return s.b + s.c (); } quux line fails, but based on http://eel.is/c++draft/expr.const#11 I wonder if it shouldn't fail (clang++ -std=c++20 rejects it), and be only accepted without the constexpr keyword before S s. Also wonder about e.g. consteval int foo () { return 42; } consteval int bar () { auto fn1 = foo; // This must be ok constexpr auto fn2 = foo; // Isn't this an error? return fn1 () + fn2 (); } constexpr int baz () { if consteval { auto fn1 = foo; // This must be ok constexpr auto fn2 = foo; // Isn't this an error? return fn1 () + fn2 (); } return 0; } auto a = bar (); static_assert (bar () == 84); static_assert (baz () == 84); (again, clang++ -std=c++20 rejects the fn2 = foo; case, but doesn't implement consteval if, so can't test the other one). For taking address of an immediate function or method if it is taken outside of immediate function context we already have diagnostics about it, but shouldn't the immediate FUNCTION_DECL discovery in cxx_eval_outermost_constant_expression be instead guarded with something like if (is_consteval || in_immediate_context ()) and be done regardless of whether t != r? 2021-10-27 Jakub Jelinek <jakub@redhat.com> PR c++/102753 * constexpr.c (cxx_eval_outermost_constant_expr): Perform find_immediate_fndecl discovery if is_consteval or in_immediate_context () rather than if is_consteval, t != r and not in immediate function's body. * g++.dg/cpp2a/consteval7.C: Expect diagnostics on quux. * g++.dg/cpp2a/consteval24.C: New test. * g++.dg/cpp23/consteval-if12.C: New test. Diff: --- gcc/cp/constexpr.c | 8 ++----- gcc/testsuite/g++.dg/cpp23/consteval-if12.C | 34 +++++++++++++++++++++++++++++ gcc/testsuite/g++.dg/cpp2a/consteval24.C | 30 +++++++++++++++++++++++++ gcc/testsuite/g++.dg/cpp2a/consteval7.C | 2 +- 4 files changed, 67 insertions(+), 7 deletions(-) diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index daa6358d08f..a31d12b7451 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -7472,12 +7472,8 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, } /* Check that immediate invocation does not return an expression referencing - any immediate function decls. They need to be allowed while parsing - immediate functions, but can't leak outside of them. */ - if (is_consteval - && t != r - && (current_function_decl == NULL_TREE - || !DECL_IMMEDIATE_FUNCTION_P (current_function_decl))) + any immediate function decls. */ + if (is_consteval || in_immediate_context ()) if (tree immediate_fndecl = cp_walk_tree_without_duplicates (&r, find_immediate_fndecl, NULL)) diff --git a/gcc/testsuite/g++.dg/cpp23/consteval-if12.C b/gcc/testsuite/g++.dg/cpp23/consteval-if12.C new file mode 100644 index 00000000000..7a47680e5d8 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/consteval-if12.C @@ -0,0 +1,34 @@ +// PR c++/102753 +// { dg-do compile { target c++20 } } +// { dg-options "" } + +struct S { + constexpr S () : s (0) {} + consteval int foo () { return 1; } + virtual consteval int bar () { return 2; } + int s; +}; + +consteval int foo () { return 42; } +consteval auto baz () { return foo; } +consteval auto qux () { return &S::foo; } +consteval auto corge () { return &S::bar; } + +constexpr int +bar () +{ + S s; + if consteval { // { dg-warning "'if consteval' only available with" "" { target c++20_only } } + constexpr auto fn1 = foo; // { dg-error "immediate evaluation returns address of immediate function" } + constexpr auto fn2 = &foo; // { dg-error "immediate evaluation returns address of immediate function" } + constexpr auto fn3 = &S::foo; // { dg-error "immediate evaluation returns address of immediate function" } + constexpr auto fn4 = &S::bar; // { dg-error "immediate evaluation returns address of immediate function" } + constexpr auto fn5 = baz (); // { dg-error "immediate evaluation returns address of immediate function" } + constexpr auto fn6 = qux (); // { dg-error "immediate evaluation returns address of immediate function" } + constexpr auto fn7 = corge (); // { dg-error "immediate evaluation returns address of immediate function" } + return fn1 () + fn2 () + (s.*fn3) () + (s.*fn4) () + fn5 () + (s.*fn6) () + (s.*fn7) (); + } + return 0; +} + +auto a = bar (); diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval24.C b/gcc/testsuite/g++.dg/cpp2a/consteval24.C new file mode 100644 index 00000000000..6d0c63c749b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/consteval24.C @@ -0,0 +1,30 @@ +// PR c++/102753 +// { dg-do compile { target c++20 } } + +struct S { + constexpr S () : s (0) {} + consteval int foo () { return 1; } + virtual consteval int bar () { return 2; } + int s; +}; + +consteval int foo () { return 42; } +consteval auto baz () { return foo; } +consteval auto qux () { return &S::foo; } +consteval auto corge () { return &S::bar; } + +consteval int +bar () +{ + S s; + constexpr auto fn1 = foo; // { dg-error "immediate evaluation returns address of immediate function" } + constexpr auto fn2 = &foo; // { dg-error "immediate evaluation returns address of immediate function" } + constexpr auto fn3 = &S::foo; // { dg-error "immediate evaluation returns address of immediate function" } + constexpr auto fn4 = &S::bar; // { dg-error "immediate evaluation returns address of immediate function" } + constexpr auto fn5 = baz (); // { dg-error "immediate evaluation returns address of immediate function" } + constexpr auto fn6 = qux (); // { dg-error "immediate evaluation returns address of immediate function" } + constexpr auto fn7 = corge (); // { dg-error "immediate evaluation returns address of immediate function" } + return fn1 () + fn2 () + (s.*fn3) () + (s.*fn4) () + fn5 () + (s.*fn6) () + (s.*fn7) (); +} + +auto a = bar (); diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval7.C b/gcc/testsuite/g++.dg/cpp2a/consteval7.C index 10e4ea41c9b..23f3d25a39e 100644 --- a/gcc/testsuite/g++.dg/cpp2a/consteval7.C +++ b/gcc/testsuite/g++.dg/cpp2a/consteval7.C @@ -7,7 +7,7 @@ constexpr auto a = bar (); // { dg-error "immediate evaluation returns address o struct S { int b; int (*c) (); }; consteval S baz () { return { 5, foo }; } consteval int qux () { S s = baz (); return s.b + s.c (); } -consteval int quux () { constexpr S s = baz (); return s.b + s.c (); } +consteval int quux () { constexpr S s = baz (); return s.b + s.c (); } // { dg-error "immediate evaluation returns address of immediate function 'consteval int foo\\(\\)'" } constexpr auto d = baz (); // { dg-error "immediate evaluation returns address of immediate function 'consteval int foo\\(\\)'" } constexpr auto e = qux (); constexpr auto f = quux ();
reply other threads:[~2021-10-27 7:28 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20211027072850.356B53858C27@sourceware.org \ --to=jakub@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).