brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.4 KiB · 9fc8185 Raw
105 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "AvoidUnconditionalPreprocessorIfCheck.h"10#include "clang/AST/ASTContext.h"11#include "clang/Lex/PPCallbacks.h"12#include "clang/Lex/Preprocessor.h"13 14using namespace clang::ast_matchers;15 16namespace clang::tidy::readability {17 18namespace {19struct AvoidUnconditionalPreprocessorIfPPCallbacks : public PPCallbacks {20  explicit AvoidUnconditionalPreprocessorIfPPCallbacks(ClangTidyCheck &Check,21                                                       Preprocessor &PP)22      : Check(Check), PP(PP) {}23 24  void If(SourceLocation Loc, SourceRange ConditionRange,25          ConditionValueKind ConditionValue) override {26    if (ConditionValue == CVK_NotEvaluated)27      return;28    SourceManager &SM = PP.getSourceManager();29    if (!isImmutable(SM, PP.getLangOpts(), ConditionRange))30      return;31 32    if (ConditionValue == CVK_True)33      Check.diag(Loc, "preprocessor condition is always 'true', consider "34                      "removing condition but leaving its contents");35    else36      Check.diag(Loc, "preprocessor condition is always 'false', consider "37                      "removing both the condition and its contents");38  }39 40  bool isImmutable(SourceManager &SM, const LangOptions &LangOpts,41                   SourceRange ConditionRange) {42    const SourceLocation Loc = ConditionRange.getBegin();43    if (Loc.isMacroID())44      return false;45 46    Token Tok;47    if (Lexer::getRawToken(Loc, Tok, SM, LangOpts, true)) {48      std::optional<Token> TokOpt = Lexer::findNextToken(Loc, SM, LangOpts);49      if (!TokOpt || TokOpt->getLocation().isMacroID())50        return false;51      Tok = *TokOpt;52    }53 54    while (Tok.getLocation() <= ConditionRange.getEnd()) {55      if (!isImmutableToken(Tok))56        return false;57 58      std::optional<Token> TokOpt =59          Lexer::findNextToken(Tok.getLocation(), SM, LangOpts);60      if (!TokOpt || TokOpt->getLocation().isMacroID())61        return false;62      Tok = *TokOpt;63    }64 65    return true;66  }67 68  bool isImmutableToken(const Token &Tok) {69    switch (Tok.getKind()) {70    case tok::eod:71    case tok::eof:72    case tok::numeric_constant:73    case tok::char_constant:74    case tok::wide_char_constant:75    case tok::utf8_char_constant:76    case tok::utf16_char_constant:77    case tok::utf32_char_constant:78    case tok::string_literal:79    case tok::wide_string_literal:80    case tok::comment:81      return true;82    case tok::raw_identifier:83      return (Tok.getRawIdentifier() == "true" ||84              Tok.getRawIdentifier() == "false");85    default:86      return Tok.getKind() >= tok::l_square &&87             Tok.getKind() <= tok::greatergreatergreater;88    }89  }90 91  ClangTidyCheck &Check;92  Preprocessor &PP;93};94 95} // namespace96 97void AvoidUnconditionalPreprocessorIfCheck::registerPPCallbacks(98    const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {99  PP->addPPCallbacks(100      std::make_unique<AvoidUnconditionalPreprocessorIfPPCallbacks>(*this,101                                                                    *PP));102}103 104} // namespace clang::tidy::readability105