10 #include "clang/Frontend/CompilerInstance.h" 14 namespace readability {
18 struct PreprocessorEntry {
24 class RedundantPreprocessorCallbacks :
public PPCallbacks {
25 enum DirectiveKind { DK_If = 0, DK_Ifdef = 1, DK_Ifndef = 2 };
28 explicit RedundantPreprocessorCallbacks(ClangTidyCheck &Check,
30 : Check(Check), PP(PP),
31 WarningDescription(
"nested redundant %select{#if|#ifdef|#ifndef}0; " 32 "consider removing it"),
33 NoteDescription(
"previous %select{#if|#ifdef|#ifndef}0 was here") {}
35 void If(SourceLocation
Loc, SourceRange ConditionRange,
39 PP.getSourceManager(), PP.getLangOpts());
40 CheckMacroRedundancy(Loc, Condition, IfStack, DK_If, DK_If,
true);
43 void Ifdef(SourceLocation Loc,
const Token &MacroNameTok,
44 const MacroDefinition &MacroDefinition)
override {
45 std::string MacroName = PP.getSpelling(MacroNameTok);
46 CheckMacroRedundancy(Loc, MacroName, IfdefStack, DK_Ifdef, DK_Ifdef,
true);
47 CheckMacroRedundancy(Loc, MacroName, IfndefStack, DK_Ifdef, DK_Ifndef,
51 void Ifndef(SourceLocation Loc,
const Token &MacroNameTok,
52 const MacroDefinition &MacroDefinition)
override {
53 std::string MacroName = PP.getSpelling(MacroNameTok);
54 CheckMacroRedundancy(Loc, MacroName, IfndefStack, DK_Ifndef, DK_Ifndef,
56 CheckMacroRedundancy(Loc, MacroName, IfdefStack, DK_Ifndef, DK_Ifdef,
60 void Endif(SourceLocation Loc, SourceLocation IfLoc)
override {
61 if (!IfStack.empty() && IfLoc == IfStack.back().Loc)
63 if (!IfdefStack.empty() && IfLoc == IfdefStack.back().Loc)
64 IfdefStack.pop_back();
65 if (!IfndefStack.empty() && IfLoc == IfndefStack.back().Loc)
66 IfndefStack.pop_back();
70 void CheckMacroRedundancy(SourceLocation Loc, StringRef MacroName,
71 SmallVector<PreprocessorEntry, 4> &Stack,
74 if (PP.getSourceManager().isInMainFile(Loc)) {
75 for (
const auto &
Entry : Stack) {
76 if (
Entry.Condition == MacroName) {
77 Check.diag(Loc, WarningDescription) << WarningKind;
78 Check.diag(
Entry.
Loc, NoteDescription, DiagnosticIDs::Note)
86 Stack.push_back({
Loc, MacroName});
89 ClangTidyCheck &Check;
91 SmallVector<PreprocessorEntry, 4> IfStack;
92 SmallVector<PreprocessorEntry, 4> IfdefStack;
93 SmallVector<PreprocessorEntry, 4> IfndefStack;
94 const std::string WarningDescription;
95 const std::string NoteDescription;
100 const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
102 ::std::make_unique<RedundantPreprocessorCallbacks>(*
this, *PP));
clang::tok::PPKeywordKind DirectiveKind
llvm::Optional< Range > getTokenRange(const SourceManager &SM, const LangOptions &LangOpts, SourceLocation TokLoc)
Returns the taken range at TokLoc.
clang::PPCallbacks::ConditionValueKind ConditionValue
void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) override
Override this to register PPCallbacks in the preprocessor.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::string Condition
Condition used after the preprocessor directive.