compiler check to compare SAL_WARN/LOG areas against sal/inc/sal/log-areas.dox
Some of the areas are guesses I've added after seeing them, whoever feels reponsible for whichever part of the code feel free to adjust them. Change-Id: I2192de84d51cc2bc7c28fa84019d38b465985d15
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
# The list of source files.
|
||||
CLANGSRC=compileplugin.cxx \
|
||||
bodynotinblock.cxx \
|
||||
sallogareas.cxx \
|
||||
unusedvariablecheck.cxx \
|
||||
|
||||
|
||||
@@ -52,7 +53,7 @@ CLANGOBJS=
|
||||
define clangbuildsrc
|
||||
$(3): $(2) $(SRCDIR)/compilerplugins/Makefile-clang.mk $(CLANGOUTDIR)/clang-timestamp
|
||||
@echo [build CXX] $(subst $(SRCDIR)/,,$(2))
|
||||
$(CXX) $(CLANGCXXFLAGS) $(CLANGDEFS) $(CLANGINCLUDES) $(2) -fPIC -c -o $(3) -MMD -MT $(3) -MP -MF $(CLANGOUTDIR)/$(1).d
|
||||
$(CXX) $(CLANGCXXFLAGS) $(CLANGDEFS) $(CLANGINCLUDES) -DSRCDIR=$(SRCDIR) $(2) -fPIC -c -o $(3) -MMD -MT $(3) -MP -MF $(CLANGOUTDIR)/$(1).d
|
||||
|
||||
-include $(CLANGOUTDIR)/$(1).d
|
||||
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#include <clang/Rewrite/Rewriter.h>
|
||||
|
||||
#include "bodynotinblock.hxx"
|
||||
#include "sallogareas.hxx"
|
||||
#include "unusedvariablecheck.hxx"
|
||||
|
||||
using namespace clang;
|
||||
@@ -40,7 +41,10 @@ DiagnosticBuilder Plugin::report( DiagnosticsEngine::Level level, StringRef mess
|
||||
if( level == DiagnosticsEngine::Error && diag.getErrorsAsFatal())
|
||||
level = DiagnosticsEngine::Fatal;
|
||||
#endif
|
||||
return diag.Report( loc, diag.getCustomDiagID( level, message ));
|
||||
if( loc.isValid())
|
||||
return diag.Report( loc, diag.getCustomDiagID( level, message ));
|
||||
else
|
||||
return diag.Report( diag.getCustomDiagID( level, message ));
|
||||
}
|
||||
|
||||
bool Plugin::ignoreLocation( SourceLocation loc )
|
||||
@@ -58,6 +62,7 @@ class PluginHandler
|
||||
explicit PluginHandler( ASTContext& context )
|
||||
: rewriter( context.getSourceManager(), context.getLangOpts())
|
||||
, bodyNotInBlock( context )
|
||||
, salLogAreas( context )
|
||||
, unusedVariableCheck( context )
|
||||
{
|
||||
}
|
||||
@@ -66,6 +71,7 @@ class PluginHandler
|
||||
if( context.getDiagnostics().hasErrorOccurred())
|
||||
return;
|
||||
bodyNotInBlock.run();
|
||||
salLogAreas.run();
|
||||
unusedVariableCheck.run();
|
||||
// TODO also LO header files? or a subdir?
|
||||
if( const RewriteBuffer* buf = rewriter.getRewriteBufferFor( context.getSourceManager().getMainFileID()))
|
||||
@@ -75,6 +81,7 @@ class PluginHandler
|
||||
private:
|
||||
Rewriter rewriter;
|
||||
BodyNotInBlock bodyNotInBlock;
|
||||
SalLogAreas salLogAreas;
|
||||
UnusedVariableCheck unusedVariableCheck;
|
||||
};
|
||||
|
||||
|
@@ -23,7 +23,7 @@ class Plugin
|
||||
public:
|
||||
explicit Plugin( ASTContext& context );
|
||||
protected:
|
||||
DiagnosticBuilder report( DiagnosticsEngine::Level level, StringRef message, SourceLocation loc );
|
||||
DiagnosticBuilder report( DiagnosticsEngine::Level level, StringRef message, SourceLocation loc = SourceLocation());
|
||||
bool ignoreLocation( SourceLocation loc );
|
||||
bool ignoreLocation( const Decl* decl );
|
||||
bool ignoreLocation( const Stmt* stmt );
|
||||
|
113
compilerplugins/clang/sallogareas.cxx
Normal file
113
compilerplugins/clang/sallogareas.cxx
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* Based on LLVM/Clang.
|
||||
*
|
||||
* This file is distributed under the University of Illinois Open Source
|
||||
* License. See LICENSE.TXT for details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sallogareas.hxx"
|
||||
|
||||
#include <clang/Basic/SourceManager.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace loplugin
|
||||
{
|
||||
|
||||
/*
|
||||
Check that areas used in SAL_LOG/SAL_WARN are listed in sal/inc/sal/log-areas.dox .
|
||||
*/
|
||||
|
||||
SalLogAreas::SalLogAreas( ASTContext& context )
|
||||
: Plugin( context )
|
||||
{
|
||||
}
|
||||
|
||||
void SalLogAreas::run()
|
||||
{
|
||||
inFunction = NULL;
|
||||
TraverseDecl( context.getTranslationUnitDecl());
|
||||
}
|
||||
|
||||
bool SalLogAreas::VisitFunctionDecl( FunctionDecl* function )
|
||||
{
|
||||
inFunction = function;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SalLogAreas::VisitCallExpr( CallExpr* call )
|
||||
{
|
||||
if( ignoreLocation( call ))
|
||||
return true;
|
||||
if( FunctionDecl* func = call->getDirectCallee())
|
||||
{
|
||||
// Optimize, getQualifiedNameAsString() is reportedly expensive.
|
||||
if( func->getNumParams() == 4 && func->getIdentifier() != NULL
|
||||
&& ( func->getName() == "sal_detail_log" || func->getName() == "log" ))
|
||||
{
|
||||
std::string qualifiedName = func->getQualifiedNameAsString();
|
||||
if( qualifiedName == "sal_detail_log" || qualifiedName == "sal::detail::log" )
|
||||
{
|
||||
if( const StringLiteral* area = dyn_cast< StringLiteral >( call->getArg( 1 )->IgnoreParenImpCasts()))
|
||||
{
|
||||
if( area->getKind() == StringLiteral::Ascii )
|
||||
checkArea( area->getBytes(), area->getExprLoc());
|
||||
else
|
||||
report( DiagnosticsEngine::Warning, "unsupported string literal kind (plugin needs fixing?) [loplugin] sallog",
|
||||
area->getLocStart());
|
||||
return true;
|
||||
}
|
||||
if( inFunction->getQualifiedNameAsString() == "sal::detail::log" )
|
||||
return true; // This function only forwards to sal_detail_log, so ok.
|
||||
report( DiagnosticsEngine::Warning, "cannot analyse log area argument (plugin needs fixing?) [loplugin] sallog",
|
||||
call->getLocStart());
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SalLogAreas::checkArea( StringRef area, SourceLocation location )
|
||||
{
|
||||
if( logAreas.empty())
|
||||
readLogAreas();
|
||||
if( !logAreas.count( area ))
|
||||
{
|
||||
report( DiagnosticsEngine::Warning, "unknown log area '%0' (check or extend sal/inc/sal/log-areas.dox) [loplugin] sallog",
|
||||
location ) << area;
|
||||
}
|
||||
}
|
||||
|
||||
void SalLogAreas::readLogAreas()
|
||||
{
|
||||
#define STRINGIFY2( s ) #s
|
||||
#define STRINGIFY( s ) STRINGIFY2( s )
|
||||
ifstream is( STRINGIFY( SRCDIR ) "/sal/inc/sal/log-areas.dox" );
|
||||
#undef STRINGIFY
|
||||
#undef STRINGIFY2
|
||||
while( is.good())
|
||||
{
|
||||
string line;
|
||||
getline( is, line );
|
||||
size_t pos = line.find( "@li @c " );
|
||||
if( pos != string::npos )
|
||||
{
|
||||
pos += strlen( "@li @c " );
|
||||
size_t end = line.find( ' ', pos );
|
||||
if( end == string::npos )
|
||||
logAreas.insert( line.substr( pos ));
|
||||
else if( pos != end )
|
||||
logAreas.insert( line.substr( pos, end - pos ));
|
||||
}
|
||||
}
|
||||
// If you get this error message, you possibly have too old icecream (ICECC_EXTRAFILES is needed).
|
||||
if( logAreas.empty())
|
||||
report( DiagnosticsEngine::Warning, "error reading log areas [loplugin] sallog" );
|
||||
}
|
||||
|
||||
} // namespace
|
39
compilerplugins/clang/sallogareas.hxx
Normal file
39
compilerplugins/clang/sallogareas.hxx
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* Based on LLVM/Clang.
|
||||
*
|
||||
* This file is distributed under the University of Illinois Open Source
|
||||
* License. See LICENSE.TXT for details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SALLOGAREAS_H
|
||||
#define SALLOGAREAS_H
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "compileplugin.hxx"
|
||||
|
||||
namespace loplugin
|
||||
{
|
||||
|
||||
class SalLogAreas
|
||||
: public RecursiveASTVisitor< SalLogAreas >
|
||||
, public Plugin
|
||||
{
|
||||
public:
|
||||
explicit SalLogAreas( ASTContext& context );
|
||||
void run();
|
||||
bool VisitFunctionDecl( FunctionDecl* function );
|
||||
bool VisitCallExpr( CallExpr* call );
|
||||
private:
|
||||
void checkArea( StringRef area, SourceLocation location );
|
||||
void readLogAreas();
|
||||
const FunctionDecl* inFunction;
|
||||
std::set< std::string > logAreas;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // SALLOGAREAS_H
|
@@ -38,13 +38,10 @@ void UnusedVariableCheck::run()
|
||||
TraverseDecl( context.getTranslationUnitDecl());
|
||||
}
|
||||
|
||||
bool UnusedVariableCheck::VisitNamedDecl( NamedDecl* declaration )
|
||||
bool UnusedVariableCheck::VisitVarDecl( VarDecl* var )
|
||||
{
|
||||
if( ignoreLocation( declaration ))
|
||||
if( ignoreLocation( var ))
|
||||
return true;
|
||||
if( !isa< VarDecl >( declaration ))
|
||||
return true;
|
||||
const VarDecl* var = cast< VarDecl >( declaration );
|
||||
if( var->isReferenced() || var->isUsed())
|
||||
return true;
|
||||
if( var->isDefinedOutsideFunctionOrMethod())
|
||||
|
@@ -23,7 +23,7 @@ class UnusedVariableCheck
|
||||
public:
|
||||
explicit UnusedVariableCheck( ASTContext& context );
|
||||
void run();
|
||||
bool VisitNamedDecl( NamedDecl* declaration );
|
||||
bool VisitVarDecl( VarDecl* var );
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
Reference in New Issue
Block a user