<div dir="ltr">Yes, I know. Trying to come up with a good solution.</div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Feb 25, 2016 at 4:59 AM, Sean Silva <span dir="ltr"><<a href="mailto:chisophugis@gmail.com" target="_blank">chisophugis@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">This or r<span style="font-size:12.8px">261737</span> seem to be causing a bot failure: <a href="http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast/builds/636" target="_blank">http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast/builds/636</a><span class="HOEnZb"><font color="#888888"><div><br></div><div>-- Sean Silva</div></font></span></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Feb 24, 2016 at 5:35 AM, Alexander Kornienko via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: alexfh<br>
Date: Wed Feb 24 07:35:32 2016<br>
New Revision: 261737<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=261737&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=261737&view=rev</a><br>
Log:<br>
[clang-tidy] Added a check for forward declaration in the potentially wrong namespace<br>
<br>
Adds a new check "misc-forward-declaration-namespace".<br>
In check, A forward declaration is considerred in a potentially wrong namespace<br>
if there is any definition/declaration with the same name exists in a different<br>
namespace.<br>
<br>
Reviewers: akuegel, hokein, alexfh<br>
<br>
Patch by Eric Liu!<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D17195" rel="noreferrer" target="_blank">http://reviews.llvm.org/D17195</a><br>
<br>
Added:<br>
    clang-tools-extra/trunk/clang-tidy/misc/ForwardDeclarationNamespaceCheck.cpp<br>
    clang-tools-extra/trunk/clang-tidy/misc/ForwardDeclarationNamespaceCheck.h<br>
    clang-tools-extra/trunk/docs/clang-tidy/checks/misc-forward-declaration-namespace.rst<br>
    clang-tools-extra/trunk/test/clang-tidy/misc-forward-declaration-namespace.cpp<br>
Modified:<br>
    clang-tools-extra/trunk/clang-tidy/misc/CMakeLists.txt<br>
    clang-tools-extra/trunk/clang-tidy/misc/MiscTidyModule.cpp<br>
    clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst<br>
