diff options
author | Marek Polacek <polacek@redhat.com> | 2019-11-22 23:48:25 +0000 |
---|---|---|
committer | Marek Polacek <mpolacek@gcc.gnu.org> | 2019-11-22 23:48:25 +0000 |
commit | 66acfb8004d65ae8c75c627b511984f7f054a2ca (patch) | |
tree | fbb1081d2d91c1f058d8bd2e05325b0119def46d /gcc | |
parent | bdaf8be1b2e3514b8bbcdd1042136e7d91b3c3f3 (diff) | |
download | gcc-66acfb8004d65ae8c75c627b511984f7f054a2ca.zip gcc-66acfb8004d65ae8c75c627b511984f7f054a2ca.tar.gz gcc-66acfb8004d65ae8c75c627b511984f7f054a2ca.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 9 | ||||
-rw-r--r-- | gcc/cp/rtti.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/constexpr-typeid1.C | 47 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/constexpr-typeid2.C | 60 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/constexpr-typeid3.C | 33 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/constexpr-typeid4.C | 19 |
8 files changed, 181 insertions, 5 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 762da08..444b339 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +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> PR c/90677 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 9ce768b..658455c 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -7021,11 +7021,14 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, return false; case TYPEID_EXPR: - /* -- a typeid expression whose operand is of polymorphic - class type; */ + /* In C++20, a typeid expression whose operand is of polymorphic + class type can be constexpr. */ { 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))) { if (flags & tf_error) diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index d987f8b..da68596 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -353,8 +353,6 @@ build_typeid (tree exp, tsubst_flags_t complain) if (processing_template_decl) 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)) && ! resolves_to_fixed_type_p (exp, &nonnull) && ! nonnull) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 201d044..1109cd6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +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> PR c/90677 diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-typeid1.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-typeid1.C new file mode 100644 index 0000000..a81f649 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-typeid1.C @@ -0,0 +1,47 @@ +// 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 ()); diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-typeid2.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-typeid2.C new file mode 100644 index 0000000..51c8fb4 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-typeid2.C @@ -0,0 +1,60 @@ +// 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 ()); diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-typeid3.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-typeid3.C new file mode 100644 index 0000000..38b9e60 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-typeid3.C @@ -0,0 +1,33 @@ +// 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); diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-typeid4.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-typeid4.C new file mode 100644 index 0000000..0a99aae --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-typeid4.C @@ -0,0 +1,19 @@ +// 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>()); |