13
13
14
14
namespace clang ::mrdocs {
15
15
16
- void
17
- OverloadsFinalizer::
18
- foldRecordMembers (std::vector<SymbolID> const & ids)
19
- {
20
- for (SymbolID const & id: ids)
21
- {
22
- Info* infoPtr = corpus_.find (id);
23
- MRDOCS_CHECK_OR_CONTINUE (infoPtr);
24
- MRDOCS_CHECK_OR_CONTINUE (infoPtr->isRecord ());
25
- operator ()(infoPtr->asRecord ());
26
- }
27
- }
28
-
29
- void
30
- OverloadsFinalizer::
31
- foldNamespaceMembers (std::vector<SymbolID> const & namespaceIds)
32
- {
33
- for (SymbolID const & namespaceId: namespaceIds)
34
- {
35
- Info* namespaceInfoPtr = corpus_.find (namespaceId);
36
- MRDOCS_CHECK_OR_CONTINUE (namespaceInfoPtr);
37
- MRDOCS_CHECK_OR_CONTINUE (namespaceInfoPtr->isNamespace ());
38
- operator ()(namespaceInfoPtr->asNamespace ());
39
- }
40
- }
41
-
42
16
namespace {
43
17
SymbolID
44
18
findBaseClassPermutation (
45
19
SymbolID const & contextId,
46
20
CorpusImpl& corpus,
47
21
ArrayRef<SymbolID> sameNameFunctionIds)
48
22
{
23
+ // Find the RecordInfo
49
24
Info* info = corpus.find (contextId);
50
25
MRDOCS_CHECK_OR (info, SymbolID::invalid);
51
- if (auto const * record = info->asRecordPtr ())
26
+ MRDOCS_CHECK_OR (info->isRecord (), SymbolID::invalid);
27
+ for (auto const & base: info->asRecordPtr ()->Bases )
52
28
{
53
- for (auto const & base: record->Bases )
29
+ // Find the i-th base class
30
+ auto const baseInfo = corpus.find (base.Type ->namedSymbol ());
31
+ MRDOCS_CHECK_OR_CONTINUE (baseInfo);
32
+ auto const baseRecord = baseInfo->asRecordPtr ();
33
+ MRDOCS_CHECK_OR_CONTINUE (baseRecord);
34
+
35
+ // Iterate over all function tranches
36
+ RecordTranche* tranchesPtrs[] = {
37
+ &baseRecord->Interface .Public ,
38
+ &baseRecord->Interface .Protected ,
39
+ &baseRecord->Interface .Private ,
40
+ };
41
+ for (RecordTranche* tranchePtr: tranchesPtrs)
54
42
{
55
- auto const baseInfo = corpus.find (base.Type ->namedSymbol ());
56
- MRDOCS_CHECK_OR_CONTINUE (baseInfo);
57
- auto const baseRecord = baseInfo->asRecordPtr ();
58
- MRDOCS_CHECK_OR_CONTINUE (baseRecord);
59
- RecordTranche* tranchesPtrs[] = {
60
- &baseRecord->Interface .Public ,
61
- &baseRecord->Interface .Protected ,
62
- &baseRecord->Interface .Private ,
43
+ std::vector<SymbolID>* trancheFunctionPtrs[] = {
44
+ &tranchePtr->Functions ,
45
+ &tranchePtr->StaticFunctions
63
46
};
64
- for (RecordTranche* tranchePtr: tranchesPtrs)
47
+ for (std::vector<SymbolID>* trancheFunctionsPtr:
48
+ trancheFunctionPtrs)
65
49
{
66
- std::vector<SymbolID>* trancheFunctionPtrs[] = {
67
- &tranchePtr->Functions ,
68
- &tranchePtr->StaticFunctions
69
- };
70
- for (std::vector<SymbolID>* trancheFunctionsPtr:
71
- trancheFunctionPtrs)
50
+ // Find an overload set that's a permutation of the same
51
+ // name functions
52
+ for (SymbolID const & baseID: *trancheFunctionsPtr)
72
53
{
73
- for (SymbolID const & baseID: *trancheFunctionsPtr)
74
- {
75
- Info* baseFuncMember = corpus.find (baseID);
76
- MRDOCS_CHECK_OR_CONTINUE (baseFuncMember);
77
- MRDOCS_CHECK_OR_CONTINUE (baseFuncMember->isOverloads ());
78
- auto * overloads = baseFuncMember->asOverloadsPtr ();
79
- MRDOCS_CHECK_OR_CONTINUE (overloads);
80
- // Does this overload set have the same functions
81
- MRDOCS_CHECK_OR_CONTINUE (
82
- std::ranges::is_permutation (
83
- overloads->Members ,
84
- sameNameFunctionIds));
85
- return overloads->id ;
86
- }
54
+ Info* baseFuncMember = corpus.find (baseID);
55
+ MRDOCS_CHECK_OR_CONTINUE (baseFuncMember);
56
+ MRDOCS_CHECK_OR_CONTINUE (baseFuncMember->isOverloads ());
57
+ auto * overloads = baseFuncMember->asOverloadsPtr ();
58
+ MRDOCS_CHECK_OR_CONTINUE (overloads);
59
+ // Does this overload set have the same functions
60
+ MRDOCS_CHECK_OR_CONTINUE (
61
+ std::ranges::is_permutation (
62
+ overloads->Members ,
63
+ sameNameFunctionIds));
64
+ return overloads->id ;
87
65
}
88
66
}
89
67
}
90
68
}
91
69
return SymbolID::invalid;
92
70
}
71
+
72
+ SymbolID
73
+ findIntroducedNamespacePermutation (
74
+ SymbolID const & contextId,
75
+ CorpusImpl& corpus,
76
+ ArrayRef<SymbolID> sameNameFunctionIds)
77
+ {
78
+ // Find the UsingInfo
79
+ Info* info = corpus.find (contextId);
80
+ MRDOCS_CHECK_OR (info, SymbolID::invalid);
81
+ MRDOCS_CHECK_OR (info->isUsing (), SymbolID::invalid);
82
+
83
+ // Find the FunctionInfo for the first shadow declaration
84
+ MRDOCS_CHECK_OR (!sameNameFunctionIds.empty (), SymbolID::invalid);
85
+ Info* firstShadowInfo = corpus.find (sameNameFunctionIds.front ());
86
+ MRDOCS_CHECK_OR (firstShadowInfo, SymbolID::invalid);
87
+ MRDOCS_CHECK_OR (firstShadowInfo->isFunction (), SymbolID::invalid);
88
+ auto * firstShadowFunction = firstShadowInfo->asFunctionPtr ();
89
+
90
+ // Find the introduced namespace of the first shadow declaration
91
+ MRDOCS_CHECK_OR (firstShadowFunction->Parent , SymbolID::invalid);
92
+ Info* parentInfo = corpus.find (firstShadowFunction->Parent );
93
+ MRDOCS_CHECK_OR (parentInfo, SymbolID::invalid);
94
+ MRDOCS_CHECK_OR (parentInfo->isNamespace (), SymbolID::invalid);
95
+ auto * parentNamespace = parentInfo->asNamespacePtr ();
96
+
97
+ // Find an overload set that's a permutation of the same name functions
98
+ for (SymbolID const & baseID: parentNamespace->Members .Functions )
99
+ {
100
+ Info* baseFuncMember = corpus.find (baseID);
101
+ MRDOCS_CHECK_OR_CONTINUE (baseFuncMember);
102
+ MRDOCS_CHECK_OR_CONTINUE (baseFuncMember->isOverloads ());
103
+ auto * overloads = baseFuncMember->asOverloadsPtr ();
104
+ MRDOCS_CHECK_OR_CONTINUE (overloads);
105
+ // Does this overload set have the same functions
106
+ MRDOCS_CHECK_OR_CONTINUE (
107
+ std::ranges::is_permutation (
108
+ overloads->Members ,
109
+ sameNameFunctionIds));
110
+ return overloads->id ;
111
+ }
112
+ return SymbolID::invalid;
113
+ }
93
114
}
94
115
95
116
void
96
117
OverloadsFinalizer::
97
118
foldOverloads (SymbolID const & contextId, std::vector<SymbolID>& functionIds, bool isStatic)
98
119
{
120
+ Info* contextInfo = corpus_.find (contextId);
121
+ MRDOCS_CHECK_OR (contextInfo);
122
+
99
123
for (auto functionIdIt = functionIds.begin ();
100
124
functionIdIt != functionIds.end ();
101
125
++functionIdIt)
102
126
{
103
127
// Get the FunctionInfo for the current id
104
- auto recordInfoPtr = corpus_.find (*functionIdIt);
105
- MRDOCS_CHECK_OR_CONTINUE (recordInfoPtr );
106
- auto * function = recordInfoPtr ->asFunctionPtr ();
128
+ auto infoPtr = corpus_.find (*functionIdIt);
129
+ MRDOCS_CHECK_OR_CONTINUE (infoPtr );
130
+ auto * function = infoPtr ->asFunctionPtr ();
107
131
MRDOCS_CHECK_OR_CONTINUE (function);
108
132
MRDOCS_CHECK_OR_CONTINUE (function->Class != FunctionClass::Destructor);
109
133
@@ -133,23 +157,56 @@ foldOverloads(SymbolID const& contextId, std::vector<SymbolID>& functionIds, boo
133
157
// Check if any of the base classes has an overload set
134
158
// with the exact same function ids. If that's the case,
135
159
// the function will create a reference.
136
- SymbolID equivalentOverloadsID = findBaseClassPermutation (
137
- contextId, corpus_, sameNameFunctionIds);
138
- if (equivalentOverloadsID)
160
+ if (contextInfo->isRecord ())
139
161
{
140
- MRDOCS_ASSERT (corpus_.find (equivalentOverloadsID));
141
- // This base overload set becomes the
142
- // representation in the record
143
- *functionIdIt = equivalentOverloadsID;
144
- auto const offset = functionIdIt - functionIds.begin ();
145
- // Erase the other function ids with
146
- // the same name
147
- for (SymbolID sameNameId: sameNameFunctionIds)
162
+ SymbolID equivalentOverloadsID = findBaseClassPermutation (
163
+ contextId,
164
+ corpus_,
165
+ sameNameFunctionIds);
166
+ if (equivalentOverloadsID)
148
167
{
149
- std::erase (functionIds, sameNameId);
168
+ MRDOCS_ASSERT (corpus_.find (equivalentOverloadsID));
169
+ // This base overload set becomes the
170
+ // representation in the record
171
+ *functionIdIt = equivalentOverloadsID;
172
+ auto const offset = functionIdIt - functionIds.begin ();
173
+ // Erase the other function ids with
174
+ // the same name
175
+ for (SymbolID sameNameId: sameNameFunctionIds)
176
+ {
177
+ std::erase (functionIds, sameNameId);
178
+ }
179
+ functionIdIt = functionIds.begin () + offset;
180
+ continue ;
181
+ }
182
+ }
183
+
184
+ // Check if the namespace of the name introduced in the
185
+ // using declaration has an overload set with the
186
+ // exact same function ids. If that's the case,
187
+ // the function will create a reference.
188
+ if (contextInfo->isUsing ())
189
+ {
190
+ SymbolID introducedOverloadsID = findIntroducedNamespacePermutation (
191
+ contextId,
192
+ corpus_,
193
+ sameNameFunctionIds);
194
+ if (introducedOverloadsID)
195
+ {
196
+ MRDOCS_ASSERT (corpus_.find (introducedOverloadsID));
197
+ // This base overload set becomes the
198
+ // representation in the record
199
+ *functionIdIt = introducedOverloadsID;
200
+ auto const offset = functionIdIt - functionIds.begin ();
201
+ // Erase the other function ids with
202
+ // the same name
203
+ for (SymbolID sameNameId: sameNameFunctionIds)
204
+ {
205
+ std::erase (functionIds, sameNameId);
206
+ }
207
+ functionIdIt = functionIds.begin () + offset;
208
+ continue ;
150
209
}
151
- functionIdIt = functionIds.begin () + offset;
152
- continue ;
153
210
}
154
211
155
212
// FunctionInfo is not unique and there's no equivalent
@@ -176,13 +233,50 @@ foldOverloads(SymbolID const& contextId, std::vector<SymbolID>& functionIds, boo
176
233
}
177
234
}
178
235
236
+ namespace {
237
+ template <class T >
238
+ constexpr
239
+ auto
240
+ toDerivedView (std::vector<SymbolID> const & ids, CorpusImpl& c)
241
+ {
242
+ return ids |
243
+ std::views::transform ([&c](SymbolID const & id) {
244
+ return c.find (id);
245
+ }) |
246
+ std::views::filter ([](Info* infoPtr) {
247
+ return infoPtr != nullptr ;
248
+ }) |
249
+ std::views::transform ([](Info* infoPtr) -> T* {
250
+ return dynamic_cast <T*>(infoPtr);
251
+ }) |
252
+ std::views::filter ([](T* ptr) {
253
+ return ptr != nullptr ;
254
+ }) |
255
+ std::views::transform ([](T* ptr) -> T& {
256
+ return *ptr;
257
+ });
258
+ }
259
+ }
260
+
179
261
void
180
262
OverloadsFinalizer::
181
263
operator ()(NamespaceInfo& I)
182
264
{
265
+ MRDOCS_CHECK_OR (!finalized_.contains (I.id ));
183
266
foldOverloads (I.id , I.Members .Functions , true );
184
- foldRecordMembers (I.Members .Records );
185
- foldNamespaceMembers (I.Members .Namespaces );
267
+ for (RecordInfo& RI: toDerivedView<RecordInfo>(I.Members .Records , corpus_))
268
+ {
269
+ operator ()(RI);
270
+ }
271
+ for (NamespaceInfo& NI: toDerivedView<NamespaceInfo>(I.Members .Namespaces , corpus_))
272
+ {
273
+ operator ()(NI);
274
+ }
275
+ for (UsingInfo& UI: toDerivedView<UsingInfo>(I.Members .Usings , corpus_))
276
+ {
277
+ operator ()(UI);
278
+ }
279
+ finalized_.emplace (I.id );
186
280
}
187
281
188
282
void
@@ -211,9 +305,39 @@ operator()(RecordInfo& I)
211
305
foldOverloads (I.id , I.Interface .Public .StaticFunctions , true );
212
306
foldOverloads (I.id , I.Interface .Protected .StaticFunctions , true );
213
307
foldOverloads (I.id , I.Interface .Private .StaticFunctions , true );
214
- foldRecordMembers (I.Interface .Public .Records );
215
- foldRecordMembers (I.Interface .Protected .Records );
216
- foldRecordMembers (I.Interface .Private .Records );
308
+ for (RecordInfo& RI: toDerivedView<RecordInfo>(I.Interface .Public .Records , corpus_)) {
309
+ operator ()(RI);
310
+ }
311
+ for (RecordInfo& RI: toDerivedView<RecordInfo>(I.Interface .Protected .Records , corpus_)) {
312
+ operator ()(RI);
313
+ }
314
+ for (RecordInfo& RI: toDerivedView<RecordInfo>(I.Interface .Private .Records , corpus_)) {
315
+ operator ()(RI);
316
+ }
317
+ finalized_.emplace (I.id );
318
+ }
319
+
320
+ void
321
+ OverloadsFinalizer::
322
+ operator ()(UsingInfo& I)
323
+ {
324
+ MRDOCS_CHECK_OR (!finalized_.contains (I.id ));
325
+ auto shadowFunctions = toDerivedView<FunctionInfo>(I.ShadowDeclarations , corpus_);
326
+ for (FunctionInfo& FI: shadowFunctions)
327
+ {
328
+ Info* PI = corpus_.find (FI.Parent );
329
+ MRDOCS_CHECK_OR_CONTINUE (PI);
330
+ if (auto * NI = PI->asNamespacePtr ())
331
+ {
332
+ operator ()(*NI);
333
+ }
334
+ else if (auto * RI = PI->asRecordPtr ())
335
+ {
336
+ operator ()(*RI);
337
+ }
338
+ break ;
339
+ }
340
+ foldOverloads (I.id , I.ShadowDeclarations , true );
217
341
finalized_.emplace (I.id );
218
342
}
219
343
0 commit comments