<br>
Modified: clang-tools-extra/trunk/clang-tidy/misc/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/CMakeLists.txt?rev=261737&r1=261736&r2=261737&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/CMakeLists.txt?rev=261737&r1=261736&r2=261737&view=diff</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/clang-tidy/misc/CMakeLists.txt (original)<br>
+++ clang-tools-extra/trunk/clang-tidy/misc/CMakeLists.txt Wed Feb 24 07:35:32 2016<br>
@@ -6,6 +6,7 @@ add_clang_library(clangTidyMiscModule<br>
   AssignOperatorSignatureCheck.cpp<br>
   BoolPointerImplicitConversionCheck.cpp<br>
   DefinitionsInHeadersCheck.cpp<br>
+  ForwardDeclarationNamespaceCheck.cpp<br>
   InaccurateEraseCheck.cpp<br>
   IncorrectRoundings.cpp<br>
   InefficientAlgorithmCheck.cpp<br>
<br>
Added: clang-tools-extra/trunk/clang-tidy/misc/ForwardDeclarationNamespaceCheck.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/ForwardDeclarationNamespaceCheck.cpp?rev=261737&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/ForwardDeclarationNamespaceCheck.cpp?rev=261737&view=auto</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/clang-tidy/misc/ForwardDeclarationNamespaceCheck.cpp (added)<br>
+++ clang-tools-extra/trunk/clang-tidy/misc/ForwardDeclarationNamespaceCheck.cpp Wed Feb 24 07:35:32 2016<br>
@@ -0,0 +1,174 @@<br>
+//===--- ForwardDeclarationNamespaceCheck.cpp - clang-tidy ------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "ForwardDeclarationNamespaceCheck.h"<br>
+#include <stack><br>
+#include <string><br>
+#include "clang/AST/ASTContext.h"<br>
+#include "clang/AST/Decl.h"<br>
+#include "clang/ASTMatchers/ASTMatchFinder.h"<br>
+#include "clang/ASTMatchers/ASTMatchers.h"<br>
+<br>
+using namespace clang::ast_matchers;<br>
+<br>
+namespace clang {<br>
+namespace tidy {<br>
+namespace misc {<br>
+<br>
+void ForwardDeclarationNamespaceCheck::registerMatchers(MatchFinder *Finder) {<br>
+  // Match all class declarations/definitions *EXCEPT*<br>
+  // 1. implicit classes, e.g. `class A {};` has implicit `class A` inside `A`.<br>
+  // 2. nested classes declared/defined inside another class.<br>
+  // 3. template class declaration, template instantiation or<br>
+  //    specialization (NOTE: extern specialization is filtered out by<br>
+  //    `unless(hasAncestor(cxxRecordDecl()))`).<br>
+  auto IsInSpecialization = hasAncestor(<br>
+      decl(anyOf(cxxRecordDecl(isExplicitTemplateSpecialization()),<br>
+                 functionDecl(isExplicitTemplateSpecialization()))));<br>
+  Finder->addMatcher(<br>
+      cxxRecordDecl(<br>
+          hasParent(decl(anyOf(namespaceDecl(), translationUnitDecl()))),<br>
+          unless(isImplicit()), unless(hasAncestor(cxxRecordDecl())),<br>
+          unless(isInstantiated()), unless(IsInSpecialization),<br>
+          unless(classTemplateSpecializationDecl()))<br>
+          .bind("record_decl"),<br>
+      this);<br>
+<br>
+  // Match all friend declarations. Classes used in friend declarations are not<br>
+  // marked as referenced in AST. We need to record all record classes used in<br>
+  // friend declarations.<br>
+  Finder->addMatcher(friendDecl().bind("friend_decl"), this);<br>
+}<br>
+<br>
+void ForwardDeclarationNamespaceCheck::check(<br>
+    const MatchFinder::MatchResult &Result) {<br>
+  if (const auto *RecordDecl =<br>
+          Result.Nodes.getNodeAs<CXXRecordDecl>("record_decl")) {<br>
+    StringRef DeclName = RecordDecl->getName();<br>
+    if (RecordDecl->isThisDeclarationADefinition()) {<br>
+      DeclNameToDefinitions[DeclName].push_back(RecordDecl);<br>
+    } else {<br>
+      // If a declaration has no definition, the definition could be in another<br>
+      // namespace (a wrong namespace).<br>
+      // NOTE: even a declaration does have definition, we still need it to<br>
+      // compare with other declarations.<br>
+      DeclNameToDeclarations[DeclName].push_back(RecordDecl);<br>
+    }<br>
+  } else {<br>
+    const auto *Decl = Result.Nodes.getNodeAs<FriendDecl>("friend_decl");<br>
+    assert(Decl && "Decl is neither record_decl nor friend decl!");<br>
+<br>
+    // Classes used in friend delarations are not marked referenced in AST,<br>
+    // so we need to check classes used in friend declarations manually to<br>
+    // reduce the rate of false positive.<br>
+    // For example, in<br>
+    //    \code<br>
+    //      struct A;<br>
+    //      struct B { friend A; };<br>
+    //    \endcode<br>
+    // `A` will not be marked as "referenced" in the AST.<br>
+    if (const TypeSourceInfo *Tsi = Decl->getFriendType()) {<br>
+      QualType Desugared = Tsi->getType().getDesugaredType(*Result.Context);<br>
+      FriendTypes.insert(Desugared.getTypePtr());<br>
+    }<br>
+  }<br>
+}<br>
+<br>
+static bool haveSameNamespaceOrTranslationUnit(const CXXRecordDecl *Decl1,<br>
+                                               const CXXRecordDecl *Decl2) {<br>
+  const DeclContext *ParentDecl1 = Decl1->getLexicalParent();<br>
+  const DeclContext *ParentDecl2 = Decl2->getLexicalParent();<br>
+<br>
+  // Since we only matched declarations whose parent is Namespace or<br>
+  // TranslationUnit declaration, the parent should be either a translation unit<br>
+  // or namespace.<br>
+  if (ParentDecl1->getDeclKind() == Decl::TranslationUnit ||<br>
+      ParentDecl2->getDeclKind() == Decl::TranslationUnit) {<br>
+    return ParentDecl1 == ParentDecl2;<br>
+  }<br>
+  assert(ParentDecl1->getDeclKind() == Decl::Namespace &&<br>
+         "ParentDecl1 declaration must be a namespace");<br>
+  assert(ParentDecl2->getDeclKind() == Decl::Namespace &&<br>
+         "ParentDecl2 declaration must be a namespace");<br>
+  auto *Ns1 = NamespaceDecl::castFromDeclContext(ParentDecl1);<br>
+  auto *Ns2 = NamespaceDecl::castFromDeclContext(ParentDecl2);<br>
+  return Ns1->getOriginalNamespace() == Ns2->getOriginalNamespace();<br>
+}<br>
+<br>
+static std::string getNameOfNamespace(const CXXRecordDecl *Decl) {<br>
+  const auto *ParentDecl = Decl->getLexicalParent();<br>
+  if (ParentDecl->getDeclKind() == Decl::TranslationUnit) {<br>
+    return "(global)";<br>
+  }<br>
+  const auto *NsDecl = cast<NamespaceDecl>(ParentDecl);<br>
+  std::string Ns;<br>
+  llvm::raw_string_ostream OStream(Ns);<br>
+  NsDecl->printQualifiedName(OStream);<br>
+  OStream.flush();<br>
+  return Ns.empty() ? "(global)" : Ns;<br>
+}<br>
+<br>
+void ForwardDeclarationNamespaceCheck::onEndOfTranslationUnit() {<br>
+  // Iterate each group of declarations by name.<br>
+  for (const auto &KeyValuePair : DeclNameToDeclarations) {<br>
+    const auto &Declarations = KeyValuePair.second;<br>
+    // If more than 1 declaration exists, we check if all are in the same<br>
+    // namespace.<br>
+    for (const auto *CurDecl : Declarations) {<br>
+      if (CurDecl->hasDefinition() || CurDecl->isReferenced()) {<br>
+        continue; // Skip forward declarations that are used/referenced.<br>
+      }<br>
+      if (FriendTypes.count(CurDecl->getTypeForDecl()) != 0) {<br>
+        continue; // Skip forward declarations referenced as friend.<br>
+      }<br>
+      if (CurDecl->getLocation().isMacroID() ||<br>
+          CurDecl->getLocation().isInvalid()) {<br>
+        continue;<br>
+      }<br>
+      // Compare with all other declarations with the same name.<br>
+      for (const auto *Decl : Declarations) {<br>
+        if (Decl == CurDecl) {<br>
+          continue; // Don't compare with self.<br>
+        }<br>
+        if (!CurDecl->hasDefinition() &&<br>
+            !haveSameNamespaceOrTranslationUnit(CurDecl, Decl)) {<br>
+          diag(CurDecl->getLocation(),<br>
+               "declaration '%0' is never referenced, but a declaration with "<br>
+               "the same name found in another namespace '%1'")<br>
+              << CurDecl->getName() << getNameOfNamespace(Decl);<br>
+          diag(Decl->getLocation(), "a declaration of '%0' is found here",<br>
+               DiagnosticIDs::Note)<br>
+              << Decl->getName();<br>
+          break; // FIXME: We only generate one warning for each declaration.<br>
+        }<br>
+      }<br>
+      // Check if a definition in another namespace exists.<br>
+      const auto DeclName = CurDecl->getName();<br>
+      if (DeclNameToDefinitions.find(DeclName) == DeclNameToDefinitions.end()) {<br>
+        continue; // No definition in this translation unit, we can skip it.<br>
+      }<br>
+      // Make a warning for each definition with the same name (in other<br>
+      // namespaces).<br>
+      const auto &Definitions = DeclNameToDefinitions[DeclName];<br>
+      for (const auto *Def : Definitions) {<br>
+        diag(CurDecl->getLocation(),<br>
+             "no definition found for '%0', but a definition with "<br>
+             "the same name '%1' found in another namespace '%2'")<br>
+            << CurDecl->getName() << Def->getName() << getNameOfNamespace(Def);<br>
+        diag(Def->getLocation(), "a definition of '%0' is found here",<br>
+             DiagnosticIDs::Note)<br>
+            << Def->getName();<br>
+      }<br>
+    }<br>
+  }<br>
+}<br>
+<br>
+} // namespace misc<br>
+} // namespace tidy<br>
+} // namespace clang<br>
<br>
Added: clang-tools-extra/trunk/clang-tidy/misc/ForwardDeclarationNamespaceCheck.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/ForwardDeclarationNamespaceCheck.h?rev=261737&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/ForwardDeclarationNamespaceCheck.h?rev=261737&view=auto</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/clang-tidy/misc/ForwardDeclarationNamespaceCheck.h (added)<br>
+++ clang-tools-extra/trunk/clang-tidy/misc/ForwardDeclarationNamespaceCheck.h Wed Feb 24 07:35:32 2016<br>
@@ -0,0 +1,59 @@<br>
+//===--- ForwardDeclarationNamespaceCheck.h - clang-tidy --------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_FORWARDDECLARATIONNAMESPACECHECK_H<br>
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_FORWARDDECLARATIONNAMESPACECHECK_H<br>
+<br>
+#include <set><br>
+#include <vector><br>
+#include "llvm/ADT/SmallPtrSet.h"<br>
+#include "../ClangTidy.h"<br>
+<br>
+namespace clang {<br>
+namespace tidy {<br>
+namespace misc {<br>
+<br>
+/// Checks if an unused forward declaration is in a wrong namespace.<br>
+///<br>
+/// The check inspects all unused forward declarations and checks if there is<br>
+/// any declaration/definition with the same name, which could indicate<br>
+/// that the forward declaration is potentially in a wrong namespace.<br>
+///<br>
+/// \code<br>
+///   namespace na { struct A; }<br>
+///   namespace nb { struct A {} };<br>
+///   nb::A a;<br>
+///   // warning : no definition found for 'A', but a definition with the same<br>
+///   name 'A' found in another namespace 'nb::'<br>
+/// \endcode<br>
+///<br>
+/// This check can only generate warnings, but it can't suggest fixes at this<br>
+/// point.<br>
+///<br>
+/// For the user-facing documentation see:<br>
+/// <a href="http://clang.llvm.org/extra/clang-tidy/checks/misc-forward-declaration-namespace.html" rel="noreferrer" target="_blank">http://clang.llvm.org/extra/clang-tidy/checks/misc-forward-declaration-namespace.html</a><br>
+class ForwardDeclarationNamespaceCheck : public ClangTidyCheck {<br>
+public:<br>
+  ForwardDeclarationNamespaceCheck(StringRef Name, ClangTidyContext *Context)<br>
+      : ClangTidyCheck(Name, Context) {}<br>
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;<br>
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;<br>
+  void onEndOfTranslationUnit() override;<br>
+<br>
+private:<br>
+  llvm::StringMap<std::vector<const CXXRecordDecl *>> DeclNameToDefinitions;<br>
+  llvm::StringMap<std::vector<const CXXRecordDecl *>> DeclNameToDeclarations;<br>
+  llvm::SmallPtrSet<const Type *, 16> FriendTypes;<br>
+};<br>
+<br>
+} // namespace misc<br>
+} // namespace tidy<br>
+} // namespace clang<br>
+<br>
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_FORWARDDECLARATIONNAMESPACECHECK_H<br>
<br>
Modified: clang-tools-extra/trunk/clang-tidy/misc/MiscTidyModule.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/MiscTidyModule.cpp?rev=261737&r1=261736&r2=261737&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/MiscTidyModule.cpp?rev=261737&r1=261736&r2=261737&view=diff</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/clang-tidy/misc/MiscTidyModule.cpp (original)<br>
+++ clang-tools-extra/trunk/clang-tidy/misc/MiscTidyModule.cpp Wed Feb 24 07:35:32 2016<br>
@@ -15,6 +15,7 @@<br>
 #include "AssignOperatorSignatureCheck.h"<br>
 #include "BoolPointerImplicitConversionCheck.h"<br>
 #include "DefinitionsInHeadersCheck.h"<br>
+#include "ForwardDeclarationNamespaceCheck.h"<br>
 #include "InaccurateEraseCheck.h"<br>
 #include "IncorrectRoundings.h"<br>
 #include "InefficientAlgorithmCheck.h"<br>
@@ -55,6 +56,8 @@ public:<br>
         "misc-bool-pointer-implicit-conversion");<br>
     CheckFactories.registerCheck<DefinitionsInHeadersCheck>(<br>
         "misc-definitions-in-headers");<br>
