bool CXXRecordDecl::lookupInBases(BaseMatchesCallback BaseMatches, CXXBasePaths &Paths, bool LookupInDependent) const { // If we didn't find anything, report that. if (!Paths.lookupInBases(getASTContext(), this, BaseMatches, LookupInDependent)) return false; // If we're not recording paths or we won't ever find ambiguities, // we're done. if (!Paths.isRecordingPaths() || !Paths.isFindingAmbiguities()) return true; // C++ [class.member.lookup]p6: // When virtual base classes are used, a hidden declaration can be // reached along a path through the sub-object lattice that does // not pass through the hiding declaration. This is not an // ambiguity. The identical use with nonvirtual base classes is an // ambiguity; in that case there is no unique instance of the name // that hides all the others. // // FIXME: This is an O(N^2) algorithm, but DPG doesn't see an easy // way to make it any faster. Paths.Paths.remove_if([&Paths](const CXXBasePath &Path) { for (const CXXBasePathElement &PE : Path) { if (!PE.Base->isVirtual()) continue; CXXRecordDecl *VBase = nullptr; if (const RecordType *Record = PE.Base->getType()->getAs<RecordType>()) VBase = cast<CXXRecordDecl>(Record->getDecl()); if (!VBase) break; // The declaration(s) we found along this path were found in a // subobject of a virtual base. Check whether this virtual // base is a subobject of any other path; if so, then the // declaration in this path are hidden by that patch. for (const CXXBasePath &HidingP : Paths) { CXXRecordDecl *HidingClass = nullptr; if (const RecordType *Record = HidingP.back().Base->getType()->getAs<RecordType>()) HidingClass = cast<CXXRecordDecl>(Record->getDecl()); if (!HidingClass) break; if (HidingClass->isVirtuallyDerivedFrom(VBase)) return true; } } return false; }); return true; }
bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches, void *UserData, CXXBasePaths &Paths) const { // If we didn't find anything, report that. if (!Paths.lookupInBases(getASTContext(), this, BaseMatches, UserData)) return false; // If we're not recording paths or we won't ever find ambiguities, // we're done. if (!Paths.isRecordingPaths() || !Paths.isFindingAmbiguities()) return true; // C++ [class.member.lookup]p6: // When virtual base classes are used, a hidden declaration can be // reached along a path through the sub-object lattice that does // not pass through the hiding declaration. This is not an // ambiguity. The identical use with nonvirtual base classes is an // ambiguity; in that case there is no unique instance of the name // that hides all the others. // // FIXME: This is an O(N^2) algorithm, but DPG doesn't see an easy // way to make it any faster. for (CXXBasePaths::paths_iterator P = Paths.begin(), PEnd = Paths.end(); P != PEnd; /* increment in loop */) { bool Hidden = false; for (CXXBasePath::iterator PE = P->begin(), PEEnd = P->end(); PE != PEEnd && !Hidden; ++PE) { if (PE->Base->isVirtual()) { CXXRecordDecl *VBase = 0; if (const RecordType *Record = PE->Base->getType()->getAs<RecordType>()) VBase = cast<CXXRecordDecl>(Record->getDecl()); if (!VBase) break; // The declaration(s) we found along this path were found in a // subobject of a virtual base. Check whether this virtual // base is a subobject of any other path; if so, then the // declaration in this path are hidden by that patch. for (CXXBasePaths::paths_iterator HidingP = Paths.begin(), HidingPEnd = Paths.end(); HidingP != HidingPEnd; ++HidingP) { CXXRecordDecl *HidingClass = 0; if (const RecordType *Record = HidingP->back().Base->getType()->getAs<RecordType>()) HidingClass = cast<CXXRecordDecl>(Record->getDecl()); if (!HidingClass) break; if (HidingClass->isVirtuallyDerivedFrom(VBase)) { Hidden = true; break; } } } } if (Hidden) P = Paths.Paths.erase(P); else ++P; } return true; }