@@ -96,12 +96,11 @@ static QualType getReplacementCastType(const Expr *CondLhs, const Expr *CondRhs,
9696 return GlobalImplicitCastType;
9797}
9898
99- static std::string createReplacement (const Expr *CondLhs, const Expr *CondRhs,
100- const Expr *AssignLhs,
101- const SourceManager &Source,
102- const LangOptions &LO,
103- StringRef FunctionName,
104- const BinaryOperator *BO) {
99+ static std::string
100+ createReplacement (const Expr *CondLhs, const Expr *CondRhs,
101+ const Expr *AssignLhs, const SourceManager &Source,
102+ const LangOptions &LO, StringRef FunctionName,
103+ const BinaryOperator *BO, StringRef Comment = " " ) {
105104 const llvm::StringRef CondLhsStr = Lexer::getSourceText (
106105 Source.getExpansionRange (CondLhs->getSourceRange ()), Source, LO);
107106 const llvm::StringRef CondRhsStr = Lexer::getSourceText (
@@ -116,7 +115,8 @@ static std::string createReplacement(const Expr *CondLhs, const Expr *CondRhs,
116115 (!GlobalImplicitCastType.isNull ()
117116 ? " <" + GlobalImplicitCastType.getAsString () + " >("
118117 : " (" ) +
119- CondLhsStr + " , " + CondRhsStr + " );" )
118+ CondLhsStr + " , " + CondRhsStr + " );" + (Comment.empty () ? " " : " " ) +
119+ Comment)
120120 .str ();
121121}
122122
@@ -172,13 +172,65 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
172172
173173 auto ReplaceAndDiagnose = [&](const llvm::StringRef FunctionName) {
174174 const SourceManager &Source = *Result.SourceManager ;
175+ llvm::SmallString<64 > Comment;
176+
177+ const auto AppendNormalized = [&](llvm::StringRef Text) {
178+ Text = Text.ltrim ();
179+ if (!Text.empty ()) {
180+ if (!Comment.empty ())
181+ Comment += " " ;
182+ Comment += Text;
183+ }
184+ };
185+
186+ const auto GetSourceText = [&](SourceLocation StartLoc,
187+ SourceLocation EndLoc) {
188+ return Lexer::getSourceText (
189+ CharSourceRange::getCharRange (
190+ Lexer::getLocForEndOfToken (StartLoc, 0 , Source, LO), EndLoc),
191+ Source, LO);
192+ };
193+
194+ // Captures:
195+ // if (cond) // Comment A
196+ // if (cond) /* Comment A */ { ... }
197+ // if (cond) /* Comment A */ x = y;
198+ AppendNormalized (
199+ GetSourceText (If->getRParenLoc (), If->getThen ()->getBeginLoc ()));
200+
201+ if (const auto *CS = dyn_cast<CompoundStmt>(If->getThen ())) {
202+ const Stmt *Inner = CS->body_front ();
203+
204+ // Captures:
205+ // if (cond) { // Comment B
206+ // ...
207+ // }
208+ // if (cond) { /* Comment B */ x = y; }
209+ AppendNormalized (GetSourceText (CS->getBeginLoc (), Inner->getBeginLoc ()));
210+
211+ // Captures:
212+ // if (cond) { x = y; // Comment C }
213+ // if (cond) { x = y; /* Comment C */ }
214+ llvm::StringRef PostInner =
215+ GetSourceText (Inner->getEndLoc (), CS->getEndLoc ());
216+
217+ // Strip the trailing semicolon to avoid fixes like:
218+ // x = std::min(x, y);; // comment
219+ const size_t Semi = PostInner.find (' ;' );
220+ if (Semi != llvm::StringRef::npos &&
221+ PostInner.take_front (Semi).trim ().empty ()) {
222+ PostInner = PostInner.drop_front (Semi + 1 );
223+ }
224+ AppendNormalized (PostInner);
225+ }
226+
175227 diag (IfLocation, " use `%0` instead of `%1`" )
176228 << FunctionName << BinaryOp->getOpcodeStr ()
177229 << FixItHint::CreateReplacement (
178230 SourceRange (IfLocation, Lexer::getLocForEndOfToken (
179231 ThenLocation, 0 , Source, LO)),
180232 createReplacement (CondLhs, CondRhs, AssignLhs, Source, LO,
181- FunctionName, BinaryOp))
233+ FunctionName, BinaryOp, Comment ))
182234 << IncludeInserter.createIncludeInsertion (
183235 Source.getFileID (If->getBeginLoc ()), AlgorithmHeader);
184236 };
0 commit comments