10#include "clang/AST/ASTContext.h"
11#include "clang/Lex/PPCallbacks.h"
12#include "clang/Lex/Preprocessor.h"
19struct AvoidUnconditionalPreprocessorIfPPCallbacks :
public PPCallbacks {
21 explicit AvoidUnconditionalPreprocessorIfPPCallbacks(ClangTidyCheck &Check,
23 : Check(Check), PP(PP) {}
25 void If(SourceLocation
Loc, SourceRange ConditionRange,
29 SourceManager &SM = PP.getSourceManager();
30 if (!isImmutable(SM, PP.getLangOpts(), ConditionRange))
34 Check.diag(
Loc,
"preprocessor condition is always 'true', consider "
35 "removing condition but leaving its contents");
37 Check.diag(
Loc,
"preprocessor condition is always 'false', consider "
38 "removing both the condition and its contents");
41 bool isImmutable(SourceManager &SM,
const LangOptions &LangOpts,
42 SourceRange ConditionRange) {
43 SourceLocation
Loc = ConditionRange.getBegin();
48 if (Lexer::getRawToken(
Loc, Tok, SM, LangOpts,
true)) {
49 std::optional<Token> TokOpt = Lexer::findNextToken(
Loc, SM, LangOpts);
50 if (!TokOpt || TokOpt->getLocation().isMacroID())
55 while (Tok.getLocation() <= ConditionRange.getEnd()) {
56 if (!isImmutableToken(Tok))
59 std::optional<Token> TokOpt =
60 Lexer::findNextToken(Tok.getLocation(), SM, LangOpts);
61 if (!TokOpt || TokOpt->getLocation().isMacroID())
69 bool isImmutableToken(
const Token &Tok) {
70 switch (Tok.getKind()) {
73 case tok::numeric_constant:
74 case tok::char_constant:
75 case tok::wide_char_constant:
76 case tok::utf8_char_constant:
77 case tok::utf16_char_constant:
78 case tok::utf32_char_constant:
79 case tok::string_literal:
80 case tok::wide_string_literal:
83 case tok::raw_identifier:
84 return (Tok.getRawIdentifier() ==
"true" ||
85 Tok.getRawIdentifier() ==
"false");
87 return Tok.getKind() >= tok::l_square && Tok.getKind() <= tok::caretcaret;
91 ClangTidyCheck &Check;
98 const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
100 std::make_unique<AvoidUnconditionalPreprocessorIfPPCallbacks>(*
this,
clang::PPCallbacks::ConditionValueKind ConditionValue
void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) override
Override this to register PPCallbacks in the preprocessor.