juliehockett created this revision.
juliehockett added reviewers: aaron.ballman, hokein, ilya-biryukov.
juliehockett added a project: clang-tools-extra.
Herald added subscribers: xazax.hun, mgorny.

Adds a checker to warn against using the std namespace, as Zircon's kernel 
lib++ policy does not allow it. Written documentation of the policy is not yet 
published, I will add the link when it is.


https://reviews.llvm.org/D53882

Files:
  clang-tools-extra/clang-tidy/zircon/CMakeLists.txt
  clang-tools-extra/clang-tidy/zircon/NoStdNamespaceCheck.cpp
  clang-tools-extra/clang-tidy/zircon/NoStdNamespaceCheck.h
  clang-tools-extra/clang-tidy/zircon/ZirconTidyModule.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/zircon-no-std-namespace.rst
  clang-tools-extra/test/clang-tidy/zircon-no-std-namespace.cpp

Index: clang-tools-extra/test/clang-tidy/zircon-no-std-namespace.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/zircon-no-std-namespace.cpp
@@ -0,0 +1,50 @@
+// RUN: %check_clang_tidy %s zircon-no-std-namespace %t
+
+int func() { return 1; }
+
+namespace std {
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use of the 'std' namespace is not allowed in Zircon kernel code
+
+typedef int std_int;
+int std_func() { return 1; }
+
+int a = 1;
+int b = func();
+std_int c;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use of the 'std' namespace is not allowed in Zircon kernel code
+int d = std_func();
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use of the 'std' namespace is not allowed in Zircon kernel code
+
+}
+
+// Warn on uses of quailfied std namespace.
+int i = 1;
+int j = func();
+std::std_int k;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use of the 'std' namespace is not allowed in Zircon kernel code
+int l = std::std_func();
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use of the 'std' namespace is not allowed in Zircon kernel code
+
+
+namespace foo {
+
+int w = 1;
+int x = func();
+std::std_int y;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use of the 'std' namespace is not allowed in Zircon kernel code
+int z = std::std_func();
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use of the 'std' namespace is not allowed in Zircon kernel code
+
+}
+
+// Warn on the alias declaration, and on users of it.
+namespace bar = std;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use of the 'std' namespace is not allowed in Zircon kernel code
+bar::std_int q;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use of the 'std' namespace is not allowed in Zircon kernel code
+
+// Warn on the using declaration, and on users of it.
+using namespace std;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use of the 'std' namespace is not allowed in Zircon kernel code
+std_int r = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use of the 'std' namespace is not allowed in Zircon kernel code
Index: clang-tools-extra/docs/clang-tidy/checks/zircon-no-std-namespace.rst
===================================================================
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/zircon-no-std-namespace.rst
@@ -0,0 +1,29 @@
+.. title:: clang-tidy - zircon-no-std-namespace
+
+zircon-no-std-namespace
+=======================
+
+Ensures code does not open ``namespace std`` as that violates Zircon's
+kernel libc++ policy. 
+
+Any code that uses:
+
+.. code-block:: c++
+
+ namespace std {
+  ...
+ }
+
+or 
+
+.. code-block:: c++
+
+ using namespace std;
+
+or uses a declaration from the ``std`` namespace:
+
+.. code-block:: c++
+
+ std::string foo;
+
+will be prompted with a warning.
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
@@ -252,4 +252,5 @@
    readability-string-compare
    readability-uniqueptr-delete-release
    readability-uppercase-literal-suffix
