@@ -28,54 +28,139 @@ foldRecordMembers(std::vector<SymbolID> const& ids)
28
28
29
29
void
30
30
OverloadsFinalizer::
31
- foldNamespaceMembers (std::vector<SymbolID> const & ids )
31
+ foldNamespaceMembers (std::vector<SymbolID> const & namespaceIds )
32
32
{
33
- for (SymbolID const & id: ids )
33
+ for (SymbolID const & namespaceId: namespaceIds )
34
34
{
35
- Info* infoPtr = corpus_.find (id );
36
- MRDOCS_CHECK_OR_CONTINUE (infoPtr );
37
- auto * ns = dynamic_cast <NamespaceInfo*>(infoPtr );
35
+ Info* namespaceInfoPtr = corpus_.find (namespaceId );
36
+ MRDOCS_CHECK_OR_CONTINUE (namespaceInfoPtr );
37
+ auto * ns = dynamic_cast <NamespaceInfo*>(namespaceInfoPtr );
38
38
MRDOCS_CHECK_OR_CONTINUE (ns);
39
39
operator ()(*ns);
40
40
}
41
41
}
42
42
43
+ namespace {
44
+ SymbolID
45
+ findBaseClassPermutation (
46
+ SymbolID const & contextId,
47
+ CorpusImpl& corpus,
48
+ ArrayRef<SymbolID> sameNameFunctionIds)
49
+ {
50
+ Info* info = corpus.find (contextId);
51
+ MRDOCS_CHECK_OR (info, SymbolID::invalid);
52
+ if (auto * record = dynamic_cast <RecordInfo*>(info))
53
+ {
54
+ bool overloadsFromBase = false ;
55
+ for (auto const & base: record->Bases )
56
+ {
57
+ auto const baseInfo = corpus.find (base.Type ->namedSymbol ());
58
+ MRDOCS_CHECK_OR_CONTINUE (baseInfo);
59
+ auto const baseRecord = dynamic_cast <RecordInfo*>(baseInfo);
60
+ MRDOCS_CHECK_OR_CONTINUE (baseRecord);
61
+ RecordTranche* tranchesPtrs[] = {
62
+ &baseRecord->Interface .Public ,
63
+ &baseRecord->Interface .Protected ,
64
+ &baseRecord->Interface .Private ,
65
+ };
66
+ for (RecordTranche* tranchePtr: tranchesPtrs)
67
+ {
68
+ std::vector<SymbolID>* trancheFunctionPtrs[] = {
69
+ &tranchePtr->Functions ,
70
+ &tranchePtr->StaticFunctions
71
+ };
72
+ for (std::vector<SymbolID>* trancheFunctionsPtr:
73
+ trancheFunctionPtrs)
74
+ {
75
+ for (SymbolID const & baseID: *trancheFunctionsPtr)
76
+ {
77
+ Info* baseFuncMember = corpus.find (baseID);
78
+ MRDOCS_CHECK_OR_CONTINUE (baseFuncMember);
79
+ MRDOCS_CHECK_OR_CONTINUE (baseFuncMember->isOverloads ());
80
+ auto * overloads = dynamic_cast <OverloadsInfo*>(baseFuncMember);
81
+ MRDOCS_CHECK_OR_CONTINUE (overloads);
82
+ // Does this overload set have the same functions
83
+ MRDOCS_CHECK_OR_CONTINUE (
84
+ std::ranges::is_permutation (
85
+ overloads->Members ,
86
+ sameNameFunctionIds));
87
+ return overloads->id ;
88
+ }
89
+ }
90
+ }
91
+ }
92
+ }
93
+ return SymbolID::invalid;
94
+ }
95
+ }
96
+
43
97
void
44
98
OverloadsFinalizer::
45
- foldOverloads (SymbolID const & parent , std::vector<SymbolID>& ids )
99
+ foldOverloads (SymbolID const & contextId , std::vector<SymbolID>& functionIds )
46
100
{
47
- for (auto it = ids.begin (); it != ids.end (); ++it)
101
+ for (auto functionIdIt = functionIds.begin ();
102
+ functionIdIt != functionIds.end ();
103
+ ++functionIdIt)
48
104
{
49
105
// Get the FunctionInfo for the current id
50
- auto infoPtr = corpus_.find (*it );
51
- MRDOCS_CHECK_OR_CONTINUE (infoPtr );
52
- auto * function = dynamic_cast <FunctionInfo*>(infoPtr );
106
+ auto recordInfoPtr = corpus_.find (*functionIdIt );
107
+ MRDOCS_CHECK_OR_CONTINUE (recordInfoPtr );
108
+ auto * function = dynamic_cast <FunctionInfo*>(recordInfoPtr );
53
109
MRDOCS_CHECK_OR_CONTINUE (function);
54
110
55
111
// Check if the FunctionInfo is unique
56
- auto sameNameIt =
57
- std::find_if (
58
- it + 1 ,
59
- ids.end (),
60
- [&](SymbolID const & otherID)
61
- {
62
- auto const otherInfoPtr = corpus_.find (otherID);
63
- MRDOCS_CHECK_OR (otherInfoPtr, false );
64
- Info& otherInfo = *otherInfoPtr;
65
- return function->Name == otherInfo.Name ;
66
- });
67
- if (sameNameIt == ids.end ())
112
+ std::ranges::subrange otherFunctionIds (
113
+ std::next (functionIdIt),
114
+ functionIds.end ());
115
+ auto isSameNameFunction = [&](SymbolID const & otherID) {
116
+ auto const otherFunctionPtr = corpus_.find (otherID);
117
+ MRDOCS_CHECK_OR (otherFunctionPtr, false );
118
+ Info const & otherInfo = *otherFunctionPtr;
119
+ return function->Name == otherInfo.Name ;
120
+ };
121
+ auto sameNameIt = std::ranges::
122
+ find_if (otherFunctionIds, isSameNameFunction);
123
+ bool const isUniqueFunction = sameNameIt == otherFunctionIds.end ();
124
+ MRDOCS_CHECK_OR_CONTINUE (!isUniqueFunction);
125
+
126
+ // Create a list of FunctionInfo overloads
127
+ auto sameNameFunctionIdsView =
128
+ std::ranges::subrange (functionIdIt, functionIds.end ()) |
129
+ std::views::filter (isSameNameFunction);
130
+ SmallVector<SymbolID, 16 > sameNameFunctionIds (
131
+ sameNameFunctionIdsView.begin (),
132
+ sameNameFunctionIdsView.end ());
133
+
134
+ // Check if any of the base classes has an overload set
135
+ // with the exact same function ids. If that's the case,
136
+ // the function will create a reference.
137
+ SymbolID equivalentOverloadsID = findBaseClassPermutation (
138
+ contextId, corpus_, sameNameFunctionIds);
139
+ if (equivalentOverloadsID)
68
140
{
141
+ MRDOCS_ASSERT (corpus_.find (equivalentOverloadsID));
142
+ // This base overload set becomes the
143
+ // representation in the record
144
+ *functionIdIt = equivalentOverloadsID;
145
+ auto const offset = functionIdIt - functionIds.begin ();
146
+ // Erase the other function ids with
147
+ // the same name
148
+ for (SymbolID sameNameId: sameNameFunctionIds)
149
+ {
150
+ std::erase (functionIds, sameNameId);
151
+ }
152
+ functionIdIt = functionIds.begin () + offset;
69
153
continue ;
70
154
}
71
155
72
- // FunctionInfo is not unique, so merge it with the other FunctionInfos
73
- // into an OverloadsInfo
74
- OverloadsInfo O (parent, function->Name );
156
+ // FunctionInfo is not unique and there's no equivalent
157
+ // overload set in base classes, so we merge it with the
158
+ // other FunctionInfos into a new OverloadsInfo
159
+ OverloadsInfo O (contextId, function->Name );
75
160
addMember (O, *function);
76
- *it = O.id ;
77
- auto const itOffset = it - ids .begin ();
78
- for (auto otherIt = it + 1 ; otherIt != ids .end (); ++otherIt)
161
+ *functionIdIt = O.id ;
162
+ auto const itOffset = functionIdIt - functionIds .begin ();
163
+ for (auto otherIt = functionIdIt + 1 ; otherIt != functionIds .end (); ++otherIt)
79
164
{
80
165
Info* otherInfoPtr = corpus_.find (*otherIt);
81
166
MRDOCS_CHECK_OR_CONTINUE (otherInfoPtr);
@@ -84,10 +169,10 @@ foldOverloads(SymbolID const& parent, std::vector<SymbolID>& ids)
84
169
if (function->Name == otherFunction->Name )
85
170
{
86
171
addMember (O, *otherFunction);
87
- otherIt = std::prev (ids .erase (otherIt));
172
+ otherIt = std::prev (functionIds .erase (otherIt));
88
173
}
89
174
}
90
- it = ids .begin () + itOffset;
175
+ functionIdIt = functionIds .begin () + itOffset;
91
176
corpus_.info_ .emplace (std::make_unique<OverloadsInfo>(std::move (O)));
92
177
}
93
178
}
@@ -105,6 +190,22 @@ void
105
190
OverloadsFinalizer::
106
191
operator ()(RecordInfo& I)
107
192
{
193
+ MRDOCS_CHECK_OR (!finalized_.contains (I.id ));
194
+ for (auto & b: I.Bases )
195
+ {
196
+ auto & BT = b.Type ;
197
+ MRDOCS_CHECK_OR (BT);
198
+ MRDOCS_CHECK_OR (BT->isNamed ());
199
+ auto & NT = dynamic_cast <NamedTypeInfo&>(*BT);
200
+ MRDOCS_CHECK_OR (NT.Name );
201
+ auto & NI = dynamic_cast <NameInfo&>(*NT.Name );
202
+ MRDOCS_CHECK_OR (NI.id );
203
+ Info* baseInfo = corpus_.find (NI.id );
204
+ MRDOCS_CHECK_OR (baseInfo);
205
+ auto * baseRecord = dynamic_cast <RecordInfo*>(baseInfo);
206
+ MRDOCS_CHECK_OR (baseRecord);
207
+ operator ()(*baseRecord);
208
+ }
108
209
foldOverloads (I.id , I.Interface .Public .Functions );
109
210
foldOverloads (I.id , I.Interface .Protected .Functions );
110
211
foldOverloads (I.id , I.Interface .Private .Functions );
@@ -114,6 +215,7 @@ operator()(RecordInfo& I)
114
215
foldRecordMembers (I.Interface .Public .Records );
115
216
foldRecordMembers (I.Interface .Protected .Records );
116
217
foldRecordMembers (I.Interface .Private .Records );
218
+ finalized_.emplace (I.id );
117
219
}
118
220
119
221
} // clang::mrdocs
0 commit comments