[clang-tools-extra] cd89330 - [clang-tidy] Add `performance-avoid-endl` check

Piotr Zegar via cfe-commits cfe-commits at lists.llvm.org
Sat Apr 22 03:51:26 PDT 2023


Author: AMS21
Date: 2023-04-22T10:50:51Z
New Revision: cd893308b5d4d058b8ec6a2c4b00843d89e25552

URL: https://github.com/llvm/llvm-project/commit/cd893308b5d4d058b8ec6a2c4b00843d89e25552
DIFF: https://github.com/llvm/llvm-project/commit/cd893308b5d4d058b8ec6a2c4b00843d89e25552.diff

LOG: [clang-tidy] Add `performance-avoid-endl` check

This check flags uses of `std::endl` on streams and suggests using the newline character `'\n'` instead. `std::endl` performs two operations: it writes a newline character to the output stream and then flushes the stream buffer, which can be less efficient than writing a single newline character using `'\n'`.

This fixes llvm#35321

Reviewed By: PiotrZSL

Differential Revision: https://reviews.llvm.org/D148318

Added: 
    clang-tools-extra/clang-tidy/performance/AvoidEndlCheck.cpp
    clang-tools-extra/clang-tidy/performance/AvoidEndlCheck.h
    clang-tools-extra/docs/clang-tidy/checks/performance/avoid-endl.rst
    clang-tools-extra/test/clang-tidy/checkers/performance/avoid-endl.cpp

Modified: 
    clang-tools-extra/clang-tidy/performance/CMakeLists.txt
    clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
    clang-tools-extra/docs/ReleaseNotes.rst
    clang-tools-extra/docs/clang-tidy/checks/list.rst

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clang-tidy/performance/AvoidEndlCheck.cpp b/clang-tools-extra/clang-tidy/performance/AvoidEndlCheck.cpp
new file mode 100644
index 0000000000000..8ecaa41754fb2
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/AvoidEndlCheck.cpp
@@ -0,0 +1,84 @@
+//===--- AvoidEndlCheck.cpp - clang-tidy ----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "AvoidEndlCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+void AvoidEndlCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      callExpr(
+          unless(isExpansionInSystemHeader()),
+          anyOf(cxxOperatorCallExpr(
+                    hasOverloadedOperatorName("<<"),
+                    hasRHS(declRefExpr(to(namedDecl(hasName("::std::endl"))))
+                               .bind("expr"))),
+                callExpr(argumentCountIs(1),
+                         callee(functionDecl(hasName("::std::endl"))))
+                    .bind("expr"))),
+      this);
+}
+
+void AvoidEndlCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Expression = Result.Nodes.getNodeAs<Expr>("expr");
+  assert(Expression);
+  assert(isa<DeclRefExpr>(Expression) || isa<CallExpr>(Expression));
+
+  // FIXME: It would be great if we could transform
+  // 'std::cout << "Hi" << std::endl;' into
+  // 'std::cout << "Hi\n"';
+
+  if (llvm::isa<DeclRefExpr>(Expression)) {
+    // Handle the more common streaming '... << std::endl' case
+    const CharSourceRange TokenRange =
+        CharSourceRange::getTokenRange(Expression->getSourceRange());
+    const StringRef SourceText = Lexer::getSourceText(
+        TokenRange, *Result.SourceManager, Result.Context->getLangOpts());
+
+    auto Diag = diag(Expression->getBeginLoc(),
+                     "do not use '%0' with streams; use '\\n' instead")
+                << SourceText;
+
+    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(
+        CharSourceRange::getTokenRange(
+            CallExpression->getCallee()->getSourceRange()),
+        *Result.SourceManager, Result.Context->getLangOpts());
+
+    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);
+  }
+}
+
+} // namespace clang::tidy::performance

