Naysh created this revision.
Naysh added reviewers: EricWF, JonasToth.
Herald added subscribers: cfe-commits, xazax.hun, mgorny.

This patch adds four new, small checks corresponding to the guidelines in 
https://abseil.io/tips/119.

The checks are:

- Alias Free Headers: makes sure header files do not use convenience aliases
- Anonymous Enclosed Aliases: suggests that using declarations be moved to 
existing anonymous namespaces
- Qualified Aliases: suggests using declarations be fully qualified
- Safely Scoped: suggests using declarations be moved to innermost namespaces


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D55346

Files:
  .gitignore
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/AliasFreeHeadersCheck.cpp
  clang-tidy/abseil/AliasFreeHeadersCheck.h
  clang-tidy/abseil/AnonymousEnclosedAliasesCheck.cpp
  clang-tidy/abseil/AnonymousEnclosedAliasesCheck.h
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/QualifiedAliasesCheck.cpp
  clang-tidy/abseil/QualifiedAliasesCheck.h
  clang-tidy/abseil/SafelyScopedCheck.cpp
  clang-tidy/abseil/SafelyScopedCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-alias-free-headers.rst
  docs/clang-tidy/checks/abseil-anonymous-enclosed-aliases.rst
  docs/clang-tidy/checks/abseil-qualified-aliases.rst
  docs/clang-tidy/checks/abseil-safely-scoped.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-alias-free-headers.hpp
  test/clang-tidy/abseil-anonymous-enclosed-aliases.cpp
  test/clang-tidy/abseil-qualified-aliases.cpp
  test/clang-tidy/abseil-safely-scoped.cpp
  test/clang-tidy/temporaries.cpp

Index: test/clang-tidy/temporaries.cpp
===================================================================
--- test/clang-tidy/temporaries.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-// REQUIRES: static-analyzer
-// RUN: clang-tidy -checks='-*,clang-analyzer-core.NullDereference' %s -- | FileCheck %s
-
-struct NoReturnDtor {
-  ~NoReturnDtor() __attribute__((noreturn));
-};
-
-extern bool check(const NoReturnDtor &);
-
-// CHECK-NOT: warning
-void testNullPointerDereferencePositive() {
-  int *value = 0;
-  // CHECK: [[@LINE+1]]:10: warning: Dereference of null pointer (loaded from variable 'value') [clang-analyzer-core.NullDereference]
-  *value = 1;
-}
-
-// CHECK-NOT: warning
-void testNullPointerDereference() {
-  int *value = 0;
-  if (check(NoReturnDtor())) {
-    // This unreachable code causes a warning if analysis of temporary
-    // destructors is not enabled.
-    *value = 1;
-  }
-}
Index: test/clang-tidy/abseil-safely-scoped.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/abseil-safely-scoped.cpp
@@ -0,0 +1,27 @@
+// RUN: %check_clang_tidy %s abseil-safely-scoped %t
+namespace bar {
+
+class something {
+
+};
+}
+
+namespace foo {
+
+using bar::something;
+
+namespace {
+
+}  // anonymous namespace
+}  // namespace foo
+// CHECK-MESSAGES: :[[@LINE-6]]:12: warning: UsingDecl 'something' should be in the innermost scope. See: https://abseil.io/tips/119 [abseil-safely-scoped]
+
+namespace foo {
+
+namespace {
+
+using ::bar::something;
+
+}  // anonymous namespace
+}  // namespace foo
+
Index: test/clang-tidy/abseil-qualified-aliases.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/abseil-qualified-aliases.cpp
@@ -0,0 +1,27 @@
+// RUN: %check_clang_tidy %s abseil-qualified-aliases %t
+
+namespace foo {
+  void f();
+  void correct();
+}
+
+namespace bar {
+  using foo::f;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: using declaration is not fully qualified: see https://abseil.io/tips/119 [abseil-qualified-aliases]
+  using ::foo::correct;
+}
+
+namespace outermost {
+  namespace middle {
+    namespace innermost {
+
+      enum Color {Red, Blue, Yellow};
+
+    } // namespace innermost
+
+    using innermost::Color;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: using declaration is not fully qualified: see https://abseil.io/tips/119 [abseil-qualified-aliases]
+
+  } // namespace middle
+} // namespace example
+
Index: test/clang-tidy/abseil-anonymous-enclosed-aliases.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/abseil-anonymous-enclosed-aliases.cpp
@@ -0,0 +1,27 @@
+// RUN: %check_clang_tidy %s abseil-anonymous-enclosed-aliases %t
+namespace bar {
+
+class something {
+
+};
+}
+
+namespace foo {
+
+using bar::something;
+
+namespace {
+
+}  // anonymous namespace
+}  // namespace foo
+// CHECK-MESSAGES: :[[@LINE-6]]:12: warning: UsingDecl 'something' should be in the anonymous namespace. See: https://abseil.io/tips/119 [abseil-anonymous-enclosed-aliases]
+
+
+namespace foo {
+
+namespace {
+
+using ::bar::something;
+
+}  // anonymous namespace
+}  // namespace foo
Index: test/clang-tidy/abseil-alias-free-headers.hpp
===================================================================
--- /dev/null
+++ test/clang-tidy/abseil-alias-free-headers.hpp
@@ -0,0 +1,10 @@
+// RUN: %check_clang_tidy %s abseil-alias-free-headers %t
+  
+namespace foo {
+  void f();
+}
+
+using foo::f;
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: convenience aliases in header files are dangerous: see http://google.github.io/styleguide/cppguide.html#Aliases [abseil-alias-free-headers]
+
+void other_function();
Index: docs/clang-tidy/checks/list.rst
===================================================================
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -4,14 +4,18 @@
 =================
 
 .. toctree::
