1 | //===- CXXInheritance.cpp - C++ Inheritance -------------------------------===// |
---|---|
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file provides routines that help analyzing C++ inheritance hierarchies. |
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/SmallVector.h" |
26 | #include "llvm/ADT/iterator_range.h" |
27 | #include <algorithm> |
28 | #include <cassert> |
29 | #include <utility> |
30 | |
31 | using namespace clang; |
32 | |
33 | /// isAmbiguous - Determines whether the set of paths provided is |
34 | /// ambiguous, i.e., there are two or more paths that refer to |
35 | /// different base class subobjects of the same type. BaseType must be |
36 | /// an unqualified, canonical class type. |
37 | bool CXXBasePaths::isAmbiguous(CanQualType BaseType) { |
38 | BaseType = BaseType.getUnqualifiedType(); |
39 | IsVirtBaseAndNumberNonVirtBases Subobjects = ClassSubobjects[BaseType]; |
40 | return Subobjects.NumberOfNonVirtBases + (Subobjects.IsVirtBase ? 1 : 0) > 1; |
41 | } |
42 | |
43 | /// clear - Clear out all prior path information. |
44 | void CXXBasePaths::clear() { |
45 | Paths.clear(); |
46 | ClassSubobjects.clear(); |
47 | VisitedDependentRecords.clear(); |
48 | ScratchPath.clear(); |
49 | DetectedVirtual = nullptr; |
50 | } |
51 | |
52 | /// Swaps the contents of this CXXBasePaths structure with the |
53 | /// contents of Other. |
54 | void CXXBasePaths::swap(CXXBasePaths &Other) { |
55 | std::swap(a&: Origin, b&: Other.Origin); |
56 | Paths.swap(x&: Other.Paths); |
57 | ClassSubobjects.swap(Other.ClassSubobjects); |
58 | VisitedDependentRecords.swap(RHS&: Other.VisitedDependentRecords); |
59 | std::swap(a&: FindAmbiguities, b&: Other.FindAmbiguities); |
60 | std::swap(a&: RecordPaths, b&: Other.RecordPaths); |
61 | std::swap(a&: DetectVirtual, b&: Other.DetectVirtual); |
62 | std::swap(a&: DetectedVirtual, b&: Other.DetectedVirtual); |
63 | } |
64 | |
65 | bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base) const { |
66 | CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false, |
67 | /*DetectVirtual=*/false); |
68 | return isDerivedFrom(Base, Paths); |
69 | } |
70 | |
71 | bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base, |
72 | CXXBasePaths &Paths) const { |
73 | if (getCanonicalDecl() == Base->getCanonicalDecl()) |
74 | return false; |
75 | |
76 | Paths.setOrigin(const_cast<CXXRecordDecl*>(this)); |
77 | |
78 | const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl(); |
79 | return lookupInBases( |
80 | BaseMatches: [BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { |
81 | return Specifier->getType()->getAsRecordDecl() && |
82 | FindBaseClass(Specifier, Path, BaseRecord: BaseDecl); |
83 | }, |
84 | Paths); |
85 | } |
86 | |
87 | bool CXXRecordDecl::isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const { |
88 | if (!getNumVBases()) |
89 | return false; |
90 | |
91 | CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false, |
92 | /*DetectVirtual=*/false); |
93 | |
94 | if (getCanonicalDecl() == Base->getCanonicalDecl()) |
95 | return false; |
96 | |
97 | Paths.setOrigin(const_cast<CXXRecordDecl*>(this)); |
98 | |
99 | const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl(); |
100 | return lookupInBases( |
101 | BaseMatches: [BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { |
102 | return FindVirtualBaseClass(Specifier, Path, BaseRecord: BaseDecl); |
103 | }, |
104 | Paths); |
105 | } |
106 | |
107 | bool CXXRecordDecl::isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const { |
108 | const CXXRecordDecl *TargetDecl = Base->getCanonicalDecl(); |
109 | return forallBases(BaseMatches: [TargetDecl](const CXXRecordDecl *Base) { |
110 | return Base->getCanonicalDecl() != TargetDecl; |
111 | }); |
112 | } |
113 | |
114 | bool |
115 | CXXRecordDecl::isCurrentInstantiation(const DeclContext *CurContext) const { |
116 | assert(isDependentContext()); |
117 | |
118 | for (; !CurContext->isFileContext(); CurContext = CurContext->getParent()) |
119 | if (CurContext->Equals(this)) |
120 | return true; |
121 | |
122 | return false; |
123 | } |
124 | |
125 | bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches) const { |
126 | SmallVector<const CXXRecordDecl*, 8> Queue; |
127 | |
128 | const CXXRecordDecl *Record = this; |
129 | while (true) { |
130 | for (const auto &I : Record->bases()) { |
131 | const RecordType *Ty = I.getType()->getAs<RecordType>(); |
132 | if (!Ty) |
133 | return false; |
134 | |
135 | CXXRecordDecl *Base = |
136 | cast_if_present<CXXRecordDecl>(Val: Ty->getDecl()->getDefinition()); |
137 | if (!Base || |
138 | (Base->isDependentContext() && |
139 | !Base->isCurrentInstantiation(Record))) { |
140 | return false; |
141 | } |
142 | |
143 | Queue.push_back(Elt: Base); |
144 | if (!BaseMatches(Base)) |
145 | return false; |
146 | } |
147 | |
148 | if (Queue.empty()) |
149 | break; |
150 | Record = Queue.pop_back_val(); // not actually a queue. |
151 | } |
152 | |
153 | return true; |
154 | } |
155 | |
156 | bool CXXBasePaths::lookupInBases(ASTContext &Context, |
157 | const CXXRecordDecl *Record, |
158 | CXXRecordDecl::BaseMatchesCallback BaseMatches, |
159 | bool LookupInDependent) { |
160 | bool FoundPath = false; |
161 | |
162 | // The access of the path down to this record. |
163 | AccessSpecifier AccessToHere = ScratchPath.Access; |
164 | bool IsFirstStep = ScratchPath.empty(); |
165 | |
166 | for (const auto &BaseSpec : Record->bases()) { |
167 | // Find the record of the base class subobjects for this type. |
168 | QualType BaseType = |
169 | Context.getCanonicalType(T: BaseSpec.getType()).getUnqualifiedType(); |
170 | |
171 | bool isCurrentInstantiation = isa<InjectedClassNameType>(Val: BaseType); |
172 | if (!isCurrentInstantiation) { |
173 | if (auto *BaseRecord = cast_if_present<CXXRecordDecl>( |
174 | Val: BaseSpec.getType()->getAsRecordDecl())) |
175 | isCurrentInstantiation = BaseRecord->isDependentContext() && |
176 | BaseRecord->isCurrentInstantiation(Record); |
177 | } |
178 | // C++ [temp.dep]p3: |
179 | // In the definition of a class template or a member of a class template, |
180 | // if a base class of the class template depends on a template-parameter, |
181 | // the base class scope is not examined during unqualified name lookup |
182 | // either at the point of definition of the class template or member or |
183 | // during an instantiation of the class tem- plate or member. |
184 | if (!LookupInDependent && |
185 | (BaseType->isDependentType() && !isCurrentInstantiation)) |
186 | continue; |
187 | |
188 | // Determine whether we need to visit this base class at all, |
189 | // updating the count of subobjects appropriately. |
190 | IsVirtBaseAndNumberNonVirtBases &Subobjects = ClassSubobjects[BaseType]; |
191 | bool VisitBase = true; |
192 | bool SetVirtual = false; |
193 | if (BaseSpec.isVirtual()) { |
194 | VisitBase = !Subobjects.IsVirtBase; |
195 | Subobjects.IsVirtBase = true; |
196 | if (isDetectingVirtual() && DetectedVirtual == nullptr) { |
197 | // If this is the first virtual we find, remember it. If it turns out |
198 | // there is no base path here, we'll reset it later. |
199 | DetectedVirtual = BaseType->getAs<RecordType>(); |
200 | SetVirtual = true; |
201 | } |
202 | } else { |
203 | ++Subobjects.NumberOfNonVirtBases; |
204 | } |
205 | if (isRecordingPaths()) { |
206 | // Add this base specifier to the current path. |
207 | CXXBasePathElement Element; |
208 | Element.Base = &BaseSpec; |
209 | Element.Class = Record; |
210 | if (BaseSpec.isVirtual()) |
211 | Element.SubobjectNumber = 0; |
212 | else |
213 | Element.SubobjectNumber = Subobjects.NumberOfNonVirtBases; |
214 | ScratchPath.push_back(Elt: Element); |
215 | |
216 | // Calculate the "top-down" access to this base class. |
217 | // The spec actually describes this bottom-up, but top-down is |
218 | // equivalent because the definition works out as follows: |
219 | // 1. Write down the access along each step in the inheritance |
220 | // chain, followed by the access of the decl itself. |
221 | // For example, in |
222 | // class A { public: int foo; }; |
223 | // class B : protected A {}; |
224 | // class C : public B {}; |
225 | // class D : private C {}; |
226 | // we would write: |
227 | // private public protected public |
228 | // 2. If 'private' appears anywhere except far-left, access is denied. |
229 | // 3. Otherwise, overall access is determined by the most restrictive |
230 | // access in the sequence. |
231 | if (IsFirstStep) |
232 | ScratchPath.Access = BaseSpec.getAccessSpecifier(); |
233 | else |
234 | ScratchPath.Access = CXXRecordDecl::MergeAccess(PathAccess: AccessToHere, |
235 | DeclAccess: BaseSpec.getAccessSpecifier()); |
236 | } |
237 | |
238 | // Track whether there's a path involving this specific base. |
239 | bool FoundPathThroughBase = false; |
240 | |
241 | if (BaseMatches(&BaseSpec, ScratchPath)) { |
242 | // We've found a path that terminates at this base. |
243 | FoundPath = FoundPathThroughBase = true; |
244 | if (isRecordingPaths()) { |
245 | // We have a path. Make a copy of it before moving on. |
246 | Paths.push_back(x: ScratchPath); |
247 | } else if (!isFindingAmbiguities()) { |
248 | // We found a path and we don't care about ambiguities; |
249 | // return immediately. |
250 | return FoundPath; |
251 | } |
252 | } else if (VisitBase) { |
253 | CXXRecordDecl *BaseRecord = nullptr; |
254 | if (LookupInDependent) { |
255 | const TemplateSpecializationType *TST = |
256 | BaseSpec.getType()->getAs<TemplateSpecializationType>(); |
257 | if (!TST) { |
258 | if (auto *RT = BaseSpec.getType()->getAs<RecordType>()) |
259 | BaseRecord = cast<CXXRecordDecl>(Val: RT->getDecl()); |
260 | } else { |
261 | TemplateName TN = TST->getTemplateName(); |
262 | if (auto *TD = |
263 | dyn_cast_or_null<ClassTemplateDecl>(Val: TN.getAsTemplateDecl())) |
264 | BaseRecord = TD->getTemplatedDecl(); |
265 | } |
266 | if (BaseRecord) { |
267 | if (!BaseRecord->hasDefinition()) |
268 | BaseRecord = nullptr; |
269 | else if (!VisitedDependentRecords.insert(Ptr: BaseRecord).second) |
270 | BaseRecord = nullptr; |
271 | } |
272 | } else { |
273 | BaseRecord = cast<CXXRecordDecl>(Val: BaseSpec.getType()->getAsRecordDecl()); |
274 | } |
275 | if (BaseRecord && |
276 | lookupInBases(Context, Record: BaseRecord, BaseMatches, LookupInDependent)) { |
277 | // C++ [class.member.lookup]p2: |
278 | // A member name f in one sub-object B hides a member name f in |
279 | // a sub-object A if A is a base class sub-object of B. Any |
280 | // declarations that are so hidden are eliminated from |
281 | // consideration. |
282 | |
283 | // There is a path to a base class that meets the criteria. If we're |
284 | // not collecting paths or finding ambiguities, we're done. |
285 | FoundPath = FoundPathThroughBase = true; |
286 | if (!isFindingAmbiguities()) |
287 | return FoundPath; |
288 | } |
289 | } |
290 | |
291 | // Pop this base specifier off the current path (if we're |
292 | // collecting paths). |
293 | if (isRecordingPaths()) { |
294 | ScratchPath.pop_back(); |
295 | } |
296 | |
297 | // If we set a virtual earlier, and this isn't a path, forget it again. |
298 | if (SetVirtual && !FoundPathThroughBase) { |
299 | DetectedVirtual = nullptr; |
300 | } |
301 | } |
302 | |
303 | // Reset the scratch path access. |
304 | ScratchPath.Access = AccessToHere; |
305 | |
306 | return FoundPath; |
307 | } |
308 | |
309 | bool CXXRecordDecl::lookupInBases(BaseMatchesCallback BaseMatches, |
310 | CXXBasePaths &Paths, |
311 | bool LookupInDependent) const { |
312 | // If we didn't find anything, report that. |
313 | if (!Paths.lookupInBases(Context&: getASTContext(), Record: this, BaseMatches, |
314 | LookupInDependent)) |
315 | return false; |
316 | |
317 | // If we're not recording paths or we won't ever find ambiguities, |
318 | // we're done. |
319 | if (!Paths.isRecordingPaths() || !Paths.isFindingAmbiguities()) |
320 | return true; |
321 | |
322 | // C++ [class.member.lookup]p6: |
323 | // When virtual base classes are used, a hidden declaration can be |
324 | // reached along a path through the sub-object lattice that does |
325 | // not pass through the hiding declaration. This is not an |
326 | // ambiguity. The identical use with nonvirtual base classes is an |
327 | // ambiguity; in that case there is no unique instance of the name |
328 | // that hides all the others. |
329 | // |
330 | // FIXME: This is an O(N^2) algorithm, but DPG doesn't see an easy |
331 | // way to make it any faster. |
332 | Paths.Paths.remove_if(pred: [&Paths](const CXXBasePath &Path) { |
333 | for (const CXXBasePathElement &PE : Path) { |
334 | if (!PE.Base->isVirtual()) |
335 | continue; |
336 | |
337 | CXXRecordDecl *VBase = nullptr; |
338 | if (const RecordType *Record = PE.Base->getType()->getAs<RecordType>()) |
339 | VBase = cast<CXXRecordDecl>(Val: Record->getDecl()); |
340 | if (!VBase) |
341 | break; |
342 | |
343 | // The declaration(s) we found along this path were found in a |
344 | // subobject of a virtual base. Check whether this virtual |
345 | // base is a subobject of any other path; if so, then the |
346 | // declaration in this path are hidden by that patch. |
347 | for (const CXXBasePath &HidingP : Paths) { |
348 | CXXRecordDecl *HidingClass = nullptr; |
349 | if (const RecordType *Record = |
350 | HidingP.back().Base->getType()->getAs<RecordType>()) |
351 | HidingClass = cast<CXXRecordDecl>(Val: Record->getDecl()); |
352 | if (!HidingClass) |
353 | break; |
354 | |
355 | if (HidingClass->isVirtuallyDerivedFrom(Base: VBase)) |
356 | return true; |
357 | } |
358 | } |
359 | return false; |
360 | }); |
361 | |
362 | return true; |
363 | } |
364 | |
365 | bool CXXRecordDecl::FindBaseClass(const CXXBaseSpecifier *Specifier, |
366 | CXXBasePath &Path, |
367 | const CXXRecordDecl *BaseRecord) { |
368 | assert(BaseRecord->getCanonicalDecl() == BaseRecord && |
369 | "User data for FindBaseClass is not canonical!"); |
370 | return cast<CXXRecordDecl>(Val: Specifier->getType()->getAsRecordDecl()) |
371 | ->getCanonicalDecl() == BaseRecord; |
372 | } |
373 | |
374 | bool CXXRecordDecl::FindVirtualBaseClass(const CXXBaseSpecifier *Specifier, |
375 | CXXBasePath &Path, |
376 | const CXXRecordDecl *BaseRecord) { |
377 | assert(BaseRecord->getCanonicalDecl() == BaseRecord && |
378 | "User data for FindBaseClass is not canonical!"); |
379 | return Specifier->isVirtual() && |
380 | cast<CXXRecordDecl>(Val: Specifier->getType()->getAsRecordDecl()) |
381 | ->getCanonicalDecl() == BaseRecord; |
382 | } |
383 | |
384 | static bool isOrdinaryMember(const NamedDecl *ND) { |
385 | return ND->isInIdentifierNamespace(Decl::IDNS_Ordinary | Decl::IDNS_Tag | |
386 | Decl::IDNS_Member); |
387 | } |
388 | |
389 | static bool findOrdinaryMember(const CXXRecordDecl *RD, CXXBasePath &Path, |
390 | DeclarationName Name) { |
391 | Path.Decls = RD->lookup(Name).begin(); |
392 | for (DeclContext::lookup_iterator I = Path.Decls, E = I.end(); I != E; ++I) |
393 | if (isOrdinaryMember(ND: *I)) |
394 | return true; |
395 | |
396 | return false; |
397 | } |
398 | |
399 | bool CXXRecordDecl::hasMemberName(DeclarationName Name) const { |
400 | CXXBasePath P; |
401 | if (findOrdinaryMember(RD: this, Path&: P, Name)) |
402 | return true; |
403 | |
404 | CXXBasePaths Paths(false, false, false); |
405 | return lookupInBases( |
406 | BaseMatches: [Name](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { |
407 | return findOrdinaryMember(RD: Specifier->getType()->getAsCXXRecordDecl(), |
408 | Path, Name); |
409 | }, |
410 | Paths); |
411 | } |
412 | |
413 | void OverridingMethods::add(unsigned OverriddenSubobject, |
414 | UniqueVirtualMethod Overriding) { |
415 | SmallVectorImpl<UniqueVirtualMethod> &SubobjectOverrides |
416 | = Overrides[OverriddenSubobject]; |
417 | if (!llvm::is_contained(Range&: SubobjectOverrides, Element: Overriding)) |
418 | SubobjectOverrides.push_back(Elt: Overriding); |
419 | } |
420 | |
421 | void OverridingMethods::add(const OverridingMethods &Other) { |
422 | for (const_iterator I = Other.begin(), IE = Other.end(); I != IE; ++I) { |
423 | for (overriding_const_iterator M = I->second.begin(), |
424 | MEnd = I->second.end(); |
425 | M != MEnd; |
426 | ++M) |
427 | add(OverriddenSubobject: I->first, Overriding: *M); |
428 | } |
429 | } |
430 | |
431 | void OverridingMethods::replaceAll(UniqueVirtualMethod Overriding) { |
432 | for (iterator I = begin(), IEnd = end(); I != IEnd; ++I) { |
433 | I->second.clear(); |
434 | I->second.push_back(Elt: Overriding); |
435 | } |
436 | } |
437 | |
438 | namespace { |
439 | |
440 | class FinalOverriderCollector { |
441 | /// The number of subobjects of a given class type that |
442 | /// occur within the class hierarchy. |
443 | llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCount; |
444 | |
445 | /// Overriders for each virtual base subobject. |
446 | llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *> VirtualOverriders; |
447 | |
448 | CXXFinalOverriderMap FinalOverriders; |
449 | |
450 | public: |
451 | ~FinalOverriderCollector(); |
452 | |
453 | void Collect(const CXXRecordDecl *RD, bool VirtualBase, |
454 | const CXXRecordDecl *InVirtualSubobject, |
455 | CXXFinalOverriderMap &Overriders); |
456 | }; |
457 | |
458 | } // namespace |
459 | |
460 | void FinalOverriderCollector::Collect(const CXXRecordDecl *RD, |
461 | bool VirtualBase, |
462 | const CXXRecordDecl *InVirtualSubobject, |
463 | CXXFinalOverriderMap &Overriders) { |
464 | unsigned SubobjectNumber = 0; |
465 | if (!VirtualBase) |
466 | SubobjectNumber |
467 | = ++SubobjectCount[cast<CXXRecordDecl>(Val: RD->getCanonicalDecl())]; |
468 | |
469 | for (const auto &Base : RD->bases()) { |
470 | if (const RecordType *RT = Base.getType()->getAs<RecordType>()) { |
471 | const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(Val: RT->getDecl()); |
472 | if (!BaseDecl->isPolymorphic()) |
473 | continue; |
474 | |
475 | if (Overriders.empty() && !Base.isVirtual()) { |
476 | // There are no other overriders of virtual member functions, |
477 | // so let the base class fill in our overriders for us. |
478 | Collect(RD: BaseDecl, VirtualBase: false, InVirtualSubobject, Overriders); |
479 | continue; |
480 | } |
481 | |
482 | // Collect all of the overridders from the base class subobject |
483 | // and merge them into the set of overridders for this class. |
484 | // For virtual base classes, populate or use the cached virtual |
485 | // overrides so that we do not walk the virtual base class (and |
486 | // its base classes) more than once. |
487 | CXXFinalOverriderMap ComputedBaseOverriders; |
488 | CXXFinalOverriderMap *BaseOverriders = &ComputedBaseOverriders; |
489 | if (Base.isVirtual()) { |
490 | CXXFinalOverriderMap *&MyVirtualOverriders = VirtualOverriders[BaseDecl]; |
491 | BaseOverriders = MyVirtualOverriders; |
492 | if (!MyVirtualOverriders) { |
493 | MyVirtualOverriders = new CXXFinalOverriderMap; |
494 | |
495 | // Collect may cause VirtualOverriders to reallocate, invalidating the |
496 | // MyVirtualOverriders reference. Set BaseOverriders to the right |
497 | // value now. |
498 | BaseOverriders = MyVirtualOverriders; |
499 | |
500 | Collect(RD: BaseDecl, VirtualBase: true, InVirtualSubobject: BaseDecl, Overriders&: *MyVirtualOverriders); |
501 | } |
502 | } else |
503 | Collect(RD: BaseDecl, VirtualBase: false, InVirtualSubobject, Overriders&: ComputedBaseOverriders); |
504 | |
505 | // Merge the overriders from this base class into our own set of |
506 | // overriders. |
507 | for (CXXFinalOverriderMap::iterator OM = BaseOverriders->begin(), |
508 | OMEnd = BaseOverriders->end(); |
509 | OM != OMEnd; |
510 | ++OM) { |
511 | const CXXMethodDecl *CanonOM = OM->first->getCanonicalDecl(); |
512 | Overriders[CanonOM].add(Other: OM->second); |
513 | } |
514 | } |
515 | } |
516 | |
517 | for (auto *M : RD->methods()) { |
518 | // We only care about virtual methods. |
519 | if (!M->isVirtual()) |
520 | continue; |
521 | |
522 | CXXMethodDecl *CanonM = M->getCanonicalDecl(); |
523 | using OverriddenMethodsRange = |
524 | llvm::iterator_range<CXXMethodDecl::method_iterator>; |
525 | OverriddenMethodsRange OverriddenMethods = CanonM->overridden_methods(); |
526 | |
527 | if (OverriddenMethods.begin() == OverriddenMethods.end()) { |
528 | // This is a new virtual function that does not override any |
529 | // other virtual function. Add it to the map of virtual |
530 | // functions for which we are tracking overridders. |
531 | |
532 | // C++ [class.virtual]p2: |
533 | // For convenience we say that any virtual function overrides itself. |
534 | Overriders[CanonM].add(OverriddenSubobject: SubobjectNumber, |
535 | Overriding: UniqueVirtualMethod(CanonM, SubobjectNumber, |
536 | InVirtualSubobject)); |
537 | continue; |
538 | } |
539 | |
540 | // This virtual method overrides other virtual methods, so it does |
541 | // not add any new slots into the set of overriders. Instead, we |
542 | // replace entries in the set of overriders with the new |
543 | // overrider. To do so, we dig down to the original virtual |
544 | // functions using data recursion and update all of the methods it |
545 | // overrides. |
546 | SmallVector<OverriddenMethodsRange, 4> Stack(1, OverriddenMethods); |
547 | while (!Stack.empty()) { |
548 | for (const CXXMethodDecl *OM : Stack.pop_back_val()) { |
549 | const CXXMethodDecl *CanonOM = OM->getCanonicalDecl(); |
550 | |
551 | // C++ [class.virtual]p2: |
552 | // A virtual member function C::vf of a class object S is |
553 | // a final overrider unless the most derived class (1.8) |
554 | // of which S is a base class subobject (if any) declares |
555 | // or inherits another member function that overrides vf. |
556 | // |
557 | // Treating this object like the most derived class, we |
558 | // replace any overrides from base classes with this |
559 | // overriding virtual function. |
560 | Overriders[CanonOM].replaceAll( |
561 | Overriding: UniqueVirtualMethod(CanonM, SubobjectNumber, |
562 | InVirtualSubobject)); |
563 | |
564 | auto OverriddenMethods = CanonOM->overridden_methods(); |
565 | if (OverriddenMethods.begin() == OverriddenMethods.end()) |
566 | continue; |
567 | |
568 | // Continue recursion to the methods that this virtual method |
569 | // overrides. |
570 | Stack.push_back(Elt: OverriddenMethods); |
571 | } |
572 | } |
573 | |
574 | // C++ [class.virtual]p2: |
575 | // For convenience we say that any virtual function overrides itself. |
576 | Overriders[CanonM].add(OverriddenSubobject: SubobjectNumber, |
577 | Overriding: UniqueVirtualMethod(CanonM, SubobjectNumber, |
578 | InVirtualSubobject)); |
579 | } |
580 | } |
581 | |
582 | FinalOverriderCollector::~FinalOverriderCollector() { |
583 | for (llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *>::iterator |
584 | VO = VirtualOverriders.begin(), VOEnd = VirtualOverriders.end(); |
585 | VO != VOEnd; |
586 | ++VO) |
587 | delete VO->second; |
588 | } |
589 | |
590 | void |
591 | CXXRecordDecl::getFinalOverriders(CXXFinalOverriderMap &FinalOverriders) const { |
592 | FinalOverriderCollector Collector; |
593 | Collector.Collect(RD: this, VirtualBase: false, InVirtualSubobject: nullptr, Overriders&: FinalOverriders); |
594 | |
595 | // Weed out any final overriders that come from virtual base class |
596 | // subobjects that were hidden by other subobjects along any path. |
597 | // This is the final-overrider variant of C++ [class.member.lookup]p10. |
598 | for (auto &OM : FinalOverriders) { |
599 | for (auto &SO : OM.second) { |
600 | SmallVectorImpl<UniqueVirtualMethod> &Overriding = SO.second; |
601 | if (Overriding.size() < 2) |
602 | continue; |
603 | |
604 | auto IsHidden = [&Overriding](const UniqueVirtualMethod &M) { |
605 | if (!M.InVirtualSubobject) |
606 | return false; |
607 | |
608 | // We have an overriding method in a virtual base class |
609 | // subobject (or non-virtual base class subobject thereof); |
610 | // determine whether there exists an other overriding method |
611 | // in a base class subobject that hides the virtual base class |
612 | // subobject. |
613 | for (const UniqueVirtualMethod &OP : Overriding) |
614 | if (&M != &OP && |
615 | OP.Method->getParent()->isVirtuallyDerivedFrom( |
616 | Base: M.InVirtualSubobject)) |
617 | return true; |
618 | return false; |
619 | }; |
620 | |
621 | // FIXME: IsHidden reads from Overriding from the middle of a remove_if |
622 | // over the same sequence! Is this guaranteed to work? |
623 | llvm::erase_if(C&: Overriding, P: IsHidden); |
624 | } |
625 | } |
626 | } |
627 | |
628 | static void |
629 | AddIndirectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context, |
630 | CXXIndirectPrimaryBaseSet& Bases) { |
631 | // If the record has a virtual primary base class, add it to our set. |
632 | const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); |
633 | if (Layout.isPrimaryBaseVirtual()) |
634 | Bases.insert(Ptr: Layout.getPrimaryBase()); |
635 | |
636 | for (const auto &I : RD->bases()) { |
637 | assert(!I.getType()->isDependentType() && |
638 | "Cannot get indirect primary bases for class with dependent bases."); |
639 | |
640 | const CXXRecordDecl *BaseDecl = |
641 | cast<CXXRecordDecl>(Val: I.getType()->getAsRecordDecl()); |
642 | |
643 | // Only bases with virtual bases participate in computing the |
644 | // indirect primary virtual base classes. |
645 | if (BaseDecl->getNumVBases()) |
646 | AddIndirectPrimaryBases(RD: BaseDecl, Context, Bases); |
647 | } |
648 | |
649 | } |
650 | |
651 | void |
652 | CXXRecordDecl::getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet& Bases) const { |
653 | ASTContext &Context = getASTContext(); |
654 | |
655 | if (!getNumVBases()) |
656 | return; |
657 | |
658 | for (const auto &I : bases()) { |
659 | assert(!I.getType()->isDependentType() && |
660 | "Cannot get indirect primary bases for class with dependent bases."); |
661 | |
662 | const CXXRecordDecl *BaseDecl = |
663 | cast<CXXRecordDecl>(Val: I.getType()->getAsRecordDecl()); |
664 | |
665 | // Only bases with virtual bases participate in computing the |
666 | // indirect primary virtual base classes. |
667 | if (BaseDecl->getNumVBases()) |
668 | AddIndirectPrimaryBases(RD: BaseDecl, Context, Bases); |
669 | } |
670 | } |
671 |
Definitions
- isAmbiguous
- clear
- swap
- isDerivedFrom
- isDerivedFrom
- isVirtuallyDerivedFrom
- isProvablyNotDerivedFrom
- isCurrentInstantiation
- forallBases
- lookupInBases
- lookupInBases
- FindBaseClass
- FindVirtualBaseClass
- isOrdinaryMember
- findOrdinaryMember
- hasMemberName
- add
- add
- replaceAll
- FinalOverriderCollector
- Collect
- ~FinalOverriderCollector
- getFinalOverriders
- AddIndirectPrimaryBases
Learn to use CMake with our Intro Training
Find out more