27 auto IsInSpecialization = hasAncestor(
28 decl(anyOf(cxxRecordDecl(isExplicitTemplateSpecialization()),
29 functionDecl(isExplicitTemplateSpecialization()))));
32 hasParent(decl(anyOf(namespaceDecl(), translationUnitDecl()))),
33 unless(isImplicit()), unless(hasAncestor(cxxRecordDecl())),
34 unless(isInstantiated()), unless(IsInSpecialization),
35 unless(classTemplateSpecializationDecl()))
42 Finder->addMatcher(friendDecl().bind(
"friend_decl"),
this);
46 const MatchFinder::MatchResult &Result) {
47 if (
const auto *RecordDecl =
48 Result.Nodes.getNodeAs<CXXRecordDecl>(
"record_decl")) {
49 StringRef DeclName = RecordDecl->getName();
50 if (RecordDecl->isThisDeclarationADefinition()) {
51 DeclNameToDefinitions[DeclName].push_back(RecordDecl);
57 DeclNameToDeclarations[DeclName].push_back(RecordDecl);
60 const auto *Decl = Result.Nodes.getNodeAs<FriendDecl>(
"friend_decl");
61 assert(Decl &&
"Decl is neither record_decl nor friend decl!");
72 if (
const TypeSourceInfo *Tsi = Decl->getFriendType())
74 Tsi->getType()->getCanonicalTypeUnqualified().getTypePtr());
79 const CXXRecordDecl *Decl2) {
80 const DeclContext *ParentDecl1 = Decl1->getLexicalParent();
81 const DeclContext *ParentDecl2 = Decl2->getLexicalParent();
86 if (ParentDecl1->getDeclKind() == Decl::TranslationUnit ||
87 ParentDecl2->getDeclKind() == Decl::TranslationUnit) {
88 return ParentDecl1 == ParentDecl2;
90 assert(ParentDecl1->getDeclKind() == Decl::Namespace &&
91 "ParentDecl1 declaration must be a namespace");
92 assert(ParentDecl2->getDeclKind() == Decl::Namespace &&
93 "ParentDecl2 declaration must be a namespace");
94 auto *Ns1 = NamespaceDecl::castFromDeclContext(ParentDecl1);
95 auto *Ns2 = NamespaceDecl::castFromDeclContext(ParentDecl2);
96 return Ns1->getFirstDecl() == Ns2->getFirstDecl();
100 const auto *ParentDecl = Decl->getLexicalParent();
101 if (ParentDecl->getDeclKind() == Decl::TranslationUnit) {
104 const auto *NsDecl = cast<NamespaceDecl>(ParentDecl);
106 llvm::raw_string_ostream OStream(Ns);
107 NsDecl->printQualifiedName(OStream);
108 return Ns.empty() ?
"(global)" : Ns;
113 for (
const auto &KeyValuePair : DeclNameToDeclarations) {
114 const auto &Declarations = KeyValuePair.second;
117 for (
const auto *CurDecl : Declarations) {
118 if (CurDecl->hasDefinition() || CurDecl->isReferenced()) {
121 if (FriendTypes.contains(CurDecl->getASTContext()
122 .getCanonicalTagType(CurDecl)
126 if (CurDecl->getLocation().isMacroID() ||
127 CurDecl->getLocation().isInvalid()) {
131 for (
const auto *Decl : Declarations) {
132 if (Decl == CurDecl) {
135 if (!CurDecl->hasDefinition() &&
137 diag(CurDecl->getLocation(),
138 "declaration %0 is never referenced, but a declaration with "
139 "the same name found in another namespace '%1'")
141 diag(Decl->getLocation(),
"a declaration of %0 is found here",
148 const auto DeclName = CurDecl->getName();
149 auto It = DeclNameToDefinitions.find(DeclName);
150 if (It == DeclNameToDefinitions.end()) {
155 const auto &Definitions = It->second;
156 for (
const auto *Def : Definitions) {
157 diag(CurDecl->getLocation(),
158 "no definition found for %0, but a definition with "
159 "the same name %1 found in another namespace '%2'")
161 diag(Def->getLocation(),
"a definition of %0 is found here",