+   abseil-alias-free-headers
+   abseil-anonymous-enclosed-aliases
    abseil-duration-division
    abseil-duration-factory-float
    abseil-faster-strsplit-delimiter
    abseil-no-internal-dependencies
    abseil-no-namespace
+   abseil-qualified-aliases
    abseil-redundant-strcat-calls
-   abseil-string-find-startswith
+   abseil-safely-scoped
    abseil-str-cat-append
+   abseil-string-find-startswith
    android-cloexec-accept
    android-cloexec-accept4
    android-cloexec-creat
@@ -151,6 +155,7 @@
    hicpp-special-member-functions (redirects to cppcoreguidelines-special-member-functions) <hicpp-special-member-functions>
    hicpp-static-assert (redirects to misc-static-assert) <hicpp-static-assert>
    hicpp-undelegated-constructor (redirects to bugprone-undelegated-constructor) <hicpp-undelegated-constructor>
+   hicpp-uppercase-literal-suffix (redirects to readability-uppercase-literal-suffix) <hicpp-uppercase-literal-suffix>
    hicpp-use-auto (redirects to modernize-use-auto) <hicpp-use-auto>
    hicpp-use-emplace (redirects to modernize-use-emplace) <hicpp-use-emplace>
    hicpp-use-equals-default (redirects to modernize-use-equals-default) <hicpp-use-equals-default>
@@ -159,7 +164,6 @@
    hicpp-use-nullptr (redirects to modernize-use-nullptr) <hicpp-use-nullptr>
    hicpp-use-override (redirects to modernize-use-override) <hicpp-use-override>
    hicpp-vararg (redirects to cppcoreguidelines-pro-type-vararg) <hicpp-vararg>
-   hicpp-uppercase-literal-suffix (redirects to readability-uppercase-literal-suffix) <hicpp-uppercase-literal-suffix>
    llvm-header-guard
    llvm-include-order
    llvm-namespace-comment
