clang-tools 8.0.0

RedundantPreprocessorCheck.cpp
Go to the documentation of this file.
1 //===--- RedundantPreprocessorCheck.cpp - clang-tidy ----------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "RedundantPreprocessorCheck.h"
11 #include "clang/Frontend/CompilerInstance.h"
12
13 namespace clang {
14 namespace tidy {
15 namespace readability {
16
17 namespace {
18 /// Information about an opening preprocessor directive.
19 struct PreprocessorEntry {
20 SourceLocation Loc;
21 /// Condition used after the preprocessor directive.
22 std::string Condition;
23 };
24
25 class RedundantPreprocessorCallbacks : public PPCallbacks {
26 enum DirectiveKind { DK_If = 0, DK_Ifdef = 1, DK_Ifndef = 2 };
27
28 public:
29 explicit RedundantPreprocessorCallbacks(ClangTidyCheck &Check,
30 Preprocessor &PP)
31 : Check(Check), PP(PP),
32 WarningDescription("nested redundant %select{#if|#ifdef|#ifndef}0; "
33 "consider removing it"),
34 NoteDescription("previous %select{#if|#ifdef|#ifndef}0 was here") {}
35
36 void If(SourceLocation Loc, SourceRange ConditionRange,
37 ConditionValueKind ConditionValue) override {
38 StringRef Condition =
39 Lexer::getSourceText(CharSourceRange::getTokenRange(ConditionRange),
40 PP.getSourceManager(), PP.getLangOpts());
41 CheckMacroRedundancy(Loc, Condition, IfStack, DK_If, DK_If, true);
42 }
43
44 void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
45 const MacroDefinition &MacroDefinition) override {
46 std::string MacroName = PP.getSpelling(MacroNameTok);
47 CheckMacroRedundancy(Loc, MacroName, IfdefStack, DK_Ifdef, DK_Ifdef, true);
48 CheckMacroRedundancy(Loc, MacroName, IfndefStack, DK_Ifdef, DK_Ifndef,
49 false);
50 }
51
52 void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
53 const MacroDefinition &MacroDefinition) override {
54 std::string MacroName = PP.getSpelling(MacroNameTok);
55 CheckMacroRedundancy(Loc, MacroName, IfndefStack, DK_Ifndef, DK_Ifndef,
56 true);
57 CheckMacroRedundancy(Loc, MacroName, IfdefStack, DK_Ifndef, DK_Ifdef,
58 false);
59 }
60
61 void Endif(SourceLocation Loc, SourceLocation IfLoc) override {
62 if (!IfStack.empty() && IfLoc == IfStack.back().Loc)
63 IfStack.pop_back();
64 if (!IfdefStack.empty() && IfLoc == IfdefStack.back().Loc)
65 IfdefStack.pop_back();
66 if (!IfndefStack.empty() && IfLoc == IfndefStack.back().Loc)
67 IfndefStack.pop_back();
68 }
69
70 private:
71 void CheckMacroRedundancy(SourceLocation Loc, StringRef MacroName,
72 SmallVector<PreprocessorEntry, 4> &Stack,
73 DirectiveKind WarningKind, DirectiveKind NoteKind,
74 bool Store) {
75 if (PP.getSourceManager().isInMainFile(Loc)) {
76 for (const auto &Entry : Stack) {
77 if (Entry.Condition == MacroName) {
78 Check.diag(Loc, WarningDescription) << WarningKind;
79 Check.diag(Entry.Loc, NoteDescription, DiagnosticIDs::Note)
80 << NoteKind;
81 }
82 }
83 }
84
85 if (Store)
86 // This is an actual directive to be remembered.
87 Stack.push_back({Loc, MacroName});
88 }
89
90 ClangTidyCheck &Check;
91 Preprocessor &PP;
92 SmallVector<PreprocessorEntry, 4> IfStack;
93 SmallVector<PreprocessorEntry, 4> IfdefStack;
94 SmallVector<PreprocessorEntry, 4> IfndefStack;
95 const std::string WarningDescription;
96 const std::string NoteDescription;
97 };
98 } // namespace
99
100 void RedundantPreprocessorCheck::registerPPCallbacks(
101 CompilerInstance &Compiler) {
102 Compiler.getPreprocessor().addPPCallbacks(
103 ::llvm::make_unique<RedundantPreprocessorCallbacks>(
104 *this, Compiler.getPreprocessor()));
105 }
106
107 } // namespace readability
108 } // namespace tidy
109 } // namespace clang
Loc
SourceLocation Loc
Definition: RedundantPreprocessorCheck.cpp:20
DirectiveKind
clang::tok::PPKeywordKind DirectiveKind
Definition: PreprocessorTracker.cpp:721
Entry::Loc
Location Loc
Definition: Modularize.cpp:439
clang::tidy::readability::RedundantPreprocessorCheck::registerPPCallbacks
void registerPPCallbacks(CompilerInstance &Compiler) override
Override this to register PPCallbacks with Compiler.
Definition: RedundantPreprocessorCheck.cpp:100
PPCallbacks
ConditionValue
clang::PPCallbacks::ConditionValueKind ConditionValue
Definition: PreprocessorTracker.cpp:673
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ChangeNamespace.cpp:18
Condition
std::string Condition
Condition used after the preprocessor directive.
Definition: RedundantPreprocessorCheck.cpp:22
Entry
Definition: Modularize.cpp:430
RedundantPreprocessorCheck.h