mgartmann updated this revision to Diff 345634.
mgartmann added a comment.

Fetched new commits from upstream `main` branch and resolved merge conflicts.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D99646

Files:
  clang-tools-extra/clang-tidy/misc/AvoidStdIoOutsideMainCheck.cpp
  clang-tools-extra/clang-tidy/misc/AvoidStdIoOutsideMainCheck.h
  clang-tools-extra/clang-tidy/misc/CMakeLists.txt
  clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/misc-avoid-std-io-outside-main.rst

Index: clang-tools-extra/docs/clang-tidy/checks/misc-avoid-std-io-outside-main.rst
===================================================================
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/misc-avoid-std-io-outside-main.rst
@@ -0,0 +1,52 @@
+.. title:: clang-tidy - misc-avoid-std-io-outside-main
+
+misc-avoid-std-io-outside-main
+=============
+
+Finds predefined standard stream objects like ``cin``, ``wcin``, ``cout``,
+``wcout``, ``cerr`` or ``wcerr``, that are used outside the ``main``
+function. It also finds uses of ``cstdio`` and ``stdio.h`` functions like
+``printf()`` outside the ``main`` function.
+
+For instance, in the following code, the use of ``std::cout`` and ``printf()``
+outside of ``main()`` would get flagged whereas the use of them inside
+``main()`` is not flagged:
+
+.. code-block:: c++
+
+  #include <iostream>
+  #include <cstdio>
+
+  void some_function() {
+    std::cout << "This triggers the check."; // NOK
+    std::printf("This triggers the check."); // NOK
+  }
+
+  int main() {
+    std::cout << "This does not trigger the check."; // OK
+    std::printf("This does not trigger the check."); // OK
+  }
+
+Since the predefined standard stream objects are global objects, their use
+outside of ``main()`` worsens a program's testability and is thus discouraged.
+Instead, those objects should only be used inside ``main()``. They can then be
+passed as arguments to other functions like so:
+
+.. code-block:: c++
+
+  #include <iostream>
+
+  void some_function(std::istream & in, std::ostream & out) {
+    out << "This does not trigger the check.";
+
+    int i{0};
+    in >> i;
+  }
+
+  int main() {
+    some_function(std::cin, std::cout);
+  }
+
+In contrast to using ``std::cin`` and ``std::cout`` directly, in the above
+example, it is possible to inject mocked stream objects into
+``some_function()`` during testing.
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
@@ -205,6 +205,7 @@
    `llvmlibc-callee-namespace <llvmlibc-callee-namespace.html>`_,
    `llvmlibc-implementation-in-namespace <llvmlibc-implementation-in-namespace.html>`_,
    `llvmlibc-restrict-system-libc-headers <llvmlibc-restrict-system-libc-headers.html>`_, "Yes"
+   `misc-misc-avoid-std-io-outside-main <misc-avoid-std-io-outside-main.html>`_,
    `misc-definitions-in-headers <misc-definitions-in-headers.html>`_, "Yes"
    `misc-misplaced-const <misc-misplaced-const.html>`_,
    `misc-new-delete-overloads <misc-new-delete-overloads.html>`_,
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -119,6 +119,14 @@
 
   Finds calls to ``new`` with missing exception handler for ``std::bad_alloc``.
 
+- New :doc:`misc-avoid-std-io-outside-main
+  <clang-tidy/checks/misc-avoid-std-io-outside-main>` check.
+
+  Finds predefined standard stream objects like ``cin``, ``wcin``, ``cout``,
+  ``wcout``, ``cerr`` or ``wcerr``, that are used outside the ``main``
+  function. It also finds uses of ``cstdio`` and ``stdio.h`` functions like
+  ``printf()`` outside the ``main`` function.
+
 New check aliases
 ^^^^^^^^^^^^^^^^^
 
Index: clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
+++ clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
@@ -9,6 +9,7 @@
 #include "../ClangTidy.h"
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
+#include "AvoidStdIoOutsideMainCheck.h"
 #include "DefinitionsInHeadersCheck.h"
 #include "MisplacedConstCheck.h"
 #include "NewDeleteOverloadsCheck.h"