Index: docs/clang-tidy/checks/abseil-safely-scoped.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/abseil-safely-scoped.rst
@@ -0,0 +1,28 @@
+.. title:: clang-tidy - abseil-safely-scoped
+
+abseil-safely-scoped
+====================
+
+Flags using declarations that are not contained in an innermost
+namespace, and suggests these declarations be moved elsewhere.
+
+Example:
+
+.. code-block:: c++
+
+  using something; // should be inside the innermost namespace bar below
+
+  namespace foo {
+  namespace bar {
+	
+  } // bar
+
+  using something_else; // shoulw be inside the innermost namespace bar above
+
+  } // foo
+
+Placing convenience aliases in upper level namespaces can lead to ambiguity in 
+which name the compiler should use. 
+
+See https://abseil.io/tips/119 for more explanation. 
+
Index: docs/clang-tidy/checks/abseil-qualified-aliases.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/abseil-qualified-aliases.rst
@@ -0,0 +1,24 @@
+.. title:: clang-tidy - abseil-qualified-aliases
+
+abseil-qualified-aliases
+========================
+
+Detects using declarations that are not fully qualified, and suggests 
+those declarations be fully qualified. 
+
+Example:
+.. code-block:: c++
+
+  namespace foo {
+    void f();
+    void correct();
+  }
+  
+  namespace bar {
+    using foo::f; // The check produces a warning here. 
+    using ::foo::correct; // The check sees no issue here.
+  }
+
+See https://abseil.io/tips/119 for an in depth justification for this
+check. 
+ 
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/clang-tidy/checks/abseil-alias-free-headers.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/abseil-alias-free-headers.rst
@@ -0,0 +1,10 @@
+.. title:: clang-tidy - abseil-alias-free-headers
+
+abseil-alias-free-headers
+=========================
+
+Flags using declarations in header files, and suggests that these aliases be removed.
+
+A using declaration placed in a header file forces users of that header file
+accept the specified alias. This is bad practice, which is why the check suggests
+such declarations be removed. 
Index: docs/ReleaseNotes.rst
===================================================================
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -67,6 +67,18 @@
 Improvements to clang-tidy
 --------------------------
 
+- New :doc:`abseil-alias-free-headers
+  <clang-tidy/checks/abseil-alias-free-headers>` check.
+
+  Flags using declarations in header files, and suggests that 
+  these aliases be removed.
+
+- New :doc:`abseil-anonymous-enclosed-aliases
+  <clang-tidy/checks/abseil-anonymous-enclosed-aliases>` check.
+
+  Finds using declarations outside of anonymous namespaces, and 
+  suggests those declarations be moved to that namespace.
+
 - New :doc:`abseil-duration-division
   <clang-tidy/checks/abseil-duration-division>` check.
 
@@ -98,12 +110,24 @@
   Ensures code does not open ``namespace absl`` as that violates Abseil's
   compatibility guidelines.
 
+- New :doc:`abseil-qualified-aliases
+  <clang-tidy/checks/abseil-qualified-aliases>` check.
+
+  Detects using declarations that are not fully qualified, and suggests 
+  those declarations be fully qualified.
+
 - New :doc:`abseil-redundant-strcat-calls
   <clang-tidy/checks/abseil-redundant-strcat-calls>` check.
 
   Suggests removal of unnecessary calls to ``absl::StrCat`` when the result is
   being passed to another ``absl::StrCat`` or ``absl::StrAppend``.
 
+- New :doc:`abseil-safely-scoped
+  <clang-tidy/checks/abseil-safely-scoped>` check.
+
+  Flags using declarations that are not contained in an innermost 
+  namespace, and suggests these declarations be moved elsewhere.
+
 - New :doc:`abseil-str-cat-append
   <clang-tidy/checks/abseil-str-cat-append>` check.
 
