Skip to content

Commit

Permalink
[clang-tidy] add default error message for performance-avoid-endl (#1…
Browse files Browse the repository at this point in the history
…07867)

use std::endl as default message when matched expr does not have valid
source text

Fixes: #107859
  • Loading branch information
HerrCai0907 authored Sep 13, 2024
1 parent c6c3803 commit b7914df
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 15 deletions.
33 changes: 18 additions & 15 deletions clang-tools-extra/clang-tidy/performance/AvoidEndlCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,38 +46,41 @@ void AvoidEndlCheck::check(const MatchFinder::MatchResult &Result) {
// Handle the more common streaming '... << std::endl' case
const CharSourceRange TokenRange =
CharSourceRange::getTokenRange(Expression->getSourceRange());
const StringRef SourceText = Lexer::getSourceText(
StringRef SourceText = Lexer::getSourceText(
TokenRange, *Result.SourceManager, Result.Context->getLangOpts());

if (SourceText.empty())
SourceText = "std::endl";
auto Diag = diag(Expression->getBeginLoc(),
"do not use '%0' with streams; use '\\n' instead")
<< SourceText;

Diag << FixItHint::CreateReplacement(TokenRange, "'\\n'");
if (TokenRange.isValid())
Diag << FixItHint::CreateReplacement(TokenRange, "'\\n'");
} else {
// Handle the less common function call 'std::endl(...)' case
const auto *CallExpression = llvm::cast<CallExpr>(Expression);
assert(CallExpression->getNumArgs() == 1);

const StringRef SourceText = Lexer::getSourceText(
StringRef SourceText = Lexer::getSourceText(
CharSourceRange::getTokenRange(
CallExpression->getCallee()->getSourceRange()),
*Result.SourceManager, Result.Context->getLangOpts());
if (SourceText.empty())
SourceText = "std::endl";
auto Diag = diag(CallExpression->getBeginLoc(),
"do not use '%0' with streams; use '\\n' instead")
<< SourceText;

const CharSourceRange ArgTokenRange = CharSourceRange::getTokenRange(
CallExpression->getArg(0)->getSourceRange());
const StringRef ArgSourceText = Lexer::getSourceText(
ArgTokenRange, *Result.SourceManager, Result.Context->getLangOpts());

const std::string ReplacementString =
std::string(ArgSourceText) + " << '\\n'";

diag(CallExpression->getBeginLoc(),
"do not use '%0' with streams; use '\\n' instead")
<< SourceText
<< FixItHint::CreateReplacement(
CharSourceRange::getTokenRange(CallExpression->getSourceRange()),
ReplacementString);
const CharSourceRange ReplacementRange =
CharSourceRange::getTokenRange(CallExpression->getSourceRange());
if (!ArgSourceText.empty() && ReplacementRange.isValid()) {
const std::string ReplacementString =
std::string(ArgSourceText) + " << '\\n'";
Diag << FixItHint::CreateReplacement(ReplacementRange, ReplacementString);
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ Changes in existing checks
<clang-tidy/checks/modernize/use-std-print>` check to support replacing
member function calls too.

- Improved :doc:`performance-avoid-endl
<clang-tidy/checks/performance/avoid-endl>` check to use ``std::endl`` as
placeholder when lexer cannot get source text.

- Improved :doc:`readability-implicit-bool-conversion
<clang-tidy/checks/readability/implicit-bool-conversion>` check
by adding the option `UseUpperCaseLiteralSuffix` to select the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,14 @@ void bad_custom_stream() {
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
// CHECK-FIXES: logger << '\n';
}

namespace gh107859 {

#define ENDL std::endl;

void bad_macro() {
std::cout << ENDL;
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
}

} // namespace gh107859

0 comments on commit b7914df

Please sign in to comment.