Ywicheng updated this revision to Diff 195656.

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

https://reviews.llvm.org/D55409

Files:
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/AnonymousEnclosedAliasesCheck.cpp
  clang-tidy/abseil/AnonymousEnclosedAliasesCheck.h
  clang-tidy/abseil/CMakeLists.txt
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-anonymous-enclosed-aliases.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-anonymous-enclosed-aliases.cpp

Index: test/clang-tidy/abseil-anonymous-enclosed-aliases.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/abseil-anonymous-enclosed-aliases.cpp
@@ -0,0 +1,56 @@
+// RUN: %check_clang_tidy %s abseil-anonymous-enclosed-aliases %t
+namespace bar {
+
+class A {};
+class B {};
+
+} // namespace bar
+
+namespace foo1 {
+
+// CHECK-MESSAGES: :[[@LINE+4]]:12: warning: using declaration 'A' should
+// be in the anonymous namespace. Use discretion when moving using declarations
+// as it might necessitate moving lines containing relevant aliases.
+// [abseil-anonymous-enclosed-aliases]
+using bar::A;
+void f(A a);
+
+namespace {} // anonymous namespace
+
+} // namespace foo1
+
+namespace foo2 {
+
+namespace {
+
+// This is okay
+using ::bar::B;
+
+} // anonymous namespace
+
+void g(B b);
+
+} // namespace foo2
+
+// Check should not be triggered below when the using declaration is at
+// function or class (instead of namespace) scope.
+namespace outer {
+
+int fun_scope() {
+  using ::bar::A;
+  return 0;
+} // function scope
+
+class Base {
+public:
+  void f();
+}; // class scope
+
+class Derived : public Base {
+public:
+  using Base::f;
+}; // class scope
+
+namespace {} // anonymous namespace
+
+} // namespace outer
\ No newline at end of file
Index: docs/clang-tidy/checks/list.rst
===================================================================
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -4,6 +4,7 @@
 =================
 
 .. toctree::
+   abseil-anonymous-enclosed-aliases
    abseil-duration-addition
    abseil-duration-comparison
    abseil-duration-conversion-cast
Index: docs/clang-tidy/checks/abseil-anonymous-enclosed-aliases.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/abseil-anonymous-enclosed-aliases.rst
@@ -0,0 +1,20 @@
+.. title:: clang-tidy - abseil-anonymous-enclosed-aliases
+
+abseil-anonymous-enclosed-aliases
+=================================
+
+Finds using declarations outside of anonymous namespaces, and
+suggests those declarations be moved to that namespace.
+
+Example:
+.. code-block:: c++
+
+  namespace foo {
+  
+  using something; // should be inside the anonymous namespace below
+
+  namespace {
+
+  } // anonymous namespace
+
+  } // foo
Index: docs/ReleaseNotes.rst
===================================================================
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -67,6 +67,12 @@
 Improvements to clang-tidy
 --------------------------
 
+- New :doc:`abseil-anonymous-enclosed-aliases
+  <clang-tidy/checks/abseil-anonymous-enclosed-aliases>` check.
+
+  Finds instances of using declarations not in an anonymous namespace
+  when there exists one.
+
 - New :doc:`abseil-duration-addition
   <clang-tidy/checks/abseil-duration-addition>` check.
 