Index: clang-tidy/abseil/SafelyScopedCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/abseil/SafelyScopedCheck.h
@@ -0,0 +1,36 @@
+//===--- SafelyScopedCheck.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_SAFELYSCOPEDCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_SAFELYSCOPEDCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+/// Detecting using declarations not in a namespace declaration or not in 
+/// the innermost layer of namespace declarations.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/abseil-safely-scoped.html
+class SafelyScopedCheck : public ClangTidyCheck {
+public:
+  SafelyScopedCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_SAFELYSCOPEDCHECK_H
Index: clang-tidy/abseil/SafelyScopedCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/abseil/SafelyScopedCheck.cpp
@@ -0,0 +1,39 @@
+//===--- SafelyScopedCheck.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 "SafelyScopedCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+void SafelyScopedCheck::registerMatchers(MatchFinder *Finder) {
+  // The target using declaration is either:
+  // 1. not in any namespace declaration, or
+  // 2. in some namespace declaration but not in the innermost layer
+  Finder->addMatcher(usingDecl(eachOf( 
+  	usingDecl(unless(hasParent(namespaceDecl()))),
+    usingDecl(hasParent(namespaceDecl(forEach(namespaceDecl())))) )
+    ).bind("use"), this);
+}
+
+void SafelyScopedCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedDecl = Result.Nodes.getNodeAs<UsingDecl>("use");
+  diag(MatchedDecl->getLocation(), "UsingDecl %0 should be in the innermost "
+    "scope. See: https://abseil.io/tips/119";)
+      << MatchedDecl;
+}
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/abseil/QualifiedAliasesCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/abseil/QualifiedAliasesCheck.h
@@ -0,0 +1,35 @@
+//===--- QualifiedAliasesCheck.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_QUALIFIEDALIASESCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_QUALIFIEDALIASESCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+/// FIXME: Write a short description.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/abseil-qualified-aliases.html
+class QualifiedAliasesCheck : public ClangTidyCheck {
+public:
+  QualifiedAliasesCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_QUALIFIEDALIASESCHECK_H
Index: clang-tidy/abseil/QualifiedAliasesCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/abseil/QualifiedAliasesCheck.cpp
@@ -0,0 +1,50 @@
+//===--- QualifiedAliasesCheck.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 "QualifiedAliasesCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+#include <string>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+void QualifiedAliasesCheck::registerMatchers(MatchFinder *Finder) {
+  // Looks for all using declarations.
+  Finder->addMatcher(usingDecl().bind("x"), this);
+}
+
+void QualifiedAliasesCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedDecl = Result.Nodes.getNodeAs<UsingDecl>("x");
+
+  // Finds the nested-name-specifier location.
+  const NestedNameSpecifierLoc QualifiedLoc = MatchedDecl->getQualifierLoc();
+  const SourceLocation FrontLoc = QualifiedLoc.getBeginLoc();
+
+  // Ignores the using declaration if its fully qualified.
+  const SourceManager *SM = Result.SourceManager;
+  CharSourceRange FrontRange = CharSourceRange();
+  FrontRange.setBegin(FrontLoc);
+  FrontRange.setEnd(FrontLoc.getLocWithOffset(2));
+  llvm::StringRef Beg = Lexer::getSourceText(FrontRange, *SM, LangOptions());
+
+  if (Beg.startswith("::"))
+    return;
+ 
+  diag(FrontLoc, "using declaration is not fully qualified: see "
+  "https://abseil.io/tips/119";);
+}
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/abseil/CMakeLists.txt
===================================================================
--- clang-tidy/abseil/CMakeLists.txt
+++ clang-tidy/abseil/CMakeLists.txt
@@ -2,12 +2,16 @@
 
 add_clang_library(clangTidyAbseilModule
   AbseilTidyModule.cpp
+  AliasFreeHeadersCheck.cpp
+  AnonymousEnclosedAliasesCheck.cpp
   DurationDivisionCheck.cpp
   DurationFactoryFloatCheck.cpp
   FasterStrsplitDelimiterCheck.cpp
   NoInternalDependenciesCheck.cpp
   NoNamespaceCheck.cpp
+  QualifiedAliasesCheck.cpp
   RedundantStrcatCallsCheck.cpp
+  SafelyScopedCheck.cpp
   StrCatAppendCheck.cpp
   StringFindStartswithCheck.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,67 @@
+//===--- 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 nodes: 
+  // 1. anonymous namespace declarations,
+  // 2. using declarations that are not inside an anonymous declaration
+  Finder->addMatcher(
+  	namespaceDecl(isAnonymous()).bind("anonymous_namespace"), this);
+  Finder->addMatcher(
+  	usingDecl(unless(hasAncestor(
+  		namespaceDecl(isAnonymous())))).bind("using_decl"), this);
+}
+
+
+void AnonymousEnclosedAliasesCheck::check(const MatchFinder::MatchResult &Result) {
+  
+  const UsingDecl *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(), 
+  			"UsingDecl %0 should be in the anonymous namespace") 
+  			<< 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 UsingDecl* CurrentUsingDecl: MatchedUsingDecls) {
+  	diag(CurrentUsingDecl->getLocation(), 
+  		"UsingDecl %0 should be in the anonymous namespace. See: "
+      "https://abseil.io/tips/119";)
+  		<< CurrentUsingDecl;
+	}
+}
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/abseil/AliasFreeHeadersCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/abseil/AliasFreeHeadersCheck.h
@@ -0,0 +1,35 @@
+//===--- AliasFreeHeadersCheck.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_ALIASFREEHEADERSCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_ALIASFREEHEADERSCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+/// FIXME: Write a short description.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/abseil-alias-free-headers.html
+class AliasFreeHeadersCheck : public ClangTidyCheck {
+public:
+  AliasFreeHeadersCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_ALIASFREEHEADERSCHECK_H
Index: clang-tidy/abseil/AliasFreeHeadersCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/abseil/AliasFreeHeadersCheck.cpp
@@ -0,0 +1,34 @@
+//===--- AliasFreeHeadersCheck.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 "AliasFreeHeadersCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+void AliasFreeHeadersCheck::registerMatchers(MatchFinder *Finder) {
+  // Match using declarations in header files.
+  Finder->addMatcher(usingDecl(isExpansionInFileMatching(".*\\.h.*")).bind("x"), 
+    this);
+}
+
+void AliasFreeHeadersCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedDecl = Result.Nodes.getNodeAs<UsingDecl>("x");
+  diag(MatchedDecl->getLocation(), "convenience aliases in header files are "
+"dangerous: see http://google.github.io/styleguide/cppguide.html#Aliases";);
+}
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/abseil/AbseilTidyModule.cpp
===================================================================
--- clang-tidy/abseil/AbseilTidyModule.cpp
+++ clang-tidy/abseil/AbseilTidyModule.cpp
@@ -10,12 +10,16 @@
 #include "../ClangTidy.h"
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
+#include "AliasFreeHeadersCheck.h"
+#include "AnonymousEnclosedAliasesCheck.h"
 #include "DurationDivisionCheck.h"
 #include "DurationFactoryFloatCheck.h"
 #include "FasterStrsplitDelimiterCheck.h"
 #include "NoInternalDependenciesCheck.h"
 #include "NoNamespaceCheck.h"
