Bug 88337

Summary: Implement P1002R1, P1327R1, P1330R0, C++20 relaxations of constexpr restrictions.
Product: gcc Reporter: Ed Smith-Rowland <emsr>
Component: c++Assignee: Marek Polacek <mpolacek>
Status: RESOLVED FIXED    
Severity: enhancement CC: antoshkka, egallager, emsr, jakub, mpolacek, webrown.cpp
Priority: P3 Keywords: patch
Version: 9.0   
Target Milestone: ---   
URL: https://gcc.gnu.org/ml/gcc-patches/2019-11/msg00650.html
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2019-08-05 00:00:00
Bug Depends on:    
Bug Blocks: 55004, 88323    

Description Ed Smith-Rowland 2018-12-03 19:22:52 UTC

    
Comment 1 Ed Smith-Rowland 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 Ed Smith-Rowland 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>());
Comment 10 Marek Polacek 2019-11-22 23:48:57 UTC
Author: mpolacek
Date: Fri Nov 22 23:48:25 2019
New Revision: 278635

URL: https://gcc.gnu.org/viewcvs?rev=278635&root=gcc&view=rev
Log:
	PR c++/88337 - P1327R1: Allow polymorphic typeid in constexpr.

Part of P1327R1 is to allow typeid with an operand of polymorphic type in
constexpr.  I found that we pretty much support it already, the only tweak
was to allow TYPEID_EXPR (only created in a template) in constexpr in C++20.

	* constexpr.c (potential_constant_expression_1): Allow a typeid
	expression whose operand is of polymorphic type in constexpr in
	C++20.
	* rtti.c (build_typeid): Remove obsolete FIXME comment.

	* g++.dg/cpp2a/constexpr-typeid1.C: New test.
	* g++.dg/cpp2a/constexpr-typeid2.C: New test.
	* g++.dg/cpp2a/constexpr-typeid3.C: New test.
	* g++.dg/cpp2a/constexpr-typeid4.C: New test.

Added:
    trunk/gcc/testsuite/g++.dg/cpp2a/constexpr-typeid1.C
    trunk/gcc/testsuite/g++.dg/cpp2a/constexpr-typeid2.C
    trunk/gcc/testsuite/g++.dg/cpp2a/constexpr-typeid3.C
    trunk/gcc/testsuite/g++.dg/cpp2a/constexpr-typeid4.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/constexpr.c
    trunk/gcc/cp/rtti.c
    trunk/gcc/testsuite/ChangeLog
Comment 11 Marek Polacek 2019-12-29 16:45:31 UTC
Author: mpolacek
Date: Sun Dec 29 16:44:41 2019
New Revision: 279755

URL: https://gcc.gnu.org/viewcvs?rev=279755&root=gcc&view=rev
Log:
	PR c++/88337 - Implement P1327R1: Allow dynamic_cast in constexpr.

This patch implements
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1327r1.html>.

When build_dynamic_cast realizes that a dynamic_cast needs a run-time check, it
generates a call to __dynamic_cast -- see dyncast.cc in libsupc++ for its
definition.  The gist of my approach is to evaluate such a call at compile time.

	* constexpr.c (cxx_dynamic_cast_fn_p): New function.
	(extract_obj_from_addr_offset): New function.
	(get_component_with_type): New function.
	(cxx_eval_dynamic_cast_fn): New function.
	(cxx_eval_call_expression): Call cxx_eval_dynamic_cast_fn for a call
	to __dynamic_cast.
	(potential_constant_expression_1): Don't give up on
	cxx_dynamic_cast_fn_p.
	* rtti.c (build_dynamic_cast_1): When creating a call to
	__dynamic_cast, use the location of the original expression.

	* g++.dg/cpp2a/constexpr-dynamic1.C: New test.
	* g++.dg/cpp2a/constexpr-dynamic10.C: New test.
	* g++.dg/cpp2a/constexpr-dynamic11.C: New test.
	* g++.dg/cpp2a/constexpr-dynamic12.C: New test.
	* g++.dg/cpp2a/constexpr-dynamic13.C: New test.
	* g++.dg/cpp2a/constexpr-dynamic14.C: New test.
	* g++.dg/cpp2a/constexpr-dynamic15.C: New test.
	* g++.dg/cpp2a/constexpr-dynamic16.C: New test.
	* g++.dg/cpp2a/constexpr-dynamic17.C: New test.
	* g++.dg/cpp2a/constexpr-dynamic2.C: New test.
	* g++.dg/cpp2a/constexpr-dynamic3.C: New test.
	* g++.dg/cpp2a/constexpr-dynamic4.C: New test.
	* g++.dg/cpp2a/constexpr-dynamic5.C: New test.
	* g++.dg/cpp2a/constexpr-dynamic6.C: New test.
	* g++.dg/cpp2a/constexpr-dynamic7.C: New test.
	* g++.dg/cpp2a/constexpr-dynamic8.C: New test.
	* g++.dg/cpp2a/constexpr-dynamic9.C: New test.

Added:
    trunk/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic1.C
    trunk/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic10.C
    trunk/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic11.C
    trunk/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic12.C
    trunk/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic13.C
    trunk/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic14.C
    trunk/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic15.C
    trunk/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic16.C
    trunk/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic17.C
    trunk/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic2.C
    trunk/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic3.C
    trunk/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic4.C
    trunk/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic5.C
    trunk/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic6.C
    trunk/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic7.C
    trunk/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic8.C
    trunk/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic9.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/constexpr.c
    trunk/gcc/cp/rtti.c
    trunk/gcc/testsuite/ChangeLog
Comment 12 Marek Polacek 2019-12-29 16:47:47 UTC
Implemented in GCC 10.