diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7433,6 +7433,8 @@ "use of typeid requires -frtti">; def err_no_dynamic_cast_with_fno_rtti : Error< "use of dynamic_cast requires -frtti">; +def warn_no_dynamic_cast_with_no_GR: Warning< + "should not use dynamic_cast with /GR-">; def err_cannot_form_pointer_to_member_of_reference_type : Error< "cannot form a pointer-to-member to member %0 of reference type %1">; diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -890,6 +890,11 @@ return; } + // MSVC warns when dynamic_cast is used with /GR-. + if (!Self.getLangOpts().RTTIData) { + Self.Diag(OpRange.getBegin(), diag::warn_no_dynamic_cast_with_no_GR); + } + // Done. Everything else is run-time checks. Kind = CK_Dynamic; } diff --git a/clang/test/SemaCXX/ms_dynamic_cast.cpp b/clang/test/SemaCXX/ms_dynamic_cast.cpp new file mode 100644 --- /dev/null +++ b/clang/test/SemaCXX/ms_dynamic_cast.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 %s -fno-rtti-data -fsyntax-only -verify + +class B { +public: + virtual ~B() = default; +}; + +class D1 : public B { +public: + ~D1() = default; + +}; + +void f() { + B *b = new D1(); + auto d = dynamic_cast(b); // expected-warning{{should not use dynamic_cast with /GR-}} +} \ No newline at end of file