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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits