clang 20.0.0git
CXXInheritance.cpp
Go to the documentation of this file.
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
15#include "clang/AST/Decl.h"
16#include "clang/AST/DeclBase.h"
17#include "clang/AST/DeclCXX.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#include <vector>
31
32using namespace clang;
33
34/// isAmbiguous - Determines whether the set of paths provided is
35/// ambiguous, i.e., there are two or more paths that refer to
36/// different base class subobjects of the same type. BaseType must be
37/// an unqualified, canonical class type.
39 BaseType = BaseType.getUnqualifiedType();
40 IsVirtBaseAndNumberNonVirtBases Subobjects = ClassSubobjects[BaseType];
41 return Subobjects.NumberOfNonVirtBases + (Subobjects.IsVirtBase ? 1 : 0) > 1;
42}
43
44/// clear - Clear out all prior path information.
46 Paths.clear();
47 ClassSubobjects.clear();
48 VisitedDependentRecords.clear();
49 ScratchPath.clear();
50 DetectedVirtual = nullptr;
51}
52
53/// Swaps the contents of this CXXBasePaths structure with the
54/// contents of Other.
56 std::swap(Origin, Other.Origin);
57 Paths.swap(Other.Paths);
58 ClassSubobjects.swap(Other.ClassSubobjects);
59 VisitedDependentRecords.swap(Other.VisitedDependentRecords);
60 std::swap(FindAmbiguities, Other.FindAmbiguities);
61 std::swap(RecordPaths, Other.RecordPaths);
62 std::swap(DetectVirtual, Other.DetectVirtual);
63 std::swap(DetectedVirtual, Other.DetectedVirtual);
64}
65
67 CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false,
68 /*DetectVirtual=*/false);
69 return isDerivedFrom(Base, Paths);
70}
71
73 CXXBasePaths &Paths) const {
74 if (getCanonicalDecl() == Base->getCanonicalDecl())
75 return false;
76
77 Paths.setOrigin(const_cast<CXXRecordDecl*>(this));
78
79 const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl();
80 return lookupInBases(
81 [BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
82 return Specifier->getType()->getAsRecordDecl() &&
83 FindBaseClass(Specifier, Path, BaseDecl);
84 },
85 Paths);
86}
87
89 if (!getNumVBases())
90 return false;
91
92 CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false,
93 /*DetectVirtual=*/false);
94
95 if (getCanonicalDecl() == Base->getCanonicalDecl())
96 return false;
97
98 Paths.setOrigin(const_cast<CXXRecordDecl*>(this));
99
100 const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl();
101 return lookupInBases(
102 [BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
103 return FindVirtualBaseClass(Specifier, Path, BaseDecl);
104 },
105 Paths);
106}
107
109 const CXXRecordDecl *TargetDecl = Base->getCanonicalDecl();
110 return forallBases([TargetDecl](const CXXRecordDecl *Base) {
111 return Base->getCanonicalDecl() != TargetDecl;
112 });
113}
114
115bool
117 assert(isDependentContext());
118
119 for (; !CurContext->isFileContext(); CurContext = CurContext->getParent())
120 if (CurContext->Equals(this))
121 return true;
122
123 return false;
124}
125
128
129 const CXXRecordDecl *Record = this;
130 while (true) {
131 for (const auto &I : Record->bases()) {
132 const RecordType *Ty = I.getType()->getAs<RecordType>();
133 if (!Ty)
134 return false;
135
137 cast_if_present<CXXRecordDecl>(Ty->getDecl()->getDefinition());
138 if (!Base ||
139 (Base->isDependentContext() &&
140 !Base->isCurrentInstantiation(Record))) {
141 return false;
142 }
143
144 Queue.push_back(Base);
145 if (!BaseMatches(Base))
146 return false;
147 }
148
149 if (Queue.empty())
150 break;
151 Record = Queue.pop_back_val(); // not actually a queue.
152 }
153
154 return true;
155}
156
157bool CXXBasePaths::lookupInBases(ASTContext &Context,
158 const CXXRecordDecl *Record,
160 bool LookupInDependent) {
161 bool FoundPath = false;
162
163 // The access of the path down to this record.
164 AccessSpecifier AccessToHere = ScratchPath.Access;
165 bool IsFirstStep = ScratchPath.empty();
166
167 for (const auto &BaseSpec : Record->bases()) {
168 // Find the record of the base class subobjects for this type.
169 QualType BaseType =
170 Context.getCanonicalType(BaseSpec.getType()).getUnqualifiedType();
171
172 bool isCurrentInstantiation = isa<InjectedClassNameType>(BaseType);
173 if (!isCurrentInstantiation) {
174 if (auto *BaseRecord = cast_if_present<CXXRecordDecl>(
175 BaseSpec.getType()->getAsRecordDecl()))
176 isCurrentInstantiation = BaseRecord->isDependentContext() &&
177 BaseRecord->isCurrentInstantiation(Record);
178 }
179 // C++ [temp.dep]p3:
180 // In the definition of a class template or a member of a class template,
181 // if a base class of the class template depends on a template-parameter,
182 // the base class scope is not examined during unqualified name lookup
183 // either at the point of definition of the class template or member or
184 // during an instantiation of the class tem- plate or member.
185 if (!LookupInDependent &&
186 (BaseType->isDependentType() && !isCurrentInstantiation))
187 continue;
188
189 // Determine whether we need to visit this base class at all,
190 // updating the count of subobjects appropriately.
191 IsVirtBaseAndNumberNonVirtBases &Subobjects = ClassSubobjects[BaseType];
192 bool VisitBase = true;
193 bool SetVirtual = false;
194 if (BaseSpec.isVirtual()) {
195 VisitBase = !Subobjects.IsVirtBase;
196 Subobjects.IsVirtBase = true;
197 if (isDetectingVirtual() && DetectedVirtual == nullptr) {
198 // If this is the first virtual we find, remember it. If it turns out
199 // there is no base path here, we'll reset it later.
200 DetectedVirtual = BaseType->getAs<RecordType>();
201 SetVirtual = true;
202 }
203 } else {
204 ++Subobjects.NumberOfNonVirtBases;
205 }
206 if (isRecordingPaths()) {
207 // Add this base specifier to the current path.
208 CXXBasePathElement Element;
209 Element.Base = &BaseSpec;
210 Element.Class = Record;
211 if (BaseSpec.isVirtual())
212 Element.SubobjectNumber = 0;
213 else
214 Element.SubobjectNumber = Subobjects.NumberOfNonVirtBases;
215 ScratchPath.push_back(Element);
216
217 // Calculate the "top-down" access to this base class.
218 // The spec actually describes this bottom-up, but top-down is
219 // equivalent because the definition works out as follows:
220 // 1. Write down the access along each step in the inheritance
221 // chain, followed by the access of the decl itself.
222 // For example, in
223 // class A { public: int foo; };
224 // class B : protected A {};
225 // class C : public B {};
226 // class D : private C {};
227 // we would write:
228 // private public protected public
229 // 2. If 'private' appears anywhere except far-left, access is denied.
230 // 3. Otherwise, overall access is determined by the most restrictive
231 // access in the sequence.
232 if (IsFirstStep)
233 ScratchPath.Access = BaseSpec.getAccessSpecifier();
234 else
235 ScratchPath.Access = CXXRecordDecl::MergeAccess(AccessToHere,
236 BaseSpec.getAccessSpecifier());
237 }
238
239 // Track whether there's a path involving this specific base.
240 bool FoundPathThroughBase = false;
241
242 if (BaseMatches(&BaseSpec, ScratchPath)) {
243 // We've found a path that terminates at this base.
244 FoundPath = FoundPathThroughBase = true;
245 if (isRecordingPaths()) {
246 // We have a path. Make a copy of it before moving on.
247 Paths.push_back(ScratchPath);
248 } else if (!isFindingAmbiguities()) {
249 // We found a path and we don't care about ambiguities;
250 // return immediately.
251 return FoundPath;
252 }
253 } else if (VisitBase) {
254 CXXRecordDecl *BaseRecord = nullptr;
255 if (LookupInDependent) {
256 const TemplateSpecializationType *TST =
257 BaseSpec.getType()->getAs<TemplateSpecializationType>();
258 if (!TST) {
259 if (auto *RT = BaseSpec.getType()->getAs<RecordType>())
260 BaseRecord = cast<CXXRecordDecl>(RT->getDecl());
261 } else {
262 TemplateName TN = TST->getTemplateName();
263 if (auto *TD =
264 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl()))
265 BaseRecord = TD->getTemplatedDecl();
266 }
267 if (BaseRecord) {
268 if (!BaseRecord->hasDefinition())
269 BaseRecord = nullptr;
270 else if (!VisitedDependentRecords.insert(BaseRecord).second)
271 BaseRecord = nullptr;
272 }
273 } else {
274 BaseRecord = cast<CXXRecordDecl>(BaseSpec.getType()->getAsRecordDecl());
275 }
276 if (BaseRecord &&
277 lookupInBases(Context, BaseRecord, BaseMatches, LookupInDependent)) {
278 // C++ [class.member.lookup]p2:
279 // A member name f in one sub-object B hides a member name f in
280 // a sub-object A if A is a base class sub-object of B. Any
281 // declarations that are so hidden are eliminated from
282 // consideration.
283
284 // There is a path to a base class that meets the criteria. If we're
285 // not collecting paths or finding ambiguities, we're done.
286 FoundPath = FoundPathThroughBase = true;
288 return FoundPath;
289 }
290 }
291
292 // Pop this base specifier off the current path (if we're
293 // collecting paths).
294 if (isRecordingPaths()) {
295 ScratchPath.pop_back();
296 }
297
298 // If we set a virtual earlier, and this isn't a path, forget it again.
299 if (SetVirtual && !FoundPathThroughBase) {
300 DetectedVirtual = nullptr;
301 }
302 }
303
304 // Reset the scratch path access.
305 ScratchPath.Access = AccessToHere;
306
307 return FoundPath;
308}
309
311 CXXBasePaths &Paths,
312 bool LookupInDependent) const {
313 // If we didn't find anything, report that.
314 if (!Paths.lookupInBases(getASTContext(), this, BaseMatches,
315 LookupInDependent))
316 return false;
317
318 // If we're not recording paths or we won't ever find ambiguities,
319 // we're done.
320 if (!Paths.isRecordingPaths() || !Paths.isFindingAmbiguities())
321 return true;
322
323 // C++ [class.member.lookup]p6:
324 // When virtual base classes are used, a hidden declaration can be
325 // reached along a path through the sub-object lattice that does
326 // not pass through the hiding declaration. This is not an
327 // ambiguity. The identical use with nonvirtual base classes is an
328 // ambiguity; in that case there is no unique instance of the name
329 // that hides all the others.
330 //
331 // FIXME: This is an O(N^2) algorithm, but DPG doesn't see an easy
332 // way to make it any faster.
333 Paths.Paths.remove_if([&Paths](const CXXBasePath &Path) {
334 for (const CXXBasePathElement &PE : Path) {
335 if (!PE.Base->isVirtual())
336 continue;
337
338 CXXRecordDecl *VBase = nullptr;
339 if (const RecordType *Record = PE.Base->getType()->getAs<RecordType>())
340 VBase = cast<CXXRecordDecl>(Record->getDecl());
341 if (!VBase)
342 break;
343
344 // The declaration(s) we found along this path were found in a
345 // subobject of a virtual base. Check whether this virtual
346 // base is a subobject of any other path; if so, then the
347 // declaration in this path are hidden by that patch.
348 for (const CXXBasePath &HidingP : Paths) {
349 CXXRecordDecl *HidingClass = nullptr;
350 if (const RecordType *Record =
351 HidingP.back().Base->getType()->getAs<RecordType>())
352 HidingClass = cast<CXXRecordDecl>(Record->getDecl());
353 if (!HidingClass)
354 break;
355
356 if (HidingClass->isVirtuallyDerivedFrom(VBase))
357 return true;
358 }
359 }
360 return false;
361 });
362
363 return true;
364}
365
368 const CXXRecordDecl *BaseRecord) {
369 assert(BaseRecord->getCanonicalDecl() == BaseRecord &&
370 "User data for FindBaseClass is not canonical!");
371 return cast<CXXRecordDecl>(Specifier->getType()->getAsRecordDecl())
372 ->getCanonicalDecl() == BaseRecord;
373}
374
377 const CXXRecordDecl *BaseRecord) {
378 assert(BaseRecord->getCanonicalDecl() == BaseRecord &&
379 "User data for FindBaseClass is not canonical!");
380 return Specifier->isVirtual() &&
381 cast<CXXRecordDecl>(Specifier->getType()->getAsRecordDecl())
382 ->getCanonicalDecl() == BaseRecord;
383}
384
385static bool isOrdinaryMember(const NamedDecl *ND) {
388}
389
391 DeclarationName Name) {
392 Path.Decls = RD->lookup(Name).begin();
393 for (DeclContext::lookup_iterator I = Path.Decls, E = I.end(); I != E; ++I)
394 if (isOrdinaryMember(*I))
395 return true;
396
397 return false;
398}
399
402 if (findOrdinaryMember(this, P, Name))
403 return true;
404
405 CXXBasePaths Paths(false, false, false);
406 return lookupInBases(
407 [Name](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
408 return findOrdinaryMember(Specifier->getType()->getAsCXXRecordDecl(),
409 Path, Name);
410 },
411 Paths);
412}
413
414static bool
417 const TemplateSpecializationType *TST =
418 Specifier->getType()->getAs<TemplateSpecializationType>();
419 if (!TST) {
420 auto *RT = Specifier->getType()->getAs<RecordType>();
421 if (!RT)
422 return false;
423 return findOrdinaryMember(cast<CXXRecordDecl>(RT->getDecl()), Path, Name);
424 }
425 TemplateName TN = TST->getTemplateName();
426 const auto *TD = dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
427 if (!TD)
428 return false;
429 CXXRecordDecl *RD = TD->getTemplatedDecl();
430 if (!RD)
431 return false;
432 return findOrdinaryMember(RD, Path, Name);
433}
434
435std::vector<const NamedDecl *> CXXRecordDecl::lookupDependentName(
436 DeclarationName Name,
437 llvm::function_ref<bool(const NamedDecl *ND)> Filter) {
438 std::vector<const NamedDecl *> Results;
439 // Lookup in the class.
440 bool AnyOrdinaryMembers = false;
441 for (const NamedDecl *ND : lookup(Name)) {
442 if (isOrdinaryMember(ND))
443 AnyOrdinaryMembers = true;
444 if (Filter(ND))
445 Results.push_back(ND);
446 }
447 if (AnyOrdinaryMembers)
448 return Results;
449
450 // Perform lookup into our base classes.
451 CXXBasePaths Paths;
452 Paths.setOrigin(this);
453 if (!lookupInBases(
456 },
457 Paths, /*LookupInDependent=*/true))
458 return Results;
459 for (DeclContext::lookup_iterator I = Paths.front().Decls, E = I.end();
460 I != E; ++I) {
461 if (isOrdinaryMember(*I) && Filter(*I))
462 Results.push_back(*I);
463 }
464 return Results;
465}
466
467void OverridingMethods::add(unsigned OverriddenSubobject,
468 UniqueVirtualMethod Overriding) {
469 SmallVectorImpl<UniqueVirtualMethod> &SubobjectOverrides
470 = Overrides[OverriddenSubobject];
471 if (!llvm::is_contained(SubobjectOverrides, Overriding))
472 SubobjectOverrides.push_back(Overriding);
473}
474
476 for (const_iterator I = Other.begin(), IE = Other.end(); I != IE; ++I) {
477 for (overriding_const_iterator M = I->second.begin(),
478 MEnd = I->second.end();
479 M != MEnd;
480 ++M)
481 add(I->first, *M);
482 }
483}
484
486 for (iterator I = begin(), IEnd = end(); I != IEnd; ++I) {
487 I->second.clear();
488 I->second.push_back(Overriding);
489 }
490}
491
492namespace {
493
494class FinalOverriderCollector {
495 /// The number of subobjects of a given class type that
496 /// occur within the class hierarchy.
497 llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCount;
498
499 /// Overriders for each virtual base subobject.
500 llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *> VirtualOverriders;
501
502 CXXFinalOverriderMap FinalOverriders;
503
504public:
505 ~FinalOverriderCollector();
506
507 void Collect(const CXXRecordDecl *RD, bool VirtualBase,
508 const CXXRecordDecl *InVirtualSubobject,
509 CXXFinalOverriderMap &Overriders);
510};
511
512} // namespace
513
514void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
515 bool VirtualBase,
516 const CXXRecordDecl *InVirtualSubobject,
517 CXXFinalOverriderMap &Overriders) {
518 unsigned SubobjectNumber = 0;
519 if (!VirtualBase)
520 SubobjectNumber
521 = ++SubobjectCount[cast<CXXRecordDecl>(RD->getCanonicalDecl())];
522
523 for (const auto &Base : RD->bases()) {
524 if (const RecordType *RT = Base.getType()->getAs<RecordType>()) {
525 const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(RT->getDecl());
526 if (!BaseDecl->isPolymorphic())
527 continue;
528
529 if (Overriders.empty() && !Base.isVirtual()) {
530 // There are no other overriders of virtual member functions,
531 // so let the base class fill in our overriders for us.
532 Collect(BaseDecl, false, InVirtualSubobject, Overriders);
533 continue;
534 }
535
536 // Collect all of the overridders from the base class subobject
537 // and merge them into the set of overridders for this class.
538 // For virtual base classes, populate or use the cached virtual
539 // overrides so that we do not walk the virtual base class (and
540 // its base classes) more than once.
541 CXXFinalOverriderMap ComputedBaseOverriders;
542 CXXFinalOverriderMap *BaseOverriders = &ComputedBaseOverriders;
543 if (Base.isVirtual()) {
544 CXXFinalOverriderMap *&MyVirtualOverriders = VirtualOverriders[BaseDecl];
545 BaseOverriders = MyVirtualOverriders;
546 if (!MyVirtualOverriders) {
547 MyVirtualOverriders = new CXXFinalOverriderMap;
548
549 // Collect may cause VirtualOverriders to reallocate, invalidating the
550 // MyVirtualOverriders reference. Set BaseOverriders to the right
551 // value now.
552 BaseOverriders = MyVirtualOverriders;
553
554 Collect(BaseDecl, true, BaseDecl, *MyVirtualOverriders);
555 }
556 } else
557 Collect(BaseDecl, false, InVirtualSubobject, ComputedBaseOverriders);
558
559 // Merge the overriders from this base class into our own set of
560 // overriders.
561 for (CXXFinalOverriderMap::iterator OM = BaseOverriders->begin(),
562 OMEnd = BaseOverriders->end();
563 OM != OMEnd;
564 ++OM) {
565 const CXXMethodDecl *CanonOM = OM->first->getCanonicalDecl();
566 Overriders[CanonOM].add(OM->second);
567 }
568 }
569 }
570
571 for (auto *M : RD->methods()) {
572 // We only care about virtual methods.
573 if (!M->isVirtual())
574 continue;
575
576 CXXMethodDecl *CanonM = M->getCanonicalDecl();
577 using OverriddenMethodsRange =
578 llvm::iterator_range<CXXMethodDecl::method_iterator>;
579 OverriddenMethodsRange OverriddenMethods = CanonM->overridden_methods();
580
581 if (OverriddenMethods.begin() == OverriddenMethods.end()) {
582 // This is a new virtual function that does not override any
583 // other virtual function. Add it to the map of virtual
584 // functions for which we are tracking overridders.
585
586 // C++ [class.virtual]p2:
587 // For convenience we say that any virtual function overrides itself.
588 Overriders[CanonM].add(SubobjectNumber,
589 UniqueVirtualMethod(CanonM, SubobjectNumber,
590 InVirtualSubobject));
591 continue;
592 }
593
594 // This virtual method overrides other virtual methods, so it does
595 // not add any new slots into the set of overriders. Instead, we
596 // replace entries in the set of overriders with the new
597 // overrider. To do so, we dig down to the original virtual
598 // functions using data recursion and update all of the methods it
599 // overrides.
600 SmallVector<OverriddenMethodsRange, 4> Stack(1, OverriddenMethods);
601 while (!Stack.empty()) {
602 for (const CXXMethodDecl *OM : Stack.pop_back_val()) {
603 const CXXMethodDecl *CanonOM = OM->getCanonicalDecl();
604
605 // C++ [class.virtual]p2:
606 // A virtual member function C::vf of a class object S is
607 // a final overrider unless the most derived class (1.8)
608 // of which S is a base class subobject (if any) declares
609 // or inherits another member function that overrides vf.
610 //
611 // Treating this object like the most derived class, we
612 // replace any overrides from base classes with this
613 // overriding virtual function.
614 Overriders[CanonOM].replaceAll(
615 UniqueVirtualMethod(CanonM, SubobjectNumber,
616 InVirtualSubobject));
617
618 auto OverriddenMethods = CanonOM->overridden_methods();
619 if (OverriddenMethods.begin() == OverriddenMethods.end())
620 continue;
621
622 // Continue recursion to the methods that this virtual method
623 // overrides.
624 Stack.push_back(OverriddenMethods);
625 }
626 }
627
628 // C++ [class.virtual]p2:
629 // For convenience we say that any virtual function overrides itself.
630 Overriders[CanonM].add(SubobjectNumber,
631 UniqueVirtualMethod(CanonM, SubobjectNumber,
632 InVirtualSubobject));
633 }
634}
635
636FinalOverriderCollector::~FinalOverriderCollector() {
637 for (llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *>::iterator
638 VO = VirtualOverriders.begin(), VOEnd = VirtualOverriders.end();
639 VO != VOEnd;
640 ++VO)
641 delete VO->second;
642}
643
644void
646 FinalOverriderCollector Collector;
647 Collector.Collect(this, false, nullptr, FinalOverriders);
648
649 // Weed out any final overriders that come from virtual base class
650 // subobjects that were hidden by other subobjects along any path.
651 // This is the final-overrider variant of C++ [class.member.lookup]p10.
652 for (auto &OM : FinalOverriders) {
653 for (auto &SO : OM.second) {
654 SmallVectorImpl<UniqueVirtualMethod> &Overriding = SO.second;
655 if (Overriding.size() < 2)
656 continue;
657
658 auto IsHidden = [&Overriding](const UniqueVirtualMethod &M) {
659 if (!M.InVirtualSubobject)
660 return false;
661
662 // We have an overriding method in a virtual base class
663 // subobject (or non-virtual base class subobject thereof);
664 // determine whether there exists an other overriding method
665 // in a base class subobject that hides the virtual base class
666 // subobject.
667 for (const UniqueVirtualMethod &OP : Overriding)
668 if (&M != &OP &&
669 OP.Method->getParent()->isVirtuallyDerivedFrom(
670 M.InVirtualSubobject))
671 return true;
672 return false;
673 };
674
675 // FIXME: IsHidden reads from Overriding from the middle of a remove_if
676 // over the same sequence! Is this guaranteed to work?
677 llvm::erase_if(Overriding, IsHidden);
678 }
679 }
680}
681
682static void
685 // If the record has a virtual primary base class, add it to our set.
686 const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
687 if (Layout.isPrimaryBaseVirtual())
688 Bases.insert(Layout.getPrimaryBase());
689
690 for (const auto &I : RD->bases()) {
691 assert(!I.getType()->isDependentType() &&
692 "Cannot get indirect primary bases for class with dependent bases.");
693
694 const CXXRecordDecl *BaseDecl =
695 cast<CXXRecordDecl>(I.getType()->getAsRecordDecl());
696
697 // Only bases with virtual bases participate in computing the
698 // indirect primary virtual base classes.
699 if (BaseDecl->getNumVBases())
700 AddIndirectPrimaryBases(BaseDecl, Context, Bases);
701 }
702
703}
704
705void
707 ASTContext &Context = getASTContext();
708
709 if (!getNumVBases())
710 return;
711
712 for (const auto &I : bases()) {
713 assert(!I.getType()->isDependentType() &&
714 "Cannot get indirect primary bases for class with dependent bases.");
715
716 const CXXRecordDecl *BaseDecl =
717 cast<CXXRecordDecl>(I.getType()->getAsRecordDecl());
718
719 // Only bases with virtual bases participate in computing the
720 // indirect primary virtual base classes.
721 if (BaseDecl->getNumVBases())
722 AddIndirectPrimaryBases(BaseDecl, Context, Bases);
723 }
724}
Defines the clang::ASTContext interface.
StringRef P
static bool findOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, DeclarationName Name)
static void AddIndirectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context, CXXIndirectPrimaryBaseSet &Bases)
static bool isOrdinaryMember(const NamedDecl *ND)
static bool findOrdinaryMember(const CXXRecordDecl *RD, CXXBasePath &Path, DeclarationName Name)
IndirectLocalPath & Path
Expr * E
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the C++ template declaration subclasses.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
llvm::MachO::Record Record
Definition: MachO.h:31
static RecordDecl * getAsRecordDecl(QualType BaseType)
C Language Family Type Representation.
const NestedNameSpecifier * Specifier
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2716
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
Definition: RecordLayout.h:38
const CXXRecordDecl * getPrimaryBase() const
getPrimaryBase - Get the primary base for this record.
Definition: RecordLayout.h:234
bool isPrimaryBaseVirtual() const
isPrimaryBaseVirtual - Get whether the primary base for this record is virtual or not.
Definition: RecordLayout.h:242
Represents a path from a specific derived class (which is not represented as part of the path) to a p...
AccessSpecifier Access
The access along this inheritance path.
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
bool isRecordingPaths() const
Whether we are recording paths.
bool isDetectingVirtual() const
Whether we are detecting virtual bases.
bool isAmbiguous(CanQualType BaseType)
Determine whether the path from the most-derived type to the given base type is ambiguous (i....
void clear()
Clear the base-paths results.
bool isFindingAmbiguities() const
Whether we are finding multiple paths to detect ambiguities.
void swap(CXXBasePaths &Other)
Swap this data structure's contents with another CXXBasePaths object.
Represents a base class of a C++ class.
Definition: DeclCXX.h:146
A mapping from each virtual member function to its set of final overriders.
A set of all the primary bases for a class.
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2078
overridden_method_range overridden_methods() const
Definition: DeclCXX.cpp:2626
CXXMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition: DeclCXX.h:2174
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
void getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet &Bases) const
Get the indirect primary bases for this class.
base_class_range bases()
Definition: DeclCXX.h:620
bool isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is provably not derived from the type Base.
method_range methods() const
Definition: DeclCXX.h:662
static AccessSpecifier MergeAccess(AccessSpecifier PathAccess, AccessSpecifier DeclAccess)
Calculates the access of a decl that is reached along a path.
Definition: DeclCXX.h:1738
bool isPolymorphic() const
Whether this class is polymorphic (C++ [class.virtual]), which means that the class contains or inher...
Definition: DeclCXX.h:1226
bool lookupInBases(BaseMatchesCallback BaseMatches, CXXBasePaths &Paths, bool LookupInDependent=false) const
Look for entities within the base classes of this C++ class, transitively searching all base class su...
bool hasDefinition() const
Definition: DeclCXX.h:572
void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const
Retrieve the final overriders for each virtual member function in the class hierarchy where this clas...
llvm::function_ref< bool(const CXXBaseSpecifier *Specifier, CXXBasePath &Path)> BaseMatchesCallback
Function type used by lookupInBases() to determine whether a specific base class subobject matches th...
Definition: DeclCXX.h:1658
bool isCurrentInstantiation(const DeclContext *CurContext) const
Determine whether this dependent class is a current instantiation, when viewed from within the given ...
bool hasMemberName(DeclarationName N) const
Determine whether this class has a member with the given name, possibly in a non-dependent base class...
llvm::function_ref< bool(const CXXRecordDecl *BaseDefinition)> ForallBasesCallback
Function type used by forallBases() as a callback.
Definition: DeclCXX.h:1634
static bool FindVirtualBaseClass(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, const CXXRecordDecl *BaseRecord)
Base-class lookup callback that determines whether the given base class specifier refers to a specifi...
static bool FindBaseClass(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, const CXXRecordDecl *BaseRecord)
Base-class lookup callback that determines whether the given base class specifier refers to a specifi...
bool isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is virtually derived from the class Base.
bool forallBases(ForallBasesCallback BaseMatches) const
Determines if the given callback holds for all the direct or indirect base classes of this type.
std::vector< const NamedDecl * > lookupDependentName(DeclarationName Name, llvm::function_ref< bool(const NamedDecl *ND)> Filter)
Performs an imprecise lookup of a dependent name in this class.
CXXRecordDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition: DeclCXX.h:524
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
Definition: DeclCXX.h:635
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
CanQual< T > getUnqualifiedType() const
Retrieve the unqualified form of this type.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1435
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:2089
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
Definition: DeclBase.h:2218
bool isFileContext() const
Definition: DeclBase.h:2160
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
Definition: DeclBase.cpp:1334
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
Definition: DeclBase.cpp:1854
ASTContext & getASTContext() const LLVM_READONLY
Definition: DeclBase.cpp:520
bool isInIdentifierNamespace(unsigned NS) const
Definition: DeclBase.h:882
@ IDNS_Ordinary
Ordinary names.
Definition: DeclBase.h:144
@ IDNS_Member
Members, declared with object declarations within tag definitions.
Definition: DeclBase.h:136
@ IDNS_Tag
Tags, declared with 'struct foo;' and referenced with 'struct foo'.
Definition: DeclBase.h:125
The name of a declaration.
This represents a decl that may have a name.
Definition: Decl.h:253
CXXRecordDecl * getAsRecordDecl() const
Retrieve the record declaration stored in this nested name specifier.
The set of methods that override a given virtual method in each subobject where it occurs.
void replaceAll(UniqueVirtualMethod Overriding)
MapType::iterator iterator
SmallVectorImpl< UniqueVirtualMethod >::const_iterator overriding_const_iterator
MapType::const_iterator const_iterator
void add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding)
A (possibly-)qualified type.
Definition: Type.h:929
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
Definition: Decl.h:4339
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:6072
RecordDecl * getDecl() const
Definition: Type.h:6082
Represents a C++ template name within the type system.
Definition: TemplateName.h:220
TemplateDecl * getAsTemplateDecl(bool IgnoreDeduced=false) const
Retrieve the underlying template declaration that this template name refers to, if known.
Represents a type template specialization; the template must be a class template, a type alias templa...
Definition: Type.h:6661
TemplateName getTemplateName() const
Retrieve the name of the template that we are specializing.
Definition: Type.h:6727
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2706
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8731
The JSON file list parser is used to communicate input to InstallAPI.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
@ Other
Other implicit parameter.
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
Definition: Specifiers.h:123
Represents an element in a path from a derived class to a base class.
Uniquely identifies a virtual method within a class hierarchy by the method itself and a class subobj...