10#include "clang/AST/ASTContext.h"
11#include "clang/Lex/PPCallbacks.h"
12#include "clang/Lex/Preprocessor.h"
19struct AvoidUnconditionalPreprocessorIfPPCallbacks :
public PPCallbacks {
20 explicit AvoidUnconditionalPreprocessorIfPPCallbacks(ClangTidyCheck &Check,
22 : Check(Check), PP(PP) {}
24 void If(SourceLocation Loc, SourceRange ConditionRange,
25 ConditionValueKind ConditionValue)
override {
26 if (ConditionValue == CVK_NotEvaluated)
28 SourceManager &SM = PP.getSourceManager();
29 if (!isImmutable(SM, PP.getLangOpts(), ConditionRange))
32 if (ConditionValue == CVK_True)
33 Check.diag(Loc,
"preprocessor condition is always 'true', consider "
34 "removing condition but leaving its contents");
36 Check.diag(Loc,
"preprocessor condition is always 'false', consider "
37 "removing both the condition and its contents");
40 bool isImmutable(SourceManager &SM,
const LangOptions &LangOpts,
41 SourceRange ConditionRange) {
42 const SourceLocation Loc = ConditionRange.getBegin();
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())
54 while (Tok.getLocation() <= ConditionRange.getEnd()) {
55 if (!isImmutableToken(Tok))
58 std::optional<Token> TokOpt =
59 Lexer::findNextToken(Tok.getLocation(), SM, LangOpts);
60 if (!TokOpt || TokOpt->getLocation().isMacroID())
68 bool isImmutableToken(
const Token &Tok) {
69 switch (Tok.getKind()) {
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:
82 case tok::raw_identifier:
83 return (Tok.getRawIdentifier() ==
"true" ||
84 Tok.getRawIdentifier() ==
"false");
86 return Tok.getKind() >= tok::l_square &&
87 Tok.getKind() <= tok::greatergreatergreater;
91 ClangTidyCheck &Check;
98 const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
100 std::make_unique<AvoidUnconditionalPreprocessorIfPPCallbacks>(*
this,
void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) override