summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@suse.cz>2013-02-02 17:45:18 +0100
committerLuboš Luňák <l.lunak@suse.cz>2013-02-02 22:59:44 +0100
commita7c3adb773e5b69601716bda181cc481090a4d59 (patch)
tree1ffbb7bb5863a316058553ba941be5b9facc7e1b /compilerplugins
parentb8f932b6a5c6ace05df975f82e682f10804dad5d (diff)
avoid having to manuall modify sources when adding a new clang plugin
Now each one registers in its .cxx file. Change-Id: I811c0d4400c2bdccc1c287269378d7e8ad8743ce
Diffstat (limited to 'compilerplugins')
-rw-r--r--compilerplugins/clang/bodynotinblock.cxx2
-rw-r--r--compilerplugins/clang/bodynotinblock.hxx2
-rw-r--r--compilerplugins/clang/lclstaticfix.cxx2
-rw-r--r--compilerplugins/clang/lclstaticfix.hxx2
-rw-r--r--compilerplugins/clang/plugin.cxx6
-rw-r--r--compilerplugins/clang/plugin.hxx71
-rw-r--r--compilerplugins/clang/pluginhandler.cxx87
-rw-r--r--compilerplugins/clang/pluginhandler.hxx25
-rw-r--r--compilerplugins/clang/postfixincrementfix.cxx2
-rw-r--r--compilerplugins/clang/postfixincrementfix.hxx2
-rw-r--r--compilerplugins/clang/removeforwardstringdecl.cxx2
-rw-r--r--compilerplugins/clang/removeforwardstringdecl.hxx2
-rw-r--r--compilerplugins/clang/sallogareas.cxx2
-rw-r--r--compilerplugins/clang/sallogareas.hxx2
-rw-r--r--compilerplugins/clang/unusedvariablecheck.cxx2
-rw-r--r--compilerplugins/clang/unusedvariablecheck.hxx2
16 files changed, 161 insertions, 52 deletions
diff --git a/compilerplugins/clang/bodynotinblock.cxx b/compilerplugins/clang/bodynotinblock.cxx
index a2e79680d8e2..74cab892166b 100644
--- a/compilerplugins/clang/bodynotinblock.cxx
+++ b/compilerplugins/clang/bodynotinblock.cxx
@@ -139,4 +139,6 @@ void BodyNotInBlock::checkBody( const Stmt* body, SourceLocation stmtLocation, c
}
}
+static Plugin::Registration< BodyNotInBlock > X( "bodynotinblock" );
+
} // namespace
diff --git a/compilerplugins/clang/bodynotinblock.hxx b/compilerplugins/clang/bodynotinblock.hxx
index 3cfc9bafc8d5..e8d35dd58480 100644
--- a/compilerplugins/clang/bodynotinblock.hxx
+++ b/compilerplugins/clang/bodynotinblock.hxx
@@ -22,7 +22,7 @@ class BodyNotInBlock
{
public:
explicit BodyNotInBlock( ASTContext& context );
- void run();
+ virtual void run();
bool VisitFunctionDecl( FunctionDecl* declaration );
private:
typedef vector< const Stmt* > StmtParents;
diff --git a/compilerplugins/clang/lclstaticfix.cxx b/compilerplugins/clang/lclstaticfix.cxx
index a5c765b229b7..e966139dbaa1 100644
--- a/compilerplugins/clang/lclstaticfix.cxx
+++ b/compilerplugins/clang/lclstaticfix.cxx
@@ -49,4 +49,6 @@ bool LclStaticFix::VisitFunctionDecl( FunctionDecl* declaration )
return true;
}
+static Plugin::Registration< LclStaticFix > X( "lclstaticfix" );
+
} // namespace
diff --git a/compilerplugins/clang/lclstaticfix.hxx b/compilerplugins/clang/lclstaticfix.hxx
index fdf9d34107e7..64e5b2919461 100644
--- a/compilerplugins/clang/lclstaticfix.hxx
+++ b/compilerplugins/clang/lclstaticfix.hxx
@@ -22,7 +22,7 @@ class LclStaticFix
{
public:
explicit LclStaticFix( ASTContext& context, Rewriter& rewriter );
- void run();
+ virtual void run();
bool VisitFunctionDecl( FunctionDecl* declaration );
};
diff --git a/compilerplugins/clang/plugin.cxx b/compilerplugins/clang/plugin.cxx
index 05172b7a9a91..9ab9f2d13f7f 100644
--- a/compilerplugins/clang/plugin.cxx
+++ b/compilerplugins/clang/plugin.cxx
@@ -55,6 +55,12 @@ bool Plugin::ignoreLocation( SourceLocation loc )
return true;
}
+void Plugin::registerPlugin( Plugin* (*create)( ASTContext&, Rewriter& ), const char* optionName, bool isRewriter )
+ {
+ PluginHandler::registerPlugin( create, optionName, isRewriter );
+ }
+
+/////
RewritePlugin::RewritePlugin( ASTContext& context, Rewriter& rewriter )
: Plugin( context )
diff --git a/compilerplugins/clang/plugin.hxx b/compilerplugins/clang/plugin.hxx
index af1394d57b6f..014329e12eb1 100644
--- a/compilerplugins/clang/plugin.hxx
+++ b/compilerplugins/clang/plugin.hxx
@@ -28,18 +28,36 @@ using namespace std;
namespace loplugin
{
+/**
+ Base class for plugins.
+
+ If you want to create a non-rewriter action, inherit from this class. Remember to also
+ use Plugin::Registration.
+*/
class Plugin
{
public:
explicit Plugin( ASTContext& context );
+ virtual ~Plugin();
+ virtual void run() = 0;
+ template< typename T > class Registration;
protected:
DiagnosticBuilder report( DiagnosticsEngine::Level level, StringRef message, SourceLocation loc = SourceLocation());
bool ignoreLocation( SourceLocation loc );
bool ignoreLocation( const Decl* decl );
bool ignoreLocation( const Stmt* stmt );
ASTContext& context;
+ private:
+ static void registerPlugin( Plugin* (*create)( ASTContext&, Rewriter& ), const char* optionName, bool isRewriter );
+ template< typename T > static Plugin* createHelper( ASTContext& context, Rewriter& rewriter );
+ enum { isRewriter = false };
};
+/**
+ Base class for rewriter plugins.
+
+ Remember to also use Plugin::Registration.
+*/
class RewritePlugin
: public Plugin
{
@@ -85,10 +103,44 @@ class RewritePlugin
bool replaceText( SourceRange range, SourceRange replacementRange );
Rewriter& rewriter;
private:
+ template< typename T > friend class Plugin::Registration;
+ template< typename T > static Plugin* createHelper( ASTContext& context, Rewriter& rewriter );
+ enum { isRewriter = true };
bool reportEditFailure( SourceLocation loc );
bool adjustForWholeStatement( SourceRange* range );
};
+/**
+ Plugin registration helper.
+
+ If you create a new helper class, create also an instance of this class to automatically register it.
+ The passed argument is name of the plugin, used for explicitly invoking rewriter plugins
+ (it is ignored for non-rewriter plugins).
+
+ @code
+ static Plugin::Registration< NameOfClass > X( "nameofclass" );
+ @endcode
+*/
+template< typename T >
+class Plugin::Registration
+ {
+ public:
+ Registration( const char* optionName );
+ };
+
+class RegistrationCreate
+ {
+ public:
+ template< typename T, bool > static T* create( ASTContext& context, Rewriter& rewriter );
+ };
+
+/////
+
+inline
+Plugin::~Plugin()
+ {
+ }
+
inline
bool Plugin::ignoreLocation( const Decl* decl )
{
@@ -101,6 +153,25 @@ bool Plugin::ignoreLocation( const Stmt* stmt )
return ignoreLocation( stmt->getLocStart());
}
+template< typename T >
+Plugin* Plugin::createHelper( ASTContext& context, Rewriter& )
+ {
+ return new T( context );
+ }
+
+template< typename T >
+Plugin* RewritePlugin::createHelper( ASTContext& context, Rewriter& rewriter )
+ {
+ return new T( context, rewriter );
+ }
+
+template< typename T >
+inline
+Plugin::Registration< T >::Registration( const char* optionName )
+ {
+ registerPlugin( &T::template createHelper< T >, optionName, T::isRewriter );
+ }
+
} // namespace
#endif // COMPILEPLUGIN_H
diff --git a/compilerplugins/clang/pluginhandler.cxx b/compilerplugins/clang/pluginhandler.cxx
index fd2c62e58caf..35d881ec52f2 100644
--- a/compilerplugins/clang/pluginhandler.cxx
+++ b/compilerplugins/clang/pluginhandler.cxx
@@ -19,39 +19,80 @@
namespace loplugin
{
+struct PluginData
+ {
+ Plugin* (*create)( ASTContext&, Rewriter& );
+ Plugin* object;
+ const char* optionName;
+ bool isRewriter;
+ };
+
+const int MAX_PLUGINS = 100;
+static PluginData plugins[ MAX_PLUGINS ];
+static int pluginCount = 0;
+static bool pluginObjectsCreated = false;
+
PluginHandler::PluginHandler( ASTContext& context, const vector< string >& args )
: rewriter( context.getSourceManager(), context.getLangOpts())
- , args( args )
- , bodyNotInBlock( context )
- , lclStaticFix( context, rewriter )
- , postfixIncrementFix( context, rewriter )
- , removeForwardStringDecl( context, rewriter )
- , salLogAreas( context )
- , unusedVariableCheck( context )
{
+ bool wasCreated = false;
+ for( int i = 0;
+ i < pluginCount;
+ ++i )
+ {
+ bool create = false;
+ if( args.empty()) // no args -> create non-writer plugins
+ create = !plugins[ i ].isRewriter;
+ else // create only the given plugin(s)
+ {
+ if( find( args.begin(), args.end(), plugins[ i ].optionName ) != args.end())
+ create = true;
+ }
+ if( create )
+ {
+ plugins[ i ].object = plugins[ i ].create( context, rewriter );
+ wasCreated = true;
+ }
+ }
+ pluginObjectsCreated = true;
+ if( !args.empty() && !wasCreated )
+ {
+ DiagnosticsEngine& diag = context.getDiagnostics();
+ diag.Report( diag.getCustomDiagID( DiagnosticsEngine::Fatal,
+ "unknown plugin tool %0 [loplugin]" )) << args.front();
+ }
+ }
+
+PluginHandler::~PluginHandler()
+ {
+ for( int i = 0;
+ i < pluginCount;
+ ++i )
+ if( plugins[ i ].object != NULL )
+ delete plugins[ i ].object;
+ }
+
+void PluginHandler::registerPlugin( Plugin* (*create)( ASTContext&, Rewriter& ), const char* optionName, bool isRewriter )
+ {
+ assert( !pluginObjectsCreated );
+ assert( pluginCount < MAX_PLUGINS );
+ plugins[ pluginCount ].create = create;
+ plugins[ pluginCount ].object = NULL;
+ plugins[ pluginCount ].optionName = optionName;
+ plugins[ pluginCount ].isRewriter = isRewriter;
+ ++pluginCount;
}
void PluginHandler::HandleTranslationUnit( ASTContext& context )
{
if( context.getDiagnostics().hasErrorOccurred())
return;
- if( isArg( "lclstaticfix" ))
- lclStaticFix.run();
- else if( isArg( "postfixincrementfix" ))
- postfixIncrementFix.run();
- else if( isArg( "removeforwardstringdecl" ))
- removeForwardStringDecl.run();
- else if( args.empty())
- {
- bodyNotInBlock.run();
- salLogAreas.run();
- unusedVariableCheck.run();
- }
- else
+ for( int i = 0;
+ i < pluginCount;
+ ++i )
{
- DiagnosticsEngine& diag = context.getDiagnostics();
- diag.Report( diag.getCustomDiagID( DiagnosticsEngine::Fatal,
- "unknown plugin tool %0 [loplugin]" )) << args.front();
+ if( plugins[ i ].object != NULL )
+ plugins[ i ].object->run();
}
for( Rewriter::buffer_iterator it = rewriter.buffer_begin();
it != rewriter.buffer_end();
diff --git a/compilerplugins/clang/pluginhandler.hxx b/compilerplugins/clang/pluginhandler.hxx
index d9ac63341122..2211275208ae 100644
--- a/compilerplugins/clang/pluginhandler.hxx
+++ b/compilerplugins/clang/pluginhandler.hxx
@@ -16,13 +16,6 @@
#include <clang/AST/ASTConsumer.h>
#include <clang/Frontend/FrontendAction.h>
-#include "bodynotinblock.hxx"
-#include "lclstaticfix.hxx"
-#include "postfixincrementfix.hxx"
-#include "removeforwardstringdecl.hxx"
-#include "sallogareas.hxx"
-#include "unusedvariablecheck.hxx"
-
namespace loplugin
{
@@ -34,17 +27,11 @@ class PluginHandler
{
public:
PluginHandler( ASTContext& context, const vector< string >& args );
+ virtual ~PluginHandler();
virtual void HandleTranslationUnit( ASTContext& context );
+ static void registerPlugin( Plugin* (*create)( ASTContext&, Rewriter& ), const char* optionName, bool isRewriter );
private:
- bool isArg( const char* arg ) const;
Rewriter rewriter;
- vector< string > args;
- BodyNotInBlock bodyNotInBlock;
- LclStaticFix lclStaticFix;
- PostfixIncrementFix postfixIncrementFix;
- RemoveForwardStringDecl removeForwardStringDecl;
- SalLogAreas salLogAreas;
- UnusedVariableCheck unusedVariableCheck;
};
/**
@@ -60,14 +47,6 @@ class LibreOfficeAction
vector< string > _args;
};
-/////
-
-inline
-bool PluginHandler::isArg( const char* arg ) const
- {
- return find( args.begin(), args.end(), arg ) != args.end();
- }
-
} // namespace
#endif // COMPILEPLUGIN_H
diff --git a/compilerplugins/clang/postfixincrementfix.cxx b/compilerplugins/clang/postfixincrementfix.cxx
index bfaf77cefa6c..2f474761830f 100644
--- a/compilerplugins/clang/postfixincrementfix.cxx
+++ b/compilerplugins/clang/postfixincrementfix.cxx
@@ -162,4 +162,6 @@ bool PostfixIncrementFix::shouldDoChange( const Expr* operand )
}
}
+static Plugin::Registration< PostfixIncrementFix > X( "postfixincrementfix" );
+
} // namespace
diff --git a/compilerplugins/clang/postfixincrementfix.hxx b/compilerplugins/clang/postfixincrementfix.hxx
index 6f6b414690b0..beae8a76e520 100644
--- a/compilerplugins/clang/postfixincrementfix.hxx
+++ b/compilerplugins/clang/postfixincrementfix.hxx
@@ -22,7 +22,7 @@ class PostfixIncrementFix
{
public:
explicit PostfixIncrementFix( ASTContext& context, Rewriter& rewriter );
- void run();
+ virtual void run();
bool VisitFunctionDecl( FunctionDecl* declaration );
private:
typedef std::vector< const Stmt* > StmtParents;
diff --git a/compilerplugins/clang/removeforwardstringdecl.cxx b/compilerplugins/clang/removeforwardstringdecl.cxx
index 45891d5d7fb3..711d9604dc9f 100644
--- a/compilerplugins/clang/removeforwardstringdecl.cxx
+++ b/compilerplugins/clang/removeforwardstringdecl.cxx
@@ -73,4 +73,6 @@ bool RemoveForwardStringDecl::tryRemoveStringForwardDecl( const Decl* decl )
return false;
}
+static Plugin::Registration< RemoveForwardStringDecl > X( "removeforwardstringdecl" );
+
} // namespace
diff --git a/compilerplugins/clang/removeforwardstringdecl.hxx b/compilerplugins/clang/removeforwardstringdecl.hxx
index 7f40e371817d..2b66a522fc4d 100644
--- a/compilerplugins/clang/removeforwardstringdecl.hxx
+++ b/compilerplugins/clang/removeforwardstringdecl.hxx
@@ -22,7 +22,7 @@ class RemoveForwardStringDecl
{
public:
explicit RemoveForwardStringDecl( ASTContext& context, Rewriter& rewriter );
- void run();
+ virtual void run();
bool VisitNamespaceDecl( NamespaceDecl* declaration );
private:
bool tryRemoveStringForwardDecl( const Decl* decl );
diff --git a/compilerplugins/clang/sallogareas.cxx b/compilerplugins/clang/sallogareas.cxx
index 7e6c187d7e9a..1a3a651a7959 100644
--- a/compilerplugins/clang/sallogareas.cxx
+++ b/compilerplugins/clang/sallogareas.cxx
@@ -131,4 +131,6 @@ void SalLogAreas::readLogAreas()
report( DiagnosticsEngine::Warning, "error reading log areas [loplugin]" );
}
+static Plugin::Registration< SalLogAreas > X( "sallogareas" );
+
} // namespace
diff --git a/compilerplugins/clang/sallogareas.hxx b/compilerplugins/clang/sallogareas.hxx
index e83e890697e4..d572591c62ee 100644
--- a/compilerplugins/clang/sallogareas.hxx
+++ b/compilerplugins/clang/sallogareas.hxx
@@ -24,7 +24,7 @@ class SalLogAreas
{
public:
explicit SalLogAreas( ASTContext& context );
- void run();
+ virtual void run();
bool VisitFunctionDecl( FunctionDecl* function );
bool VisitCallExpr( CallExpr* call );
private:
diff --git a/compilerplugins/clang/unusedvariablecheck.cxx b/compilerplugins/clang/unusedvariablecheck.cxx
index 759b9fa946ec..93ad85163607 100644
--- a/compilerplugins/clang/unusedvariablecheck.cxx
+++ b/compilerplugins/clang/unusedvariablecheck.cxx
@@ -100,4 +100,6 @@ bool UnusedVariableCheck::VisitVarDecl( VarDecl* var )
return true;
}
+static Plugin::Registration< UnusedVariableCheck > X( "unusedvariablecheck" );
+
} // namespace
diff --git a/compilerplugins/clang/unusedvariablecheck.hxx b/compilerplugins/clang/unusedvariablecheck.hxx
index 7bf1cdd15ddd..6ccdee3e193e 100644
--- a/compilerplugins/clang/unusedvariablecheck.hxx
+++ b/compilerplugins/clang/unusedvariablecheck.hxx
@@ -22,7 +22,7 @@ class UnusedVariableCheck
{
public:
explicit UnusedVariableCheck( ASTContext& context );
- void run();
+ virtual void run();
bool VisitVarDecl( VarDecl* var );
};