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