Index: clang-tidy/abseil/CMakeLists.txt
===================================================================
--- clang-tidy/abseil/CMakeLists.txt
+++ clang-tidy/abseil/CMakeLists.txt
@@ -2,6 +2,7 @@
 
 add_clang_library(clangTidyAbseilModule
   AbseilTidyModule.cpp
+  AnonymousEnclosedAliasesCheck.cpp
   DurationAdditionCheck.cpp
   DurationComparisonCheck.cpp
   DurationConversionCastCheck.cpp
Index: clang-tidy/abseil/AnonymousEnclosedAliasesCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/abseil/AnonymousEnclosedAliasesCheck.h
@@ -0,0 +1,40 @@
+//===--- AnonymousEnclosedAliasesCheck.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_ABSEIL_ANONYMOUSENCLOSEDALIASESCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_ANONYMOUSENCLOSEDALIASESCHECK_H
+
+#include "../ClangTidy.h"
+#include <vector>
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+/// Detecting incorrect practice of putting using declarations outside an
+/// anonymous namespace when there exists one.
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/
+/// abseil-anonymous-enclosed-aliases.html
+class AnonymousEnclosedAliasesCheck : public ClangTidyCheck {
+public:
+  AnonymousEnclosedAliasesCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+private:
+  const NamespaceDecl* AnonymousNamespaceDecl;
+  std::vector<const UsingDecl*> MatchedUsingDecls;
+};
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_ANONYMOUSENCLOSEDALIASESCHECK_H
Index: clang-tidy/abseil/AnonymousEnclosedAliasesCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/abseil/AnonymousEnclosedAliasesCheck.cpp
@@ -0,0 +1,79 @@
+//===--- AnonymousEnclosedAliasesCheck.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 "AnonymousEnclosedAliasesCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+void AnonymousEnclosedAliasesCheck::registerMatchers(MatchFinder *Finder) {
+  // We try to match two types of nodes:
+  // 1. anonymous namespace declarations,
+  // 2. using declarations that are not inside an anonymous namespace and
+  // not inside any other scope.
+  Finder->addMatcher(
+      namespaceDecl(allOf(namespaceDecl(isAnonymous()),
+                          namespaceDecl(isExpansionInMainFile())))
+          .bind("anonymous_namespace"),
+      this);
+  Finder->addMatcher(
+      usingDecl(
+          allOf(usingDecl(isExpansionInMainFile()),
+                usingDecl(unless(hasAncestor(functionDecl()))),
+                usingDecl(unless(hasAncestor(cxxRecordDecl()))),
+                usingDecl(unless(hasAncestor(namespaceDecl(isAnonymous()))))))
+          .bind("using_decl"),
+      this);
+}
+
+void AnonymousEnclosedAliasesCheck::check(
+    const MatchFinder::MatchResult &Result) {
+
+  const auto *MatchedUsingDecl =
+      Result.Nodes.getNodeAs<UsingDecl>("using_decl");
+  // If a potential using declaration is matched,
+  if (MatchedUsingDecl) {
+    // and if an anonymous namespace declaration has already been found,
+    // the matched using declaration is a target, and we print out
+    // the diagnostics for it. Otherwise, we add the using declaration
+    // to the vector containing all candidate using declarations.
+    if (AnonymousNamespaceDecl) {
+      diag(MatchedUsingDecl->getLocation(),
+           "using declaration %0 should be in the anonymous namespace. "
+           "Use discretion when moving using declarations as it might "
+           "necessitate moving lines containing relevant aliases.")
+          << MatchedUsingDecl;
+    } else {
+      MatchedUsingDecls.push_back(MatchedUsingDecl);
+    }
+    return;
+  }
+  // Otherwise, an anonymous namespace declaration is matched. In this case,
+  // all the previously matched namespace declarations in the vector
+  // CurrentUsingDecl are our targets, and we print out the
+  // diagnostics for all of them.
+  AnonymousNamespaceDecl =
+      Result.Nodes.getNodeAs<NamespaceDecl>("anonymous_namespace");
+  for (const auto *CurrentUsingDecl : MatchedUsingDecls) {
+    diag(CurrentUsingDecl->getLocation(),
+         "using declaration %0 should be in the anonymous namespace. "
+         "Use discretion when moving using declarations as it might "
+         "necessitate moving lines containing relevant aliases.")
+        << CurrentUsingDecl;
+  }
+}
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/abseil/AbseilTidyModule.cpp
===================================================================
--- clang-tidy/abseil/AbseilTidyModule.cpp
+++ clang-tidy/abseil/AbseilTidyModule.cpp
@@ -9,6 +9,7 @@
 #include "../ClangTidy.h"
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
+#include "AnonymousEnclosedAliasesCheck.h"
 #include "DurationAdditionCheck.h"
 #include "DurationComparisonCheck.h"
 #include "DurationConversionCastCheck.h"
@@ -33,6 +34,8 @@
 class AbseilModule : public ClangTidyModule {
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<AnonymousEnclosedAliasesCheck>(
+        "abseil-anonymous-enclosed-aliases");
     CheckFactories.registerCheck<DurationAdditionCheck>(
         "abseil-duration-addition");
     CheckFactories.registerCheck<DurationComparisonCheck>(
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to