diff  --git a/clang-tools-extra/clang-tidy/performance/AvoidEndlCheck.h b/clang-tools-extra/clang-tidy/performance/AvoidEndlCheck.h
new file mode 100644
index 0000000000000..db75fbcf4e89f
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/AvoidEndlCheck.h
@@ -0,0 +1,40 @@
+//===--- AvoidEndlCheck.h - clang-tidy --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_AVOIDENDLCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_AVOIDENDLCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::performance {
+
+/// ClangTidyCheck Checks to flag for uses of 'std::endl' on streams and
+/// suggests using the newline character '"\n"' instead.
+///
+/// For the user-facing documentation see:
+/// https://clang.llvm.org/extra/clang-tidy/checks/performance/avoid-endl.html
+class AvoidEndlCheck : public ClangTidyCheck {
+public:
+  AvoidEndlCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+
+  bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+    return LangOpts.CPlusPlus;
+  }
+
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+  std::optional<TraversalKind> getCheckTraversalKind() const override {
+    return TK_IgnoreUnlessSpelledInSource;
+  }
+};
+
+} // namespace clang::tidy::performance
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_AVOIDENDLCHECK_H

diff  --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 3153646416927..f6676bcf4be43 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS
   )
 
 add_clang_library(clangTidyPerformanceModule
+  AvoidEndlCheck.cpp
   FasterStringFindCheck.cpp
   ForRangeCopyCheck.cpp
   ImplicitConversionInLoopCheck.cpp

diff  --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 30a195f76b4ec..b5151a1cc8939 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -9,6 +9,7 @@
 #include "../ClangTidy.h"
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
+#include "AvoidEndlCheck.h"
 #include "FasterStringFindCheck.h"
 #include "ForRangeCopyCheck.h"
 #include "ImplicitConversionInLoopCheck.h"
@@ -31,6 +32,7 @@ namespace performance {
 class PerformanceModule : public ClangTidyModule {
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<AvoidEndlCheck>("performance-avoid-endl");
     CheckFactories.registerCheck<FasterStringFindCheck>(
         "performance-faster-string-find");
     CheckFactories.registerCheck<ForRangeCopyCheck>(

diff  --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 55c3416235952..49f880c971a34 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -150,6 +150,11 @@ New checks
   Converts standard library type traits of the form ``traits<...>::type`` and
   ``traits<...>::value`` into ``traits_t<...>`` and ``traits_v<...>`` respectively.
 
+- New :doc:`performance-avoid-endl
+  <clang-tidy/checks/performance/avoid-endl>` check.
+
+  Finds uses of ``std::endl`` on streams and replaces them with ``'\n'``.
+
 - New :doc:`readability-avoid-unconditional-preprocessor-if
   <clang-tidy/checks/readability/avoid-unconditional-preprocessor-if>` check.
 

diff  --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index be0d32e65a7f6..3ddd257e70de6 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -314,6 +314,7 @@ Clang-Tidy Checks
    `objc-super-self <objc/super-self.html>`_, "Yes"
    `openmp-exception-escape <openmp/exception-escape.html>`_,
    `openmp-use-default-none <openmp/use-default-none.html>`_,
+   `performance-avoid-endl <performance/avoid-endl.html>`_, "Yes"
    `performance-faster-string-find <performance/faster-string-find.html>`_, "Yes"
    `performance-for-range-copy <performance/for-range-copy.html>`_, "Yes"
    `performance-implicit-conversion-in-loop <performance/implicit-conversion-in-loop.html>`_,

diff  --git a/clang-tools-extra/docs/clang-tidy/checks/performance/avoid-endl.rst b/clang-tools-extra/docs/clang-tidy/checks/performance/avoid-endl.rst
new file mode 100644
index 0000000000000..d02bd6312a76b
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/performance/avoid-endl.rst
@@ -0,0 +1,56 @@
+.. title:: clang-tidy - performance-avoid-endl
+
+performance-avoid-endl
+============================
+
+Checks for uses of ``std::endl`` on streams and suggests using the newline
+character ``'\n'`` instead.
+
+Rationale:
+Using ``std::endl`` on streams can be less efficient than using the newline
+character ``'\n'`` because ``std::endl`` performs two operations: it writes a
+newline character to the output stream and then flushes the stream buffer.
+Writing a single newline character using ``'\n'`` does not trigger a flush,
+which can improve performance. In addition, flushing the stream buffer can
+cause additional overhead when working with streams that are buffered.
+
+Example:
+
+Consider the following code:
+
+.. code-block:: c++
+    #include <iostream>
+
+    int main() {
+      std::cout << "Hello" << std::endl;
+    }
+
+Which gets transformed into:
+
+.. code-block:: c++
+    #include <iostream>
+
+    int main() {
+      std::cout << "Hello" << '\n';
+    }
+
+This code writes a single newline character to the ``std::cout`` stream without
+flushing the stream buffer.
+
+Additionally, it is important to note that the standard C++ streams (like
+``std::cerr``, ``std::wcerr``, ``std::clog`` and ``std::wclog``)
+always flush after a write operation, unless ``std::ios_base::sync_with_stdio``
+is set to ``false``. regardless of whether ``std::endl`` or ``'\n'`` is used.
+Therefore, using ``'\n'`` with these streams will not
+result in any performance gain, but it is still recommended to use
+``'\n'`` for consistency and readability.
+
+If you do need to flush the stream buffer, you can use ``std::flush``
+explicitly like this:
+
+.. code-block:: c++
+    #include <iostream>
+
+    int main() {
+      std::cout << "Hello\n" << std::flush;
+    }

diff  --git a/clang-tools-extra/test/clang-tidy/checkers/performance/avoid-endl.cpp b/clang-tools-extra/test/clang-tidy/checkers/performance/avoid-endl.cpp
new file mode 100644
index 0000000000000..462b88773d231
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/performance/avoid-endl.cpp
@@ -0,0 +1,227 @@
+// RUN: %check_clang_tidy %s performance-avoid-endl %t
+
+namespace std {
+  template <typename CharT>
+  class basic_ostream {
+    public:
+    template <typename T>
+    basic_ostream& operator<<(T);
+    basic_ostream& operator<<(basic_ostream<CharT>& (*)(basic_ostream<CharT>&));
+  };
+
+  template <typename CharT>
+  class basic_iostream : public basic_ostream<CharT> {};
+
+  using ostream = basic_ostream<char>;
+  using wostream = basic_ostream<wchar_t>;
+
+  using iostream = basic_iostream<char>;
+  using wiostream = basic_iostream<wchar_t>;
+
+  ostream cout;
+  wostream wcout;
+
+  ostream cerr;
+  wostream wcerr;
+
+  ostream clog;
+  wostream wclog;
+
+  template<typename CharT>
+  basic_ostream<CharT>& endl(basic_ostream<CharT>&);
+} // namespace std
+
+void good() {
+  std::cout << "Hello" << '\n';
+  std::cout << "World\n";
+
+  std::wcout << "Hello" << '\n';
+  std::wcout << "World\n";
+
+  std::cerr << "Hello" << '\n';
+  std::cerr << "World\n";
+
+  std::wcerr << "Hello" << '\n';
+  std::wcerr << "World\n";
+
+  std::clog << "Hello" << '\n';
+  std::clog << "World\n";
+
+  std::wclog << "Hello" << '\n';
+  std::wclog << "World\n";
+}
+
+void bad() {
+  std::cout << "World" << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::cout << "World" << '\n';
+  std::wcout << "World" << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::wcout << "World" << '\n';
+  std::cerr << "World" << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::cerr << "World" << '\n';
+  std::wcerr << "World" << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::wcerr << "World" << '\n';
+  std::clog << "World" << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::clog << "World" << '\n';
+  std::wclog << "World" << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::wclog << "World" << '\n';
+}
+
+void bad_single_argument() {
+  std::cout << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::cout << '\n';
+  std::wcout << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::wcout << '\n';
+  std::cerr << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::cerr << '\n';
+  std::wcerr << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::wcerr << '\n';
+  std::clog << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::clog << '\n';
+  std::wclog << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::wclog << '\n';
+}
+
+void bad_multiple() {
+  std::cout << "Hello" << std::endl << "World" << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-MESSAGES: :[[@LINE-2]]:51: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::cout << "Hello" << '\n' << "World" << '\n';
+  std::wcout << "Hello" << std::endl << "World" << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-MESSAGES: :[[@LINE-2]]:52: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::wcout << "Hello" << '\n' << "World" << '\n';
+  std::cerr << "Hello" << std::endl << "World" << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-MESSAGES: :[[@LINE-2]]:51: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::cerr << "Hello" << '\n' << "World" << '\n';
+  std::wcerr << "Hello" << std::endl << "World" << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-MESSAGES: :[[@LINE-2]]:52: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::wcerr << "Hello" << '\n' << "World" << '\n';
+  std::clog << "Hello" << std::endl << "World" << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-MESSAGES: :[[@LINE-2]]:51: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::clog << "Hello" << '\n' << "World" << '\n';
+  std::wclog << "Hello" << std::endl << "World" << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-MESSAGES: :[[@LINE-2]]:52: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::wclog << "Hello" << '\n' << "World" << '\n';
+}
+
+void bad_function_call() {
+  std::endl(std::cout);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::cout << '\n';
+  std::endl(std::cout << "Hi");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::cout << "Hi" << '\n';
+  std::endl(std::wcout);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::wcout << '\n';
+  std::endl(std::wcout << "Hi");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::wcout << "Hi" << '\n';
+  std::endl(std::cerr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::cerr << '\n';
+  std::endl(std::cerr << "Hi");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::cerr << "Hi" << '\n';
+  std::endl(std::wcerr);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::wcerr << '\n';
+  std::endl(std::wcerr << "Hi");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::wcerr << "Hi" << '\n';
+  std::endl(std::clog);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::clog << '\n';
+  std::endl(std::clog << "Hi");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::clog << "Hi" << '\n';
+  std::endl(std::wclog);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::wclog << '\n';
+  std::endl(std::wclog << "Hi");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: std::wclog << "Hi" << '\n';
+}
+
+void bad_user_stream() {
+  std::iostream my_iostream;
+  std::wiostream my_wiostream;
+  std::ostream my_ostream;
+  std::wostream my_wostream;
+
+  my_iostream << "Hi" << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: my_iostream << "Hi" << '\n';
+  my_wiostream << "Hi" << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: my_wiostream << "Hi" << '\n';
+  my_ostream << "Hi" << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: my_ostream << "Hi" << '\n';
+  my_wostream << "Hi" << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: my_wostream << "Hi" << '\n';
+
+  std::endl(my_iostream);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: my_iostream << '\n';
+  std::endl(my_wiostream);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: my_wiostream << '\n';
+  std::endl(my_ostream);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: my_ostream << '\n';
+  std::endl(my_wostream);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: my_wostream << '\n';
+}
+
+using namespace std;
+void bad_using_namespace_std() {
+  cout << "Hello" << endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: cout << "Hello" << '\n';
+  endl(cout);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: cout << '\n';
+}
+
+namespace my_prefix = std;
+void bad_using_user_namespace() {
+  my_prefix::cout << "Hello" << my_prefix::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: do not use 'my_prefix::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: my_prefix::cout << "Hello" << '\n';
+  my_prefix::endl(my_prefix::cout);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use 'my_prefix::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: my_prefix::cout << '\n';
+}
+
+struct CustomLogger {
+  template <typename T>
+  std::ostream& operator<<(T);
+  std::ostream& operator<<(std::ostream& (*)(std::ostream&));
+};
+
+void bad_custom_stream() {
+  CustomLogger logger;
+
+  logger << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]
+  // CHECK-FIXES: logger << '\n';
+}


        


More information about the cfe-commits mailing list