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