2016-06-20 23:38:11 +02:00
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* 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/.
*/
2019-03-07 14:31:17 +01:00
# ifndef LO_CLANG_SHARED_PLUGINS
2016-06-28 18:54:31 +02:00
# include "check.hxx"
2016-06-20 23:38:11 +02:00
# include "plugin.hxx"
/* OWeakObject::release() disposes weak references. If that isn't done
* because a sub - class improperly overrides release ( ) then
* OWeakConnectionPoint : : m_pObject continues to point to the deleted object
* and that could result in use - after - free .
*/
namespace {
class WeakObject
2019-03-05 16:15:22 +01:00
: public loplugin : : FilteringPlugin < WeakObject >
2016-06-20 23:38:11 +02:00
{
public :
2019-03-05 16:15:22 +01:00
explicit WeakObject ( loplugin : : InstantiationData const & rData ) : FilteringPlugin ( rData )
2017-11-07 11:50:47 +01:00
{ }
2016-06-20 23:38:11 +02:00
2019-03-07 14:31:17 +01:00
virtual bool preRun ( ) override {
return compiler . getLangOpts ( ) . CPlusPlus ; // no OWeakObject in C
}
2016-06-20 23:38:11 +02:00
void run ( ) override {
2019-03-07 14:31:17 +01:00
if ( preRun ( ) ) {
2016-06-20 23:38:11 +02:00
TraverseDecl ( compiler . getASTContext ( ) . getTranslationUnitDecl ( ) ) ;
}
}
bool isDerivedFromOWeakObject ( CXXMethodDecl const * const pMethodDecl )
{
QualType const pClass ( pMethodDecl - > getParent ( ) - > getTypeForDecl ( ) , 0 ) ;
if ( loplugin : : TypeCheck ( pClass ) . Class ( " OWeakObject " ) . Namespace ( " cppu " ) )
{
return true ;
}
// hopefully it's faster to recurse overridden methods than the
// thicket of WeakImplHelper32 but that is purely speculation
for ( auto it = pMethodDecl - > begin_overridden_methods ( ) ;
it ! = pMethodDecl - > end_overridden_methods ( ) ; + + it )
{
if ( isDerivedFromOWeakObject ( * it ) )
{
return true ;
}
}
return false ;
}
bool VisitCXXMethodDecl ( CXXMethodDecl const * const pMethodDecl )
{
if ( ignoreLocation ( pMethodDecl ) ) {
return true ;
}
2017-09-28 18:14:13 +02:00
if ( ! pMethodDecl - > isThisDeclarationADefinition ( )
| | pMethodDecl - > isLateTemplateParsed ( ) )
{
2016-06-20 23:38:11 +02:00
return true ;
}
if ( ! pMethodDecl - > isInstance ( ) ) {
return true ;
}
// this is too "simple", if a NamedDecl class has a getName() member expecting it to actually work would clearly be unreasonable if (pMethodDecl->getName() != "release") {
if ( auto const i = pMethodDecl - > getIdentifier ( ) ) {
if ( i ! = nullptr & & ! i - > isStr ( " release " ) ) {
return true ;
}
}
if ( pMethodDecl - > getNumParams ( ) ! = 0 ) {
return true ;
}
if ( loplugin : : TypeCheck ( QualType ( pMethodDecl - > getParent ( ) - > getTypeForDecl ( ) , 0 ) ) . Class ( " OWeakObject " ) . Namespace ( " cppu " ) )
{
return true ;
}
CXXMethodDecl const * pOverridden ( nullptr ) ;
for ( auto it = pMethodDecl - > begin_overridden_methods ( ) ;
it ! = pMethodDecl - > end_overridden_methods ( ) ; + + it )
{
if ( auto const i = ( * it ) - > getIdentifier ( ) ) {
if ( i ! = nullptr & & i - > isStr ( " release " ) ) {
pOverridden = * it ;
break ;
}
}
}
if ( pOverridden = = nullptr )
{
return true ;
}
if ( ! isDerivedFromOWeakObject ( pOverridden ) )
{
return true ;
}
CompoundStmt const * const pCompoundStatement (
dyn_cast < CompoundStmt > ( pMethodDecl - > getBody ( ) ) ) ;
2016-06-28 16:25:55 +02:00
for ( auto i = pCompoundStatement - > body_begin ( ) ;
i ! = pCompoundStatement - > body_end ( ) ; + + i )
2016-06-20 23:38:11 +02:00
{
// note: this is not a CXXMemberCallExpr
2016-06-28 16:25:55 +02:00
CallExpr const * const pCallExpr ( dyn_cast < CallExpr > ( * i ) ) ;
2016-06-20 23:38:11 +02:00
if ( pCallExpr )
{
// note: this is only sometimes a CXXMethodDecl
FunctionDecl const * const pCalled ( pCallExpr - > getDirectCallee ( ) ) ;
2016-06-24 17:27:18 +02:00
if ( pCalled - > getName ( ) = = " release " )
2016-06-20 23:38:11 +02:00
{
2016-06-24 17:27:18 +02:00
//this never works && pCalled == pOverridden
if ( pCalled - > getParent ( ) = = pOverridden - > getParent ( ) )
{
return true ;
}
// Allow this convenient shortcut:
auto td = dyn_cast < TypeDecl > ( pCalled - > getParent ( ) ) ;
if ( td ! = nullptr
2017-01-26 15:36:47 +02:00
& & ( loplugin : : TypeCheck ( td ) . Class ( " OWeakObject " ) . Namespace ( " cppu " ) . GlobalNamespace ( )
| | loplugin : : TypeCheck ( td ) . Class ( " OWeakAggObject " ) . Namespace ( " cppu " ) . GlobalNamespace ( ) ) )
2016-06-24 17:27:18 +02:00
{
return true ;
}
2016-06-20 23:38:11 +02:00
}
}
}
2020-07-06 03:39:12 +02:00
// allowlist
2017-01-26 15:36:47 +02:00
auto tc = loplugin : : TypeCheck ( pMethodDecl - > getParent ( ) ) ;
if ( tc . Class ( " OWeakAggObject " ) . Namespace ( " cppu " ) . GlobalNamespace ( ) // conditional call
| | tc . Class ( " WeakComponentImplHelperBase " ) . Namespace ( " cppu " ) . GlobalNamespace ( ) // extra magic
| | tc . Class ( " WeakAggComponentImplHelperBase " ) . Namespace ( " cppu " ) . GlobalNamespace ( ) // extra magic
| | tc . Class ( " CDOMImplementation " ) . Namespace ( " DOM " ) . GlobalNamespace ( ) // a static oddity
| | tc . Class ( " SwXTextFrame " ) . GlobalNamespace ( ) // ambiguous, 3 parents
| | tc . Class ( " SwXTextDocument " ) . GlobalNamespace ( ) // ambiguous, ~4 parents
| | tc . Class ( " SdStyleSheet " ) . GlobalNamespace ( ) // same extra magic as WeakComponentImplHelperBase
| | tc . Class ( " SdXImpressDocument " ) . GlobalNamespace ( ) // same extra magic as WeakComponentImplHelperBase
2016-06-20 23:38:11 +02:00
)
{
return true ;
}
report ( DiagnosticsEngine : : Warning ,
" override of OWeakObject::release() does not call superclass release() " ,
pMethodDecl - > getLocation ( ) )
< < pMethodDecl - > getSourceRange ( ) ;
return true ;
}
} ;
2019-03-07 14:31:17 +01:00
loplugin : : Plugin : : Registration < WeakObject > weakobject ( " weakobject " ) ;
2016-06-20 23:38:11 +02:00
} // namespace
2019-03-07 14:31:17 +01:00
# endif // LO_CLANG_SHARED_PLUGINS
2016-06-20 23:38:11 +02:00
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */