diff options
author | Miklos Vajna <vmiklos@vmiklos.hu> | 2019-01-11 07:59:47 +0000 |
---|---|---|
committer | Miklos Vajna <vmiklos@vmiklos.hu> | 2019-01-11 07:59:47 +0000 |
commit | 98ef5337c9dfab72ad8f93a83b6429dfd0da168e (patch) | |
tree | ca8a7fb7c972c6b88dcf918f44ff6b2358864325 /clang-tools-extra/clang-tidy | |
parent | 114ad37c1dc805e1dfd694e076257f87f1b705d0 (diff) | |
download | llvm-98ef5337c9dfab72ad8f93a83b6429dfd0da168e.zip llvm-98ef5337c9dfab72ad8f93a83b6429dfd0da168e.tar.gz llvm-98ef5337c9dfab72ad8f93a83b6429dfd0da168e.tar.bz2 |
[clang-tidy] new check 'readability-redundant-preprocessor'
Finds potentially redundant preprocessor directives.
Reviewed By: aaron.ballman
Differential Revision: https://reviews.llvm.org/D54349
llvm-svn: 350922
Diffstat (limited to 'clang-tools-extra/clang-tidy')
4 files changed, 148 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt index c429b81..b48e307e 100644 --- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt @@ -24,6 +24,7 @@ add_clang_library(clangTidyReadabilityModule RedundantDeclarationCheck.cpp RedundantFunctionPtrDereferenceCheck.cpp RedundantMemberInitCheck.cpp + RedundantPreprocessorCheck.cpp RedundantSmartptrGetCheck.cpp RedundantStringCStrCheck.cpp RedundantStringInitCheck.cpp diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp index 8dab296..e032d1f 100644 --- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp @@ -31,6 +31,7 @@ #include "RedundantDeclarationCheck.h" #include "RedundantFunctionPtrDereferenceCheck.h" #include "RedundantMemberInitCheck.h" +#include "RedundantPreprocessorCheck.h" #include "RedundantSmartptrGetCheck.h" #include "RedundantStringCStrCheck.h" #include "RedundantStringInitCheck.h" @@ -83,6 +84,8 @@ public: "readability-redundant-function-ptr-dereference"); CheckFactories.registerCheck<RedundantMemberInitCheck>( "readability-redundant-member-init"); + CheckFactories.registerCheck<RedundantPreprocessorCheck>( + "readability-redundant-preprocessor"); CheckFactories.registerCheck<SimplifySubscriptExprCheck>( "readability-simplify-subscript-expr"); CheckFactories.registerCheck<StaticAccessedThroughInstanceCheck>( diff --git a/clang-tools-extra/clang-tidy/readability/RedundantPreprocessorCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantPreprocessorCheck.cpp new file mode 100644 index 0000000..352e234 --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/RedundantPreprocessorCheck.cpp @@ -0,0 +1,109 @@ +//===--- RedundantPreprocessorCheck.cpp - clang-tidy ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "RedundantPreprocessorCheck.h" +#include "clang/Frontend/CompilerInstance.h" + +namespace clang { +namespace tidy { +namespace readability { + +namespace { +/// Information about an opening preprocessor directive. +struct PreprocessorEntry { + SourceLocation Loc; + /// Condition used after the preprocessor directive. + std::string Condition; +}; + +class RedundantPreprocessorCallbacks : public PPCallbacks { + enum DirectiveKind { DK_If = 0, DK_Ifdef = 1, DK_Ifndef = 2 }; + +public: + explicit RedundantPreprocessorCallbacks(ClangTidyCheck &Check, + Preprocessor &PP) + : Check(Check), PP(PP), + WarningDescription("nested redundant %select{#if|#ifdef|#ifndef}0; " + "consider removing it"), + NoteDescription("previous %select{#if|#ifdef|#ifndef}0 was here") {} + + void If(SourceLocation Loc, SourceRange ConditionRange, + ConditionValueKind ConditionValue) override { + StringRef Condition = + Lexer::getSourceText(CharSourceRange::getTokenRange(ConditionRange), + PP.getSourceManager(), PP.getLangOpts()); + CheckMacroRedundancy(Loc, Condition, IfStack, DK_If, DK_If, true); + } + + void Ifdef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDefinition &MacroDefinition) override { + std::string MacroName = PP.getSpelling(MacroNameTok); + CheckMacroRedundancy(Loc, MacroName, IfdefStack, DK_Ifdef, DK_Ifdef, true); + CheckMacroRedundancy(Loc, MacroName, IfndefStack, DK_Ifdef, DK_Ifndef, + false); + } + + void Ifndef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDefinition &MacroDefinition) override { + std::string MacroName = PP.getSpelling(MacroNameTok); + CheckMacroRedundancy(Loc, MacroName, IfndefStack, DK_Ifndef, DK_Ifndef, + true); + CheckMacroRedundancy(Loc, MacroName, IfdefStack, DK_Ifndef, DK_Ifdef, + false); + } + + void Endif(SourceLocation Loc, SourceLocation IfLoc) override { + if (!IfStack.empty() && IfLoc == IfStack.back().Loc) + IfStack.pop_back(); + if (!IfdefStack.empty() && IfLoc == IfdefStack.back().Loc) + IfdefStack.pop_back(); + if (!IfndefStack.empty() && IfLoc == IfndefStack.back().Loc) + IfndefStack.pop_back(); + } + +private: + void CheckMacroRedundancy(SourceLocation Loc, StringRef MacroName, + SmallVector<PreprocessorEntry, 4> &Stack, + DirectiveKind WarningKind, DirectiveKind NoteKind, + bool Store) { + if (PP.getSourceManager().isInMainFile(Loc)) { + for (const auto &Entry : Stack) { + if (Entry.Condition == MacroName) { + Check.diag(Loc, WarningDescription) << WarningKind; + Check.diag(Entry.Loc, NoteDescription, DiagnosticIDs::Note) + << NoteKind; + } + } + } + + if (Store) + // This is an actual directive to be remembered. + Stack.push_back({Loc, MacroName}); + } + + ClangTidyCheck &Check; + Preprocessor &PP; + SmallVector<PreprocessorEntry, 4> IfStack; + SmallVector<PreprocessorEntry, 4> IfdefStack; + SmallVector<PreprocessorEntry, 4> IfndefStack; + const std::string WarningDescription; + const std::string NoteDescription; +}; +} // namespace + +void RedundantPreprocessorCheck::registerPPCallbacks( + CompilerInstance &Compiler) { + Compiler.getPreprocessor().addPPCallbacks( + ::llvm::make_unique<RedundantPreprocessorCallbacks>( + *this, Compiler.getPreprocessor())); +} + +} // namespace readability +} // namespace tidy +} // namespace clang diff --git a/clang-tools-extra/clang-tidy/readability/RedundantPreprocessorCheck.h b/clang-tools-extra/clang-tidy/readability/RedundantPreprocessorCheck.h new file mode 100644 index 0000000..d440765 --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/RedundantPreprocessorCheck.h @@ -0,0 +1,35 @@ +//===--- RedundantPreprocessorCheck.h - clang-tidy --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTPREPROCESSORCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTPREPROCESSORCHECK_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace readability { + +/// This check flags redundant preprocessor directives: nested directives with +/// the same condition. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/readability-redundant-preprocessor.html +class RedundantPreprocessorCheck : public ClangTidyCheck { +public: + RedundantPreprocessorCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerPPCallbacks(CompilerInstance &Compiler) override; +}; + +} // namespace readability +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTPREPROCESSORCHECK_H |