Caslyn updated this revision to Diff 535546.
Caslyn marked 12 inline comments as done.
Caslyn added a comment.

Changes per 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,183 @@
+// 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));
+
+class TriviallyDestructibleClass {
+ public:
+  // This is a trivially destructible class.
+  int I;
+  float F;
+  char C;
+  char Cs[10];
+};
+
+class NonTriviallyDestructibleClass {
+ public:
+  // We need a destructor to make the class non trivially destructible.
+  ~NonTriviallyDestructibleClass() { Var = 0; }
+  int Var;
+};
+
+template <class T>
+class NonTriviallyDestructibleTemplateClass {
+ public:
+  // We need a destructor to make the class non trivially destructible.
+  ~NonTriviallyDestructibleTemplateClass() { Var = 0; }
+  int Var;
+  T Var2;
+};
+
+int GlobalI;
+_Atomic size_t GlobalAtomic;
+
+TriviallyDestructibleClass Tdc;
+
+NonTriviallyDestructibleClass Ntdc;
+// CHECK-MESSAGES: [[@LINE-1]]:31: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+
+[[clang::no_destroy]] NonTriviallyDestructibleClass NtdcNoDestory;
+
+TriviallyDestructibleClass TdcArray[2] = { TriviallyDestructibleClass(), TriviallyDestructibleClass()};
+
+NonTriviallyDestructibleClass NtdcArray[2] = {
+    NonTriviallyDestructibleClass(), NonTriviallyDestructibleClass()};
+// CHECK-MESSAGES: [[@LINE-2]]:31: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+
+const TriviallyDestructibleClass TdcConstArray[2] = {
+    TriviallyDestructibleClass(), TriviallyDestructibleClass()};
+
+const NonTriviallyDestructibleClass NtdcConstArray[2] = {
+    NonTriviallyDestructibleClass(), NonTriviallyDestructibleClass()};
+// CHECK-MESSAGES: [[@LINE-2]]:37: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+
+TriviallyDestructibleClass TdcMultiArray[2][2] = {
+    {TriviallyDestructibleClass(), TriviallyDestructibleClass()},
+    {TriviallyDestructibleClass(), TriviallyDestructibleClass()}};
+
+NonTriviallyDestructibleClass NtdcMultiArray[2][2] = {
+    {NonTriviallyDestructibleClass(), NonTriviallyDestructibleClass()},
+    {NonTriviallyDestructibleClass(), NonTriviallyDestructibleClass()}};
+// CHECK-MESSAGES: [[@LINE-3]]:31: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+
+const TriviallyDestructibleClass TdcMultiConstArray[2][2] = {
+    {TriviallyDestructibleClass(), TriviallyDestructibleClass()},
+    {TriviallyDestructibleClass(), TriviallyDestructibleClass()}};
+
+const NonTriviallyDestructibleClass NtdcMultiConstArray[2][2] = {
+    {NonTriviallyDestructibleClass(), NonTriviallyDestructibleClass()},
+    {NonTriviallyDestructibleClass(), NonTriviallyDestructibleClass()}};
+// CHECK-MESSAGES: [[@LINE-3]]:37: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+
+typedef TriviallyDestructibleClass TDCArray[1];
+TDCArray TdcTypedefArray[1];
+
+typedef NonTriviallyDestructibleClass NTDCArray[1];
+NTDCArray NTdcTypedefArray[1];
+// CHECK-MESSAGES: [[@LINE-1]]:11: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+
+const TriviallyDestructibleClass& getTdcRef() {
+  TriviallyDestructibleClass Tdc;
+  return Tdc;
+}
+
+const NonTriviallyDestructibleClass& getNtdcRef() {
+  NonTriviallyDestructibleClass Ntdc;
+  return Ntdc;
+}
+
+typedef const TriviallyDestructibleClass& TdcConstRef;
+typedef const NonTriviallyDestructibleClass& NtdcConstRef;
+
+void testLifetimeExtension() {
+  static const TriviallyDestructibleClass &Tdc = getTdcRef();
+  static TdcConstRef TdcTypedef = getTdcRef();
+
+  static const NonTriviallyDestructibleClass& Ntdc = getNtdcRef();
+  // CHECK-MESSAGES: [[@LINE-1]]:47: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+  static NtdcConstRef NtdcTypedef = getNtdcRef();
+  // CHECK-MESSAGES: [[@LINE-1]]:23: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+
+  static const NonTriviallyDestructibleClass &ExtendedLifetimeNtdc = {};
+  // CHECK-MESSAGES: [[@LINE-1]]:47: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+
+  /*
+  // TODO: fix false-positive match
+  // Static references with function scope are allowed if they don't have
+  // lifetime-extension.
+  static const NonTriviallyDestructibleClass &ConstRefFuncNtdc =
+      *new NonTriviallyDestructibleClass;
+  */
+}
+
+/*
+// TODO: fix false-positive match
+static const NonTriviallyDestructibleClass &ConstRefNtdc =
+    *new NonTriviallyDestructibleClass;
+*/
+
+template<typename T>
+const T& f() {
+static T Value;
+// CHECK-MESSAGES: [[@LINE-1]]:10: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+return Value;
+}
+
+void func() {
+  static TriviallyDestructibleClass FuncTdc = f<TriviallyDestructibleClass>();
+
+  static NonTriviallyDestructibleClass FuncNtdc = f<NonTriviallyDestructibleClass>();
+  // CHECK-MESSAGES: [[@LINE-1]]:40: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+
+  static NonTriviallyDestructibleClass Ntdc;
+  // CHECK-MESSAGES: [[@LINE-1]]:40: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+
+  static int FuncJ = 0;
+  static TriviallyDestructibleClass Tdc;
+
+  // 'thread_local' variables in functions are allowed without restrictions.
+  thread_local NonTriviallyDestructibleClass TlNtdc;
+}
+
+thread_local NonTriviallyDestructibleClass TlNtdc;
+// CHECK-MESSAGES: [[@LINE-1]]:44: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+
+class ContainsStaticVars {
+  static NonTriviallyDestructibleClass ClassNtdc;
+  static NonTriviallyDestructibleTemplateClass<int> ClassNtdt;
+  int LocalVar;
+  static int ClassCounter;
+  static TriviallyDestructibleClass ClassTriviallyDestructible;
+};
+
+NonTriviallyDestructibleClass ContainsStaticVars::ClassNtdc;
+// CHECK-MESSAGES: [[@LINE-1]]:51: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+NonTriviallyDestructibleTemplateClass<int> ContainsStaticVars::ClassNtdt;
+// CHECK-MESSAGES: [[@LINE-1]]:64: warning: non trivially destructible static and global variables are forbidden [fuchsia-global-variables]
+
+int ContainsStaticVars::ClassCounter = 42;
+TriviallyDestructibleClass ContainsStaticVars::ClassTriviallyDestructible;
+
+// Test exemptions configured through options
+
+class LazyRE2 {
+ public:
+  LazyRE2();
+};
+
+LazyRE2 Lre2;
+
+template <class Type>
+class ThreadLocal {
+ public:
+  // We need a destructor to make the class non trivially destructible.
+  ~ThreadLocal() {}
+};
+
+ThreadLocal<int> GlobalThreadLocal;
+
+void foo() {
+  static ThreadLocal<int> StaticThreadLocal;
+}
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,45 @@
+.. 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;
+
+`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,96 @@
+//===--- 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"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using llvm::StringRef;
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::fuchsia {
+namespace {
+AST_MATCHER(CXXRecordDecl, hasNonTrivialDestructor) {
+  return Node.hasNonTrivialDestructor();
+}
+} // namespace
+
+GlobalVariablesCheck::GlobalVariablesCheck(StringRef Name,
+                                           ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      IgnoreVars(utils::options::parseStringList(Options.get("Ignore", ""))) {}
+
+void GlobalVariablesCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      varDecl(
+          allOf(hasGlobalStorage(), isDefinition()),
+          anyOf(hasType(hasCanonicalType(references(qualType()))),
+                hasType(arrayType()),
+                hasType(cxxRecordDecl(hasNonTrivialDestructor()))),
+          unless(isConstexpr()), unless(isConstinit()),
+          unless(hasAttr(clang::attr::NoDestroy)),
+          unless(hasType(qualType(hasCanonicalType(hasDeclaration(
+              cxxRecordDecl(matchers::matchesAnyListedName(IgnoreVars))))))))
+          .bind("non_trivial_dtor_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 with non-trivial-destructors.
+  if (Decl->getLocation().isMacroID()) {
+    return;
+  }
+
+  // 'thread_local' variables in functions are allowed without restrictions.
+  auto *DeclContext = Decl->getDeclContext();
+  if (!isa<NamespaceDecl>(DeclContext) &&
+      !isa<TranslationUnitDecl>(DeclContext)) {
+    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>("non_trivial_dtor_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