diff --git a/compilerplugins/clang/test/typeidcomparison.cxx b/compilerplugins/clang/test/typeidcomparison.cxx new file mode 100644 index 000000000000..31ab749a2496 --- /dev/null +++ b/compilerplugins/clang/test/typeidcomparison.cxx @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +struct Base +{ + virtual ~Base(); +}; + +struct Derived : Base +{ +}; + +void good(Base* p) +{ + (void)(typeid(*p) == typeid(Derived)); + (void)(typeid(Derived) == typeid(*p)); + (void)(typeid(*p) != typeid(Derived)); + (void)(typeid(Derived) != typeid(*p)); +} + +void bad(Base* p) +{ + // expected-error@+1 {{comparison of type info of mixed pointer and non-pointer types 'Base *' and 'Derived' can never succeed [loplugin:typeidcomparison]}} + (void)(typeid(p) == typeid(Derived)); + // expected-error@+1 {{comparison of type info of mixed pointer and non-pointer types 'Derived' and 'Base *' can never succeed [loplugin:typeidcomparison]}} + (void)(typeid(Derived) == typeid(p)); + // expected-error@+1 {{comparison of type info of mixed pointer and non-pointer types 'Base *' and 'Derived' can never succeed [loplugin:typeidcomparison]}} + (void)(typeid(p) != typeid(Derived)); + // expected-error@+1 {{comparison of type info of mixed pointer and non-pointer types 'Derived' and 'Base *' can never succeed [loplugin:typeidcomparison]}} + (void)(typeid(Derived) != typeid(p)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/compilerplugins/clang/typeidcomparison.cxx b/compilerplugins/clang/typeidcomparison.cxx new file mode 100644 index 000000000000..359231f262e6 --- /dev/null +++ b/compilerplugins/clang/typeidcomparison.cxx @@ -0,0 +1,90 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// Find (in-)equality comparisons between typeid expressions that can never succeed. For now, just +// detects cases where the two involved types are structurally different, one a pointer type and the +// other a non-pointer type. + +#ifndef LO_CLANG_SHARED_PLUGINS + +#include "plugin.hxx" + +namespace +{ +class TypeidComparison final : public loplugin::FilteringPlugin +{ +public: + explicit TypeidComparison(loplugin::InstantiationData const& data) + : FilteringPlugin(data) + { + } + + // For CXXRewrittenBinaryOperator `typeid(...) != typeid(...)`: + bool shouldVisitImplicitCode() const { return true; } + + bool preRun() override { return compiler.getLangOpts().CPlusPlus; } + + void run() override + { + if (preRun()) + { + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); + } + } + + bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr const* expr) + { + if (ignoreLocation(expr)) + { + return true; + } + auto const op = expr->getOperator(); + if (op != OO_EqualEqual && op != OO_ExclaimEqual) + { + return true; + } + assert(expr->getNumArgs() == 2); + auto const e1 = dyn_cast(expr->getArg(0)->IgnoreParenImpCasts()); + if (e1 == nullptr) + { + return true; + } + auto const e2 = dyn_cast(expr->getArg(1)->IgnoreParenImpCasts()); + if (e2 == nullptr) + { + return true; + } + auto const t1 = getOperandType(e1); + auto const t2 = getOperandType(e2); + if (t1->isPointerType() == t2->isPointerType()) + { + return true; + } + report(DiagnosticsEngine::Warning, + "comparison of type info of mixed pointer and non-pointer types %0 and %1 can never " + "succeed", + expr->getExprLoc()) + << t1 << t2 << expr->getSourceRange(); + return true; + } + +private: + QualType getOperandType(CXXTypeidExpr const* expr) + { + return expr->isTypeOperand() ? expr->getTypeOperand(compiler.getASTContext()) + : expr->getExprOperand()->getType(); + } +}; + +static loplugin::Plugin::Registration typeidcomparison("typeidcomparison"); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/solenv/CompilerTest_compilerplugins_clang.mk b/solenv/CompilerTest_compilerplugins_clang.mk index 93ebf8468228..66b0579dd69b 100644 --- a/solenv/CompilerTest_compilerplugins_clang.mk +++ b/solenv/CompilerTest_compilerplugins_clang.mk @@ -95,6 +95,7 @@ $(eval $(call gb_CompilerTest_add_exception_objects,compilerplugins_clang, \ compilerplugins/clang/test/stringview \ compilerplugins/clang/test/stringviewparam \ compilerplugins/clang/test/typedefparam \ + compilerplugins/clang/test/typeidcomparison \ compilerplugins/clang/test/unnecessarycatchthrow \ compilerplugins/clang/test/unnecessaryoverride \ compilerplugins/clang/test/unnecessaryoverride-dtor \ diff --git a/sw/inc/istype.hxx b/sw/inc/istype.hxx new file mode 100644 index 000000000000..ec7dac428d61 --- /dev/null +++ b/sw/inc/istype.hxx @@ -0,0 +1,21 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include + +template bool isType(T2* p) +{ + return p != nullptr && typeid(*p) == typeid(T1); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sw/source/core/access/accmap.cxx b/sw/source/core/access/accmap.cxx index 7704b16f3e52..e8a106aa5892 100644 --- a/sw/source/core/access/accmap.cxx +++ b/sw/source/core/access/accmap.cxx @@ -42,6 +42,7 @@ #include "acccell.hxx" #include "acctable.hxx" #include +#include #include #include #include @@ -198,7 +199,7 @@ void SwDrawModellListener_Impl::Notify( SfxBroadcaster& /*rBC*/, if (pSdrHint->GetObject() && ( dynamic_cast< const SwFlyDrawObj* >(pSdrHint->GetObject()) != nullptr || dynamic_cast< const SwVirtFlyDrawObj* >(pSdrHint->GetObject()) != nullptr || - typeid(SdrObject) == typeid(pSdrHint->GetObject()) ) ) + isType(pSdrHint->GetObject()) ) ) { return; } diff --git a/sw/source/core/doc/doclay.cxx b/sw/source/core/doc/doclay.cxx index 7d3ad61e46b4..34bf4fabbcac 100644 --- a/sw/source/core/doc/doclay.cxx +++ b/sw/source/core/doc/doclay.cxx @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -139,7 +140,7 @@ SdrObject* SwDoc::CloneSdrObj( const SdrObject& rObj, bool bMoveWithinDoc, SdrLayerID nLayerIdForClone = rObj.GetLayer(); if ( dynamic_cast( pObj) == nullptr && dynamic_cast( pObj) == nullptr && - typeid(SdrObject) != typeid(pObj) ) + !isType(pObj) ) { if ( getIDocumentDrawModelAccess().IsVisibleLayerId( nLayerIdForClone ) ) { diff --git a/sw/source/uibase/app/docsh2.cxx b/sw/source/uibase/app/docsh2.cxx index 9e606f0b4095..208848bf9a05 100644 --- a/sw/source/uibase/app/docsh2.cxx +++ b/sw/source/uibase/app/docsh2.cxx @@ -66,6 +66,7 @@ #include #include #include +#include #include #include #include @@ -467,13 +468,13 @@ void SwDocShell::Execute(SfxRequest& rReq) SfxViewFrame *pTmpFrame = SfxViewFrame::GetFirst(this); SfxViewShell* pViewShell = SfxViewShell::Current(); SwView* pCurrView = dynamic_cast< SwView *> ( pViewShell ); - bool bCurrent = typeid(SwPagePreview) == typeid( pViewShell ); + bool bCurrent = isType( pViewShell ); while( pTmpFrame ) // search Preview { - if( typeid(SwView) == typeid( pTmpFrame->GetViewShell()) ) + if( isType( pTmpFrame->GetViewShell()) ) bOnly = false; - else if( typeid(SwPagePreview) == typeid( pTmpFrame->GetViewShell())) + else if( isType( pTmpFrame->GetViewShell())) { pTmpFrame->GetFrame().Appear(); bFound = true;