+#include "QualifiedAliasesCheck.h"
 #include "RedundantStrcatCallsCheck.h"
+#include "SafelyScopedCheck.h"
 #include "StringFindStartswithCheck.h"
 #include "StrCatAppendCheck.h"
 
@@ -26,6 +30,10 @@
 class AbseilModule : public ClangTidyModule {
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<AliasFreeHeadersCheck>(
+        "abseil-alias-free-headers");
+    CheckFactories.registerCheck<AnonymousEnclosedAliasesCheck>(
+        "abseil-anonymous-enclosed-aliases");
     CheckFactories.registerCheck<DurationDivisionCheck>(
         "abseil-duration-division");
     CheckFactories.registerCheck<DurationFactoryFloatCheck>(
@@ -35,8 +43,12 @@
     CheckFactories.registerCheck<NoInternalDependenciesCheck>(
         "abseil-no-internal-dependencies");
     CheckFactories.registerCheck<NoNamespaceCheck>("abseil-no-namespace");
+    CheckFactories.registerCheck<QualifiedAliasesCheck>(
+        "abseil-qualified-aliases");
     CheckFactories.registerCheck<RedundantStrcatCallsCheck>(
         "abseil-redundant-strcat-calls");
+    CheckFactories.registerCheck<SafelyScopedCheck>(
+        "abseil-safely-scoped");
     CheckFactories.registerCheck<StrCatAppendCheck>(
         "abseil-str-cat-append");
     CheckFactories.registerCheck<StringFindStartswithCheck>(
Index: .gitignore
===================================================================
--- .gitignore
+++ .gitignore
@@ -18,6 +18,8 @@
 # vim swap files
 .*.swp
 .sw?
+# Others
+.DS_Store
 
 #==============================================================================#
 # Explicit files to ignore (only matches one).
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to