diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 1243380ca8a6b..dfd99f836d0f8 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -773,6 +773,11 @@ bool Compiler::VisitCastExpr(const CastExpr *CE) { case CK_ToVoid: return discard(SubExpr); + case CK_Dynamic: + // This initially goes through VisitCXXDynamicCastExpr, where we emit + // a diagnostic if appropriate. + return this->delegate(SubExpr); + default: return this->emitInvalid(CE); } diff --git a/clang/test/AST/ByteCode/cxx20.cpp b/clang/test/AST/ByteCode/cxx20.cpp index cb788fa3e2c07..ea4843e95b01f 100644 --- a/clang/test/AST/ByteCode/cxx20.cpp +++ b/clang/test/AST/ByteCode/cxx20.cpp @@ -1201,3 +1201,13 @@ namespace NonPureVirtualCall { int main() { check(); } } + +namespace DyamicCast { + struct X { + virtual constexpr ~X() {} + }; + struct Y : X {}; + constexpr Y y; + constexpr const X *p = &y; + constexpr const Y *q = dynamic_cast(p); +} diff --git a/clang/test/SemaCXX/constant-expression-p2280r4.cpp b/clang/test/SemaCXX/constant-expression-p2280r4.cpp index 5cbfaffd04aa0..21283c04a1db2 100644 --- a/clang/test/SemaCXX/constant-expression-p2280r4.cpp +++ b/clang/test/SemaCXX/constant-expression-p2280r4.cpp @@ -278,11 +278,13 @@ namespace dropped_note { namespace dynamic { struct A {virtual ~A();}; struct B : A {}; - void f(A& a) { + void f(A& a) { // interpreter-note 2{{declared here}} constexpr B* b = dynamic_cast(&a); // expected-error {{must be initialized by a constant expression}} \ - // nointerpreter-note {{dynamic_cast applied to object 'a' whose dynamic type is not constant}} + // nointerpreter-note {{dynamic_cast applied to object 'a' whose dynamic type is not constant}} \ + // interpreter-note {{pointer to 'a' is not a constant expression}} constexpr void* b2 = dynamic_cast(&a); // expected-error {{must be initialized by a constant expression}} \ - // nointerpreter-note {{dynamic_cast applied to object 'a' whose dynamic type is not constant}} + // nointerpreter-note {{dynamic_cast applied to object 'a' whose dynamic type is not constant}} \ + // interpreter-note {{pointer to 'a' is not a constant expression}} } } @@ -415,9 +417,7 @@ namespace InvalidConstexprFn { }; constexpr int virtual_call(const PolyBase& b) { return b.get(); } constexpr auto* type(const PolyBase& b) { return &typeid(b); } - // FIXME: Intepreter doesn't support constexpr dynamic_cast yet. - constexpr const void* dyncast(const PolyBase& b) { return dynamic_cast(&b); } // interpreter-error {{constexpr function never produces a constant expression}} \ - // interpreter-note 2 {{subexpression not valid in a constant expression}} + constexpr const void* dyncast(const PolyBase& b) { return dynamic_cast(&b); } constexpr int sub(const int (&a)[], const int (&b)[]) { return a-b; } constexpr const int* add(const int &a) { return &a+3; } @@ -427,7 +427,7 @@ namespace InvalidConstexprFn { static_assert(get_derived_member(Derived{}) == 0); static_assert(virtual_call(PolyDerived{}) == 1); static_assert(type(PolyDerived{}) != nullptr); - static_assert(dyncast(PolyDerived{}) != nullptr); // interpreter-error {{static assertion expression is not an integral constant expression}} interpreter-note {{in call}} + static_assert(dyncast(PolyDerived{}) != nullptr); static_assert(sub(arr, arr) == 0); static_assert(add(arr[0]) == &arr[3]); }