1 //===--- AvoidUnconditionalPreprocessorIfCheck.cpp - clang-tidy -----------===//
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-exception
7 //===----------------------------------------------------------------------===//
9 #include "AvoidUnconditionalPreprocessorIfCheck.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/Lex/PPCallbacks.h"
12 #include "clang/Lex/Preprocessor.h"
14 using namespace clang::ast_matchers
;
16 namespace clang::tidy::readability
{
19 struct AvoidUnconditionalPreprocessorIfPPCallbacks
: public PPCallbacks
{
21 explicit AvoidUnconditionalPreprocessorIfPPCallbacks(ClangTidyCheck
&Check
,
23 : Check(Check
), PP(PP
) {}
25 void If(SourceLocation Loc
, SourceRange ConditionRange
,
26 ConditionValueKind ConditionValue
) override
{
27 if (ConditionValue
== CVK_NotEvaluated
)
29 SourceManager
&SM
= PP
.getSourceManager();
30 if (!isImmutable(SM
, PP
.getLangOpts(), ConditionRange
))
33 if (ConditionValue
== CVK_True
)
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
&&
88 Tok
.getKind() <= tok::greatergreatergreater
;
92 ClangTidyCheck
&Check
;
98 void AvoidUnconditionalPreprocessorIfCheck::registerPPCallbacks(
99 const SourceManager
&SM
, Preprocessor
*PP
, Preprocessor
*ModuleExpanderPP
) {
101 std::make_unique
<AvoidUnconditionalPreprocessorIfPPCallbacks
>(*this,
105 } // namespace clang::tidy::readability