77// ===----------------------------------------------------------------------===//
88
99#include " TrueMacroCheck.h"
10- #include " clang/ASTMatchers/ASTMatchFinder.h"
1110#include " clang/Lex/MacroInfo.h"
1211#include " clang/Lex/PPCallbacks.h"
1312#include " clang/Lex/Preprocessor.h"
14- #include < iostream>
1513
1614using namespace clang ::ast_matchers;
1715
@@ -22,11 +20,20 @@ class MacroCallback : public PPCallbacks {
2220 static constexpr const char *TrueMacroSpelling = " true" ;
2321
2422public:
25- MacroCallback (TrueMacroCheck *Check, const SourceManager &SM,
26- Preprocessor *PP)
27- : Check(Check), SM(&SM), PP(PP) {}
23+ MacroCallback (TrueMacroCheck *Check, Preprocessor *PP)
24+ : Check(Check), PP(PP) {}
2825 void MacroDefined (const Token &MacroNameTok,
2926 const MacroDirective *MD) override {
27+ if (TrueDefined)
28+ return ;
29+
30+ const MacroInfo *MI = MD->getMacroInfo ();
31+ for (const Token &Tok : MI->tokens ()) {
32+ if (PP->getSpelling (Tok) == TrueMacroSpelling)
33+ emitDiagnostics (Tok.getLocation (),
34+ {Tok.getLocation (), Tok.getEndLoc ()});
35+ }
36+
3037 if (PP->getSpelling (MacroNameTok) == TrueMacroSpelling)
3138 TrueDefined = true ;
3239 }
@@ -44,12 +51,32 @@ class MacroCallback : public PPCallbacks {
4451 Lexer::getSourceText (CharSourceRange::getTokenRange (ConditionRange),
4552 PP->getSourceManager (), PP->getLangOpts ());
4653
47- for (auto &&Identifier : identifiersInCondition (Condition))
48- std::cout << Identifier.str () << ' ' << Identifier.size () << ' \n ' ;
54+ if (!TrueDefined && Condition == TrueMacroSpelling) {
55+ emitDiagnostics (ConditionRange.getBegin (), ConditionRange);
56+ return ;
57+ }
58+
59+ for (auto &&Identifier : identifiersInCondition (Condition)) {
60+ if (!TrueDefined && Identifier == TrueMacroSpelling) {
61+ emitDiagnostics (Loc, {}, true );
62+ break ;
63+ }
64+ }
4965 }
5066
5167private:
52- void emitDiagnostic () {}
68+ void emitDiagnostics (SourceLocation Loc, SourceRange ReplaceRange,
69+ bool InCondition = false ) {
70+ DiagnosticBuilder Builder =
71+ Check->diag (Loc, " in C 'true'%select{| in the condition}0 is treated "
72+ " as an undefined "
73+ " macro and evaluates to a falsy value; "
74+ " consider replacing it with '1'" )
75+ << InCondition;
76+
77+ if (!InCondition)
78+ Builder << FixItHint::CreateReplacement (ReplaceRange, " 1" );
79+ }
5380
5481 std::vector<StringRef> identifiersInCondition (StringRef Condition) {
5582 const static auto Start = [](char C) {
@@ -83,15 +110,14 @@ class MacroCallback : public PPCallbacks {
83110 bool TrueDefined = false ;
84111
85112 TrueMacroCheck *Check;
86- const SourceManager *SM;
87113 Preprocessor *PP;
88114};
89115} // namespace
90116
91117void TrueMacroCheck::registerPPCallbacks (const SourceManager &SM,
92118 Preprocessor *PP,
93119 Preprocessor *ModuleExpanderPP) {
94- PP->addPPCallbacks (std::make_unique<MacroCallback>(this , SM, PP));
120+ PP->addPPCallbacks (std::make_unique<MacroCallback>(this , PP));
95121}
96122
97123} // namespace clang::tidy::bugprone
0 commit comments