Caslyn updated this revision to Diff 533832.
Caslyn marked 4 inline comments as done.
Caslyn added a comment.

Fixes from review.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D152953

Files:
  clang-tools-extra/clang-tidy/fuchsia/CMakeLists.txt
  clang-tools-extra/clang-tidy/fuchsia/FuchsiaTidyModule.cpp
  clang-tools-extra/clang-tidy/fuchsia/GlobalVariablesCheck.cpp
  clang-tools-extra/clang-tidy/fuchsia/GlobalVariablesCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/fuchsia/global-variables.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/checkers/fuchsia/global-variables.cpp
  llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/fuchsia/BUILD.gn

Index: llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/fuchsia/BUILD.gn
===================================================================
--- llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/fuchsia/BUILD.gn
+++ llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/fuchsia/BUILD.gn
@@ -16,6 +16,7 @@
     "DefaultArgumentsDeclarationsCheck.cpp",
     "FuchsiaTidyModule.cpp",
     "MultipleInheritanceCheck.cpp",
+    "GlobalVariablesCheck.cpp",
     "OverloadedOperatorCheck.cpp",
     "StaticallyConstructedObjectsCheck.cpp",
     "TrailingReturnCheck.cpp",
Index: clang-tools-extra/test/clang-tidy/checkers/fuchsia/global-variables.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/fuchsia/global-variables.cpp
@@ -0,0 +1,168 @@
+// RUN: %check_clang_tidy %s fuchsia-global-variables %t \
+// RUN: -config="{CheckOptions: \
+// RUN:           [{key: fuchsia-global-variables.Ignore, value: 'LazyRE2;ThreadLocal'}] \
+// RUN:          }"
+
+using size_t = decltype(sizeof(int));
+
+namespace std {
+template<class T, size_t N>
+struct array {
+  ~array() {};
+  T Element;
+};
+template<class T>
+struct array<T, 0> {};
+}  // namespace std */
+
+class TriviallyDestructibleClass {
+ public:
+  // This is a trivially destructible class.
+  TriviallyDestructibleClass() : I(0) {}
+  TriviallyDestructibleClass(int I) : I(I) {}
+
+  int I;
+  float F;
+  char C;
+  char Cs[10];
+};
+
+class NonTriviallyDestructibleClass {
+ public:
+  NonTriviallyDestructibleClass() : Var(0) {}
+  NonTriviallyDestructibleClass(int Var) : Var(Var) {}
+  // We need a destructor to make the class non trivially destructible.
+  ~NonTriviallyDestructibleClass() {}
+  int Var;
+};
+
+template <class T>
+class NonTriviallyDestructibleTemplateClass {
+ public:
+  // We need a destructor to make the class non trivially destructible.
+  ~NonTriviallyDestructibleTemplateClass() {}
+  int Var;
+  T Var2;
+};
+
+int global_i;
+_Atomic size_t global_atomic;
+
+TriviallyDestructibleClass trivially_destructible_class;
+
+NonTriviallyDestructibleClass non_trivially_destructible;
+// CHECK-MESSAGES: [[@LINE-1]]:31: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+
+[[clang::no_destroy]] NonTriviallyDestructibleClass non_trivially_destructible_no_destroy;
+
+TriviallyDestructibleClass trivially_destructible_array[2] = {
+    TriviallyDestructibleClass(1), TriviallyDestructibleClass(2)};
+
+NonTriviallyDestructibleClass non_trivially_destructible_array[2] = {
+    NonTriviallyDestructibleClass(1), NonTriviallyDestructibleClass(2)};
+// CHECK-MESSAGES: [[@LINE-2]]:31: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+
+const TriviallyDestructibleClass trivially_destructible_const_array[2] = {
+    TriviallyDestructibleClass(1), TriviallyDestructibleClass(2)};
+
+const NonTriviallyDestructibleClass non_trivially_destructible_const_array[2] = {
+    NonTriviallyDestructibleClass(1), NonTriviallyDestructibleClass(2)};
+// CHECK-MESSAGES: [[@LINE-2]]:37: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+
+TriviallyDestructibleClass trivially_destructible_multi_array[2][2] = {
+    {TriviallyDestructibleClass(1), TriviallyDestructibleClass(2)},
+    {TriviallyDestructibleClass(3), TriviallyDestructibleClass(4)}};
+
+NonTriviallyDestructibleClass non_trivially_destructible_multi_array[2][2] = {
+    {NonTriviallyDestructibleClass(1), NonTriviallyDestructibleClass(2)},
+    {NonTriviallyDestructibleClass(3), NonTriviallyDestructibleClass(4)}};
+// CHECK-MESSAGES: [[@LINE-3]]:31: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+
+const TriviallyDestructibleClass const_trivially_destructible_multi_array[2][2] = {
+    {TriviallyDestructibleClass(1), TriviallyDestructibleClass(2)},
+    {TriviallyDestructibleClass(3), TriviallyDestructibleClass(4)}};
+
+const NonTriviallyDestructibleClass const_non_trivially_destructible_multi_array[2][2] = {
+    {NonTriviallyDestructibleClass(1), NonTriviallyDestructibleClass(2)},
+    {NonTriviallyDestructibleClass(3), NonTriviallyDestructibleClass(4)}};
+// CHECK-MESSAGES: [[@LINE-3]]:37: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+
+typedef TriviallyDestructibleClass TDCArray[1];
+TDCArray tdc_array[1];
+
+typedef NonTriviallyDestructibleClass NTDCArray[1];
+NTDCArray ntdc_array[1];
+// CHECK-MESSAGES: [[@LINE-1]]:11: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+
+typedef TriviallyDestructibleClass& tdc_ref;
+tdc_ref typedef_ref_tdc =
+    *new TriviallyDestructibleClass;
+
+typedef NonTriviallyDestructibleClass& ntdc_ref;
+ntdc_ref typedef_ref_ntdc =
+    *new NonTriviallyDestructibleClass;
+
+void func() {
+  static NonTriviallyDestructibleClass func_ntdc;
+  // CHECK-MESSAGES: [[@LINE-1]]:40: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+
+  static int func_j = 0;
+  static TriviallyDestructibleClass func_tdc;
+
+  // Static references with function scope are allowed if they don't have
+  // lifetime-extension.
+  static const NonTriviallyDestructibleClass &const_ref_func_ntdc =
+      *new NonTriviallyDestructibleClass;
+
+  static const NonTriviallyDestructibleClass
+      &extended_lifetime_const_ref_func_ntdc = {};
+  // CHECK-MESSAGES: [[@LINE-1]]:8: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+
+  // 'thread_local' variables in functions are allowed without restrictions.
+  thread_local NonTriviallyDestructibleClass tl_func_ntdc(1);
+}
+
+thread_local NonTriviallyDestructibleClass tl_ntdc(1);
+// CHECK-MESSAGES: [[@LINE-1]]:44: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+
+static const NonTriviallyDestructibleClass &const_ref_ntdc =
+    *new NonTriviallyDestructibleClass;
+
+class ContainsStaticVars {
+  static NonTriviallyDestructibleClass class_ntdc;
+  static NonTriviallyDestructibleTemplateClass<int> class_ntdt;
+  int local_var;
+  static int class_counter;
+  static TriviallyDestructibleClass class_trivially_destructible;
+};
+
+NonTriviallyDestructibleClass ContainsStaticVars::class_ntdc;
+// CHECK-MESSAGES: [[@LINE-1]]:51: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+NonTriviallyDestructibleTemplateClass<int> ContainsStaticVars::class_ntdt;
+// CHECK-MESSAGES: [[@LINE-1]]:64: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+
+int ContainsStaticVars::class_counter = 42;
+TriviallyDestructibleClass ContainsStaticVars::class_trivially_destructible;
+
+// Test exemptions configured through options
+
+class LazyRE2 {
+ public:
+  LazyRE2();
+};
+
+LazyRE2 lre2;
+
+template <class Type>
+class ThreadLocal {
+ public:
+  ThreadLocal() {}
+  // We need a destructor to make the class non trivially destructible.
+  ~ThreadLocal() {}
+};
+
+ThreadLocal<int> global_thread_local;
+
+void foo() {
+  static ThreadLocal<int> static_thread_local;
+}
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
@@ -213,6 +213,7 @@
    `cppcoreguidelines-virtual-class-destructor <cppcoreguidelines/virtual-class-destructor.html>`_, "Yes"
    `darwin-avoid-spinlock <darwin/avoid-spinlock.html>`_,
    `darwin-dispatch-once-nonstatic <darwin/dispatch-once-nonstatic.html>`_, "Yes"
