summaryrefslogtreecommitdiffstats
path: root/compilerplugins/clang/store/tutorial
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /compilerplugins/clang/store/tutorial
parentInitial commit. (diff)
downloadlibreoffice-upstream.tar.xz
libreoffice-upstream.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compilerplugins/clang/store/tutorial')
-rw-r--r--compilerplugins/clang/store/tutorial/tutorial1.cxx68
-rw-r--r--compilerplugins/clang/store/tutorial/tutorial1.hxx35
-rw-r--r--compilerplugins/clang/store/tutorial/tutorial1_example.cxx21
-rw-r--r--compilerplugins/clang/store/tutorial/tutorial2.cxx95
-rw-r--r--compilerplugins/clang/store/tutorial/tutorial2.hxx35
-rw-r--r--compilerplugins/clang/store/tutorial/tutorial2_example.cxx18
-rw-r--r--compilerplugins/clang/store/tutorial/tutorial3.cxx77
-rw-r--r--compilerplugins/clang/store/tutorial/tutorial3.hxx37
8 files changed, 386 insertions, 0 deletions
diff --git a/compilerplugins/clang/store/tutorial/tutorial1.cxx b/compilerplugins/clang/store/tutorial/tutorial1.cxx
new file mode 100644
index 000000000..9f7c97fb7
--- /dev/null
+++ b/compilerplugins/clang/store/tutorial/tutorial1.cxx
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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( const InstantiationData& data )
+ : FilteringPlugin( data )
+ {
+ }
+
+// 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( compiler.getASTContext().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( const 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 > tutorial1( "tutorial1" );
+
+} // namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/compilerplugins/clang/store/tutorial/tutorial1.hxx b/compilerplugins/clang/store/tutorial/tutorial1.hxx
new file mode 100644
index 000000000..10f73f04b
--- /dev/null
+++ b/compilerplugins/clang/store/tutorial/tutorial1.hxx
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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.
+ *
+ */
+
+#pragma once
+
+#include "plugin.hxx"
+
+namespace loplugin
+{
+
+// The class implementing the plugin action.
+class Tutorial1
+ // Inherits from the Clang class that will allow examining the Clang AST tree (i.e. syntax tree).
+ : public FilteringPlugin< Tutorial1 >
+ {
+ public:
+ // Ctor, nothing special.
+ Tutorial1( const InstantiationData& data );
+ // The function that will be called to perform the actual action.
+ virtual void run() override;
+ // Function from Clang, it will be called for every return statement in the source.
+ bool VisitReturnStmt( const ReturnStmt* returnstmt );
+ };
+
+} // namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/compilerplugins/clang/store/tutorial/tutorial1_example.cxx b/compilerplugins/clang/store/tutorial/tutorial1_example.cxx
new file mode 100644
index 000000000..1ec0e1e59
--- /dev/null
+++ b/compilerplugins/clang/store/tutorial/tutorial1_example.cxx
@@ -0,0 +1,21 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+// This is just an example file to see what AST looks like for return statements.
+// To the AST, run :
+// clang++ -fsyntax-only -Xclang -ast-dump tutorial1_example.cxx
+
+void f()
+ {
+ return;
+ }
+
+bool g()
+ {
+ return false;
+ }
+
+bool h()
+ {
+ return 3 > 2;
+ }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/compilerplugins/clang/store/tutorial/tutorial2.cxx b/compilerplugins/clang/store/tutorial/tutorial2.cxx
new file mode 100644
index 000000000..49aaaa631
--- /dev/null
+++ b/compilerplugins/clang/store/tutorial/tutorial2.cxx
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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( const InstantiationData& data )
+ : FilteringPlugin( data )
+ {
+ }
+
+void Tutorial2::run()
+ {
+ // The Clang AST helper class will call VisitIfStmt for every if statement.
+ TraverseDecl( compiler.getASTContext().getTranslationUnitDecl());
+ }
+
+// This function is called for every if statement.
+bool Tutorial2::VisitIfStmt( const 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( const 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 > tutorial2( "tutorial2" );
+
+} // namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/compilerplugins/clang/store/tutorial/tutorial2.hxx b/compilerplugins/clang/store/tutorial/tutorial2.hxx
new file mode 100644
index 000000000..9ae2de354
--- /dev/null
+++ b/compilerplugins/clang/store/tutorial/tutorial2.hxx
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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.
+ *
+ */
+
+#pragma once
+
+#include "plugin.hxx"
+
+namespace loplugin
+{
+
+// The same like for Tutorial1.
+class Tutorial2
+ : public FilteringPlugin< Tutorial2 >
+ {
+ public:
+ Tutorial2( const InstantiationData& data );
+ virtual void run() override;
+ // Will be called for every if statement.
+ bool VisitIfStmt( const IfStmt* ifstmt );
+ private:
+ // Helper function to check if the statement is 'return false;'.
+ bool isReturnFalse( const Stmt* stmt );
+ };
+
+} // namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/compilerplugins/clang/store/tutorial/tutorial2_example.cxx b/compilerplugins/clang/store/tutorial/tutorial2_example.cxx
new file mode 100644
index 000000000..7d72ff68d
--- /dev/null
+++ b/compilerplugins/clang/store/tutorial/tutorial2_example.cxx
@@ -0,0 +1,18 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+// This is just an example file to see what AST looks like for return statements.
+// To 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;
+ }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/compilerplugins/clang/store/tutorial/tutorial3.cxx b/compilerplugins/clang/store/tutorial/tutorial3.cxx
new file mode 100644
index 000000000..33a1249a3
--- /dev/null
+++ b/compilerplugins/clang/store/tutorial/tutorial3.cxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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( const InstantiationData& data )
+ : FilteringRewritePlugin( data )
+ {
+ }
+
+void Tutorial3::run()
+ {
+ TraverseDecl( compiler.getASTContext().getTranslationUnitDecl());
+ }
+
+bool Tutorial3::VisitIfStmt( const 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( const 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 > tutorial3( "tutorial3" );
+
+} // namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/compilerplugins/clang/store/tutorial/tutorial3.hxx b/compilerplugins/clang/store/tutorial/tutorial3.hxx
new file mode 100644
index 000000000..11378ef76
--- /dev/null
+++ b/compilerplugins/clang/store/tutorial/tutorial3.hxx
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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.
+ *
+ */
+
+#pragma once
+
+#include "plugin.hxx"
+
+namespace loplugin
+{
+
+// Similar like for Tutorial2, but this time the base class is RewritePlugin.
+class Tutorial3
+ : public loplugin::FilteringRewritePlugin< Tutorial3 >
+ {
+ public:
+ // One more argument for ctor.
+ Tutorial3( const InstantiationData& data );
+ virtual void run() override;
+ // Will be called for every if statement.
+ bool VisitIfStmt( const IfStmt* ifstmt );
+ private:
+ // Helper function to check if the statement is 'return false;' and
+ // modify it if yes.
+ void modifyReturnFalse( const Stmt* stmt );
+ };
+
+} // namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */