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()' Tested x86_64-linux, ok for trunk? 2020-01-24 Marek Polacek <pola...@redhat.com> 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/constexpr.c | 15 ++++++++++++- .../g++.dg/cpp2a/constexpr-dynamic18.C | 22 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic18.C 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 %<dynamic_cast%> 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/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<const Derived&>(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; +} base-commit: 55dd44535d2e4e5703c0103c26e7c51ab8c502c4 -- Marek Polacek • Red Hat, Inc. • 300 A St, Boston, MA