+   `fuchsia-global-variables<fuchsia/global-variables.html>`_,
    `fuchsia-default-arguments-calls <fuchsia/default-arguments-calls.html>`_,
    `fuchsia-default-arguments-declarations <fuchsia/default-arguments-declarations.html>`_, "Yes"
    `fuchsia-multiple-inheritance <fuchsia/multiple-inheritance.html>`_,
Index: clang-tools-extra/docs/clang-tidy/checks/fuchsia/global-variables.rst
===================================================================
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/fuchsia/global-variables.rst
@@ -0,0 +1,48 @@
+.. title:: clang-tidy - fuchsia-global-variables
+
+fuchsia-global-variables
+=============================
+
+Warns of static and global variables with non-trivial destructors.
+
+For example:
+
+.. code-block:: c++
+
+  // No warning
+  class PODClass {
+  public:
+    int Var;
+    float F;
+    char C;
+    char Cs[10];
+  };
+
+  // No warning
+  PODClass pod_class;
+
+  class NonPODClass {
+  public:
+    NonPODClass() : Var(0) {}
+    NonPODClass(int Var) : Var(Var) {}
+    ~NonPODClass() {
+      cout << "Running destructor";
+    }
+    int Var;
+  };
+
+  // Warning
+  NonPODClass non_pod_class;
+
+`std::array` produces a warning only if it contains a member that is not
+trivially destructible.
+
+`thread_local` variables in functions are permitted without restrictions.
+
+Options
+-------
+
+.. option:: Ignore
+
+   Semicolon-separated list of names of types for the check to ignore. Default
+   is empty.
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -159,6 +159,11 @@
   Warns when an rvalue reference function parameter is never moved within
   the function body.
 
