Bug 110344 - [C++26] P2738R1 - constexpr cast from void*
Summary: [C++26] P2738R1 - constexpr cast from void*
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 14.0
: P3 normal
Target Milestone: 14.0
Assignee: Jason Merrill
URL:
Keywords:
Depends on:
Blocks: c++26-core
  Show dependency treegraph
 
Reported: 2023-06-21 16:16 UTC by Marek Polacek
Modified: 2023-07-14 22:38 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2023-06-22 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Marek Polacek 2023-06-21 16:16:19 UTC
See <https://wg21.link/P2738R1>.
Comment 1 Andrew Pinski 2023-06-22 06:28:33 UTC
Confirmed.
Comment 2 Jason Merrill 2023-06-24 21:55:04 UTC
Reduced version of the paper's testcase that we already (wrongly) accept:

class Doer {
private:
  const void *ob;
  int (*fn)(const void *);
public:
  template <typename T>
  constexpr Doer(const T &t)
    : ob{&t},
      fn{[](const void *p) { return static_cast<const T *>(p)->doit(); }}
  {}
  constexpr int operator()() const { return fn(ob); }
};
struct Thing { constexpr int doit() const { return 42; }; };
static_assert (Doer(Thing())() == 42);
Comment 3 Jason Merrill 2023-06-24 21:57:43 UTC
Version of the paper testcase that just adds constexpr, that we currently reject:

#include <string_view>
struct Sheep {
  constexpr std::string_view speak() const noexcept { return "Baaaaaa"; }
};
struct Cow {
  constexpr std::string_view speak() const noexcept { return "Mooo"; }
};
class Animal_View {
private:
  const void *animal;
  std::string_view (*speak_function)(const void *);
public:
  template <typename Animal>
  constexpr Animal_View(const Animal &a)
    : animal{&a}, speak_function{[](const void *object) {
                                   return static_cast<const Animal *>(object)->speak();
                                 }} {}
  constexpr std::string_view speak() const noexcept {
    return speak_function(animal);
  }
};
// This is the key bit here. This is a single concrete function                                                                     
// that can take anything that happens to have the "Animal_View"                                                                    
// interface                                                                                                                        
constexpr std::string_view do_speak(Animal_View av) { return av.speak(); }
int main() {
  // A Cow is a cow. The only think that makes it special                                                                           
  // is that it has a "std::string_view speak() const" member                                                                       
  constexpr Cow cow;
  constexpr auto result = do_speak(cow);
  return static_cast<int>(result.size());
}
Comment 4 CVS Commits 2023-06-28 03:29:58 UTC
The trunk branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

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

commit r14-2146-ga1c6e9631ca33990a2b7411060ca4d18db081a7d
Author: Jason Merrill <jason@redhat.com>
Date:   Sat Jun 24 05:15:02 2023 -0400

    c++: C++26 constexpr cast from void* [PR110344]
    
    P2768 allows static_cast from void* to ob* in constant evaluation if the
    pointer does in fact point to an object of the appropriate type.
    cxx_fold_indirect_ref already does the work of finding such an object if it
    happens to be a subobject rather than the outermost object at that address,
    as in constexpr-voidptr2.C.
    
            P2768
            PR c++/110344
    
    gcc/c-family/ChangeLog:
    
            * c-cppbuiltin.cc (c_cpp_builtins): Update __cpp_constexpr.
    
    gcc/cp/ChangeLog:
    
            * constexpr.cc (cxx_eval_constant_expression): In C++26, allow cast
            from void* to the type of a pointed-to object.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp26/constexpr-voidptr1.C: New test.
            * g++.dg/cpp26/constexpr-voidptr2.C: New test.
            * g++.dg/cpp26/feat-cxx26.C: New test.
Comment 5 Jason Merrill 2023-06-28 03:34:38 UTC
Implemented for GCC 14.
Comment 6 CVS Commits 2023-07-14 22:38:01 UTC
The trunk branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

https://gcc.gnu.org/g:8d344146727da02eb5c62fbf6cee97a4e96d63db

commit r14-2535-g8d344146727da02eb5c62fbf6cee97a4e96d63db
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Jul 14 09:37:21 2023 -0400

    c++: c++26 regression fixes
    
    Apparently I wasn't actually running the testsuite in C++26 mode like I
    thought I was, so there were some failures I wasn't seeing.
    
    The constexpr hunk fixes regressions with the P2738 implementation; we still
    need to use the old handling for casting from void pointers to heap
    variables.
    
            PR c++/110344
    
    gcc/cp/ChangeLog:
    
            * constexpr.cc (cxx_eval_constant_expression): Move P2738 handling
            after heap handling.
            * name-lookup.cc (get_cxx_dialect_name): Add C++26.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp0x/constexpr-cast2.C: Adjust for P2738.
            * g++.dg/ipa/devirt-45.C: Handle -fimplicit-constexpr.