File tree Expand file tree Collapse file tree 15 files changed +236
-20
lines changed
Expand file tree Collapse file tree 15 files changed +236
-20
lines changed Original file line number Diff line number Diff line change @@ -753,10 +753,7 @@ populate(
753753 {
754754 for (clang::FriendDecl const * FD : D->friends ())
755755 {
756- // Check if the friend is a fundamental type
757- // Declaring a fundamental type like `int` as a friend of a
758- // class or struct does not have any practical effect. Thus,
759- // it's not considered part of the public API.
756+ // Skip meaningless builtin friend types
760757 if (clang::TypeSourceInfo const * TSI = FD->getFriendType ())
761758 {
762759 clang::Type const * T = TSI->getType ().getTypePtrOrNull ();
@@ -1216,9 +1213,13 @@ populate(
12161213 }
12171214 else if (clang::NamedDecl const * ND = D->getFriendDecl ())
12181215 {
1219- // ND can be a function or a class
1216+ // ND can be a function or a class; converge to the semantic owner
1217+ // (primary template or canonical decl) before traversing so friend
1218+ // graphs built from many instantiations collapse to a single node.
1219+ clang::Decl const * Target = canonicalFriendTarget (ND);
1220+ MRDOCS_CHECK_OR (Target);
12201221 ScopeExitRestore s (mode_, Dependency);
1221- if (Symbol const * SI = traverse (dyn_cast<clang::Decl>(ND) ))
1222+ if (Symbol const * SI = findOrTraverse (Target ))
12221223 {
12231224 I.id = SI->id ;
12241225 }
Original file line number Diff line number Diff line change @@ -87,6 +87,45 @@ SubstituteConstraintExpressionWithoutSatisfaction(
8787 return SubstConstr.get ();
8888}
8989
90+ clang::Decl const *
91+ canonicalFriendTarget (clang::NamedDecl const * ND)
92+ {
93+ if (!ND)
94+ return nullptr ;
95+
96+ if (auto const * CTSD = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(ND))
97+ {
98+ if (auto * T = CTSD->getSpecializedTemplate ())
99+ return T->getTemplatedDecl ()->getCanonicalDecl ();
100+ }
101+
102+ if (auto const * CRD = llvm::dyn_cast<clang::CXXRecordDecl>(ND))
103+ {
104+ if (auto * CTD = CRD->getDescribedClassTemplate ())
105+ return CTD->getTemplatedDecl ()->getCanonicalDecl ();
106+ }
107+
108+ if (auto const * VTS = llvm::dyn_cast<clang::VarTemplateSpecializationDecl>(ND))
109+ {
110+ if (auto * VT = VTS->getSpecializedTemplate ())
111+ return VT->getTemplatedDecl ()->getCanonicalDecl ();
112+ }
113+
114+ if (auto const * VTD = llvm::dyn_cast<clang::VarTemplateDecl>(ND))
115+ return VTD->getTemplatedDecl ()->getCanonicalDecl ();
116+
117+ if (auto const * FD = llvm::dyn_cast<clang::FunctionDecl>(ND))
118+ {
119+ if (auto const * PT = FD->getPrimaryTemplate ())
120+ return PT->getTemplatedDecl ()->getCanonicalDecl ();
121+ }
122+
123+ if (auto const * FTD = llvm::dyn_cast<clang::FunctionTemplateDecl>(ND))
124+ return FTD->getTemplatedDecl ()->getCanonicalDecl ();
125+
126+ return ND->getCanonicalDecl ();
127+ }
128+
90129clang::AccessSpecifier
91130getAccess (clang::Decl const * D)
92131{
Original file line number Diff line number Diff line change @@ -50,6 +50,15 @@ SubstituteConstraintExpressionWithoutSatisfaction(
5050 const clang::Sema::TemplateCompareNewDeclInfo &DeclInfo,
5151 const clang::Expr *ConstrExpr);
5252
53+ /* * Collapse a friend target (function/class/template) to its canonical owner.
54+
55+ This resolves friend declarations that name template specializations or
56+ redeclarations to the primary/canonical declaration so traversal and
57+ symbol IDs converge on a single entity.
58+ */
59+ clang::Decl const *
60+ canonicalFriendTarget (clang::NamedDecl const * ND);
61+
5362/* * Determine the MrDocs Info type for a Clang DeclType
5463
5564 This trait associates a Clang Decl type with the corresponding
Original file line number Diff line number Diff line change 11< html lang ="en ">
22< head >
33< title > Reference</ title >
4+ < meta charset ="utf-8 ">
45</ head >
56< body >
67< div >
78< h1 > Reference</ h1 >
89< div >
910< div >
10- < h2 id ="index "> </ h2 >
11+ < h2 id ="index ">
12+ Global Namespace< a class ="mrdocs-anchor " href ="#index " aria-label ="Permalink "> #</ a >
13+ </ h2 >
1114</ div >
1215</ div >
1316
1417</ div >
15- < div >
16- < h4 > Created with < a href ="https://www.mrdocs.com "> MrDocs</ a > </ h4 >
17- </ div >
18+ < footer class =" mrdocs-footer " >
19+ < span > Created with < a href ="https://www.mrdocs.com "> MrDocs</ a > </ span >
20+ </ footer >
1821</ body >
1922</ html >
Original file line number Diff line number Diff line change 1919 </struct >
2020 <function name =" f1" id =" CnO51rIKTzfiVKHkR3TdPa0eo+8=" >
2121 <file short-path =" noreturn.cpp" source-path =" noreturn.cpp" line =" 1" />
22- <file short-path =" noreturn.cpp" source-path =" noreturn.cpp" line =" 9" />
2322 <attr id =" is-no-return" />
2423 </function >
2524</namespace >
Original file line number Diff line number Diff line change 1515 <file short-path =" friend-duplicate.cpp" source-path =" friend-duplicate.cpp" line =" 12" class =" def" />
1616 </class >
1717 <function name =" f" id =" s6nsa+zVhpzzrN+yUVPP5rvdXqs=" >
18- <file short-path =" friend-duplicate.cpp" source-path =" friend-duplicate.cpp" line =" 9" />
19- <file short-path =" friend-duplicate.cpp" source-path =" friend-duplicate.cpp" line =" 8" />
2018 <file short-path =" friend-duplicate.cpp" source-path =" friend-duplicate.cpp" line =" 7" />
2119 <file short-path =" friend-duplicate.cpp" source-path =" friend-duplicate.cpp" line =" 14" />
2220 </function >
Original file line number Diff line number Diff line change 2121 </class >
2222 <function name =" f" id =" s6nsa+zVhpzzrN+yUVPP5rvdXqs=" >
2323 <file short-path =" friend-excluded.cpp" source-path =" friend-excluded.cpp" line =" 7" />
24- <file short-path =" friend-excluded.cpp" source-path =" friend-excluded.cpp" line =" 13" />
2524 </function >
2625</namespace >
2726</mrdocs >
Original file line number Diff line number Diff line change 1818 <file short-path =" friend-fn-member.cpp" source-path =" friend-fn-member.cpp" line =" 1" class =" def" />
1919 <function class =" constructor" name =" X" id =" 6Jx2eK9l4C46QIRucTvox+6PH2k=" >
2020 <file short-path =" friend-fn-member.cpp" source-path =" friend-fn-member.cpp" line =" 3" />
21- <file short-path =" friend-fn-member.cpp" source-path =" friend-fn-member.cpp" line =" 13" />
2221 <doc >
2322 <brief >
2423 <text >Default constructor</text >
2726 </function >
2827 <function class =" destructor" name =" ~X" id =" HK6hbp0kJrHWxbYoHddN1v/GCWc=" >
2928 <file short-path =" friend-fn-member.cpp" source-path =" friend-fn-member.cpp" line =" 4" />
30- <file short-path =" friend-fn-member.cpp" source-path =" friend-fn-member.cpp" line =" 14" />
3129 <doc >
3230 <brief >
3331 <text >Destructor</text >
3634 </function >
3735 <function name =" foo" id =" wZtQh+QR5vgNZmk34MnRmnKO5MI=" >
3836 <file short-path =" friend-fn-member.cpp" source-path =" friend-fn-member.cpp" line =" 8" />
39- <file short-path =" friend-fn-member.cpp" source-path =" friend-fn-member.cpp" line =" 15" />
4037 <return >
4138 <type class =" pointer" >
4239 <pointee-type name =" char" />
Original file line number Diff line number Diff line change 1616 </struct >
1717 <function name =" f" id =" s6nsa+zVhpzzrN+yUVPP5rvdXqs=" >
1818 <file short-path =" friend-fn-multi-2nd.cpp" source-path =" friend-fn-multi-2nd.cpp" line =" 3" />
19- <file short-path =" friend-fn-multi-2nd.cpp" source-path =" friend-fn-multi-2nd.cpp" line =" 9" />
2019 <file short-path =" friend-fn-multi-2nd.cpp" source-path =" friend-fn-multi-2nd.cpp" line =" 12" />
2120 <doc >
2221 <brief >
Original file line number Diff line number Diff line change 1616 </struct >
1717 <function name =" f" id =" s6nsa+zVhpzzrN+yUVPP5rvdXqs=" >
1818 <file short-path =" friend-fn-multi-free.cpp" source-path =" friend-fn-multi-free.cpp" line =" 3" />
19- <file short-path =" friend-fn-multi-free.cpp" source-path =" friend-fn-multi-free.cpp" line =" 8" />
2019 <file short-path =" friend-fn-multi-free.cpp" source-path =" friend-fn-multi-free.cpp" line =" 12" />
2120 <doc >
2221 <brief >
You can’t perform that action at this time.
0 commit comments