+- New :doc:`fuchsia-global-variables
+  <clang-tidy/checks/fuchsia/global-variables>` check.
+
+  Checks static and global variables that are not trivially destructible.
+
 - New :doc:`llvmlibc-inline-function-decl
   <clang-tidy/checks/llvmlibc/inline-function-decl>` check.
 
Index: clang-tools-extra/clang-tidy/fuchsia/GlobalVariablesCheck.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/fuchsia/GlobalVariablesCheck.h
@@ -0,0 +1,35 @@
+//===--- GlobalVariablesCheck.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_FUCHSIA_GLOBAL_VARIABLES_CHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_GLOBAL_VARIABLES_CHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::fuchsia {
+
+/// GlobalVariables with non-trivial destructors are disallowed
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/fuchsia/global-variables.html
+class GlobalVariablesCheck : public ClangTidyCheck {
+public:
+  GlobalVariablesCheck(StringRef Name, ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void checkType(const ast_matchers::MatchFinder::MatchResult &Result,
+                 const VarDecl *decl, const QualType type);
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  const std::vector<StringRef> IgnoreVars;
+};
+
+} // namespace clang::tidy::fuchsia
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_GLOBAL_VARIABLES_CHECK_H
Index: clang-tools-extra/clang-tidy/fuchsia/GlobalVariablesCheck.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/fuchsia/GlobalVariablesCheck.cpp
@@ -0,0 +1,89 @@
+//===--- GlobalVariablesCheck.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 "GlobalVariablesCheck.h"
+#include "../utils/Matchers.h"
+#include "../utils/OptionsUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using llvm::StringRef;
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::fuchsia {
+
+GlobalVariablesCheck::GlobalVariablesCheck(StringRef Name,
+                                           ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      IgnoreVars(utils::options::parseStringList(Options.get("Ignore", ""))) {}
+
+void GlobalVariablesCheck::registerMatchers(MatchFinder *Finder) {
+  const auto is_global_or_static_candidate =
+      allOf(hasGlobalStorage(), isDefinition(), unless(isConstexpr()),
+            unless(hasAttr(clang::attr::NoDestroy)), unless(isConstinit()),
+            // Exception: references without lifetime-extension.
+            unless(allOf(hasType(references(qualType())),
+                         unless(hasInitializer(exprWithCleanups(
+                             has(materializeTemporaryExpr())))))));
+
+  Finder->addMatcher(
+      varDecl(is_global_or_static_candidate,
+              unless(hasType(cxxRecordDecl(hasAnyName(IgnoreVars)))))
+          .bind("global_var"),
+      this);
+}
+
+void GlobalVariablesCheck::checkType(const MatchFinder::MatchResult &Result,
+                                     const VarDecl *decl, QualType type) {
+  if (type.getNonReferenceType().isDestructedType() == QualType::DK_none) {
+    return;
+  }
+
+  // Ignore variables which are declared in macros even if they are static or
+  // global variables of non-POD types.
+  if (decl->getLocation().isMacroID()) {
+    return;
+  }
+
+  // 'thread_local' variables in functions are allowed without restrictions.
+  auto *decl_context = decl->getDeclContext();
+  if (!isa<NamespaceDecl>(decl_context) &&
+      !isa<TranslationUnitDecl>(decl_context)) {
+    if (decl->getTLSKind() == VarDecl::TLS_Dynamic ||
+        decl->getTLSKind() == VarDecl::TLS_Static) {
+      return;
+    }
+  }
+
+  // 'thread_local' variables with no dynamic initialization are allowed
+  // everywhere.
+  if (decl->getTLSKind() == VarDecl::TLS_Static) {
+    return;
+  }
+
+  // Objective-C ARC-managed objects are allowed everywhere.
+  if (type->isObjCLifetimeType()) {
+    return;
+  }
+
+  diag(decl->getLocation(),
+       "non trivially destructible static and global variables are forbidden");
+}
+
+void GlobalVariablesCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *decl = Result.Nodes.getNodeAs<VarDecl>("global_var")) {
+    QualType type = decl->getType().getCanonicalType();
+    checkType(Result, decl, type);
+  }
+}
+
+void GlobalVariablesCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "Ignore",
+                utils::options::serializeStringList(IgnoreVars));
+}
+} // namespace clang::tidy::fuchsia
Index: clang-tools-extra/clang-tidy/fuchsia/FuchsiaTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/fuchsia/FuchsiaTidyModule.cpp
+++ clang-tools-extra/clang-tidy/fuchsia/FuchsiaTidyModule.cpp
@@ -12,6 +12,7 @@
 #include "../google/UnnamedNamespaceInHeaderCheck.h"
 #include "DefaultArgumentsCallsCheck.h"
 #include "DefaultArgumentsDeclarationsCheck.h"
+#include "GlobalVariablesCheck.h"
 #include "MultipleInheritanceCheck.h"
 #include "OverloadedOperatorCheck.h"
 #include "StaticallyConstructedObjectsCheck.h"
@@ -31,6 +32,8 @@
         "fuchsia-default-arguments-calls");
     CheckFactories.registerCheck<DefaultArgumentsDeclarationsCheck>(
         "fuchsia-default-arguments-declarations");
+    CheckFactories.registerCheck<GlobalVariablesCheck>(
+        "fuchsia-global-variables");
     CheckFactories.registerCheck<google::build::UnnamedNamespaceInHeaderCheck>(
         "fuchsia-header-anon-namespaces");
     CheckFactories.registerCheck<MultipleInheritanceCheck>(
Index: clang-tools-extra/clang-tidy/fuchsia/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/fuchsia/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/fuchsia/CMakeLists.txt
@@ -8,6 +8,7 @@
   DefaultArgumentsDeclarationsCheck.cpp
   FuchsiaTidyModule.cpp
   MultipleInheritanceCheck.cpp
+  GlobalVariablesCheck.cpp
   OverloadedOperatorCheck.cpp
   StaticallyConstructedObjectsCheck.cpp
   TrailingReturnCheck.cpp
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to