+    CheckFactories.registerCheck<ForwardDeclarationNamespaceCheck>(<br>
+        "misc-forward-declaration-namespace");<br>
     CheckFactories.registerCheck<InaccurateEraseCheck>(<br>
         "misc-inaccurate-erase");<br>
     CheckFactories.registerCheck<IncorrectRoundings>(<br>
<br>
Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst?rev=261737&r1=261736&r2=261737&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst?rev=261737&r1=261736&r2=261737&view=diff</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original)<br>
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Wed Feb 24 07:35:32 2016<br>
@@ -51,6 +51,7 @@ Clang-Tidy Checks<br>
    misc-assign-operator-signature<br>
    misc-bool-pointer-implicit-conversion<br>
    misc-definitions-in-headers<br>
+   misc-forward-declaration-namespace<br>
    misc-inaccurate-erase<br>
    misc-incorrect-roundings<br>
    misc-inefficient-algorithm<br>
<br>
Added: clang-tools-extra/trunk/docs/clang-tidy/checks/misc-forward-declaration-namespace.rst<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/misc-forward-declaration-namespace.rst?rev=261737&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/misc-forward-declaration-namespace.rst?rev=261737&view=auto</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/docs/clang-tidy/checks/misc-forward-declaration-namespace.rst (added)<br>
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/misc-forward-declaration-namespace.rst Wed Feb 24 07:35:32 2016<br>
@@ -0,0 +1,19 @@<br>
+.. title:: clang-tidy - misc-forward-declaration-namespace<br>
+<br>
+misc-forward-declaration-namespace<br>
+==================================<br>
+<br>
+Checks if an unused forward declaration is in a wrong namespace.<br>
+<br>
+The check inspects all unused forward declarations and checks if there is any<br>
+declaration/definition with the same name existing, which could indicate that<br>
+the forward declaration is in a potentially wrong namespace.<br>
+<br>
+.. code:: c++<br>
+  namespace na { struct A; }<br>
+  namespace nb { struct A {}; }<br>
+  nb::A a;<br>
+  // warning : no definition found for 'A', but a definition with the same name<br>
+  // 'A' found in another namespace 'nb::'<br>
+<br>
+This check can only generate warnings, but it can't suggest a fix at this point.<br>
<br>
Added: clang-tools-extra/trunk/test/clang-tidy/misc-forward-declaration-namespace.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/misc-forward-declaration-namespace.cpp?rev=261737&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/misc-forward-declaration-namespace.cpp?rev=261737&view=auto</a><br>
==============================================================================<br>
--- clang-tools-extra/trunk/test/clang-tidy/misc-forward-declaration-namespace.cpp (added)<br>
+++ clang-tools-extra/trunk/test/clang-tidy/misc-forward-declaration-namespace.cpp Wed Feb 24 07:35:32 2016<br>
@@ -0,0 +1,163 @@<br>
+// RUN: %check_clang_tidy %s misc-forward-declaration-namespace %t<br>
+<br>
+namespace {<br>
+// This is a declaration in a wrong namespace.<br>
+class T_A;<br>
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration 'T_A' is never referenced, but a declaration with the same name found in another namespace 'na' [misc-forward-declaration-namespace]<br>
+// CHECK-MESSAGES: note: a declaration of 'T_A' is found here<br>
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: no definition found for 'T_A', but a definition with the same name 'T_A' found in another namespace '(global)' [misc-forward-declaration-namespace]<br>
+// CHECK-MESSAGES: note: a definition of 'T_A' is found here<br>
+}<br>
+<br>
+namespace na {<br>
+// This is a declaration in a wrong namespace.<br>
+class T_A;<br>
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration 'T_A' is never referenced, but a declaration with the same name found in another namespace '(anonymous)'<br>
+// CHECK-MESSAGES: note: a declaration of 'T_A' is found here<br>
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: no definition found for 'T_A', but a definition with the same name 'T_A' found in another namespace '(global)'<br>
+// CHECK-MESSAGES: note: a definition of 'T_A' is found here<br>
+}<br>
+<br>
+class T_A;<br>
+<br>
+class T_A {<br>
+  int x;<br>
+};<br>
+<br>
+class NESTED;<br>
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: no definition found for 'NESTED', but a definition with the same name 'NESTED' found in another namespace '(anonymous namespace)::nq::(anonymous)'<br>
+// CHECK-MESSAGES: note: a definition of 'NESTED' is found here<br>
+<br>
+namespace {<br>
+namespace nq {<br>
+namespace {<br>
+class NESTED {};<br>
+}<br>
+}<br>
+}<br>
+<br>
+namespace na {<br>
+class T_B;<br>
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration 'T_B' is never referenced, but a declaration with the same name found in another namespace 'nb'<br>
+// CHECK-MESSAGES: note: a declaration of 'T_B' is found here<br>
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: no definition found for 'T_B', but a definition with the same name 'T_B' found in another namespace 'nb'<br>
+// CHECK-MESSAGES: note: a definition of 'T_B' is found here<br>
+}<br>
+<br>
+namespace nb {<br>
+class T_B;<br>
+}<br>
+<br>
+namespace nb {<br>
+class T_B {<br>
+  int x;<br>
+};<br>
+}<br>
+<br>
+namespace na {<br>
+class T_B;<br>
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration 'T_B' is never referenced, but a declaration with the same name found in another namespace 'nb'<br>
+// CHECK-MESSAGES: note: a declaration of 'T_B' is found here<br>
+// CHECK-MESSAGES: :[[@LINE-3]]:7: warning: no definition found for 'T_B', but a definition with the same name 'T_B' found in another namespace 'nb'<br>
+// CHECK-MESSAGES: note: a definition of 'T_B' is found here<br>
+}<br>
+<br>
+// A simple forward declaration. Although it is never used, but no declaration<br>
+// with the same name is found in other namespace.<br>
+class OUTSIDER;<br>
+<br>
+namespace na {<br>
+// This class is referenced declaration, we don't generate warning.<br>
+class OUTSIDER_1;<br>
+}<br>
+<br>
+void f(na::OUTSIDER_1);<br>
+<br>
+namespace nc {<br>
+// This class is referenced as friend in OOP.<br>
+class OUTSIDER_1;<br>
+<br>
+class OOP {<br>
+  friend struct OUTSIDER_1;<br>
+};<br>
+}<br>
+<br>
+namespace nd {<br>
+class OUTSIDER_1;<br>
+void f(OUTSIDER_1 *);<br>
+}<br>
+<br>
+namespace nb {<br>
+class OUTSIDER_1;<br>
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration 'OUTSIDER_1' is never referenced, but a declaration with the same name found in another namespace 'na'<br>
+// CHECK-MESSAGES: note: a declaration of 'OUTSIDER_1' is found here<br>
+}<br>
+<br>
+<br>
+namespace na {<br>
+template<typename T><br>
+class T_C;<br>
+}<br>
+<br>
+namespace nb {<br>
+// FIXME: this is an error, but we don't consider template class declaration<br>
+// now.<br>
+template<typename T><br>
+class T_C;<br>
+}<br>
+<br>
+namespace na {<br>
+template<typename T><br>
+class T_C {<br>
+  int x;<br>
+};<br>
+}<br>
+<br>
+namespace na {<br>
+<br>
+template <typename T><br>
+class T_TEMP {<br>
+  template <typename _Tp1><br>
+  struct rebind { typedef T_TEMP<_Tp1> other; };<br>
+};<br>
+<br>
+// We ignore class template specialization.<br>
+template class T_TEMP<char>;<br>
+}<br>
+<br>
+namespace nb {<br>
+<br>
+template <typename T><br>
+class T_TEMP_1 {<br>
+  template <typename _Tp1><br>
+  struct rebind { typedef T_TEMP_1<_Tp1> other; };<br>
+};<br>
+<br>
+// We ignore class template specialization.<br>
+extern template class T_TEMP_1<char>;<br>
+}<br>
+<br>
+namespace nd {<br>
+class D;<br>
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration 'D' is never referenced, but a declaration with the same name found in another namespace 'nd::ne'<br>
+// CHECK-MESSAGES: note: a declaration of 'D' is found here<br>
+}<br>
+<br>
+namespace nd {<br>
+namespace ne {<br>
+class D;<br>
+}<br>
+}<br>
+<br>
+int f(nd::ne::D &d);<br>
+<br>
+<br>
+// This should be ignored by the check.<br>
+template <typename... Args><br>
+class Observer {<br>
+  class Impl;<br>
+};<br>
+<br>
+template <typename... Args><br>
+class Observer<Args...>::Impl {<br>
+};<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>