@@ -38,8 +38,6 @@ void NumericlimitmaxcheckCheck::registerMatchers(MatchFinder *Finder) {
3838 if (!getLangOpts ().CPlusPlus )
3939 return ;
4040
41- // ... inside registerMatchers() ...
42-
4341 auto NegOneLiteral = integerLiteral (equals (-1 ));
4442 auto ZeroLiteral = integerLiteral (equals (0 ));
4543
@@ -73,48 +71,43 @@ void NumericlimitmaxcheckCheck::registerMatchers(MatchFinder *Finder) {
7371 auto UnsignedLiteralNegOne =
7472 integerLiteral (equals (-1 ), hasType (isUnsignedInteger ()));
7573
76- // *** ADD THIS NEW MATCHER ***
77- // Matches -1 or ~0 when they are a branch of a ternary operator
78- // that is itself being implicitly cast to unsigned.
74+ // To handle ternary branch case
7975 auto TernaryBranch =
8076 expr (anyOf (NegOneExpr, BitNotZero),
81- hasAncestor ( // <-- Use hasAncestor to look up the tree
82- conditionalOperator (
83- // Check that the conditional operator itself has an ancestor
84- // which is the implicit cast to unsigned
85- hasAncestor (implicitCastExpr (hasType (isUnsignedInteger ()))
77+ hasAncestor (conditionalOperator (
78+ hasAncestor (implicitCastExpr (hasType (isUnsignedInteger ()
79+ ))
8680 .bind (" outerCast" )))))
8781 .bind (" unsignedMaxExpr" );
8882
89- // *** MODIFY THIS PART ***
90- auto OldCombined =
83+ auto Combined =
9184 expr (anyOf (
9285 ExplicitCastOfNegOrBitnot,
9386 ImplicitNegOneToUnsigned,
9487 UnsignedBitNotZero,
9588 UnsignedLiteralNegOne
9689 )).bind (" unsignedMaxExpr" );
9790
98- Finder->addMatcher (OldCombined , this );
99- Finder->addMatcher (TernaryBranch, this ); // Add the new matcher
91+ Finder->addMatcher (Combined , this );
92+ Finder->addMatcher (TernaryBranch, this );
10093}
10194
10295
10396void NumericlimitmaxcheckCheck::check (const MatchFinder::MatchResult &Result) {
104- const auto *E = Result.Nodes .getNodeAs <Expr>(" unsignedMaxExpr" );
105- const auto *OuterCast = Result.Nodes .getNodeAs <CastExpr>(" outerCast" ); // Get the cast
97+ const auto *E = Result.Nodes .getNodeAs <Expr>(" unsignedMaxExpr" );
98+ const auto *OuterCast = Result.Nodes .getNodeAs <CastExpr>(" outerCast" );
10699
107100 if (!E)
108101 return ;
109102
110- ASTContext &Ctx = *Result.Context ; // Get context * before* first use
103+ ASTContext &Ctx = *Result.Context ; // Get context before first use
111104
112105 QualType QT;
113106 if (OuterCast) {
114- // This is our new ternary matcher. Get type from the * cast* .
107+ // This is ternary matcher. Get type from the cast.
115108 QT = OuterCast->getType ();
116109 } else {
117- // This is the old logic. Get type from the bound expression.
110+ // Get type from the bound expression.
118111 QT = E->getType ();
119112 }
120113
@@ -123,19 +116,14 @@ const auto *E = Result.Nodes.getNodeAs<Expr>("unsignedMaxExpr");
123116
124117 const SourceManager &SM = Ctx.getSourceManager ();
125118
126- // *** ADD THIS LOGIC BLOCK ***
127- // This logic prevents double-reporting for the *old* matchers.
128- // We skip it for the new ternary matcher (when OuterCast is not null)
129- // because the ternary matcher binds the *inner* expression, and we
130- // *do* want to report it.
131119 if (!OuterCast) {
132- auto Parents = Ctx.getParents (*E); // This fixes the [-Wunused] warning
120+ auto Parents = Ctx.getParents (*E);
133121 if (!Parents.empty ()) {
134122 for (const auto &Parent : Parents) {
135123 // Check if parent is an explicit cast to unsigned
136124 if (const auto *ParentCast = Parent.get <ExplicitCastExpr>()) {
137125 if (ParentCast->getType ()->isUnsignedIntegerType ()) {
138- // Skip this match - the cast itself will be (or was) reported
126+ // Skip this match, avoids double reporting
139127 return ;
140128 }
141129 }
@@ -153,14 +141,10 @@ const auto *E = Result.Nodes.getNodeAs<Expr>("unsignedMaxExpr");
153141 }
154142 }
155143 }
156- // ... (rest of parent checking logic) ...
157- // ...
158- // Determine the unsigned destination type
159- // QualType QT = E->getType(); // This line is moved up and modified
144+
160145 if (QT.isNull () || !QT->isUnsignedIntegerType ())
161146 return ;
162147
163- // Get a printable type string
164148 std::string TypeStr = QT.getUnqualifiedType ().getAsString ();
165149 if (const auto *Typedef = QT->getAs <TypedefType>()) {
166150 TypeStr = Typedef->getDecl ()->getName ().str ();
@@ -171,22 +155,22 @@ const auto *E = Result.Nodes.getNodeAs<Expr>("unsignedMaxExpr");
171155 Lexer::getSourceText (CharSourceRange::getTokenRange (E->getSourceRange ()),
172156 SM, getLangOpts ());
173157
174- // Build replacement text
158+ // Suggestion to the user regarding the usage of unsigned ~0 or -1
175159 std::string Replacement = " std::numeric_limits<" + TypeStr + " >::max()" ;
176160
177- // Create diagnostic
161+ // gives warning message if unsigned ~0 or -1 are used instead of numeric_limit::max()
178162 auto Diag = diag (E->getBeginLoc (),
179163 " use 'std::numeric_limits<%0>::max()' instead of '%1'" )
180164 << TypeStr << OriginalText;
181165
182- // Add fix-it hints
166+ // suggest hint for fixing it
183167 Diag << FixItHint::CreateReplacement (E->getSourceRange (), Replacement);
184168
185- // Add include for <limits>
169+ // includes the <limits> which contains the numeric_limits::max()
186170 FileID FID = SM.getFileID (E->getBeginLoc ());
187171 if (auto IncludeHint = Inserter.createIncludeInsertion (FID, " <limits>" )) {
188172 Diag << *IncludeHint;
189173 }
190174}
191175
192- } // namespace clang::tidy::readability
176+ } // namespace clang::tidy::readability
0 commit comments