Bug 88337 - Implement P1002R1, P1327R1, P1330R0, C++20 relaxations of constexpr restrictions.
Summary: Implement P1002R1, P1327R1, P1330R0, C++20 relaxations of constexpr restricti...
Status: ASSIGNED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 9.0
: P3 enhancement
Target Milestone: ---
Assignee: Marek Polacek
URL:
Keywords: patch
Depends on:
Blocks: 88323
  Show dependency treegraph
 
Reported: 2018-12-03 19:22 UTC by emsr
Modified: 2019-11-10 21:03 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2019-08-05 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description emsr 2018-12-03 19:22:52 UTC

    
Comment 1 emsr 2018-12-03 22:45:51 UTC
LOL, this compiles:

// P1330R0 - Changing the active member of a union inside constexpr
union Foo
{
  int i;
  float f;
};

constexpr int
use()
{
  Foo foo{};
  foo.i = 3;
  foo.f = 1.2f;

  return 1;
}
Comment 2 emsr 2019-03-02 05:29:18 UTC
It looks like try blocks in constexpr is in.  p1002r1.  This may be enough to do some constexpr library bits.
Comment 3 Jakub Jelinek 2019-03-02 09:34:41 UTC
P1330R0 should be now implemented correctly, please report if you see any issues
(for -std=c++2a, with error for -std=c++{11,14,17}).

The dynamic_cast/rtti constexpr relaxation is not implemented, that one is related to PR63164.
Comment 4 Marek Polacek 2019-10-28 17:17:55 UTC
P1002R1 and P1330R0 were implemented in GCC 9.  Taking this PR since I'm looking into P1327R1 (for GCC 10).
Comment 5 Marek Polacek 2019-10-28 22:03:56 UTC
Looks like we need to teach constexpr how to evaluate a call to __dynamic_cast.
Comment 6 Marek Polacek 2019-10-30 16:27:00 UTC
First steps: this now compiles in c++2a:

struct B {
  virtual void baz () {}
};
 
struct D : B { };

constexpr bool
fn ()
{
  bool ok = true;
  B b;
  B *b1 = &b;
  if (D *pd = dynamic_cast<D*>(b1))
    ok = false;

  D d;
  B *b2 = &d;
  if (D *pd = dynamic_cast<D*>(b2))
    /*OK*/;
  else
   ok = false;
    
  return ok;
}

static_assert(fn ());
Comment 7 Marek Polacek 2019-10-31 21:25:12 UTC
Sidecast now works too:

struct A {
  virtual void afn () {}
};
 
struct B {
  virtual void bfn () {}
};

struct D : A, B { };

constexpr bool
fn ()
{
  bool ok = true;
  D d;
  A *a = &d;
  if (B *bp = dynamic_cast<B*>(a))
    /*OK*/;
  else
    ok = false;

  A &ar = d;
  B &br = dynamic_cast<B&>(ar);

  return ok;
}

static_assert(fn ());
Comment 8 Marek Polacek 2019-11-10 20:49:49 UTC
Patch posted:
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg00650.html

For the typeid case, it seems that all that needs to be done is to resolve

 356   /* FIXME when integrating with c_fully_fold, mark
 357      resolves_to_fixed_type_p case as a non-constant expression.  */
 358   if (TYPE_POLYMORPHIC_P (TREE_TYPE (exp))
 359       && ! resolves_to_fixed_type_p (exp, &nonnull)
 360       && ! nonnull)
Comment 9 Marek Polacek 2019-11-10 21:03:10 UTC
Not entirely true, this template case should be accepted:

#include <typeinfo>

struct B { virtual void f(); };
struct B2 : B { };

template<typename T>
constexpr bool
fn ()
{
  constexpr B2 b2;
  static_assert(&typeid(b2) == &typeid(B2));
  return true;
}

static_assert (fn<int>());