summaryrefslogtreecommitdiff
path: root/compilerplugins/clang/store/tutorial/tutorial2.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'compilerplugins/clang/store/tutorial/tutorial2.cxx')
-rw-r--r--compilerplugins/clang/store/tutorial/tutorial2.cxx92
1 files changed, 92 insertions, 0 deletions
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