1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #include "clang/AST/CXXInheritance.h" |
14 | #include "clang/AST/ASTContext.h" |
15 | #include "clang/AST/Decl.h" |
16 | #include "clang/AST/DeclBase.h" |
17 | #include "clang/AST/DeclCXX.h" |
18 | #include "clang/AST/DeclTemplate.h" |
19 | #include "clang/AST/RecordLayout.h" |
20 | #include "clang/AST/TemplateName.h" |
21 | #include "clang/AST/Type.h" |
22 | #include "clang/Basic/LLVM.h" |
23 | #include "llvm/ADT/DenseMap.h" |
24 | #include "llvm/ADT/STLExtras.h" |
25 | #include "llvm/ADT/SetVector.h" |
26 | #include "llvm/ADT/SmallVector.h" |
27 | #include "llvm/ADT/iterator_range.h" |
28 | #include "llvm/Support/Casting.h" |
29 | #include <algorithm> |
30 | #include <utility> |
31 | #include <cassert> |
32 | #include <vector> |
33 | |
34 | using namespace clang; |
35 | |
36 | |
37 | |
38 | void CXXBasePaths::ComputeDeclsFound() { |
39 | (0) . __assert_fail ("NumDeclsFound == 0 && !DeclsFound && \"Already computed the set of declarations\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/CXXInheritance.cpp", 40, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(NumDeclsFound == 0 && !DeclsFound && |
40 | (0) . __assert_fail ("NumDeclsFound == 0 && !DeclsFound && \"Already computed the set of declarations\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/CXXInheritance.cpp", 40, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "Already computed the set of declarations"); |
41 | |
42 | llvm::SmallSetVector<NamedDecl *, 8> Decls; |
43 | for (paths_iterator Path = begin(), PathEnd = end(); Path != PathEnd; ++Path) |
44 | Decls.insert(Path->Decls.front()); |
45 | |
46 | NumDeclsFound = Decls.size(); |
47 | DeclsFound = llvm::make_unique<NamedDecl *[]>(NumDeclsFound); |
48 | std::copy(Decls.begin(), Decls.end(), DeclsFound.get()); |
49 | } |
50 | |
51 | CXXBasePaths::decl_range CXXBasePaths::found_decls() { |
52 | if (NumDeclsFound == 0) |
53 | ComputeDeclsFound(); |
54 | |
55 | return decl_range(decl_iterator(DeclsFound.get()), |
56 | decl_iterator(DeclsFound.get() + NumDeclsFound)); |
57 | } |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | bool CXXBasePaths::isAmbiguous(CanQualType BaseType) { |
64 | BaseType = BaseType.getUnqualifiedType(); |
65 | IsVirtBaseAndNumberNonVirtBases Subobjects = ClassSubobjects[BaseType]; |
66 | return Subobjects.NumberOfNonVirtBases + (Subobjects.IsVirtBase ? 1 : 0) > 1; |
67 | } |
68 | |
69 | |
70 | void CXXBasePaths::clear() { |
71 | Paths.clear(); |
72 | ClassSubobjects.clear(); |
73 | VisitedDependentRecords.clear(); |
74 | ScratchPath.clear(); |
75 | DetectedVirtual = nullptr; |
76 | } |
77 | |
78 | |
79 | |
80 | void CXXBasePaths::swap(CXXBasePaths &Other) { |
81 | std::swap(Origin, Other.Origin); |
82 | Paths.swap(Other.Paths); |
83 | ClassSubobjects.swap(Other.ClassSubobjects); |
84 | VisitedDependentRecords.swap(Other.VisitedDependentRecords); |
85 | std::swap(FindAmbiguities, Other.FindAmbiguities); |
86 | std::swap(RecordPaths, Other.RecordPaths); |
87 | std::swap(DetectVirtual, Other.DetectVirtual); |
88 | std::swap(DetectedVirtual, Other.DetectedVirtual); |
89 | } |
90 | |
91 | bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base) const { |
92 | CXXBasePaths Paths(, , |
93 | ); |
94 | return isDerivedFrom(Base, Paths); |
95 | } |
96 | |
97 | bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base, |
98 | CXXBasePaths &Paths) const { |
99 | if (getCanonicalDecl() == Base->getCanonicalDecl()) |
100 | return false; |
101 | |
102 | Paths.setOrigin(const_cast<CXXRecordDecl*>(this)); |
103 | |
104 | const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl(); |
105 | return lookupInBases( |
106 | [BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { |
107 | return FindBaseClass(Specifier, Path, BaseDecl); |
108 | }, |
109 | Paths); |
110 | } |
111 | |
112 | bool CXXRecordDecl::isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const { |
113 | if (!getNumVBases()) |
114 | return false; |
115 | |
116 | CXXBasePaths Paths(, , |
117 | ); |
118 | |
119 | if (getCanonicalDecl() == Base->getCanonicalDecl()) |
120 | return false; |
121 | |
122 | Paths.setOrigin(const_cast<CXXRecordDecl*>(this)); |
123 | |
124 | const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl(); |
125 | return lookupInBases( |
126 | [BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { |
127 | return FindVirtualBaseClass(Specifier, Path, BaseDecl); |
128 | }, |
129 | Paths); |
130 | } |
131 | |
132 | bool CXXRecordDecl::isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const { |
133 | const CXXRecordDecl *TargetDecl = Base->getCanonicalDecl(); |
134 | return forallBases([TargetDecl](const CXXRecordDecl *Base) { |
135 | return Base->getCanonicalDecl() != TargetDecl; |
136 | }); |
137 | } |
138 | |
139 | bool |
140 | CXXRecordDecl::isCurrentInstantiation(const DeclContext *CurContext) const { |
141 | assert(isDependentContext()); |
142 | |
143 | for (; !CurContext->isFileContext(); CurContext = CurContext->getParent()) |
144 | if (CurContext->Equals(this)) |
145 | return true; |
146 | |
147 | return false; |
148 | } |
149 | |
150 | bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches, |
151 | bool AllowShortCircuit) const { |
152 | SmallVector<const CXXRecordDecl*, 8> Queue; |
153 | |
154 | const CXXRecordDecl *Record = this; |
155 | bool AllMatches = true; |
156 | while (true) { |
157 | for (const auto &I : Record->bases()) { |
158 | const RecordType *Ty = I.getType()->getAs<RecordType>(); |
159 | if (!Ty) { |
160 | if (AllowShortCircuit) return false; |
161 | AllMatches = false; |
162 | continue; |
163 | } |
164 | |
165 | CXXRecordDecl *Base = |
166 | cast_or_null<CXXRecordDecl>(Ty->getDecl()->getDefinition()); |
167 | if (!Base || |
168 | (Base->isDependentContext() && |
169 | !Base->isCurrentInstantiation(Record))) { |
170 | if (AllowShortCircuit) return false; |
171 | AllMatches = false; |
172 | continue; |
173 | } |
174 | |
175 | Queue.push_back(Base); |
176 | if (!BaseMatches(Base)) { |
177 | if (AllowShortCircuit) return false; |
178 | AllMatches = false; |
179 | continue; |
180 | } |
181 | } |
182 | |
183 | if (Queue.empty()) |
184 | break; |
185 | Record = Queue.pop_back_val(); |
186 | } |
187 | |
188 | return AllMatches; |
189 | } |
190 | |
191 | bool CXXBasePaths::lookupInBases(ASTContext &Context, |
192 | const CXXRecordDecl *Record, |
193 | CXXRecordDecl::BaseMatchesCallback BaseMatches, |
194 | bool LookupInDependent) { |
195 | bool FoundPath = false; |
196 | |
197 | |
198 | AccessSpecifier AccessToHere = ScratchPath.Access; |
199 | bool IsFirstStep = ScratchPath.empty(); |
200 | |
201 | for (const auto &BaseSpec : Record->bases()) { |
202 | |
203 | QualType BaseType = |
204 | Context.getCanonicalType(BaseSpec.getType()).getUnqualifiedType(); |
205 | |
206 | |
207 | |
208 | |
209 | |
210 | |
211 | |
212 | if (!LookupInDependent && BaseType->isDependentType()) |
213 | continue; |
214 | |
215 | |
216 | |
217 | IsVirtBaseAndNumberNonVirtBases &Subobjects = ClassSubobjects[BaseType]; |
218 | bool VisitBase = true; |
219 | bool SetVirtual = false; |
220 | if (BaseSpec.isVirtual()) { |
221 | VisitBase = !Subobjects.IsVirtBase; |
222 | Subobjects.IsVirtBase = true; |
223 | if (isDetectingVirtual() && DetectedVirtual == nullptr) { |
224 | |
225 | |
226 | DetectedVirtual = BaseType->getAs<RecordType>(); |
227 | SetVirtual = true; |
228 | } |
229 | } else { |
230 | ++Subobjects.NumberOfNonVirtBases; |
231 | } |
232 | if (isRecordingPaths()) { |
233 | |
234 | CXXBasePathElement Element; |
235 | Element.Base = &BaseSpec; |
236 | Element.Class = Record; |
237 | if (BaseSpec.isVirtual()) |
238 | Element.SubobjectNumber = 0; |
239 | else |
240 | Element.SubobjectNumber = Subobjects.NumberOfNonVirtBases; |
241 | ScratchPath.push_back(Element); |
242 | |
243 | |
244 | |
245 | |
246 | |
247 | |
248 | |
249 | |
250 | |
251 | |
252 | |
253 | |
254 | |
255 | |
256 | |
257 | |
258 | if (IsFirstStep) |
259 | ScratchPath.Access = BaseSpec.getAccessSpecifier(); |
260 | else |
261 | ScratchPath.Access = CXXRecordDecl::MergeAccess(AccessToHere, |
262 | BaseSpec.getAccessSpecifier()); |
263 | } |
264 | |
265 | |
266 | bool FoundPathThroughBase = false; |
267 | |
268 | if (BaseMatches(&BaseSpec, ScratchPath)) { |
269 | |
270 | FoundPath = FoundPathThroughBase = true; |
271 | if (isRecordingPaths()) { |
272 | |
273 | Paths.push_back(ScratchPath); |
274 | } else if (!isFindingAmbiguities()) { |
275 | |
276 | |
277 | return FoundPath; |
278 | } |
279 | } else if (VisitBase) { |
280 | CXXRecordDecl *BaseRecord; |
281 | if (LookupInDependent) { |
282 | BaseRecord = nullptr; |
283 | const TemplateSpecializationType *TST = |
284 | BaseSpec.getType()->getAs<TemplateSpecializationType>(); |
285 | if (!TST) { |
286 | if (auto *RT = BaseSpec.getType()->getAs<RecordType>()) |
287 | BaseRecord = cast<CXXRecordDecl>(RT->getDecl()); |
288 | } else { |
289 | TemplateName TN = TST->getTemplateName(); |
290 | if (auto *TD = |
291 | dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) |
292 | BaseRecord = TD->getTemplatedDecl(); |
293 | } |
294 | if (BaseRecord) { |
295 | if (!BaseRecord->hasDefinition() || |
296 | VisitedDependentRecords.count(BaseRecord)) { |
297 | BaseRecord = nullptr; |
298 | } else { |
299 | VisitedDependentRecords.insert(BaseRecord); |
300 | } |
301 | } |
302 | } else { |
303 | BaseRecord = cast<CXXRecordDecl>( |
304 | BaseSpec.getType()->castAs<RecordType>()->getDecl()); |
305 | } |
306 | if (BaseRecord && |
307 | lookupInBases(Context, BaseRecord, BaseMatches, LookupInDependent)) { |
308 | |
309 | |
310 | |
311 | |
312 | |
313 | |
314 | |
315 | |
316 | FoundPath = FoundPathThroughBase = true; |
317 | if (!isFindingAmbiguities()) |
318 | return FoundPath; |
319 | } |
320 | } |
321 | |
322 | |
323 | |
324 | if (isRecordingPaths()) { |
325 | ScratchPath.pop_back(); |
326 | } |
327 | |
328 | |
329 | if (SetVirtual && !FoundPathThroughBase) { |
330 | DetectedVirtual = nullptr; |
331 | } |
332 | } |
333 | |
334 | |
335 | ScratchPath.Access = AccessToHere; |
336 | |
337 | return FoundPath; |
338 | } |
339 | |
340 | bool CXXRecordDecl::lookupInBases(BaseMatchesCallback BaseMatches, |
341 | CXXBasePaths &Paths, |
342 | bool LookupInDependent) const { |
343 | |
344 | if (!Paths.lookupInBases(getASTContext(), this, BaseMatches, |
345 | LookupInDependent)) |
346 | return false; |
347 | |
348 | |
349 | |
350 | if (!Paths.isRecordingPaths() || !Paths.isFindingAmbiguities()) |
351 | return true; |
352 | |
353 | |
354 | |
355 | |
356 | |
357 | |
358 | |
359 | |
360 | |
361 | |
362 | |
363 | Paths.Paths.remove_if([&Paths](const CXXBasePath &Path) { |
364 | for (const CXXBasePathElement &PE : Path) { |
365 | if (!PE.Base->isVirtual()) |
366 | continue; |
367 | |
368 | CXXRecordDecl *VBase = nullptr; |
369 | if (const RecordType *Record = PE.Base->getType()->getAs<RecordType>()) |
370 | VBase = cast<CXXRecordDecl>(Record->getDecl()); |
371 | if (!VBase) |
372 | break; |
373 | |
374 | |
375 | |
376 | |
377 | |
378 | for (const CXXBasePath &HidingP : Paths) { |
379 | CXXRecordDecl *HidingClass = nullptr; |
380 | if (const RecordType *Record = |
381 | HidingP.back().Base->getType()->getAs<RecordType>()) |
382 | HidingClass = cast<CXXRecordDecl>(Record->getDecl()); |
383 | if (!HidingClass) |
384 | break; |
385 | |
386 | if (HidingClass->isVirtuallyDerivedFrom(VBase)) |
387 | return true; |
388 | } |
389 | } |
390 | return false; |
391 | }); |
392 | |
393 | return true; |
394 | } |
395 | |
396 | bool CXXRecordDecl::FindBaseClass(const CXXBaseSpecifier *Specifier, |
397 | CXXBasePath &Path, |
398 | const CXXRecordDecl *BaseRecord) { |
399 | (0) . __assert_fail ("BaseRecord->getCanonicalDecl() == BaseRecord && \"User data for FindBaseClass is not canonical!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/CXXInheritance.cpp", 400, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(BaseRecord->getCanonicalDecl() == BaseRecord && |
400 | (0) . __assert_fail ("BaseRecord->getCanonicalDecl() == BaseRecord && \"User data for FindBaseClass is not canonical!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/CXXInheritance.cpp", 400, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "User data for FindBaseClass is not canonical!"); |
401 | return Specifier->getType()->castAs<RecordType>()->getDecl() |
402 | ->getCanonicalDecl() == BaseRecord; |
403 | } |
404 | |
405 | bool CXXRecordDecl::FindVirtualBaseClass(const CXXBaseSpecifier *Specifier, |
406 | CXXBasePath &Path, |
407 | const CXXRecordDecl *BaseRecord) { |
408 | (0) . __assert_fail ("BaseRecord->getCanonicalDecl() == BaseRecord && \"User data for FindBaseClass is not canonical!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/CXXInheritance.cpp", 409, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(BaseRecord->getCanonicalDecl() == BaseRecord && |
409 | (0) . __assert_fail ("BaseRecord->getCanonicalDecl() == BaseRecord && \"User data for FindBaseClass is not canonical!\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/CXXInheritance.cpp", 409, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "User data for FindBaseClass is not canonical!"); |
410 | return Specifier->isVirtual() && |
411 | Specifier->getType()->castAs<RecordType>()->getDecl() |
412 | ->getCanonicalDecl() == BaseRecord; |
413 | } |
414 | |
415 | bool CXXRecordDecl::FindTagMember(const CXXBaseSpecifier *Specifier, |
416 | CXXBasePath &Path, |
417 | DeclarationName Name) { |
418 | RecordDecl *BaseRecord = |
419 | Specifier->getType()->castAs<RecordType>()->getDecl(); |
420 | |
421 | for (Path.Decls = BaseRecord->lookup(Name); |
422 | !Path.Decls.empty(); |
423 | Path.Decls = Path.Decls.slice(1)) { |
424 | if (Path.Decls.front()->isInIdentifierNamespace(IDNS_Tag)) |
425 | return true; |
426 | } |
427 | |
428 | return false; |
429 | } |
430 | |
431 | static bool findOrdinaryMember(RecordDecl *BaseRecord, CXXBasePath &Path, |
432 | DeclarationName Name) { |
433 | const unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | |
434 | Decl::IDNS_Member; |
435 | for (Path.Decls = BaseRecord->lookup(Name); |
436 | !Path.Decls.empty(); |
437 | Path.Decls = Path.Decls.slice(1)) { |
438 | if (Path.Decls.front()->isInIdentifierNamespace(IDNS)) |
439 | return true; |
440 | } |
441 | |
442 | return false; |
443 | } |
444 | |
445 | bool CXXRecordDecl::FindOrdinaryMember(const CXXBaseSpecifier *Specifier, |
446 | CXXBasePath &Path, |
447 | DeclarationName Name) { |
448 | RecordDecl *BaseRecord = |
449 | Specifier->getType()->castAs<RecordType>()->getDecl(); |
450 | return findOrdinaryMember(BaseRecord, Path, Name); |
451 | } |
452 | |
453 | bool CXXRecordDecl::FindOrdinaryMemberInDependentClasses( |
454 | const CXXBaseSpecifier *Specifier, CXXBasePath &Path, |
455 | DeclarationName Name) { |
456 | const TemplateSpecializationType *TST = |
457 | Specifier->getType()->getAs<TemplateSpecializationType>(); |
458 | if (!TST) { |
459 | auto *RT = Specifier->getType()->getAs<RecordType>(); |
460 | if (!RT) |
461 | return false; |
462 | return findOrdinaryMember(RT->getDecl(), Path, Name); |
463 | } |
464 | TemplateName TN = TST->getTemplateName(); |
465 | const auto *TD = dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl()); |
466 | if (!TD) |
467 | return false; |
468 | CXXRecordDecl *RD = TD->getTemplatedDecl(); |
469 | if (!RD) |
470 | return false; |
471 | return findOrdinaryMember(RD, Path, Name); |
472 | } |
473 | |
474 | bool CXXRecordDecl::FindOMPReductionMember(const CXXBaseSpecifier *Specifier, |
475 | CXXBasePath &Path, |
476 | DeclarationName Name) { |
477 | RecordDecl *BaseRecord = |
478 | Specifier->getType()->castAs<RecordType>()->getDecl(); |
479 | |
480 | for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty(); |
481 | Path.Decls = Path.Decls.slice(1)) { |
482 | if (Path.Decls.front()->isInIdentifierNamespace(IDNS_OMPReduction)) |
483 | return true; |
484 | } |
485 | |
486 | return false; |
487 | } |
488 | |
489 | bool CXXRecordDecl::FindOMPMapperMember(const CXXBaseSpecifier *Specifier, |
490 | CXXBasePath &Path, |
491 | DeclarationName Name) { |
492 | RecordDecl *BaseRecord = |
493 | Specifier->getType()->castAs<RecordType>()->getDecl(); |
494 | |
495 | for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty(); |
496 | Path.Decls = Path.Decls.slice(1)) { |
497 | if (Path.Decls.front()->isInIdentifierNamespace(IDNS_OMPMapper)) |
498 | return true; |
499 | } |
500 | |
501 | return false; |
502 | } |
503 | |
504 | bool CXXRecordDecl:: |
505 | FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier, |
506 | CXXBasePath &Path, |
507 | DeclarationName Name) { |
508 | RecordDecl *BaseRecord = |
509 | Specifier->getType()->castAs<RecordType>()->getDecl(); |
510 | |
511 | for (Path.Decls = BaseRecord->lookup(Name); |
512 | !Path.Decls.empty(); |
513 | Path.Decls = Path.Decls.slice(1)) { |
514 | |
515 | if (isa<TypedefNameDecl>(Path.Decls.front()) || |
516 | Path.Decls.front()->isInIdentifierNamespace(IDNS_Tag)) |
517 | return true; |
518 | } |
519 | |
520 | return false; |
521 | } |
522 | |
523 | std::vector<const NamedDecl *> CXXRecordDecl::lookupDependentName( |
524 | const DeclarationName &Name, |
525 | llvm::function_ref<bool(const NamedDecl *ND)> Filter) { |
526 | std::vector<const NamedDecl *> Results; |
527 | |
528 | DeclContext::lookup_result DirectResult = lookup(Name); |
529 | if (!DirectResult.empty()) { |
530 | for (const NamedDecl *ND : DirectResult) { |
531 | if (Filter(ND)) |
532 | Results.push_back(ND); |
533 | } |
534 | return Results; |
535 | } |
536 | |
537 | CXXBasePaths Paths; |
538 | Paths.setOrigin(this); |
539 | if (!lookupInBases( |
540 | [&](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { |
541 | return CXXRecordDecl::FindOrdinaryMemberInDependentClasses( |
542 | Specifier, Path, Name); |
543 | }, |
544 | Paths, )) |
545 | return Results; |
546 | for (const NamedDecl *ND : Paths.front().Decls) { |
547 | if (Filter(ND)) |
548 | Results.push_back(ND); |
549 | } |
550 | return Results; |
551 | } |
552 | |
553 | void OverridingMethods::add(unsigned OverriddenSubobject, |
554 | UniqueVirtualMethod Overriding) { |
555 | SmallVectorImpl<UniqueVirtualMethod> &SubobjectOverrides |
556 | = Overrides[OverriddenSubobject]; |
557 | if (std::find(SubobjectOverrides.begin(), SubobjectOverrides.end(), |
558 | Overriding) == SubobjectOverrides.end()) |
559 | SubobjectOverrides.push_back(Overriding); |
560 | } |
561 | |
562 | void OverridingMethods::add(const OverridingMethods &Other) { |
563 | for (const_iterator I = Other.begin(), IE = Other.end(); I != IE; ++I) { |
564 | for (overriding_const_iterator M = I->second.begin(), |
565 | MEnd = I->second.end(); |
566 | M != MEnd; |
567 | ++M) |
568 | add(I->first, *M); |
569 | } |
570 | } |
571 | |
572 | void OverridingMethods::replaceAll(UniqueVirtualMethod Overriding) { |
573 | for (iterator I = begin(), IEnd = end(); I != IEnd; ++I) { |
574 | I->second.clear(); |
575 | I->second.push_back(Overriding); |
576 | } |
577 | } |
578 | |
579 | namespace { |
580 | |
581 | class FinalOverriderCollector { |
582 | |
583 | |
584 | llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCount; |
585 | |
586 | |
587 | llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *> VirtualOverriders; |
588 | |
589 | CXXFinalOverriderMap FinalOverriders; |
590 | |
591 | public: |
592 | ~FinalOverriderCollector(); |
593 | |
594 | void Collect(const CXXRecordDecl *RD, bool VirtualBase, |
595 | const CXXRecordDecl *InVirtualSubobject, |
596 | CXXFinalOverriderMap &Overriders); |
597 | }; |
598 | |
599 | } |
600 | |
601 | void FinalOverriderCollector::Collect(const CXXRecordDecl *RD, |
602 | bool VirtualBase, |
603 | const CXXRecordDecl *InVirtualSubobject, |
604 | CXXFinalOverriderMap &Overriders) { |
605 | unsigned SubobjectNumber = 0; |
606 | if (!VirtualBase) |
607 | SubobjectNumber |
608 | = ++SubobjectCount[cast<CXXRecordDecl>(RD->getCanonicalDecl())]; |
609 | |
610 | for (const auto &Base : RD->bases()) { |
611 | if (const RecordType *RT = Base.getType()->getAs<RecordType>()) { |
612 | const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(RT->getDecl()); |
613 | if (!BaseDecl->isPolymorphic()) |
614 | continue; |
615 | |
616 | if (Overriders.empty() && !Base.isVirtual()) { |
617 | |
618 | |
619 | Collect(BaseDecl, false, InVirtualSubobject, Overriders); |
620 | continue; |
621 | } |
622 | |
623 | |
624 | |
625 | |
626 | |
627 | |
628 | CXXFinalOverriderMap ComputedBaseOverriders; |
629 | CXXFinalOverriderMap *BaseOverriders = &ComputedBaseOverriders; |
630 | if (Base.isVirtual()) { |
631 | CXXFinalOverriderMap *&MyVirtualOverriders = VirtualOverriders[BaseDecl]; |
632 | BaseOverriders = MyVirtualOverriders; |
633 | if (!MyVirtualOverriders) { |
634 | MyVirtualOverriders = new CXXFinalOverriderMap; |
635 | |
636 | |
637 | |
638 | |
639 | BaseOverriders = MyVirtualOverriders; |
640 | |
641 | Collect(BaseDecl, true, BaseDecl, *MyVirtualOverriders); |
642 | } |
643 | } else |
644 | Collect(BaseDecl, false, InVirtualSubobject, ComputedBaseOverriders); |
645 | |
646 | |
647 | |
648 | for (CXXFinalOverriderMap::iterator OM = BaseOverriders->begin(), |
649 | OMEnd = BaseOverriders->end(); |
650 | OM != OMEnd; |
651 | ++OM) { |
652 | const CXXMethodDecl *CanonOM = OM->first->getCanonicalDecl(); |
653 | Overriders[CanonOM].add(OM->second); |
654 | } |
655 | } |
656 | } |
657 | |
658 | for (auto *M : RD->methods()) { |
659 | |
660 | if (!M->isVirtual()) |
661 | continue; |
662 | |
663 | CXXMethodDecl *CanonM = M->getCanonicalDecl(); |
664 | using OverriddenMethodsRange = |
665 | llvm::iterator_range<CXXMethodDecl::method_iterator>; |
666 | OverriddenMethodsRange OverriddenMethods = CanonM->overridden_methods(); |
667 | |
668 | if (OverriddenMethods.begin() == OverriddenMethods.end()) { |
669 | |
670 | |
671 | |
672 | |
673 | |
674 | |
675 | Overriders[CanonM].add(SubobjectNumber, |
676 | UniqueVirtualMethod(CanonM, SubobjectNumber, |
677 | InVirtualSubobject)); |
678 | continue; |
679 | } |
680 | |
681 | |
682 | |
683 | |
684 | |
685 | |
686 | |
687 | SmallVector<OverriddenMethodsRange, 4> Stack(1, OverriddenMethods); |
688 | while (!Stack.empty()) { |
689 | for (const CXXMethodDecl *OM : Stack.pop_back_val()) { |
690 | const CXXMethodDecl *CanonOM = OM->getCanonicalDecl(); |
691 | |
692 | |
693 | |
694 | |
695 | |
696 | |
697 | |
698 | |
699 | |
700 | |
701 | Overriders[CanonOM].replaceAll( |
702 | UniqueVirtualMethod(CanonM, SubobjectNumber, |
703 | InVirtualSubobject)); |
704 | |
705 | auto OverriddenMethods = CanonOM->overridden_methods(); |
706 | if (OverriddenMethods.begin() == OverriddenMethods.end()) |
707 | continue; |
708 | |
709 | |
710 | |
711 | Stack.push_back(OverriddenMethods); |
712 | } |
713 | } |
714 | |
715 | |
716 | |
717 | Overriders[CanonM].add(SubobjectNumber, |
718 | UniqueVirtualMethod(CanonM, SubobjectNumber, |
719 | InVirtualSubobject)); |
720 | } |
721 | } |
722 | |
723 | FinalOverriderCollector::~FinalOverriderCollector() { |
724 | for (llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *>::iterator |
725 | VO = VirtualOverriders.begin(), VOEnd = VirtualOverriders.end(); |
726 | VO != VOEnd; |
727 | ++VO) |
728 | delete VO->second; |
729 | } |
730 | |
731 | void |
732 | CXXRecordDecl::getFinalOverriders(CXXFinalOverriderMap &FinalOverriders) const { |
733 | FinalOverriderCollector Collector; |
734 | Collector.Collect(this, false, nullptr, FinalOverriders); |
735 | |
736 | |
737 | |
738 | |
739 | for (auto &OM : FinalOverriders) { |
740 | for (auto &SO : OM.second) { |
741 | SmallVectorImpl<UniqueVirtualMethod> &Overriding = SO.second; |
742 | if (Overriding.size() < 2) |
743 | continue; |
744 | |
745 | auto IsHidden = [&Overriding](const UniqueVirtualMethod &M) { |
746 | if (!M.InVirtualSubobject) |
747 | return false; |
748 | |
749 | |
750 | |
751 | |
752 | |
753 | |
754 | for (const UniqueVirtualMethod &OP : Overriding) |
755 | if (&M != &OP && |
756 | OP.Method->getParent()->isVirtuallyDerivedFrom( |
757 | M.InVirtualSubobject)) |
758 | return true; |
759 | return false; |
760 | }; |
761 | |
762 | Overriding.erase( |
763 | std::remove_if(Overriding.begin(), Overriding.end(), IsHidden), |
764 | Overriding.end()); |
765 | } |
766 | } |
767 | } |
768 | |
769 | static void |
770 | AddIndirectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context, |
771 | CXXIndirectPrimaryBaseSet& Bases) { |
772 | |
773 | const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); |
774 | if (Layout.isPrimaryBaseVirtual()) |
775 | Bases.insert(Layout.getPrimaryBase()); |
776 | |
777 | for (const auto &I : RD->bases()) { |
778 | (0) . __assert_fail ("!I.getType()->isDependentType() && \"Cannot get indirect primary bases for class with dependent bases.\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/CXXInheritance.cpp", 779, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!I.getType()->isDependentType() && |
779 | (0) . __assert_fail ("!I.getType()->isDependentType() && \"Cannot get indirect primary bases for class with dependent bases.\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/CXXInheritance.cpp", 779, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "Cannot get indirect primary bases for class with dependent bases."); |
780 | |
781 | const CXXRecordDecl *BaseDecl = |
782 | cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl()); |
783 | |
784 | |
785 | |
786 | if (BaseDecl->getNumVBases()) |
787 | AddIndirectPrimaryBases(BaseDecl, Context, Bases); |
788 | } |
789 | |
790 | } |
791 | |
792 | void |
793 | CXXRecordDecl::getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet& Bases) const { |
794 | ASTContext &Context = getASTContext(); |
795 | |
796 | if (!getNumVBases()) |
797 | return; |
798 | |
799 | for (const auto &I : bases()) { |
800 | (0) . __assert_fail ("!I.getType()->isDependentType() && \"Cannot get indirect primary bases for class with dependent bases.\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/CXXInheritance.cpp", 801, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!I.getType()->isDependentType() && |
801 | (0) . __assert_fail ("!I.getType()->isDependentType() && \"Cannot get indirect primary bases for class with dependent bases.\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/CXXInheritance.cpp", 801, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "Cannot get indirect primary bases for class with dependent bases."); |
802 | |
803 | const CXXRecordDecl *BaseDecl = |
804 | cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl()); |
805 | |
806 | |
807 | |
808 | if (BaseDecl->getNumVBases()) |
809 | AddIndirectPrimaryBases(BaseDecl, Context, Bases); |
810 | } |
811 | } |
812 | |