summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@suse.cz>2012-10-09 14:50:19 +0200
committerLuboš Luňák <l.lunak@suse.cz>2012-10-09 17:25:27 +0200
commit13e39545eac66b628f9ef3c89cc03d2003e5d317 (patch)
tree0b29dc22c823d46c69782c5510bc0a340fcf9abe /compilerplugins
parent02a8d36ebf3d54784903f2899eafe010bedf2f4c (diff)
compiler check for unused variables
This is for variables that the compiler itself cannot figure out (e.g. non-trivial ctors). The classes need to be marked manually. Change-Id: I0109972e11e20578b1adc32065f701a871ee21aa
Diffstat (limited to 'compilerplugins')
-rw-r--r--compilerplugins/Makefile-clang.mk2
-rw-r--r--compilerplugins/README7
-rw-r--r--compilerplugins/clang/compileplugin.cxx5
-rw-r--r--compilerplugins/clang/unusedvariablecheck.cxx112
-rw-r--r--compilerplugins/clang/unusedvariablecheck.hxx35
5 files changed, 160 insertions, 1 deletions
diff --git a/compilerplugins/Makefile-clang.mk b/compilerplugins/Makefile-clang.mk
index 1797e424ddb1..9b37fb9939c7 100644
--- a/compilerplugins/Makefile-clang.mk
+++ b/compilerplugins/Makefile-clang.mk
@@ -9,7 +9,7 @@
# Make sure variables in this Makefile do not conflict with other variables (e.g. from gbuild).
# The list of source files.
-CLANGSRC=compileplugin.cxx
+CLANGSRC=compileplugin.cxx unusedvariablecheck.cxx
# You may occassionally want to override some of these
diff --git a/compilerplugins/README b/compilerplugins/README
index 98ac70c85ef5..2430d40fb72e 100644
--- a/compilerplugins/README
+++ b/compilerplugins/README
@@ -21,6 +21,13 @@ are found or explicitly using --enable-compiler-plugins.
The compile plugin is used during normal compilation to perform additional checks.
All warnings and errors are marked '[loplugin]' in the message.
+==== Unused variable check ====
+
+- unused parameter 'foo' [loplugin]
+- unused variable 'foo' [loplugin]
+
+Additional check for unused variables.
+
== Code documentation / howtos ==
diff --git a/compilerplugins/clang/compileplugin.cxx b/compilerplugins/clang/compileplugin.cxx
index fb2632e3d2cd..2b1647560117 100644
--- a/compilerplugins/clang/compileplugin.cxx
+++ b/compilerplugins/clang/compileplugin.cxx
@@ -17,6 +17,8 @@
#include <clang/Frontend/FrontendPluginRegistry.h>
#include <clang/Rewrite/Rewriter.h>
+#include "unusedvariablecheck.hxx"
+
using namespace clang;
namespace loplugin
@@ -31,12 +33,14 @@ class PluginHandler
public:
explicit PluginHandler( ASTContext& context )
: rewriter( context.getSourceManager(), context.getLangOpts())
+ , unusedVariableCheck( context )
{
}
virtual void HandleTranslationUnit( ASTContext& context )
{
if( context.getDiagnostics().hasErrorOccurred())
return;
+ unusedVariableCheck.run();
// TODO also LO header files? or a subdir?
if( const RewriteBuffer* buf = rewriter.getRewriteBufferFor( context.getSourceManager().getMainFileID()))
buf->write( llvm::outs());
@@ -44,6 +48,7 @@ class PluginHandler
}
private:
Rewriter rewriter;
+ UnusedVariableCheck unusedVariableCheck;
};
/**
diff --git a/compilerplugins/clang/unusedvariablecheck.cxx b/compilerplugins/clang/unusedvariablecheck.cxx
new file mode 100644
index 000000000000..029e637b578c
--- /dev/null
+++ b/compilerplugins/clang/unusedvariablecheck.cxx
@@ -0,0 +1,112 @@
+/*
+ * 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 "unusedvariablecheck.hxx"
+
+#include <clang/Basic/SourceManager.h>
+
+using namespace clang;
+
+namespace loplugin
+{
+
+/*
+Check for unused classes where the compiler cannot decide (e.g. because of
+non-trivial or extern ctors) if a variable is unused if only its ctor/dtor
+are called and nothing else. For example std::vector is a class where
+the ctor may call further functions, but an unused std::string variable
+does nothing. On the other hand, std::auto_ptr instances are used
+for their dtors and so are not unused even if not otherwise accessed.
+
+Classes which are safe to be warned about need to be marked using
+SAL_WARN_UNUSED (see e.g. OUString). For external classes such as std::vector
+that cannot be edited there is a manual list below.
+*/
+
+UnusedVariableCheck::UnusedVariableCheck( ASTContext& context )
+ : context( context )
+ {
+ }
+
+void UnusedVariableCheck::run()
+ {
+ TraverseDecl( context.getTranslationUnitDecl());
+ }
+
+DiagnosticBuilder UnusedVariableCheck::report( DiagnosticsEngine::Level level, StringRef message, SourceLocation loc )
+ {
+ // Do some mappings (e.g. for -Werror) that clang does not do for custom messages for some reason.
+ DiagnosticsEngine& diag = context.getDiagnostics();
+ if( level == DiagnosticsEngine::Warning && diag.getWarningsAsErrors())
+ level = DiagnosticsEngine::Error;
+ if( level == DiagnosticsEngine::Error && diag.getErrorsAsFatal())
+ level = DiagnosticsEngine::Fatal;
+ return diag.Report( loc, diag.getCustomDiagID( level, message ));
+ }
+
+bool UnusedVariableCheck::VisitNamedDecl( NamedDecl* declaration )
+ {
+ // TODO also LO header files? or a subdir?
+ if( !context.getSourceManager().isFromMainFile( declaration->getLocStart()))
+ return true;
+ if( !isa< VarDecl >( declaration ))
+ return true;
+ const VarDecl* var = cast< VarDecl >( declaration );
+ if( var->isReferenced() || var->isUsed())
+ return true;
+ if( CXXRecordDecl* type = var->getType()->getAsCXXRecordDecl())
+ {
+ bool warn_unused = false;
+ if( type->hasAttrs())
+ {
+ // Clang currently has no support for custom attributes, but
+ // the annotate attribute comes close, so check for __attribute__((annotate("lo_warn_unused")))
+ for( specific_attr_iterator<AnnotateAttr> i = type->specific_attr_begin<AnnotateAttr>(),
+ e = type->specific_attr_end<AnnotateAttr>();
+ i != e;
+ ++i )
+ {
+ if( (*i)->getAnnotation() == "lo_warn_unused" )
+ {
+ warn_unused = true;
+ break;
+ }
+ }
+ }
+ if( !warn_unused )
+ {
+ std::string n = type->getQualifiedNameAsString();
+ // Check some common non-LO types.
+ if( n == "std::string" || n == "std::basic_string"
+ || n == "std::list" || n == "std::__debug::list"
+ || n == "std::vector" || n == "std::__debug::vector" )
+ warn_unused = true;
+ }
+ if( warn_unused )
+ {
+ if( const ParmVarDecl* param = dyn_cast< ParmVarDecl >( var ))
+ {
+ // If this declaration does not have a body, then the parameter is indeed not used,
+ // so ignore.
+ if( const FunctionDecl* func = dyn_cast< FunctionDecl >( param->getParentFunctionOrMethod()))
+ if( !func->doesThisDeclarationHaveABody())
+ return true;
+ report( DiagnosticsEngine::Warning, "unused parameter %0 [loplugin]",
+ var->getLocStart()) << var->getDeclName();
+ }
+ else
+ report( DiagnosticsEngine::Warning, "unused variable %0 [loplugin]",
+ var->getLocStart()) << var->getDeclName();
+ }
+ }
+ return true;
+ }
+
+} // namespace
diff --git a/compilerplugins/clang/unusedvariablecheck.hxx b/compilerplugins/clang/unusedvariablecheck.hxx
new file mode 100644
index 000000000000..c49532a86414
--- /dev/null
+++ b/compilerplugins/clang/unusedvariablecheck.hxx
@@ -0,0 +1,35 @@
+/*
+ * 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 UNUSEDVARIABLECHECK_H
+#define UNUSEDVARIABLECHECK_H
+
+#include <clang/AST/RecursiveASTVisitor.h>
+
+using namespace clang;
+
+namespace loplugin
+{
+
+class UnusedVariableCheck
+ : public RecursiveASTVisitor< UnusedVariableCheck >
+ {
+ public:
+ explicit UnusedVariableCheck( ASTContext& context );
+ void run();
+ bool VisitNamedDecl( NamedDecl* declaration );
+ private:
+ DiagnosticBuilder report( DiagnosticsEngine::Level level, StringRef message, SourceLocation loc );
+ ASTContext& context;
+ };
+
+} // namespace
+
+#endif // UNUSEDVARIABLECHECK_H