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