summaryrefslogtreecommitdiff
path: root/compilerplugins/clang
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@suse.cz>2013-02-02 22:59:17 +0100
committerLuboš Luňák <l.lunak@suse.cz>2013-02-02 22:59:46 +0100
commit4fd910a096532fed2552c67bceabe237a9e3c7d6 (patch)
tree6ea0e4eee6813cf5e7b735afda358499e7289d76 /compilerplugins/clang
parent18e615189df93cb704c32553a41505a1bdc984f1 (diff)
tutorial examples for writing new Clang plugin actions
http://wiki.documentfoundation.org/Clang_plugins Change-Id: Ieb4fc186490e81ab961c094ca0a7fcdabc0f348f
Diffstat (limited to 'compilerplugins/clang')
-rw-r--r--compilerplugins/clang/store/tutorial/tutorial1.cxx65
-rw-r--r--compilerplugins/clang/store/tutorial/tutorial1.hxx38
-rw-r--r--compilerplugins/clang/store/tutorial/tutorial1_example.cxx18
-rw-r--r--compilerplugins/clang/store/tutorial/tutorial2.cxx92
-rw-r--r--compilerplugins/clang/store/tutorial/tutorial2.hxx37
-rw-r--r--compilerplugins/clang/store/tutorial/tutorial2_example.cxx15
-rw-r--r--compilerplugins/clang/store/tutorial/tutorial3.cxx74
-rw-r--r--compilerplugins/clang/store/tutorial/tutorial3.hxx39
8 files changed, 378 insertions, 0 deletions
diff --git a/compilerplugins/clang/store/tutorial/tutorial1.cxx b/compilerplugins/clang/store/tutorial/tutorial1.cxx
new file mode 100644
index 000000000000..fa1ec44e351d
--- /dev/null
+++ b/compilerplugins/clang/store/tutorial/tutorial1.cxx
@@ -0,0 +1,65 @@
+/*
+ * 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 "tutorial1.hxx"
+
+/*
+This is a compile check.
+
+Checks all return statements and warns if they return literal false (i.e. 'return false').
+*/
+
+namespace loplugin
+{
+
+// Ctor, nothing special, pass the argument(s).
+Tutorial1::Tutorial1( ASTContext& context )
+ : Plugin( context )
+ {
+ }
+
+// Perform the actual action.
+void Tutorial1::run()
+ {
+ // Traverse the whole AST of the translation unit (i.e. examine the whole source file).
+ // The Clang AST helper class will call VisitReturnStmt for every return statement.
+ TraverseDecl( context.getTranslationUnitDecl());
+ }
+
+// This function is called for every return statement.
+// Returning true means to continue with examining the AST, false means to stop (just always return true).
+bool Tutorial1::VisitReturnStmt( ReturnStmt* returnstmt )
+ {
+ // Helper function from the LO base plugin class, call at the very beginning to ignore sources
+ // that should not be processed (e.g. system headers).
+ if( ignoreLocation( returnstmt ))
+ return true;
+ // Get the expression in the return statement (see ReturnStmt API docs).
+ const Expr* expression = returnstmt->getRetValue();
+ if( expression == NULL )
+ return true; // plain 'return;' without expression
+ // Check if the expression is a bool literal (Clang uses dyn_cast<> instead of dynamic_cast<>).
+ if( const CXXBoolLiteralExpr* boolliteral = dyn_cast< CXXBoolLiteralExpr >( expression ))
+ { // It is.
+ if( boolliteral->getValue() == false ) // Is it 'return false;' ? (See CXXBoolLiteralExpr API docs)
+ { // Ok, warn, use LO plugin helper function.
+ report( DiagnosticsEngine::Warning, // It's just a warning.
+ "returning false", // the message
+ boolliteral->getLocStart()) // and the exact position where the message should point
+ << returnstmt->getSourceRange(); // and the full return statement to highlight (optional)
+ }
+ }
+ return true;
+ }
+
+// Register the plugin action with the LO plugin handling.
+static Plugin::Registration< Tutorial1 > X( "tutorial1" );
+
+} // namespace
diff --git a/compilerplugins/clang/store/tutorial/tutorial1.hxx b/compilerplugins/clang/store/tutorial/tutorial1.hxx
new file mode 100644
index 000000000000..0f5127db65a8
--- /dev/null
+++ b/compilerplugins/clang/store/tutorial/tutorial1.hxx
@@ -0,0 +1,38 @@
+/*
+ * 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 TUTORIAL1_H
+#define TUTORIAL1_H
+
+#include "plugin.hxx"
+
+namespace loplugin
+{
+
+// The class implementing the plugin action.
+class Tutorial1
+ // Inherits from the Clang class that will allow examing the Clang AST tree (i.e. syntax tree).
+ : public RecursiveASTVisitor< Tutorial1 >
+ // And the base class for LO Clang plugins.
+ , public Plugin
+ {
+ public:
+ // Ctor, nothing special.
+ Tutorial1( ASTContext& context );
+ // The function that will be called to perform the actual action.
+ virtual void run();
+ // Function from Clang, it will be called for every return statement in the source.
+ bool VisitReturnStmt( ReturnStmt* returnstmt );
+ };
+
+} // namespace
+
+#endif // POSTFIXINCREMENTFIX_H
+
diff --git a/compilerplugins/clang/store/tutorial/tutorial1_example.cxx b/compilerplugins/clang/store/tutorial/tutorial1_example.cxx
new file mode 100644
index 000000000000..ca4c768fdd50
--- /dev/null
+++ b/compilerplugins/clang/store/tutorial/tutorial1_example.cxx
@@ -0,0 +1,18 @@
+// This is just an example file to see what AST looks like for return statements.
+// To the the AST, run :
+// clang++ -fsyntax-only -Xclang -ast-dump tutorial1_example.cxx
+
+void f()
+ {
+ return;
+ }
+
+bool g()
+ {
+ return false;
+ }
+
+bool h()
+ {
+ return 3 > 2;
+ }
diff --git a/compilerplugins/clang/store/tutorial/tutorial2.cxx b/compilerplugins/clang/store/tutorial/tutorial2.cxx
new file mode 100644
index 000000000000..d5fc60b822a3
--- /dev/null
+++ b/compilerplugins/clang/store/tutorial/tutorial2.cxx
@@ -0,0 +1,92 @@
+/*
+ * 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 "tutorial2.hxx"
+
+/*
+This is a compile check.
+
+Warns about if statements with a comparison followed by literal return false:
+if( a == 1 )
+ return false;
+*/
+
+namespace loplugin
+{
+
+Tutorial2::Tutorial2( ASTContext& context )
+ : Plugin( context )
+ {
+ }
+
+void Tutorial2::run()
+ {
+ // The Clang AST helper class will call VisitIfStmt for every if statement.
+ TraverseDecl( context.getTranslationUnitDecl());
+ }
+
+// This function is called for every if statement.
+bool Tutorial2::VisitIfStmt( IfStmt* ifstmt )
+ {
+ if( ignoreLocation( ifstmt ))
+ return true;
+ // Check if the condition of the if statement is a binary operator.
+ if( const BinaryOperator* oper = dyn_cast< BinaryOperator >( ifstmt->getCond()))
+ {
+ // And if it's operator==.
+ if( oper->getOpcode() == BO_EQ )
+ {
+ // Now check if the sub-statement is 'return false'.
+ const Stmt* warn = NULL; // The return statement (for the warning message).
+ // Check if the sub-statement is directly 'return false;'.
+ if( isReturnFalse( ifstmt->getThen()))
+ warn = ifstmt->getThen();
+ // Check if the sub-statement is '{ return false; }'
+ else if( CompoundStmt* compound = dyn_cast< CompoundStmt >( ifstmt->getThen()))
+ {
+ if( compound->size() == 1 ) // one statement
+ if( isReturnFalse( *compound->body_begin())) // check the one sub-statement
+ warn = *compound->body_begin();
+ }
+ if( warn != NULL ) // there is a return statement to warn about.
+ {
+ report( DiagnosticsEngine::Warning,
+ "returning false after if with equality comparison",
+ cast< ReturnStmt >( warn )->getRetValue()->getLocStart()) // the 'false' in the return
+ << warn->getSourceRange();
+ // Also add a note showing the if statement.
+ report( DiagnosticsEngine::Note,
+ "the if statement is here",
+ ifstmt->getLocStart());
+ }
+ }
+ }
+ return true;
+ }
+
+bool Tutorial2::isReturnFalse( const Stmt* stmt )
+ {
+ // Is it return statement?
+ if( const ReturnStmt* returnstmt = dyn_cast< ReturnStmt >( stmt ))
+ {
+ // dyn_cast_or_null<> can also be passed NULL, unlike dyn_cast<>
+ if( const CXXBoolLiteralExpr* boolliteral = dyn_cast_or_null< CXXBoolLiteralExpr >( returnstmt->getRetValue()))
+ {
+ if( boolliteral->getValue() == false )
+ return true;
+ }
+ }
+ return false;
+ }
+
+// Register the plugin action with the LO plugin handling.
+static Plugin::Registration< Tutorial2 > X( "tutorial2" );
+
+} // namespace
diff --git a/compilerplugins/clang/store/tutorial/tutorial2.hxx b/compilerplugins/clang/store/tutorial/tutorial2.hxx
new file mode 100644
index 000000000000..97c56bad195b
--- /dev/null
+++ b/compilerplugins/clang/store/tutorial/tutorial2.hxx
@@ -0,0 +1,37 @@
+/*
+ * 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 TUTORIAL2_H
+#define TUTORIAL2_H
+
+#include "plugin.hxx"
+
+namespace loplugin
+{
+
+// The same like for Tutorial1.
+class Tutorial2
+ : public RecursiveASTVisitor< Tutorial2 >
+ , public Plugin
+ {
+ public:
+ Tutorial2( ASTContext& context );
+ virtual void run();
+ // Will be called for every if statement.
+ bool VisitIfStmt( IfStmt* ifstmt );
+ private:
+ // Helper function to check if the statement is 'return false;'.
+ bool isReturnFalse( const Stmt* stmt );
+ };
+
+} // namespace
+
+#endif // POSTFIXINCREMENTFIX_H
+
diff --git a/compilerplugins/clang/store/tutorial/tutorial2_example.cxx b/compilerplugins/clang/store/tutorial/tutorial2_example.cxx
new file mode 100644
index 000000000000..d3c14ab7c13c
--- /dev/null
+++ b/compilerplugins/clang/store/tutorial/tutorial2_example.cxx
@@ -0,0 +1,15 @@
+// This is just an example file to see what AST looks like for return statements.
+// To the the AST, run :
+// clang++ -fsyntax-only -Xclang -ast-dump tutorial1_example.cxx
+
+bool g()
+ {
+ if( 1 == 2 )
+ return false;
+ if( 1 == 2 )
+ {
+ return false;
+ }
+ if( true )
+ return false;
+ }
diff --git a/compilerplugins/clang/store/tutorial/tutorial3.cxx b/compilerplugins/clang/store/tutorial/tutorial3.cxx
new file mode 100644
index 000000000000..e0589f64b671
--- /dev/null
+++ b/compilerplugins/clang/store/tutorial/tutorial3.cxx
@@ -0,0 +1,74 @@
+/*
+ * 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 "tutorial3.hxx"
+
+/*
+This is a rewriter.
+
+It looks for if statements with a comparison followed by literal return false
+and modifies the return statements to 'return maybereturntrue;'
+*/
+
+namespace loplugin
+{
+
+// Ctor, pass arguments.
+Tutorial3::Tutorial3( ASTContext& context, Rewriter& rewriter )
+ : RewritePlugin( context, rewriter )
+ {
+ }
+
+void Tutorial3::run()
+ {
+ TraverseDecl( context.getTranslationUnitDecl());
+ }
+
+bool Tutorial3::VisitIfStmt( IfStmt* ifstmt )
+ {
+ if( ignoreLocation( ifstmt ))
+ return true;
+ if( const BinaryOperator* oper = dyn_cast< BinaryOperator >( ifstmt->getCond()))
+ {
+ if( oper->getOpcode() == BO_EQ )
+ {
+ // Modify the sub-statement if it is 'return false'.
+ modifyReturnFalse( ifstmt->getThen());
+ // Modify the sub-statement if it is '{ return false; }'.
+ if( CompoundStmt* compound = dyn_cast< CompoundStmt >( ifstmt->getThen()))
+ {
+ if( compound->size() == 1 ) // one statement
+ modifyReturnFalse( *compound->body_begin());
+ }
+ }
+ }
+ return true;
+ }
+
+void Tutorial3::modifyReturnFalse( const Stmt* stmt )
+ {
+ // Is it return statement?
+ if( const ReturnStmt* returnstmt = dyn_cast< ReturnStmt >( stmt ))
+ {
+ // dyn_cast_or_null<> can also be passed NULL, unlike dyn_cast<>
+ if( const CXXBoolLiteralExpr* boolliteral = dyn_cast_or_null< CXXBoolLiteralExpr >( returnstmt->getRetValue()))
+ {
+ if( boolliteral->getValue() == false )
+ { // It is, modify the false to true using LO plugin helper function.
+ replaceText( boolliteral->getSourceRange(), "maybereturntrue" );
+ }
+ }
+ }
+ }
+
+// Register the plugin action with the LO plugin handling.
+static Plugin::Registration< Tutorial3 > X( "tutorial3" );
+
+} // namespace
diff --git a/compilerplugins/clang/store/tutorial/tutorial3.hxx b/compilerplugins/clang/store/tutorial/tutorial3.hxx
new file mode 100644
index 000000000000..69747ee8cf14
--- /dev/null
+++ b/compilerplugins/clang/store/tutorial/tutorial3.hxx
@@ -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 TUTORIAL3_H
+#define TUTORIAL3_H
+
+#include "plugin.hxx"
+
+namespace loplugin
+{
+
+// Similar like for Tutorial2, but this time the base class is RewritePlugin.
+class Tutorial3
+ : public RecursiveASTVisitor< Tutorial3 >
+ , public RewritePlugin
+ {
+ public:
+ // One more argument for ctor.
+ Tutorial3( ASTContext& context, Rewriter& rewriter );
+ virtual void run();
+ // Will be called for every if statement.
+ bool VisitIfStmt( IfStmt* ifstmt );
+ private:
+ // Helper function to check if the statement is 'return false;' and
+ // modify it if yes.
+ void modifyReturnFalse( const Stmt* stmt );
+ };
+
+} // namespace
+
+#endif // POSTFIXINCREMENTFIX_H
+