Bug 115744 - [C++26] P2747R2 - constexpr placement new
Summary: [C++26] P2747R2 - constexpr placement new
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 15.0
: P3 normal
Target Milestone: 15.0
Assignee: Jakub Jelinek
URL:
Keywords:
Depends on:
Blocks: c++26-core 115754
  Show dependency treegraph
 
Reported: 2024-07-02 08:41 UTC by Jakub Jelinek
Modified: 2024-08-20 20:52 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2024-07-02 00:00:00


Attachments
gcc15-pr115744-wip.patch (1.64 KB, patch)
2024-07-02 14:01 UTC, Jakub Jelinek
Details | Diff
gcc15-pr115744.patch (2.38 KB, patch)
2024-07-03 09:45 UTC, Jakub Jelinek
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Jakub Jelinek 2024-07-02 08:41:39 UTC
See <https://wg21.link/P2747R2>.
Comment 1 Jakub Jelinek 2024-07-02 14:01:28 UTC
Created attachment 58563 [details]
gcc15-pr115744-wip.patch

Untested WIP patch.
Comment 2 Jason Merrill 2024-07-02 14:10:35 UTC
(In reply to Jakub Jelinek from comment #1)
> Untested WIP patch.

In the conversion lval change, I'd think we want vc_discard for conversion to void, and to pass through whatever lval for VIEW_CONVERT_EXPR.
Comment 3 Jakub Jelinek 2024-07-03 09:45:38 UTC
Created attachment 58580 [details]
gcc15-pr115744.patch

With the PR115754 change in, this seems mostly about the FTMs and making placement new constexpr.
The only thing that doesn't work is the
new (p + 1) int[]{2, 3};      // error (in this paper)
case from the paper xfailed in the last testcase, the IL has there
<<< Unknown tree: expr_stmt
  (void) (TARGET_EXPR <D.2640, (void *) TARGET_EXPR <D.2641, VIEW_CONVERT_EXPR<int *>(b) + 4>>, TARGET_EXPR <D.2642, operator new [] (8, NON_LVALUE_EXPR <D.2640>)>,   int * D.2643;
  <<< Unknown tree: expr_stmt
    (void) (D.2643 = (int *) D.2642) >>>;
and so there is nothing that would trigger some error during constexpr evaluation.
Shouldn't build_new_1 for maybe_constexpr_fn (current_function_decl) in the array_p case add some extra cast to the array type it is looking for rather
than just the ultimate element type?
Comment 4 GCC Commits 2024-08-08 09:08:39 UTC
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:afa3a4a52cf91485477e4aaa5f05987ec7ff869d

commit r15-2815-gafa3a4a52cf91485477e4aaa5f05987ec7ff869d
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Thu Aug 8 11:05:36 2024 +0200

    c++, libstdc++: Implement C++26 P2747R2 - constexpr placement new [PR115744]
    
    With the PR115754 fix in, constexpr placement new mostly just works,
    so this patch just adds constexpr keyword to the placement new operators
    in <new>, adds FTMs and testsuite coverage.
    
    There is one accepts-invalid though, the
    new (p + 1) int[]{2, 3};      // error (in this paper)
    case from the paper.  Can we handle that incrementally?
    The problem with that is I think calling operator new now that it is
    constexpr should be fine even in that case in constant expressions, so
    int *p = std::allocator<int>{}.allocate(3);
    int *q = operator new[] (sizeof (int) * 2, p + 1);
    should be ok, so it can't be easily the placement new operator call
    itself on whose constexpr evaluation we try something special, it should
    be on the new expression, but constexpr.cc actually sees only
    <<< Unknown tree: expr_stmt
      (void) (TARGET_EXPR <D.2640, (void *) TARGET_EXPR <D.2641, VIEW_CONVERT_EXPR<int *>(b) + 4>>, TARGET_EXPR <D.2642, operator new [] (8, NON_LVALUE_EXPR <D.2640>)>,   int * D.2643;
      <<< Unknown tree: expr_stmt
        (void) (D.2643 = (int *) D.2642) >>>;
    and that is just fine by the preexisting constexpr evaluation rules.
    
    Should build_new_1 emit some extra cast for the array cases with placement
    new in maybe_constexpr_fn (current_function_decl) that the existing P2738
    code would catch?
    
    2024-08-08  Jakub Jelinek  <jakub@redhat.com>
    
            PR c++/115744
    gcc/c-family/
            * c-cppbuiltin.cc (c_cpp_builtins): Change __cpp_constexpr
            from 202306L to 202406L for C++26.
    gcc/testsuite/
            * g++.dg/cpp2a/construct_at.h (operator new, operator new[]):
            Use constexpr instead of inline if __cpp_constexpr >= 202406L.
            * g++.dg/cpp26/constexpr-new1.C: New test.
            * g++.dg/cpp26/constexpr-new2.C: New test.
            * g++.dg/cpp26/constexpr-new3.C: New test.
            * g++.dg/cpp26/feat-cxx26.C (__cpp_constexpr): Adjust expected
            value.
    libstdc++-v3/
            * libsupc++/new (__glibcxx_want_constexpr_new): Define before
            including bits/version.h.
            (_GLIBCXX_PLACEMENT_CONSTEXPR): Define.
            (operator new, operator new[]): Use it for placement new instead
            of inline.
            * include/bits/version.def (constexpr_new): New FTM.
            * include/bits/version.h: Regenerate.
Comment 5 Jakub Jelinek 2024-08-08 09:10:50 UTC
Implemented for 15.1+.
Comment 6 GCC Commits 2024-08-20 20:52:47 UTC
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>:

https://gcc.gnu.org/g:20c63093db0f230ef49a298cdb0611f38e470203

commit r15-3049-g20c63093db0f230ef49a298cdb0611f38e470203
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Tue Aug 20 21:47:29 2024 +0100

    libstdc++: Adjust testcase for constexpr placement new [PR115744]
    
    This test now fails in C++26 mode because the declaration in <new> is
    constexpr and the one in the test isn't. Add constexpr to the test.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/115744
            * testsuite/18_support/headers/new/synopsis.cc [C++26]: Add
            constexpr to placement operator new and operator new[].