From ebf267b87d4b557dff488f87f66df3628e3da957 Mon Sep 17 00:00:00 2001 From: Zequan Wu Date: Tue, 15 Sep 2020 13:44:22 -0700 Subject: [PATCH] [Sema][MSVC] warn at dynamic_cast/typeid when /GR- is given Differential Revision: https://reviews.llvm.org/D86369 --- clang/include/clang/Basic/DiagnosticGroups.td | 2 ++ .../clang/Basic/DiagnosticSemaKinds.td | 6 ++++ clang/lib/Sema/SemaCast.cpp | 12 +++++++ clang/lib/Sema/SemaExprCXX.cpp | 11 ++++++- clang/test/SemaCXX/ms-no-rtti-data.cpp | 32 +++++++++++++++++++ clang/test/SemaCXX/no-rtti-data.cpp | 32 +++++++++++++++++++ 6 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 clang/test/SemaCXX/ms-no-rtti-data.cpp create mode 100644 clang/test/SemaCXX/no-rtti-data.cpp diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 6b4dcc850612..a9bd52b8afcd 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1235,3 +1235,5 @@ in addition with the pragmas or -fmax-tokens flag to get any warnings. } def WebAssemblyExceptionSpec : DiagGroup<"wasm-exception-spec">; + +def RTTI : DiagGroup<"rtti">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index e0d700c66724..f6ded1b4ee26 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7451,6 +7451,12 @@ def err_no_typeid_with_fno_rtti : Error< "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_rtti_disabled: Warning< + "dynamic_cast will not work since RTTI data is disabled by " + "%select{-fno-rtti-data|/GR-}0">, InGroup; +def warn_no_typeid_with_rtti_disabled: Warning< + "typeid will not work since RTTI data is disabled by " + "%select{-fno-rtti-data|/GR-}0">, InGroup; 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 index f718154ce6db..d59f1880a7ff 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -889,6 +889,18 @@ void CastOperation::CheckDynamicCast() { return; } + // Warns when dynamic_cast is used with RTTI data disabled. + if (!Self.getLangOpts().RTTIData) { + bool MicrosoftABI = + Self.getASTContext().getTargetInfo().getCXXABI().isMicrosoft(); + bool isClangCL = Self.getDiagnostics().getDiagnosticOptions().getFormat() == + DiagnosticOptions::MSVC; + if (MicrosoftABI || !DestPointee->isVoidType()) + Self.Diag(OpRange.getBegin(), + diag::warn_no_dynamic_cast_with_rtti_disabled) + << isClangCL; + } + // Done. Everything else is run-time checks. Kind = CK_Dynamic; } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index b5d4276f22b4..08b56413d8bf 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -663,7 +663,16 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, } // The operand is an expression. - return BuildCXXTypeId(TypeInfoType, OpLoc, (Expr*)TyOrExpr, RParenLoc); + ExprResult Result = + BuildCXXTypeId(TypeInfoType, OpLoc, (Expr *)TyOrExpr, RParenLoc); + + if (!getLangOpts().RTTIData && !Result.isInvalid()) + if (auto *CTE = dyn_cast(Result.get())) + if (CTE->isPotentiallyEvaluated() && !CTE->isMostDerived(Context)) + Diag(OpLoc, diag::warn_no_typeid_with_rtti_disabled) + << (getDiagnostics().getDiagnosticOptions().getFormat() == + DiagnosticOptions::MSVC); + return Result; } /// Grabs __declspec(uuid()) off a type, or returns 0 if we cannot resolve to diff --git a/clang/test/SemaCXX/ms-no-rtti-data.cpp b/clang/test/SemaCXX/ms-no-rtti-data.cpp new file mode 100644 index 000000000000..aef167d8a373 --- /dev/null +++ b/clang/test/SemaCXX/ms-no-rtti-data.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 %s -triple x86_64-windows-msvc -fdiagnostics-format msvc -fno-rtti-data -fsyntax-only -verify + +namespace std { +struct type_info {}; +} // namespace std +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{{dynamic_cast will not work since RTTI data is disabled by /GR-}} + void *v = dynamic_cast(b); // expected-warning{{dynamic_cast will not work since RTTI data is disabled by /GR-}} + + (void)typeid(int); + (void)typeid(b); + (void)typeid(*b); // expected-warning{{typeid will not work since RTTI data is disabled by /GR-}} + B b2 = *b; + (void)typeid(b2); + (void)typeid(*&b2); // expected-warning{{typeid will not work since RTTI data is disabled by /GR-}} + (void)typeid((B &)b2); + + B &br = b2; + (void)typeid(br); // expected-warning{{typeid will not work since RTTI data is disabled by /GR-}} + (void)typeid(&br); +} \ No newline at end of file diff --git a/clang/test/SemaCXX/no-rtti-data.cpp b/clang/test/SemaCXX/no-rtti-data.cpp new file mode 100644 index 000000000000..af0dc7c11bb8 --- /dev/null +++ b/clang/test/SemaCXX/no-rtti-data.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 %s -triple x86_64-unknown-linux -fno-rtti-data -fsyntax-only -verify + +namespace std { +struct type_info {}; +} // namespace std +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{{dynamic_cast will not work since RTTI data is disabled by -fno-rtti-data}} + void *v = dynamic_cast(b); + + (void)typeid(int); + (void)typeid(b); + (void)typeid(*b); // expected-warning{{typeid will not work since RTTI data is disabled by -fno-rtti-data}} + B b2 = *b; + (void)typeid(b2); + (void)typeid(*&b2); // expected-warning{{typeid will not work since RTTI data is disabled by -fno-rtti-data}} + (void)typeid((B &)b2); + + B &br = b2; + (void)typeid(br); // expected-warning{{typeid will not work since RTTI data is disabled by -fno-rtti-data}} + (void)typeid(&br); +} \ No newline at end of file