@@ -31,6 +32,8 @@
 class MiscModule : public ClangTidyModule {
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<AvoidStdIoOutsideMainCheck>(
+        "misc-avoid-std-io-outside-main");
     CheckFactories.registerCheck<DefinitionsInHeadersCheck>(
         "misc-definitions-in-headers");
     CheckFactories.registerCheck<MisplacedConstCheck>("misc-misplaced-const");
Index: clang-tools-extra/clang-tidy/misc/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/misc/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/misc/CMakeLists.txt
@@ -4,6 +4,7 @@
   )
 
 add_clang_library(clangTidyMiscModule
+  AvoidStdIoOutsideMainCheck.cpp
   DefinitionsInHeadersCheck.cpp
   MiscTidyModule.cpp
   MisplacedConstCheck.cpp
Index: clang-tools-extra/clang-tidy/misc/AvoidStdIoOutsideMainCheck.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/misc/AvoidStdIoOutsideMainCheck.h
@@ -0,0 +1,49 @@
+//===--- AvoidStdIoOutsideMainCheck.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_MISC_AVOIDSTDIOOUTSIDEMAINCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_AVOIDSTDIOOUTSIDEMAINCHECK_H
+
+#include "../ClangTidyCheck.h"
+#include <string>
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// Finds predefined standard stream objects like ``cin``, ``wcin``, ``cout``,
+/// ``wcout``, ``cerr`` or ``wcerr``, that are used outside the ``main``
+/// function. It also finds uses of ``cstdio`` and ``stdio.h`` functions like
+/// ``printf()`` outside the ``main`` function.
+///
+/// For the user-facing documentation and examples see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc-avoid-std-io-outside-main.html
+class AvoidStdIoOutsideMainCheck : public ClangTidyCheck {
+public:
+  AvoidStdIoOutsideMainCheck(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;
+
+private:
+  const std::vector<std::string> StdIOStreams = {"cin",   "wcin", "cout",
+                                                 "wcout", "cerr", "wcerr"};
+  const std::vector<std::string> CLikeIOFunctions = {
+      "printf", "vprintf", "puts", "putchar", "scanf", "getchar", "gets"};
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_AVOIDSTDIOOUTSIDEMAINCHECK_H
Index: clang-tools-extra/clang-tidy/misc/AvoidStdIoOutsideMainCheck.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/misc/AvoidStdIoOutsideMainCheck.cpp
@@ -0,0 +1,70 @@
+//===--- AvoidStdIoOutsideMainCheck.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 "AvoidStdIoOutsideMainCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+void AvoidStdIoOutsideMainCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      declRefExpr(to(varDecl(hasAnyName(SmallVector<StringRef>(
+                                 StdIOStreams.begin(), StdIOStreams.end())),
+                             isInStdNamespace())),
+                  unless(forFunction(isMain())))
+          .bind("StdStreamObject"),
+      this);
+
+  Finder->addMatcher(
+      declRefExpr(hasDeclaration(functionDecl(hasAnyName(SmallVector<StringRef>(
+                      CLikeIOFunctions.begin(), CLikeIOFunctions.end())))),
+                  unless(forFunction(isMain())))
+          .bind("CLibFunction"),
+      this);
+
+  /// Matcher for indirect stdio uses:
+  /// \code
+  ///   auto Print = &puts;
+  ///   Print("This is using stdio");
+  /// \endcode
+  Finder->addMatcher(
+      declRefExpr(
+          hasDeclaration(varDecl(hasDescendant(declRefExpr(
+              hasDeclaration(functionDecl(hasAnyName(SmallVector<StringRef>(
+                  CLikeIOFunctions.begin(), CLikeIOFunctions.end())))))))),
+          unless(forFunction(isMain())))
+          .bind("CLibFunction"),
+      this);
+}
+
+void AvoidStdIoOutsideMainCheck::check(const MatchFinder::MatchResult &Result) {
+
+  if (const auto *MatchedStreamObj =
+          Result.Nodes.getNodeAs<DeclRefExpr>("StdStreamObject")) {
+    diag(MatchedStreamObj->getLocation(),
+         "predefined standard stream objects should "
+         "not be used outside the main function");
+    return;
+  }
+
+  if (const auto *MatchedCLibFunc =
+          Result.Nodes.getNodeAs<DeclRefExpr>("CLibFunction")) {
+    diag(MatchedCLibFunc->getLocation(),
+         "cstdio functions should not be used outside the main function");
+    return;
+  }
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to