xref: /minix3/external/bsd/llvm/dist/clang/lib/AST/CXXInheritance.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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