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