From de0684bf3f72c1e7a29704bce215ab40bcb84bb6 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Fri, 24 Jan 2020 18:08:58 -0500 Subject: [PATCH] c++: Poor diagnostic for dynamic_cast in constexpr context [PR93414] I neglected to add a proper diagnostic for the reference dynamic_cast case when the operand of a dynamic_cast doesn't refer to a public base of Derived, resulting in suboptimal error message error: call to non-'constexpr' function 'void* __cxa_bad_cast()' 2020-01-25 Marek Polacek PR c++/93414 - poor diagnostic for dynamic_cast in constexpr context. * constexpr.c (cxx_eval_dynamic_cast_fn): Add a reference dynamic_cast diagnostic. * g++.dg/cpp2a/constexpr-dynamic18.C: New test. --- gcc/cp/ChangeLog | 6 +++++ gcc/cp/constexpr.c | 15 ++++++++++++- gcc/testsuite/ChangeLog | 5 +++++ .../g++.dg/cpp2a/constexpr-dynamic18.C | 22 +++++++++++++++++++ 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic18.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ca5676631ad..0dc1ad21228 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2020-01-25 Marek Polacek + + PR c++/93414 - poor diagnostic for dynamic_cast in constexpr context. + * constexpr.c (cxx_eval_dynamic_cast_fn): Add a reference + dynamic_cast diagnostic. + 2020-01-24 Jason Merrill PR c++/93400 - ICE with constrained friend. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 8e8806345c1..577022e9b9a 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -1888,7 +1888,20 @@ cxx_eval_dynamic_cast_fn (const constexpr_ctx *ctx, tree call, if (tree t = (TREE_CODE (obj) == COMPONENT_REF ? TREE_OPERAND (obj, 1) : obj)) if (TREE_CODE (t) != FIELD_DECL || !DECL_FIELD_IS_BASE (t)) - return integer_zero_node; + { + if (reference_p) + { + if (!ctx->quiet) + { + error_at (loc, "reference % failed"); + inform (loc, "dynamic type %qT of its operand does " + "not have a base class of type %qT", + objtype, type); + } + *non_constant_p = true; + } + return integer_zero_node; + } /* [class.cdtor] When a dynamic_cast is used in a constructor ... or in a destructor ... if the operand of the dynamic_cast refers diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 67958396265..587603ffb46 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-01-25 Marek Polacek + + PR c++/93414 - poor diagnostic for dynamic_cast in constexpr context. + * g++.dg/cpp2a/constexpr-dynamic18.C: New test. + 2020-01-25 Feng Xue PR ipa/93166 diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic18.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic18.C new file mode 100644 index 00000000000..346f9f56470 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic18.C @@ -0,0 +1,22 @@ +// PR c++/93414 - poor diagnostic for dynamic_cast in constexpr context. +// { dg-do compile { target c++2a } } +// Here 'b' doesn't point/refer to a public base of Derived. + +struct Base { + constexpr virtual ~Base(){} +}; + +struct Derived: Base { + constexpr ~Derived(){} +}; + +constexpr const Derived& cast(const Base& b) { + return dynamic_cast(b); // { dg-error "reference .dynamic_cast. failed" } +// { dg-message "dynamic type .const Base. of its operand does not have a base class of type .Derived." "" { target *-*-* } .-1 } +} + +auto test() { + static constexpr Base b; + constexpr auto res = cast(b); + return res; +} -- 2.30.2