Make google-build-using-namespace skip std::.*literals
authorAlexander Kornienko <alexfh@google.com>
Mon, 15 May 2017 17:37:48 +0000 (17:37 +0000)
committerAlexander Kornienko <alexfh@google.com>
Mon, 15 May 2017 17:37:48 +0000 (17:37 +0000)
Summary:
C++14 added a couple of user-defined literals in the standard library. E.g.
std::chrono_literals and std::literals::chrono_literals . Using them
requires a using directive so do not warn in google-build-using-namespace
if namespace name starts with "std::" and ends with "literals".

Reviewers: alexfh

Reviewed By: alexfh

Subscribers: cfe-commits

Patch by Martin Ejdestig!

Differential Revision: https://reviews.llvm.org/D33010

llvm-svn: 303085

clang-tools-extra/clang-tidy/google/UsingNamespaceDirectiveCheck.cpp
clang-tools-extra/clang-tidy/google/UsingNamespaceDirectiveCheck.h
clang-tools-extra/test/clang-tidy/google-namespaces.cpp

index 6fc6fd3..60a46f8 100644 (file)
@@ -34,12 +34,32 @@ void UsingNamespaceDirectiveCheck::check(
   if (U->isImplicit() || !Loc.isValid())
     return;
 
+  // Do not warn if namespace is a std namespace with user-defined literals. The
+  // user-defined literals can only be used with a using directive.
+  if (isStdLiteralsNamespace(U->getNominatedNamespace()))
+    return;
+
   diag(Loc, "do not use namespace using-directives; "
             "use using-declarations instead");
   // TODO: We could suggest a list of using directives replacing the using
   //       namespace directive.
 }
 
+bool UsingNamespaceDirectiveCheck::isStdLiteralsNamespace(
+    const NamespaceDecl *NS) {
+  if (!NS->getName().endswith("literals"))
+    return false;
+
+  const auto *Parent = dyn_cast_or_null<NamespaceDecl>(NS->getParent());
+  if (!Parent)
+    return false;
+
+  if (Parent->isStdNamespace())
+    return true;
+
+  return Parent->getName() == "literals" && Parent->getParent() &&
+         Parent->getParent()->isStdNamespace();
+}
 } // namespace build
 } // namespace google
 } // namespace tidy
index a36f380..2be65c1 100644 (file)
@@ -38,6 +38,9 @@ public:
       : ClangTidyCheck(Name, Context) {}
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  static bool isStdLiteralsNamespace(const NamespaceDecl *NS);
 };
 
 } // namespace build
index 891aee3..9bda3c0 100644 (file)
@@ -6,3 +6,47 @@ using namespace spaaaace;
 // CHECK: :[[@LINE-1]]:1: warning: do not use namespace using-directives; use using-declarations instead [google-build-using-namespace]
 
 using spaaaace::core; // no-warning
+
+namespace std {
+inline namespace literals {
+inline namespace chrono_literals {
+}
+inline namespace complex_literals {
+}
+inline namespace string_literals {
+}
+}
+}
+
+using namespace std::chrono_literals;            // no-warning
+using namespace std::complex_literals;           // no-warning
+using namespace std::literals;                   // no-warning
+using namespace std::literals::chrono_literals;  // no-warning
+using namespace std::literals::complex_literals; // no-warning
+using namespace std::literals::string_literals;  // no-warning
+using namespace std::string_literals;            // no-warning
+
+namespace literals {}
+
+using namespace literals;
+// CHECK: :[[@LINE-1]]:1: warning: do not use namespace using-directives; use using-declarations instead [google-build-using-namespace]
+
+namespace foo {
+inline namespace literals {
+inline namespace bar_literals {}
+}
+}
+
+using namespace foo::literals;
+// CHECK: :[[@LINE-1]]:1: warning: do not use namespace using-directives; use using-declarations instead [google-build-using-namespace]
+
+using namespace foo::bar_literals;
+// CHECK: :[[@LINE-1]]:1: warning: do not use namespace using-directives; use using-declarations instead [google-build-using-namespace]
+
+using namespace foo::literals::bar_literals;
+// CHECK: :[[@LINE-1]]:1: warning: do not use namespace using-directives; use using-declarations instead [google-build-using-namespace]
+
+namespace foo_literals {}
+
+using namespace foo_literals;
+// CHECK: :[[@LINE-1]]:1: warning: do not use namespace using-directives; use using-declarations instead [google-build-using-namespace]