Commit 66acfb80 by Marek Polacek Committed by Marek Polacek

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.

From-SVN: r278635
parent bdaf8be1
2019-11-22 Marek Polacek <polacek@redhat.com>
PR c++/88337 - P1327R1: Allow polymorphic typeid in constexpr.
* 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.
2019-11-22 Jakub Jelinek <jakub@redhat.com> 2019-11-22 Jakub Jelinek <jakub@redhat.com>
PR c/90677 PR c/90677
......
...@@ -7021,11 +7021,14 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, ...@@ -7021,11 +7021,14 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
return false; return false;
case TYPEID_EXPR: case TYPEID_EXPR:
/* -- a typeid expression whose operand is of polymorphic /* In C++20, a typeid expression whose operand is of polymorphic
class type; */ class type can be constexpr. */
{ {
tree e = TREE_OPERAND (t, 0); tree e = TREE_OPERAND (t, 0);
if (!TYPE_P (e) && !type_dependent_expression_p (e) if (cxx_dialect < cxx2a
&& strict
&& !TYPE_P (e)
&& !type_dependent_expression_p (e)
&& TYPE_POLYMORPHIC_P (TREE_TYPE (e))) && TYPE_POLYMORPHIC_P (TREE_TYPE (e)))
{ {
if (flags & tf_error) if (flags & tf_error)
......
...@@ -353,8 +353,6 @@ build_typeid (tree exp, tsubst_flags_t complain) ...@@ -353,8 +353,6 @@ build_typeid (tree exp, tsubst_flags_t complain)
if (processing_template_decl) if (processing_template_decl)
return build_min (TYPEID_EXPR, const_type_info_type_node, exp); return build_min (TYPEID_EXPR, const_type_info_type_node, exp);
/* FIXME when integrating with c_fully_fold, mark
resolves_to_fixed_type_p case as a non-constant expression. */
if (TYPE_POLYMORPHIC_P (TREE_TYPE (exp)) if (TYPE_POLYMORPHIC_P (TREE_TYPE (exp))
&& ! resolves_to_fixed_type_p (exp, &nonnull) && ! resolves_to_fixed_type_p (exp, &nonnull)
&& ! nonnull) && ! nonnull)
......
2019-11-22 Marek Polacek <polacek@redhat.com>
PR c++/88337 - P1327R1: Allow polymorphic typeid in constexpr.
* 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.
2019-11-22 Jakub Jelinek <jakub@redhat.com> 2019-11-22 Jakub Jelinek <jakub@redhat.com>
PR c/90677 PR c/90677
......
// PR c++/88337 - Implement P1327R1: Allow dynamic_cast/typeid in constexpr.
// { dg-do compile { target c++2a } }
// Test non-polymorphic type.
#include <typeinfo>
struct B {
const std::type_info &ti = typeid (*this);
};
struct D : B { };
constexpr B b;
constexpr D d;
static_assert (&b.ti == &typeid (B));
static_assert (&B{}.ti == &typeid (B));
static_assert (&B().ti == &typeid (B));
static_assert (&typeid ((B())) == &typeid (B));
static_assert (&typeid ((B{})) == &typeid (B));
static_assert (&d.ti == &typeid (B));
static_assert (&D{}.ti == &typeid (B));
static_assert (&D().ti == &typeid (B));
static_assert (&typeid ((D())) == &typeid (D));
static_assert (&typeid ((D{})) == &typeid (D));
extern D ed;
static_assert (&typeid (ed) == &typeid (D));
constexpr const B &r = d;
static_assert (&typeid (r) == &typeid (B));
constexpr bool
test ()
{
// If expression is not a glvalue expression of polymorphic type,
// typeid does not evaluate the expression
bool ok = true;
(void) typeid (ok = false, D());
(void) typeid (ok = false, B());
(void) typeid (ok = false, b);
(void) typeid (ok = false, d);
return ok;
}
static_assert (test ());
// PR c++/88337 - Implement P1327R1: Allow dynamic_cast/typeid in constexpr.
// { dg-do compile { target c++2a } }
// Test polymorphic type.
#include <typeinfo>
struct B {
virtual void foo ();
const std::type_info &ti_base = typeid (*this);
};
struct D : B {
const std::type_info &ti = typeid (*this);
};
constexpr B b;
constexpr D d;
static_assert (&b.ti_base == &typeid (B));
static_assert (&B{}.ti_base == &typeid (B));
static_assert (&B().ti_base == &typeid (B));
static_assert (&typeid ((B())) == &typeid (B));
static_assert (&typeid ((B{})) == &typeid (B));
static_assert (&d.ti == &typeid (D));
static_assert (&D{}.ti == &typeid (D));
static_assert (&D().ti == &typeid (D));
static_assert (&typeid ((D())) == &typeid (D));
static_assert (&typeid ((D{})) == &typeid (D));
extern D ed;
// ??? Should this succeed?
static_assert (&typeid (ed) == &typeid (D));
constexpr const B &r = d;
static_assert (&typeid (r) == &typeid (D));
constexpr bool
test ()
{
// If expression is a glvalue expression that identifies an object
// of a polymorphic type, the typeid expression evaluates the expression.
bool ok = true;
// Not a glvalue.
(void) typeid (ok = false, D());
(void) typeid (ok = false, B());
if (!ok)
return false;
// Polymorphic glvalue -- this needs to be evaluated.
ok = false;
(void) typeid (ok = true, b);
if (!ok)
return false;
ok = false;
(void) typeid (ok = true, d);
return ok;
}
static_assert (test ());
// PR c++/88337 - Implement P1327R1: Allow dynamic_cast/typeid in constexpr.
// { dg-do compile { target c++2a } }
// Test typeid in a template.
#include <typeinfo>
struct B { virtual void fn (); };
struct D : B { };
void abort ();
template<typename>
constexpr void
fn ()
{
D d;
if (&typeid (d) != &typeid (D))
abort ();
}
constexpr bool b1 = (fn<int>(), true);
// Type-dependent.
template<typename T>
constexpr void
fn2 ()
{
T t{};
if (&typeid (t) != &typeid (T))
abort ();
}
constexpr bool b2 = (fn2<int>(), true);
constexpr bool b3 = (fn2<B>(), true);
constexpr bool b4 = (fn2<D>(), true);
// PR c++/88337 - Implement P1327R1: Allow dynamic_cast/typeid in constexpr.
// { dg-do compile { target c++17 } }
// Test typeid in a template.
#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)); // { dg-error ".typeid. is not a constant expression because .b2. is of polymorphic type|non-constant condition" "" { target c++17_down } }
return true;
}
static_assert (fn<int>());
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment