10b57cec5SDimitry Andric //===- CXXInheritance.cpp - C++ Inheritance -------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file provides routines that help analyzing C++ inheritance hierarchies.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "clang/AST/CXXInheritance.h"
140b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
150b57cec5SDimitry Andric #include "clang/AST/Decl.h"
160b57cec5SDimitry Andric #include "clang/AST/DeclBase.h"
170b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h"
180b57cec5SDimitry Andric #include "clang/AST/DeclTemplate.h"
190b57cec5SDimitry Andric #include "clang/AST/RecordLayout.h"
200b57cec5SDimitry Andric #include "clang/AST/TemplateName.h"
210b57cec5SDimitry Andric #include "clang/AST/Type.h"
220b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
230b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
240b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
250b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
260b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h"
270b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
280b57cec5SDimitry Andric #include <algorithm>
290b57cec5SDimitry Andric #include <utility>
300b57cec5SDimitry Andric #include <cassert>
310b57cec5SDimitry Andric #include <vector>
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric using namespace clang;
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric /// isAmbiguous - Determines whether the set of paths provided is
360b57cec5SDimitry Andric /// ambiguous, i.e., there are two or more paths that refer to
370b57cec5SDimitry Andric /// different base class subobjects of the same type. BaseType must be
380b57cec5SDimitry Andric /// an unqualified, canonical class type.
isAmbiguous(CanQualType BaseType)390b57cec5SDimitry Andric bool CXXBasePaths::isAmbiguous(CanQualType BaseType) {
400b57cec5SDimitry Andric   BaseType = BaseType.getUnqualifiedType();
410b57cec5SDimitry Andric   IsVirtBaseAndNumberNonVirtBases Subobjects = ClassSubobjects[BaseType];
420b57cec5SDimitry Andric   return Subobjects.NumberOfNonVirtBases + (Subobjects.IsVirtBase ? 1 : 0) > 1;
430b57cec5SDimitry Andric }
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric /// clear - Clear out all prior path information.
clear()460b57cec5SDimitry Andric void CXXBasePaths::clear() {
470b57cec5SDimitry Andric   Paths.clear();
480b57cec5SDimitry Andric   ClassSubobjects.clear();
490b57cec5SDimitry Andric   VisitedDependentRecords.clear();
500b57cec5SDimitry Andric   ScratchPath.clear();
510b57cec5SDimitry Andric   DetectedVirtual = nullptr;
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric /// Swaps the contents of this CXXBasePaths structure with the
550b57cec5SDimitry Andric /// contents of Other.
swap(CXXBasePaths & Other)560b57cec5SDimitry Andric void CXXBasePaths::swap(CXXBasePaths &Other) {
570b57cec5SDimitry Andric   std::swap(Origin, Other.Origin);
580b57cec5SDimitry Andric   Paths.swap(Other.Paths);
590b57cec5SDimitry Andric   ClassSubobjects.swap(Other.ClassSubobjects);
600b57cec5SDimitry Andric   VisitedDependentRecords.swap(Other.VisitedDependentRecords);
610b57cec5SDimitry Andric   std::swap(FindAmbiguities, Other.FindAmbiguities);
620b57cec5SDimitry Andric   std::swap(RecordPaths, Other.RecordPaths);
630b57cec5SDimitry Andric   std::swap(DetectVirtual, Other.DetectVirtual);
640b57cec5SDimitry Andric   std::swap(DetectedVirtual, Other.DetectedVirtual);
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric 
isDerivedFrom(const CXXRecordDecl * Base) const670b57cec5SDimitry Andric bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base) const {
680b57cec5SDimitry Andric   CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false,
690b57cec5SDimitry Andric                      /*DetectVirtual=*/false);
700b57cec5SDimitry Andric   return isDerivedFrom(Base, Paths);
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric 
isDerivedFrom(const CXXRecordDecl * Base,CXXBasePaths & Paths) const730b57cec5SDimitry Andric bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base,
740b57cec5SDimitry Andric                                   CXXBasePaths &Paths) const {
750b57cec5SDimitry Andric   if (getCanonicalDecl() == Base->getCanonicalDecl())
760b57cec5SDimitry Andric     return false;
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   Paths.setOrigin(const_cast<CXXRecordDecl*>(this));
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl();
810b57cec5SDimitry Andric   return lookupInBases(
820b57cec5SDimitry Andric       [BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
8306c3fb27SDimitry Andric         return Specifier->getType()->getAsRecordDecl() &&
8406c3fb27SDimitry Andric                FindBaseClass(Specifier, Path, BaseDecl);
850b57cec5SDimitry Andric       },
860b57cec5SDimitry Andric       Paths);
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric 
isVirtuallyDerivedFrom(const CXXRecordDecl * Base) const890b57cec5SDimitry Andric bool CXXRecordDecl::isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const {
900b57cec5SDimitry Andric   if (!getNumVBases())
910b57cec5SDimitry Andric     return false;
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false,
940b57cec5SDimitry Andric                      /*DetectVirtual=*/false);
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   if (getCanonicalDecl() == Base->getCanonicalDecl())
970b57cec5SDimitry Andric     return false;
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   Paths.setOrigin(const_cast<CXXRecordDecl*>(this));
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl();
1020b57cec5SDimitry Andric   return lookupInBases(
1030b57cec5SDimitry Andric       [BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
1040b57cec5SDimitry Andric         return FindVirtualBaseClass(Specifier, Path, BaseDecl);
1050b57cec5SDimitry Andric       },
1060b57cec5SDimitry Andric       Paths);
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric 
isProvablyNotDerivedFrom(const CXXRecordDecl * Base) const1090b57cec5SDimitry Andric bool CXXRecordDecl::isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const {
1100b57cec5SDimitry Andric   const CXXRecordDecl *TargetDecl = Base->getCanonicalDecl();
1110b57cec5SDimitry Andric   return forallBases([TargetDecl](const CXXRecordDecl *Base) {
1120b57cec5SDimitry Andric     return Base->getCanonicalDecl() != TargetDecl;
1130b57cec5SDimitry Andric   });
1140b57cec5SDimitry Andric }
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric bool
isCurrentInstantiation(const DeclContext * CurContext) const1170b57cec5SDimitry Andric CXXRecordDecl::isCurrentInstantiation(const DeclContext *CurContext) const {
1180b57cec5SDimitry Andric   assert(isDependentContext());
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   for (; !CurContext->isFileContext(); CurContext = CurContext->getParent())
1210b57cec5SDimitry Andric     if (CurContext->Equals(this))
1220b57cec5SDimitry Andric       return true;
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   return false;
1250b57cec5SDimitry Andric }
1260b57cec5SDimitry Andric 
forallBases(ForallBasesCallback BaseMatches) const1275ffd83dbSDimitry Andric bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches) const {
1280b57cec5SDimitry Andric   SmallVector<const CXXRecordDecl*, 8> Queue;
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   const CXXRecordDecl *Record = this;
1310b57cec5SDimitry Andric   while (true) {
1320b57cec5SDimitry Andric     for (const auto &I : Record->bases()) {
1330b57cec5SDimitry Andric       const RecordType *Ty = I.getType()->getAs<RecordType>();
1345ffd83dbSDimitry Andric       if (!Ty)
1355ffd83dbSDimitry Andric         return false;
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric       CXXRecordDecl *Base =
1380b57cec5SDimitry Andric             cast_or_null<CXXRecordDecl>(Ty->getDecl()->getDefinition());
1390b57cec5SDimitry Andric       if (!Base ||
1400b57cec5SDimitry Andric           (Base->isDependentContext() &&
1410b57cec5SDimitry Andric            !Base->isCurrentInstantiation(Record))) {
1425ffd83dbSDimitry Andric         return false;
1430b57cec5SDimitry Andric       }
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric       Queue.push_back(Base);
1465ffd83dbSDimitry Andric       if (!BaseMatches(Base))
1475ffd83dbSDimitry Andric         return false;
1480b57cec5SDimitry Andric     }
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric     if (Queue.empty())
1510b57cec5SDimitry Andric       break;
1520b57cec5SDimitry Andric     Record = Queue.pop_back_val(); // not actually a queue.
1530b57cec5SDimitry Andric   }
1540b57cec5SDimitry Andric 
1555ffd83dbSDimitry Andric   return true;
1560b57cec5SDimitry Andric }
1570b57cec5SDimitry Andric 
lookupInBases(ASTContext & Context,const CXXRecordDecl * Record,CXXRecordDecl::BaseMatchesCallback BaseMatches,bool LookupInDependent)1580b57cec5SDimitry Andric bool CXXBasePaths::lookupInBases(ASTContext &Context,
1590b57cec5SDimitry Andric                                  const CXXRecordDecl *Record,
1600b57cec5SDimitry Andric                                  CXXRecordDecl::BaseMatchesCallback BaseMatches,
1610b57cec5SDimitry Andric                                  bool LookupInDependent) {
1620b57cec5SDimitry Andric   bool FoundPath = false;
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   // The access of the path down to this record.
1650b57cec5SDimitry Andric   AccessSpecifier AccessToHere = ScratchPath.Access;
1660b57cec5SDimitry Andric   bool IsFirstStep = ScratchPath.empty();
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   for (const auto &BaseSpec : Record->bases()) {
1690b57cec5SDimitry Andric     // Find the record of the base class subobjects for this type.
1700b57cec5SDimitry Andric     QualType BaseType =
1710b57cec5SDimitry Andric         Context.getCanonicalType(BaseSpec.getType()).getUnqualifiedType();
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric     // C++ [temp.dep]p3:
1740b57cec5SDimitry Andric     //   In the definition of a class template or a member of a class template,
1750b57cec5SDimitry Andric     //   if a base class of the class template depends on a template-parameter,
1760b57cec5SDimitry Andric     //   the base class scope is not examined during unqualified name lookup
1770b57cec5SDimitry Andric     //   either at the point of definition of the class template or member or
1780b57cec5SDimitry Andric     //   during an instantiation of the class tem- plate or member.
1790b57cec5SDimitry Andric     if (!LookupInDependent && BaseType->isDependentType())
1800b57cec5SDimitry Andric       continue;
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric     // Determine whether we need to visit this base class at all,
1830b57cec5SDimitry Andric     // updating the count of subobjects appropriately.
1840b57cec5SDimitry Andric     IsVirtBaseAndNumberNonVirtBases &Subobjects = ClassSubobjects[BaseType];
1850b57cec5SDimitry Andric     bool VisitBase = true;
1860b57cec5SDimitry Andric     bool SetVirtual = false;
1870b57cec5SDimitry Andric     if (BaseSpec.isVirtual()) {
1880b57cec5SDimitry Andric       VisitBase = !Subobjects.IsVirtBase;
1890b57cec5SDimitry Andric       Subobjects.IsVirtBase = true;
1900b57cec5SDimitry Andric       if (isDetectingVirtual() && DetectedVirtual == nullptr) {
1910b57cec5SDimitry Andric         // If this is the first virtual we find, remember it. If it turns out
1920b57cec5SDimitry Andric         // there is no base path here, we'll reset it later.
1930b57cec5SDimitry Andric         DetectedVirtual = BaseType->getAs<RecordType>();
1940b57cec5SDimitry Andric         SetVirtual = true;
1950b57cec5SDimitry Andric       }
1960b57cec5SDimitry Andric     } else {
1970b57cec5SDimitry Andric       ++Subobjects.NumberOfNonVirtBases;
1980b57cec5SDimitry Andric     }
1990b57cec5SDimitry Andric     if (isRecordingPaths()) {
2000b57cec5SDimitry Andric       // Add this base specifier to the current path.
2010b57cec5SDimitry Andric       CXXBasePathElement Element;
2020b57cec5SDimitry Andric       Element.Base = &BaseSpec;
2030b57cec5SDimitry Andric       Element.Class = Record;
2040b57cec5SDimitry Andric       if (BaseSpec.isVirtual())
2050b57cec5SDimitry Andric         Element.SubobjectNumber = 0;
2060b57cec5SDimitry Andric       else
2070b57cec5SDimitry Andric         Element.SubobjectNumber = Subobjects.NumberOfNonVirtBases;
2080b57cec5SDimitry Andric       ScratchPath.push_back(Element);
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric       // Calculate the "top-down" access to this base class.
2110b57cec5SDimitry Andric       // The spec actually describes this bottom-up, but top-down is
2120b57cec5SDimitry Andric       // equivalent because the definition works out as follows:
2130b57cec5SDimitry Andric       // 1. Write down the access along each step in the inheritance
2140b57cec5SDimitry Andric       //    chain, followed by the access of the decl itself.
2150b57cec5SDimitry Andric       //    For example, in
2160b57cec5SDimitry Andric       //      class A { public: int foo; };
2170b57cec5SDimitry Andric       //      class B : protected A {};
2180b57cec5SDimitry Andric       //      class C : public B {};
2190b57cec5SDimitry Andric       //      class D : private C {};
2200b57cec5SDimitry Andric       //    we would write:
2210b57cec5SDimitry Andric       //      private public protected public
2220b57cec5SDimitry Andric       // 2. If 'private' appears anywhere except far-left, access is denied.
2230b57cec5SDimitry Andric       // 3. Otherwise, overall access is determined by the most restrictive
2240b57cec5SDimitry Andric       //    access in the sequence.
2250b57cec5SDimitry Andric       if (IsFirstStep)
2260b57cec5SDimitry Andric         ScratchPath.Access = BaseSpec.getAccessSpecifier();
2270b57cec5SDimitry Andric       else
2280b57cec5SDimitry Andric         ScratchPath.Access = CXXRecordDecl::MergeAccess(AccessToHere,
2290b57cec5SDimitry Andric                                                  BaseSpec.getAccessSpecifier());
2300b57cec5SDimitry Andric     }
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric     // Track whether there's a path involving this specific base.
2330b57cec5SDimitry Andric     bool FoundPathThroughBase = false;
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric     if (BaseMatches(&BaseSpec, ScratchPath)) {
2360b57cec5SDimitry Andric       // We've found a path that terminates at this base.
2370b57cec5SDimitry Andric       FoundPath = FoundPathThroughBase = true;
2380b57cec5SDimitry Andric       if (isRecordingPaths()) {
2390b57cec5SDimitry Andric         // We have a path. Make a copy of it before moving on.
2400b57cec5SDimitry Andric         Paths.push_back(ScratchPath);
2410b57cec5SDimitry Andric       } else if (!isFindingAmbiguities()) {
2420b57cec5SDimitry Andric         // We found a path and we don't care about ambiguities;
2430b57cec5SDimitry Andric         // return immediately.
2440b57cec5SDimitry Andric         return FoundPath;
2450b57cec5SDimitry Andric       }
2460b57cec5SDimitry Andric     } else if (VisitBase) {
2470b57cec5SDimitry Andric       CXXRecordDecl *BaseRecord;
2480b57cec5SDimitry Andric       if (LookupInDependent) {
2490b57cec5SDimitry Andric         BaseRecord = nullptr;
2500b57cec5SDimitry Andric         const TemplateSpecializationType *TST =
2510b57cec5SDimitry Andric             BaseSpec.getType()->getAs<TemplateSpecializationType>();
2520b57cec5SDimitry Andric         if (!TST) {
2530b57cec5SDimitry Andric           if (auto *RT = BaseSpec.getType()->getAs<RecordType>())
2540b57cec5SDimitry Andric             BaseRecord = cast<CXXRecordDecl>(RT->getDecl());
2550b57cec5SDimitry Andric         } else {
2560b57cec5SDimitry Andric           TemplateName TN = TST->getTemplateName();
2570b57cec5SDimitry Andric           if (auto *TD =
2580b57cec5SDimitry Andric                   dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl()))
2590b57cec5SDimitry Andric             BaseRecord = TD->getTemplatedDecl();
2600b57cec5SDimitry Andric         }
2610b57cec5SDimitry Andric         if (BaseRecord) {
2620b57cec5SDimitry Andric           if (!BaseRecord->hasDefinition() ||
2630b57cec5SDimitry Andric               VisitedDependentRecords.count(BaseRecord)) {
2640b57cec5SDimitry Andric             BaseRecord = nullptr;
2650b57cec5SDimitry Andric           } else {
2660b57cec5SDimitry Andric             VisitedDependentRecords.insert(BaseRecord);
2670b57cec5SDimitry Andric           }
2680b57cec5SDimitry Andric         }
2690b57cec5SDimitry Andric       } else {
2700b57cec5SDimitry Andric         BaseRecord = cast<CXXRecordDecl>(
2710b57cec5SDimitry Andric             BaseSpec.getType()->castAs<RecordType>()->getDecl());
2720b57cec5SDimitry Andric       }
2730b57cec5SDimitry Andric       if (BaseRecord &&
2740b57cec5SDimitry Andric           lookupInBases(Context, BaseRecord, BaseMatches, LookupInDependent)) {
2750b57cec5SDimitry Andric         // C++ [class.member.lookup]p2:
2760b57cec5SDimitry Andric         //   A member name f in one sub-object B hides a member name f in
2770b57cec5SDimitry Andric         //   a sub-object A if A is a base class sub-object of B. Any
2780b57cec5SDimitry Andric         //   declarations that are so hidden are eliminated from
2790b57cec5SDimitry Andric         //   consideration.
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric         // There is a path to a base class that meets the criteria. If we're
2820b57cec5SDimitry Andric         // not collecting paths or finding ambiguities, we're done.
2830b57cec5SDimitry Andric         FoundPath = FoundPathThroughBase = true;
2840b57cec5SDimitry Andric         if (!isFindingAmbiguities())
2850b57cec5SDimitry Andric           return FoundPath;
2860b57cec5SDimitry Andric       }
2870b57cec5SDimitry Andric     }
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric     // Pop this base specifier off the current path (if we're
2900b57cec5SDimitry Andric     // collecting paths).
2910b57cec5SDimitry Andric     if (isRecordingPaths()) {
2920b57cec5SDimitry Andric       ScratchPath.pop_back();
2930b57cec5SDimitry Andric     }
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric     // If we set a virtual earlier, and this isn't a path, forget it again.
2960b57cec5SDimitry Andric     if (SetVirtual && !FoundPathThroughBase) {
2970b57cec5SDimitry Andric       DetectedVirtual = nullptr;
2980b57cec5SDimitry Andric     }
2990b57cec5SDimitry Andric   }
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric   // Reset the scratch path access.
3020b57cec5SDimitry Andric   ScratchPath.Access = AccessToHere;
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric   return FoundPath;
3050b57cec5SDimitry Andric }
3060b57cec5SDimitry Andric 
lookupInBases(BaseMatchesCallback BaseMatches,CXXBasePaths & Paths,bool LookupInDependent) const3070b57cec5SDimitry Andric bool CXXRecordDecl::lookupInBases(BaseMatchesCallback BaseMatches,
3080b57cec5SDimitry Andric                                   CXXBasePaths &Paths,
3090b57cec5SDimitry Andric                                   bool LookupInDependent) const {
3100b57cec5SDimitry Andric   // If we didn't find anything, report that.
3110b57cec5SDimitry Andric   if (!Paths.lookupInBases(getASTContext(), this, BaseMatches,
3120b57cec5SDimitry Andric                            LookupInDependent))
3130b57cec5SDimitry Andric     return false;
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric   // If we're not recording paths or we won't ever find ambiguities,
3160b57cec5SDimitry Andric   // we're done.
3170b57cec5SDimitry Andric   if (!Paths.isRecordingPaths() || !Paths.isFindingAmbiguities())
3180b57cec5SDimitry Andric     return true;
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric   // C++ [class.member.lookup]p6:
3210b57cec5SDimitry Andric   //   When virtual base classes are used, a hidden declaration can be
3220b57cec5SDimitry Andric   //   reached along a path through the sub-object lattice that does
3230b57cec5SDimitry Andric   //   not pass through the hiding declaration. This is not an
3240b57cec5SDimitry Andric   //   ambiguity. The identical use with nonvirtual base classes is an
3250b57cec5SDimitry Andric   //   ambiguity; in that case there is no unique instance of the name
3260b57cec5SDimitry Andric   //   that hides all the others.
3270b57cec5SDimitry Andric   //
3280b57cec5SDimitry Andric   // FIXME: This is an O(N^2) algorithm, but DPG doesn't see an easy
3290b57cec5SDimitry Andric   // way to make it any faster.
3300b57cec5SDimitry Andric   Paths.Paths.remove_if([&Paths](const CXXBasePath &Path) {
3310b57cec5SDimitry Andric     for (const CXXBasePathElement &PE : Path) {
3320b57cec5SDimitry Andric       if (!PE.Base->isVirtual())
3330b57cec5SDimitry Andric         continue;
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric       CXXRecordDecl *VBase = nullptr;
3360b57cec5SDimitry Andric       if (const RecordType *Record = PE.Base->getType()->getAs<RecordType>())
3370b57cec5SDimitry Andric         VBase = cast<CXXRecordDecl>(Record->getDecl());
3380b57cec5SDimitry Andric       if (!VBase)
3390b57cec5SDimitry Andric         break;
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric       // The declaration(s) we found along this path were found in a
3420b57cec5SDimitry Andric       // subobject of a virtual base. Check whether this virtual
3430b57cec5SDimitry Andric       // base is a subobject of any other path; if so, then the
3440b57cec5SDimitry Andric       // declaration in this path are hidden by that patch.
3450b57cec5SDimitry Andric       for (const CXXBasePath &HidingP : Paths) {
3460b57cec5SDimitry Andric         CXXRecordDecl *HidingClass = nullptr;
3470b57cec5SDimitry Andric         if (const RecordType *Record =
3480b57cec5SDimitry Andric                 HidingP.back().Base->getType()->getAs<RecordType>())
3490b57cec5SDimitry Andric           HidingClass = cast<CXXRecordDecl>(Record->getDecl());
3500b57cec5SDimitry Andric         if (!HidingClass)
3510b57cec5SDimitry Andric           break;
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric         if (HidingClass->isVirtuallyDerivedFrom(VBase))
3540b57cec5SDimitry Andric           return true;
3550b57cec5SDimitry Andric       }
3560b57cec5SDimitry Andric     }
3570b57cec5SDimitry Andric     return false;
3580b57cec5SDimitry Andric   });
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric   return true;
3610b57cec5SDimitry Andric }
3620b57cec5SDimitry Andric 
FindBaseClass(const CXXBaseSpecifier * Specifier,CXXBasePath & Path,const CXXRecordDecl * BaseRecord)3630b57cec5SDimitry Andric bool CXXRecordDecl::FindBaseClass(const CXXBaseSpecifier *Specifier,
3640b57cec5SDimitry Andric                                   CXXBasePath &Path,
3650b57cec5SDimitry Andric                                   const CXXRecordDecl *BaseRecord) {
3660b57cec5SDimitry Andric   assert(BaseRecord->getCanonicalDecl() == BaseRecord &&
3670b57cec5SDimitry Andric          "User data for FindBaseClass is not canonical!");
3680b57cec5SDimitry Andric   return Specifier->getType()->castAs<RecordType>()->getDecl()
3690b57cec5SDimitry Andric             ->getCanonicalDecl() == BaseRecord;
3700b57cec5SDimitry Andric }
3710b57cec5SDimitry Andric 
FindVirtualBaseClass(const CXXBaseSpecifier * Specifier,CXXBasePath & Path,const CXXRecordDecl * BaseRecord)3720b57cec5SDimitry Andric bool CXXRecordDecl::FindVirtualBaseClass(const CXXBaseSpecifier *Specifier,
3730b57cec5SDimitry Andric                                          CXXBasePath &Path,
3740b57cec5SDimitry Andric                                          const CXXRecordDecl *BaseRecord) {
3750b57cec5SDimitry Andric   assert(BaseRecord->getCanonicalDecl() == BaseRecord &&
3760b57cec5SDimitry Andric          "User data for FindBaseClass is not canonical!");
3770b57cec5SDimitry Andric   return Specifier->isVirtual() &&
3780b57cec5SDimitry Andric          Specifier->getType()->castAs<RecordType>()->getDecl()
3790b57cec5SDimitry Andric             ->getCanonicalDecl() == BaseRecord;
3800b57cec5SDimitry Andric }
3810b57cec5SDimitry Andric 
isOrdinaryMember(const NamedDecl * ND)382e8d8bef9SDimitry Andric static bool isOrdinaryMember(const NamedDecl *ND) {
383e8d8bef9SDimitry Andric   return ND->isInIdentifierNamespace(Decl::IDNS_Ordinary | Decl::IDNS_Tag |
384e8d8bef9SDimitry Andric                                      Decl::IDNS_Member);
3850b57cec5SDimitry Andric }
3860b57cec5SDimitry Andric 
findOrdinaryMember(const CXXRecordDecl * RD,CXXBasePath & Path,DeclarationName Name)387e8d8bef9SDimitry Andric static bool findOrdinaryMember(const CXXRecordDecl *RD, CXXBasePath &Path,
388e8d8bef9SDimitry Andric                                DeclarationName Name) {
389fe6060f1SDimitry Andric   Path.Decls = RD->lookup(Name).begin();
390fe6060f1SDimitry Andric   for (DeclContext::lookup_iterator I = Path.Decls, E = I.end(); I != E; ++I)
391fe6060f1SDimitry Andric     if (isOrdinaryMember(*I))
392e8d8bef9SDimitry Andric       return true;
393e8d8bef9SDimitry Andric 
3940b57cec5SDimitry Andric   return false;
3950b57cec5SDimitry Andric }
3960b57cec5SDimitry Andric 
hasMemberName(DeclarationName Name) const397e8d8bef9SDimitry Andric bool CXXRecordDecl::hasMemberName(DeclarationName Name) const {
398e8d8bef9SDimitry Andric   CXXBasePath P;
399e8d8bef9SDimitry Andric   if (findOrdinaryMember(this, P, Name))
4000b57cec5SDimitry Andric     return true;
401e8d8bef9SDimitry Andric 
402e8d8bef9SDimitry Andric   CXXBasePaths Paths(false, false, false);
403e8d8bef9SDimitry Andric   return lookupInBases(
404e8d8bef9SDimitry Andric       [Name](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
405e8d8bef9SDimitry Andric         return findOrdinaryMember(Specifier->getType()->getAsCXXRecordDecl(),
406e8d8bef9SDimitry Andric                                   Path, Name);
407e8d8bef9SDimitry Andric       },
408e8d8bef9SDimitry Andric       Paths);
4090b57cec5SDimitry Andric }
4100b57cec5SDimitry Andric 
411e8d8bef9SDimitry Andric static bool
findOrdinaryMemberInDependentClasses(const CXXBaseSpecifier * Specifier,CXXBasePath & Path,DeclarationName Name)412e8d8bef9SDimitry Andric findOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier,
413e8d8bef9SDimitry Andric                                      CXXBasePath &Path, DeclarationName Name) {
4140b57cec5SDimitry Andric   const TemplateSpecializationType *TST =
4150b57cec5SDimitry Andric       Specifier->getType()->getAs<TemplateSpecializationType>();
4160b57cec5SDimitry Andric   if (!TST) {
4170b57cec5SDimitry Andric     auto *RT = Specifier->getType()->getAs<RecordType>();
4180b57cec5SDimitry Andric     if (!RT)
4190b57cec5SDimitry Andric       return false;
420e8d8bef9SDimitry Andric     return findOrdinaryMember(cast<CXXRecordDecl>(RT->getDecl()), Path, Name);
4210b57cec5SDimitry Andric   }
4220b57cec5SDimitry Andric   TemplateName TN = TST->getTemplateName();
4230b57cec5SDimitry Andric   const auto *TD = dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
4240b57cec5SDimitry Andric   if (!TD)
4250b57cec5SDimitry Andric     return false;
4260b57cec5SDimitry Andric   CXXRecordDecl *RD = TD->getTemplatedDecl();
4270b57cec5SDimitry Andric   if (!RD)
4280b57cec5SDimitry Andric     return false;
4290b57cec5SDimitry Andric   return findOrdinaryMember(RD, Path, Name);
4300b57cec5SDimitry Andric }
4310b57cec5SDimitry Andric 
lookupDependentName(DeclarationName Name,llvm::function_ref<bool (const NamedDecl * ND)> Filter)4320b57cec5SDimitry Andric std::vector<const NamedDecl *> CXXRecordDecl::lookupDependentName(
433e8d8bef9SDimitry Andric     DeclarationName Name,
4340b57cec5SDimitry Andric     llvm::function_ref<bool(const NamedDecl *ND)> Filter) {
4350b57cec5SDimitry Andric   std::vector<const NamedDecl *> Results;
4360b57cec5SDimitry Andric   // Lookup in the class.
437e8d8bef9SDimitry Andric   bool AnyOrdinaryMembers = false;
438e8d8bef9SDimitry Andric   for (const NamedDecl *ND : lookup(Name)) {
439e8d8bef9SDimitry Andric     if (isOrdinaryMember(ND))
440e8d8bef9SDimitry Andric       AnyOrdinaryMembers = true;
4410b57cec5SDimitry Andric     if (Filter(ND))
4420b57cec5SDimitry Andric       Results.push_back(ND);
4430b57cec5SDimitry Andric   }
444e8d8bef9SDimitry Andric   if (AnyOrdinaryMembers)
4450b57cec5SDimitry Andric     return Results;
446e8d8bef9SDimitry Andric 
4470b57cec5SDimitry Andric   // Perform lookup into our base classes.
4480b57cec5SDimitry Andric   CXXBasePaths Paths;
4490b57cec5SDimitry Andric   Paths.setOrigin(this);
4500b57cec5SDimitry Andric   if (!lookupInBases(
4510b57cec5SDimitry Andric           [&](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
452e8d8bef9SDimitry Andric             return findOrdinaryMemberInDependentClasses(Specifier, Path, Name);
4530b57cec5SDimitry Andric           },
4540b57cec5SDimitry Andric           Paths, /*LookupInDependent=*/true))
4550b57cec5SDimitry Andric     return Results;
456fe6060f1SDimitry Andric   for (DeclContext::lookup_iterator I = Paths.front().Decls, E = I.end();
457fe6060f1SDimitry Andric        I != E; ++I) {
458fe6060f1SDimitry Andric     if (isOrdinaryMember(*I) && Filter(*I))
459fe6060f1SDimitry Andric       Results.push_back(*I);
4600b57cec5SDimitry Andric   }
4610b57cec5SDimitry Andric   return Results;
4620b57cec5SDimitry Andric }
4630b57cec5SDimitry Andric 
add(unsigned OverriddenSubobject,UniqueVirtualMethod Overriding)4640b57cec5SDimitry Andric void OverridingMethods::add(unsigned OverriddenSubobject,
4650b57cec5SDimitry Andric                             UniqueVirtualMethod Overriding) {
4660b57cec5SDimitry Andric   SmallVectorImpl<UniqueVirtualMethod> &SubobjectOverrides
4670b57cec5SDimitry Andric     = Overrides[OverriddenSubobject];
468349cc55cSDimitry Andric   if (!llvm::is_contained(SubobjectOverrides, Overriding))
4690b57cec5SDimitry Andric     SubobjectOverrides.push_back(Overriding);
4700b57cec5SDimitry Andric }
4710b57cec5SDimitry Andric 
add(const OverridingMethods & Other)4720b57cec5SDimitry Andric void OverridingMethods::add(const OverridingMethods &Other) {
4730b57cec5SDimitry Andric   for (const_iterator I = Other.begin(), IE = Other.end(); I != IE; ++I) {
4740b57cec5SDimitry Andric     for (overriding_const_iterator M = I->second.begin(),
4750b57cec5SDimitry Andric                                 MEnd = I->second.end();
4760b57cec5SDimitry Andric          M != MEnd;
4770b57cec5SDimitry Andric          ++M)
4780b57cec5SDimitry Andric       add(I->first, *M);
4790b57cec5SDimitry Andric   }
4800b57cec5SDimitry Andric }
4810b57cec5SDimitry Andric 
replaceAll(UniqueVirtualMethod Overriding)4820b57cec5SDimitry Andric void OverridingMethods::replaceAll(UniqueVirtualMethod Overriding) {
4830b57cec5SDimitry Andric   for (iterator I = begin(), IEnd = end(); I != IEnd; ++I) {
4840b57cec5SDimitry Andric     I->second.clear();
4850b57cec5SDimitry Andric     I->second.push_back(Overriding);
4860b57cec5SDimitry Andric   }
4870b57cec5SDimitry Andric }
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric namespace {
4900b57cec5SDimitry Andric 
4910b57cec5SDimitry Andric class FinalOverriderCollector {
4920b57cec5SDimitry Andric   /// The number of subobjects of a given class type that
4930b57cec5SDimitry Andric   /// occur within the class hierarchy.
4940b57cec5SDimitry Andric   llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCount;
4950b57cec5SDimitry Andric 
4960b57cec5SDimitry Andric   /// Overriders for each virtual base subobject.
4970b57cec5SDimitry Andric   llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *> VirtualOverriders;
4980b57cec5SDimitry Andric 
4990b57cec5SDimitry Andric   CXXFinalOverriderMap FinalOverriders;
5000b57cec5SDimitry Andric 
5010b57cec5SDimitry Andric public:
5020b57cec5SDimitry Andric   ~FinalOverriderCollector();
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric   void Collect(const CXXRecordDecl *RD, bool VirtualBase,
5050b57cec5SDimitry Andric                const CXXRecordDecl *InVirtualSubobject,
5060b57cec5SDimitry Andric                CXXFinalOverriderMap &Overriders);
5070b57cec5SDimitry Andric };
5080b57cec5SDimitry Andric 
5090b57cec5SDimitry Andric } // namespace
5100b57cec5SDimitry Andric 
Collect(const CXXRecordDecl * RD,bool VirtualBase,const CXXRecordDecl * InVirtualSubobject,CXXFinalOverriderMap & Overriders)5110b57cec5SDimitry Andric void FinalOverriderCollector::Collect(const CXXRecordDecl *RD,
5120b57cec5SDimitry Andric                                       bool VirtualBase,
5130b57cec5SDimitry Andric                                       const CXXRecordDecl *InVirtualSubobject,
5140b57cec5SDimitry Andric                                       CXXFinalOverriderMap &Overriders) {
5150b57cec5SDimitry Andric   unsigned SubobjectNumber = 0;
5160b57cec5SDimitry Andric   if (!VirtualBase)
5170b57cec5SDimitry Andric     SubobjectNumber
5180b57cec5SDimitry Andric       = ++SubobjectCount[cast<CXXRecordDecl>(RD->getCanonicalDecl())];
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric   for (const auto &Base : RD->bases()) {
5210b57cec5SDimitry Andric     if (const RecordType *RT = Base.getType()->getAs<RecordType>()) {
5220b57cec5SDimitry Andric       const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(RT->getDecl());
5230b57cec5SDimitry Andric       if (!BaseDecl->isPolymorphic())
5240b57cec5SDimitry Andric         continue;
5250b57cec5SDimitry Andric 
5260b57cec5SDimitry Andric       if (Overriders.empty() && !Base.isVirtual()) {
5270b57cec5SDimitry Andric         // There are no other overriders of virtual member functions,
5280b57cec5SDimitry Andric         // so let the base class fill in our overriders for us.
5290b57cec5SDimitry Andric         Collect(BaseDecl, false, InVirtualSubobject, Overriders);
5300b57cec5SDimitry Andric         continue;
5310b57cec5SDimitry Andric       }
5320b57cec5SDimitry Andric 
5330b57cec5SDimitry Andric       // Collect all of the overridders from the base class subobject
5340b57cec5SDimitry Andric       // and merge them into the set of overridders for this class.
5350b57cec5SDimitry Andric       // For virtual base classes, populate or use the cached virtual
5360b57cec5SDimitry Andric       // overrides so that we do not walk the virtual base class (and
5370b57cec5SDimitry Andric       // its base classes) more than once.
5380b57cec5SDimitry Andric       CXXFinalOverriderMap ComputedBaseOverriders;
5390b57cec5SDimitry Andric       CXXFinalOverriderMap *BaseOverriders = &ComputedBaseOverriders;
5400b57cec5SDimitry Andric       if (Base.isVirtual()) {
5410b57cec5SDimitry Andric         CXXFinalOverriderMap *&MyVirtualOverriders = VirtualOverriders[BaseDecl];
5420b57cec5SDimitry Andric         BaseOverriders = MyVirtualOverriders;
5430b57cec5SDimitry Andric         if (!MyVirtualOverriders) {
5440b57cec5SDimitry Andric           MyVirtualOverriders = new CXXFinalOverriderMap;
5450b57cec5SDimitry Andric 
5460b57cec5SDimitry Andric           // Collect may cause VirtualOverriders to reallocate, invalidating the
5470b57cec5SDimitry Andric           // MyVirtualOverriders reference. Set BaseOverriders to the right
5480b57cec5SDimitry Andric           // value now.
5490b57cec5SDimitry Andric           BaseOverriders = MyVirtualOverriders;
5500b57cec5SDimitry Andric 
5510b57cec5SDimitry Andric           Collect(BaseDecl, true, BaseDecl, *MyVirtualOverriders);
5520b57cec5SDimitry Andric         }
5530b57cec5SDimitry Andric       } else
5540b57cec5SDimitry Andric         Collect(BaseDecl, false, InVirtualSubobject, ComputedBaseOverriders);
5550b57cec5SDimitry Andric 
5560b57cec5SDimitry Andric       // Merge the overriders from this base class into our own set of
5570b57cec5SDimitry Andric       // overriders.
5580b57cec5SDimitry Andric       for (CXXFinalOverriderMap::iterator OM = BaseOverriders->begin(),
5590b57cec5SDimitry Andric                                OMEnd = BaseOverriders->end();
5600b57cec5SDimitry Andric            OM != OMEnd;
5610b57cec5SDimitry Andric            ++OM) {
5620b57cec5SDimitry Andric         const CXXMethodDecl *CanonOM = OM->first->getCanonicalDecl();
5630b57cec5SDimitry Andric         Overriders[CanonOM].add(OM->second);
5640b57cec5SDimitry Andric       }
5650b57cec5SDimitry Andric     }
5660b57cec5SDimitry Andric   }
5670b57cec5SDimitry Andric 
5680b57cec5SDimitry Andric   for (auto *M : RD->methods()) {
5690b57cec5SDimitry Andric     // We only care about virtual methods.
5700b57cec5SDimitry Andric     if (!M->isVirtual())
5710b57cec5SDimitry Andric       continue;
5720b57cec5SDimitry Andric 
5730b57cec5SDimitry Andric     CXXMethodDecl *CanonM = M->getCanonicalDecl();
5740b57cec5SDimitry Andric     using OverriddenMethodsRange =
5750b57cec5SDimitry Andric         llvm::iterator_range<CXXMethodDecl::method_iterator>;
5760b57cec5SDimitry Andric     OverriddenMethodsRange OverriddenMethods = CanonM->overridden_methods();
5770b57cec5SDimitry Andric 
5780b57cec5SDimitry Andric     if (OverriddenMethods.begin() == OverriddenMethods.end()) {
5790b57cec5SDimitry Andric       // This is a new virtual function that does not override any
5800b57cec5SDimitry Andric       // other virtual function. Add it to the map of virtual
5810b57cec5SDimitry Andric       // functions for which we are tracking overridders.
5820b57cec5SDimitry Andric 
5830b57cec5SDimitry Andric       // C++ [class.virtual]p2:
5840b57cec5SDimitry Andric       //   For convenience we say that any virtual function overrides itself.
5850b57cec5SDimitry Andric       Overriders[CanonM].add(SubobjectNumber,
5860b57cec5SDimitry Andric                              UniqueVirtualMethod(CanonM, SubobjectNumber,
5870b57cec5SDimitry Andric                                                  InVirtualSubobject));
5880b57cec5SDimitry Andric       continue;
5890b57cec5SDimitry Andric     }
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric     // This virtual method overrides other virtual methods, so it does
5920b57cec5SDimitry Andric     // not add any new slots into the set of overriders. Instead, we
5930b57cec5SDimitry Andric     // replace entries in the set of overriders with the new
5940b57cec5SDimitry Andric     // overrider. To do so, we dig down to the original virtual
5950b57cec5SDimitry Andric     // functions using data recursion and update all of the methods it
5960b57cec5SDimitry Andric     // overrides.
5970b57cec5SDimitry Andric     SmallVector<OverriddenMethodsRange, 4> Stack(1, OverriddenMethods);
5980b57cec5SDimitry Andric     while (!Stack.empty()) {
5990b57cec5SDimitry Andric       for (const CXXMethodDecl *OM : Stack.pop_back_val()) {
6000b57cec5SDimitry Andric         const CXXMethodDecl *CanonOM = OM->getCanonicalDecl();
6010b57cec5SDimitry Andric 
6020b57cec5SDimitry Andric         // C++ [class.virtual]p2:
6030b57cec5SDimitry Andric         //   A virtual member function C::vf of a class object S is
6040b57cec5SDimitry Andric         //   a final overrider unless the most derived class (1.8)
6050b57cec5SDimitry Andric         //   of which S is a base class subobject (if any) declares
6060b57cec5SDimitry Andric         //   or inherits another member function that overrides vf.
6070b57cec5SDimitry Andric         //
6080b57cec5SDimitry Andric         // Treating this object like the most derived class, we
6090b57cec5SDimitry Andric         // replace any overrides from base classes with this
6100b57cec5SDimitry Andric         // overriding virtual function.
6110b57cec5SDimitry Andric         Overriders[CanonOM].replaceAll(
6120b57cec5SDimitry Andric                                UniqueVirtualMethod(CanonM, SubobjectNumber,
6130b57cec5SDimitry Andric                                                    InVirtualSubobject));
6140b57cec5SDimitry Andric 
6150b57cec5SDimitry Andric         auto OverriddenMethods = CanonOM->overridden_methods();
6160b57cec5SDimitry Andric         if (OverriddenMethods.begin() == OverriddenMethods.end())
6170b57cec5SDimitry Andric           continue;
6180b57cec5SDimitry Andric 
6190b57cec5SDimitry Andric         // Continue recursion to the methods that this virtual method
6200b57cec5SDimitry Andric         // overrides.
6210b57cec5SDimitry Andric         Stack.push_back(OverriddenMethods);
6220b57cec5SDimitry Andric       }
6230b57cec5SDimitry Andric     }
6240b57cec5SDimitry Andric 
6250b57cec5SDimitry Andric     // C++ [class.virtual]p2:
6260b57cec5SDimitry Andric     //   For convenience we say that any virtual function overrides itself.
6270b57cec5SDimitry Andric     Overriders[CanonM].add(SubobjectNumber,
6280b57cec5SDimitry Andric                            UniqueVirtualMethod(CanonM, SubobjectNumber,
6290b57cec5SDimitry Andric                                                InVirtualSubobject));
6300b57cec5SDimitry Andric   }
6310b57cec5SDimitry Andric }
6320b57cec5SDimitry Andric 
~FinalOverriderCollector()6330b57cec5SDimitry Andric FinalOverriderCollector::~FinalOverriderCollector() {
6340b57cec5SDimitry Andric   for (llvm::DenseMap<const CXXRecordDecl *, CXXFinalOverriderMap *>::iterator
6350b57cec5SDimitry Andric          VO = VirtualOverriders.begin(), VOEnd = VirtualOverriders.end();
6360b57cec5SDimitry Andric        VO != VOEnd;
6370b57cec5SDimitry Andric        ++VO)
6380b57cec5SDimitry Andric     delete VO->second;
6390b57cec5SDimitry Andric }
6400b57cec5SDimitry Andric 
6410b57cec5SDimitry Andric void
getFinalOverriders(CXXFinalOverriderMap & FinalOverriders) const6420b57cec5SDimitry Andric CXXRecordDecl::getFinalOverriders(CXXFinalOverriderMap &FinalOverriders) const {
6430b57cec5SDimitry Andric   FinalOverriderCollector Collector;
6440b57cec5SDimitry Andric   Collector.Collect(this, false, nullptr, FinalOverriders);
6450b57cec5SDimitry Andric 
6460b57cec5SDimitry Andric   // Weed out any final overriders that come from virtual base class
6470b57cec5SDimitry Andric   // subobjects that were hidden by other subobjects along any path.
6480b57cec5SDimitry Andric   // This is the final-overrider variant of C++ [class.member.lookup]p10.
6490b57cec5SDimitry Andric   for (auto &OM : FinalOverriders) {
6500b57cec5SDimitry Andric     for (auto &SO : OM.second) {
6510b57cec5SDimitry Andric       SmallVectorImpl<UniqueVirtualMethod> &Overriding = SO.second;
6520b57cec5SDimitry Andric       if (Overriding.size() < 2)
6530b57cec5SDimitry Andric         continue;
6540b57cec5SDimitry Andric 
6550b57cec5SDimitry Andric       auto IsHidden = [&Overriding](const UniqueVirtualMethod &M) {
6560b57cec5SDimitry Andric         if (!M.InVirtualSubobject)
6570b57cec5SDimitry Andric           return false;
6580b57cec5SDimitry Andric 
6590b57cec5SDimitry Andric         // We have an overriding method in a virtual base class
6600b57cec5SDimitry Andric         // subobject (or non-virtual base class subobject thereof);
6610b57cec5SDimitry Andric         // determine whether there exists an other overriding method
6620b57cec5SDimitry Andric         // in a base class subobject that hides the virtual base class
6630b57cec5SDimitry Andric         // subobject.
6640b57cec5SDimitry Andric         for (const UniqueVirtualMethod &OP : Overriding)
6650b57cec5SDimitry Andric           if (&M != &OP &&
6660b57cec5SDimitry Andric               OP.Method->getParent()->isVirtuallyDerivedFrom(
6670b57cec5SDimitry Andric                   M.InVirtualSubobject))
6680b57cec5SDimitry Andric             return true;
6690b57cec5SDimitry Andric         return false;
6700b57cec5SDimitry Andric       };
6710b57cec5SDimitry Andric 
67213138422SDimitry Andric       // FIXME: IsHidden reads from Overriding from the middle of a remove_if
67313138422SDimitry Andric       // over the same sequence! Is this guaranteed to work?
674349cc55cSDimitry Andric       llvm::erase_if(Overriding, IsHidden);
6750b57cec5SDimitry Andric     }
6760b57cec5SDimitry Andric   }
6770b57cec5SDimitry Andric }
6780b57cec5SDimitry Andric 
6790b57cec5SDimitry Andric static void
AddIndirectPrimaryBases(const CXXRecordDecl * RD,ASTContext & Context,CXXIndirectPrimaryBaseSet & Bases)6800b57cec5SDimitry Andric AddIndirectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context,
6810b57cec5SDimitry Andric                         CXXIndirectPrimaryBaseSet& Bases) {
6820b57cec5SDimitry Andric   // If the record has a virtual primary base class, add it to our set.
6830b57cec5SDimitry Andric   const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
6840b57cec5SDimitry Andric   if (Layout.isPrimaryBaseVirtual())
6850b57cec5SDimitry Andric     Bases.insert(Layout.getPrimaryBase());
6860b57cec5SDimitry Andric 
6870b57cec5SDimitry Andric   for (const auto &I : RD->bases()) {
6880b57cec5SDimitry Andric     assert(!I.getType()->isDependentType() &&
6890b57cec5SDimitry Andric            "Cannot get indirect primary bases for class with dependent bases.");
6900b57cec5SDimitry Andric 
6910b57cec5SDimitry Andric     const CXXRecordDecl *BaseDecl =
6920b57cec5SDimitry Andric       cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
6930b57cec5SDimitry Andric 
6940b57cec5SDimitry Andric     // Only bases with virtual bases participate in computing the
6950b57cec5SDimitry Andric     // indirect primary virtual base classes.
6960b57cec5SDimitry Andric     if (BaseDecl->getNumVBases())
6970b57cec5SDimitry Andric       AddIndirectPrimaryBases(BaseDecl, Context, Bases);
6980b57cec5SDimitry Andric   }
6990b57cec5SDimitry Andric 
7000b57cec5SDimitry Andric }
7010b57cec5SDimitry Andric 
7020b57cec5SDimitry Andric void
getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet & Bases) const7030b57cec5SDimitry Andric CXXRecordDecl::getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet& Bases) const {
7040b57cec5SDimitry Andric   ASTContext &Context = getASTContext();
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric   if (!getNumVBases())
7070b57cec5SDimitry Andric     return;
7080b57cec5SDimitry Andric 
7090b57cec5SDimitry Andric   for (const auto &I : bases()) {
7100b57cec5SDimitry Andric     assert(!I.getType()->isDependentType() &&
7110b57cec5SDimitry Andric            "Cannot get indirect primary bases for class with dependent bases.");
7120b57cec5SDimitry Andric 
7130b57cec5SDimitry Andric     const CXXRecordDecl *BaseDecl =
7140b57cec5SDimitry Andric       cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
7150b57cec5SDimitry Andric 
7160b57cec5SDimitry Andric     // Only bases with virtual bases participate in computing the
7170b57cec5SDimitry Andric     // indirect primary virtual base classes.
7180b57cec5SDimitry Andric     if (BaseDecl->getNumVBases())
7190b57cec5SDimitry Andric       AddIndirectPrimaryBases(BaseDecl, Context, Bases);
7200b57cec5SDimitry Andric   }
7210b57cec5SDimitry Andric }
722