AMS21 updated this revision to Diff 513582.
AMS21 added a comment.

Rename to `performance-avoid-endl`


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D148318/new/

https://reviews.llvm.org/D148318

Files:
  clang-tools-extra/clang-tidy/performance/AvoidEndlCheck.cpp
  clang-tools-extra/clang-tidy/performance/AvoidEndlCheck.h
  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
  clang-tools-extra/docs/clang-tidy/checks/performance/avoid-endl.rst
  clang-tools-extra/test/clang-tidy/checkers/performance/avoid-endl.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/performance/avoid-endl.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/performance/avoid-endl.cpp
@@ -0,0 +1,71 @@
+// 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) {
+      return *this;
+    }
+
+    basic_ostream& operator<<( basic_ostream<CharT>& (*func)
+        (basic_ostream<CharT>&))
+    {
+      return func(*this);
+    }
+  };
+
+  template <typename CharT>
+  class basic_iostream : public basic_ostream<CharT> {
+  };
+
+  using ostream = basic_ostream<char>;
+  using iostream = basic_iostream<char>;
+
+  iostream cout;
+  iostream cerr;
+
+  template<typename CharT>
+  basic_ostream<CharT>& endl(basic_ostream<CharT>& os)
+  {
+    return os;
+  }
+} // namespace std
+
+void good() {
+  std::cout << "Hello" << '\n';
+  std::cout << "World\n";
+
+  std::cerr << "Hello" << '\n';
+  std::cerr << "World\n";
+}
+
+void bad() {
+  std::cout << "World" << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: do not use std::endl with iostreams; use '\n' instead
+  std::cerr << "World" << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: do not use std::endl with iostreams; use '\n' instead
+}
+
+void bad_single_argument() {
+  std::cout << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not use std::endl with iostreams; use '\n' instead
+  std::cerr << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: do not use std::endl with iostreams; use '\n' instead
+}
+
+void bad_multiple() {
+  std::cout << "Hello" << std::endl << "World" << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: do not use std::endl with iostreams; use '\n' instead
+  std::cerr << "Hello" << std::endl << "World" << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: do not use std::endl with iostreams; use '\n' instead
+}
+
+void bad_user_stream() {
+  std::iostream my_stream;
+
+  my_stream << "Hi" << std::endl;
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not use std::endl with iostreams; use '\n' instead
+}
Index: clang-tools-extra/docs/clang-tidy/checks/performance/avoid-endl.rst
===================================================================
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/performance/avoid-endl.rst
@@ -0,0 +1,34 @@
+.. title:: clang-tidy - performance-avoid-endl
+
+performance-avoid-endl
+======================
+
+Checks for uses of ``std::endl`` on iostreams and suggests using the newline character ``'\n'`` instead.
+
+Rationale:
+Using ``std::endl`` on iostreams 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;
+    }
+
+The ``std::endl`` on line 4 performs two operations: it writes a newline character to the ``std::cout`` stream and then flushes the stream buffer. This can be less efficient than using the newline character ``'\n'`` instead:
+
+.. 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.
+
+If you do need to flush the stream buffer explicitly, you can just use ``std::flush``.
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===================================================================
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -313,6 +313,7 @@
    `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>`_,
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -142,6 +142,11 @@
   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.
 
Index: clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ 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 @@
 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>(
Index: clang-tools-extra/clang-tidy/performance/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -4,6 +4,7 @@
   )
 
 add_clang_library(clangTidyPerformanceModule
+  AvoidEndlCheck.cpp
   FasterStringFindCheck.cpp
   ForRangeCopyCheck.cpp
   ImplicitConversionInLoopCheck.cpp
Index: clang-tools-extra/clang-tidy/performance/AvoidEndlCheck.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/performance/AvoidEndlCheck.h
@@ -0,0 +1,35 @@
+//===--- 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 to flag all uses of std::endl on iostreams.
+///
+/// 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;
+};
+
+} // namespace clang::tidy::performance
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_AVOIDENDLCHECK_H
Index: clang-tools-extra/clang-tidy/performance/AvoidEndlCheck.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/performance/AvoidEndlCheck.cpp
@@ -0,0 +1,47 @@
+//===--- 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"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+void AvoidEndlCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      findAll(cxxOperatorCallExpr(
+          hasOverloadedOperatorName("<<"),
+          callee(cxxMethodDecl(ofClass(
+              hasAnyName("::std::basic_ostream", "::std::basic_iostream")))),
+          hasDescendant(
+              expr(declRefExpr(to(functionDecl(hasName("::std::endl"))))
+                       .bind("endl"))))),
+      this);
+}
+
+void AvoidEndlCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *EndlCall = Result.Nodes.getNodeAs<DeclRefExpr>("endl");
+
+  if (!EndlCall)
+    return;
+
+  auto Diag = diag(EndlCall->getBeginLoc(),
+                   "do not use std::endl with iostreams; use '\\n' instead");
+
+  // Add a fix-it hint to replace std::endl with '\n'
+  Diag << FixItHint::CreateReplacement(
+      CharSourceRange::getCharRange(EndlCall->getSourceRange()), "'\\n'");
+}
+
+} // namespace clang::tidy::performance
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to