diff options
author | Luboš Luňák <l.lunak@suse.cz> | 2012-10-09 14:50:19 +0200 |
---|---|---|
committer | Luboš Luňák <l.lunak@suse.cz> | 2012-10-09 17:25:27 +0200 |
commit | 13e39545eac66b628f9ef3c89cc03d2003e5d317 (patch) | |
tree | 0b29dc22c823d46c69782c5510bc0a340fcf9abe /compilerplugins | |
parent | 02a8d36ebf3d54784903f2899eafe010bedf2f4c (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.mk | 2 | ||||
-rw-r--r-- | compilerplugins/README | 7 | ||||
-rw-r--r-- | compilerplugins/clang/compileplugin.cxx | 5 | ||||
-rw-r--r-- | compilerplugins/clang/unusedvariablecheck.cxx | 112 | ||||
-rw-r--r-- | compilerplugins/clang/unusedvariablecheck.hxx | 35 |
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 |