+   zircon-no-std-namespace
    zircon-temporary-objects
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -170,6 +170,12 @@
   <clang-tidy/checks/readability-redundant-smartptr-get>` check does not warn
   about calls inside macros anymore by default.
 
+- New :doc:`zircon-no-std-namespace
+  <clang-tidy/checks/zircon-no-std-namespace>` check.
+
+  Warns when the `std` namespace is used, as its use is against Zircon's libc++
+  policy for the kernel.
+
 Improvements to include-fixer
 -----------------------------
 
Index: clang-tools-extra/clang-tidy/zircon/ZirconTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/zircon/ZirconTidyModule.cpp
+++ clang-tools-extra/clang-tidy/zircon/ZirconTidyModule.cpp
@@ -10,6 +10,7 @@
 #include "../ClangTidy.h"
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
+#include "NoStdNamespaceCheck.h"
 #include "TemporaryObjectsCheck.h"
 
 using namespace clang::ast_matchers;
@@ -24,6 +25,8 @@
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
     CheckFactories.registerCheck<TemporaryObjectsCheck>(
         "zircon-temporary-objects");
+    CheckFactories.registerCheck<NoStdNamespaceCheck>(
+        "zircon-no-std-namespace");
   }
 };
 
Index: clang-tools-extra/clang-tidy/zircon/NoStdNamespaceCheck.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/zircon/NoStdNamespaceCheck.h
@@ -0,0 +1,37 @@
+//===--- NoStdNamespace.h - clang-tidy---------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ZIRCON_NOSTDNAMESPACECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ZIRCON_NOSTDNAMESPACECHECK_H
+
+#include "../ClangTidy.h"
+#include "../utils/OptionsUtils.h"
+
+namespace clang {
+namespace tidy {
+namespace zircon {
+
+/// Use of the std namespace is not allowed in the Zircon kernel according to
+/// its libc++ policy.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/zircon-no-std-namespace.html
+class NoStdNamespaceCheck : public ClangTidyCheck {
+public:
+  NoStdNamespaceCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace zircon
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ZIRCON_NOSTDNAMESPACECHECK_H
Index: clang-tools-extra/clang-tidy/zircon/NoStdNamespaceCheck.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/zircon/NoStdNamespaceCheck.cpp
@@ -0,0 +1,90 @@
+//===--- NoStdNamespaceCheck.cpp - clang-tidy------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "NoStdNamespaceCheck.h"
+#include "../utils/OptionsUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include <string>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace zircon {
+
+namespace {
+
+AST_MATCHER(NamespaceDecl, isStdNamespace) { return Node.isStdNamespace(); }
+
+AST_MATCHER(NamespaceAliasDecl, isAliasedToStd) {
+  if (const auto *AN = Node.getAliasedNamespace()) {
+    // If this aliases to an actual namespace, check if its std. If it doesn't,
+    // it aliases to another alias and thus shouldn't be flagged.
+    if (const auto *N = dyn_cast<NamespaceDecl>(AN))
+      return N->isStdNamespace();
+  }
+  return false;
+}
+
+AST_MATCHER_P(UsingDirectiveDecl, redirectsTo,
+              ast_matchers::internal::Matcher<NamespaceDecl>, InnerMatcher) {
+  if (const auto *N = Node.getNominatedNamespace())
+    return InnerMatcher.matches(*N, Finder, Builder);
+  return false;
+}
+
+} // namespace
+
+void NoStdNamespaceCheck::registerMatchers(MatchFinder *Finder) {
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  // Match all values scoped to std namespace.
+  Finder->addMatcher(
+      valueDecl(hasType(decl(hasDeclContext(namespaceDecl(isStdNamespace())))))
+          .bind("stdVar"),
+      this);
+  Finder->addMatcher(namespaceDecl(isStdNamespace()).bind("stdNamespace"),
+                     this);
+  Finder->addMatcher(callExpr(callee(functionDecl(hasDeclContext(
+                                  namespaceDecl(isStdNamespace())))))
+                         .bind("stdCall"),
+                     this);
+  Finder->addMatcher(namespaceAliasDecl(isAliasedToStd()).bind("stdAlias"),
+                     this);
+  Finder->addMatcher(
+      usingDirectiveDecl(redirectsTo(namespaceDecl(isStdNamespace())))
+          .bind("stdUsing"),
+      this);
+}
+
+void NoStdNamespaceCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *D = Result.Nodes.getNodeAs<ValueDecl>("stdVar"))
+    diag(D->getBeginLoc(),
+         "use of the 'std' namespace is not allowed in Zircon kernel code");
+  if (const auto *D = Result.Nodes.getNodeAs<NamespaceDecl>("stdNamespace"))
+    diag(D->getLocation(),
+         "use of the 'std' namespace is not allowed in Zircon kernel code");
+  if (const auto *D = Result.Nodes.getNodeAs<CallExpr>("stdCall"))
+    diag(D->getBeginLoc(),
+         "use of the 'std' namespace is not allowed in Zircon kernel code");
+  if (const auto *D = Result.Nodes.getNodeAs<NamespaceAliasDecl>("stdAlias"))
+    diag(D->getTargetNameLoc(),
+         "use of the 'std' namespace is not allowed in Zircon kernel code");
+  if (const auto *D = Result.Nodes.getNodeAs<UsingDirectiveDecl>("stdUsing"))
+    diag(D->getLocation(),
+         "use of the 'std' namespace is not allowed in Zircon kernel code");
+}
+
+} // namespace zircon
+} // namespace tidy
+} // namespace clang
Index: clang-tools-extra/clang-tidy/zircon/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/zircon/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/zircon/CMakeLists.txt
@@ -1,6 +1,7 @@
 set(LLVM_LINK_COMPONENTS support)
 
 add_clang_library(clangTidyZirconModule
+  NoStdNamespaceCheck.cpp
   TemporaryObjectsCheck.cpp
   ZirconTidyModule.cpp
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to