Mercurial > hg > CbC > CbC_llvm
view clang-tools-extra/clang-tidy/readability/RedundantPreprocessorCheck.cpp @ 236:c4bab56944e8 llvm-original
LLVM 16
author | kono |
---|---|
date | Wed, 09 Nov 2022 17:45:10 +0900 |
parents | 79ff65ed7e25 |
children | 1f2b6ac9f198 |
line wrap: on
line source
//===--- RedundantPreprocessorCheck.cpp - clang-tidy ----------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "RedundantPreprocessorCheck.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Lex/Lexer.h" #include "clang/Lex/PPCallbacks.h" #include "clang/Lex/Preprocessor.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; }; const char WarningDescription[] = "nested redundant %select{#if|#ifdef|#ifndef}0; consider removing it"; const char NoteDescription[] = "previous %select{#if|#ifdef|#ifndef}0 was here"; 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) {} 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, std::string(MacroName)}); } ClangTidyCheck &Check; Preprocessor &PP; SmallVector<PreprocessorEntry, 4> IfStack; SmallVector<PreprocessorEntry, 4> IfdefStack; SmallVector<PreprocessorEntry, 4> IfndefStack; }; } // namespace void RedundantPreprocessorCheck::registerPPCallbacks( const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) { PP->addPPCallbacks( ::std::make_unique<RedundantPreprocessorCallbacks>(*this, *PP)); } } // namespace readability } // namespace tidy } // namespace clang