+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
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)
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)
+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
--- /dev/null
+// 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 ());
--- /dev/null
+// 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 ());
--- /dev/null
+// 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);
--- /dev/null
+// 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>());