11 #include "clang/Frontend/CompilerInstance.h" 15 namespace readability {
19 struct PreprocessorEntry {
25 class RedundantPreprocessorCallbacks :
public PPCallbacks {
26 enum DirectiveKind { DK_If = 0, DK_Ifdef = 1, DK_Ifndef = 2 };
29 explicit RedundantPreprocessorCallbacks(ClangTidyCheck &Check,
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") {}
36 void If(SourceLocation
Loc, SourceRange ConditionRange,
39 Lexer::getSourceText(CharSourceRange::getTokenRange(ConditionRange),
40 PP.getSourceManager(), PP.getLangOpts());
41 CheckMacroRedundancy(Loc, Condition, IfStack, DK_If, DK_If,
true);
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,
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,
57 CheckMacroRedundancy(Loc, MacroName, IfdefStack, DK_Ifndef, DK_Ifdef,
61 void Endif(SourceLocation Loc, SourceLocation IfLoc)
override {
62 if (!IfStack.empty() && IfLoc == IfStack.back().Loc)
64 if (!IfdefStack.empty() && IfLoc == IfdefStack.back().Loc)
65 IfdefStack.pop_back();
66 if (!IfndefStack.empty() && IfLoc == IfndefStack.back().Loc)
67 IfndefStack.pop_back();
71 void CheckMacroRedundancy(SourceLocation Loc, StringRef MacroName,
72 SmallVector<PreprocessorEntry, 4> &Stack,
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)
87 Stack.push_back({
Loc, MacroName});
90 ClangTidyCheck &Check;
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;
101 CompilerInstance &Compiler) {
102 Compiler.getPreprocessor().addPPCallbacks(
103 ::llvm::make_unique<RedundantPreprocessorCallbacks>(
104 *
this, Compiler.getPreprocessor()));
clang::tok::PPKeywordKind DirectiveKind
void registerPPCallbacks(CompilerInstance &Compiler) override
Override this to register PPCallbacks with Compiler.
clang::PPCallbacks::ConditionValueKind ConditionValue
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::string Condition
Condition used after the preprocessor directive.