CXXInheritance.cpp revision 92f883177b162928a8e632e4e3b93fafd2b26072
1a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor//===------ CXXInheritance.cpp - C++ Inheritance ----------------*- C++ -*-===// 2a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor// 3a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor// The LLVM Compiler Infrastructure 4a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor// 5a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor// This file is distributed under the University of Illinois Open Source 6a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor// License. See LICENSE.TXT for details. 7a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor// 8a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor//===----------------------------------------------------------------------===// 9a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor// 10a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor// This file provides routines that help analyzing C++ inheritance hierarchies. 11a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor// 12a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor//===----------------------------------------------------------------------===// 13a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor#include "clang/AST/CXXInheritance.h" 14a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor#include "clang/AST/DeclCXX.h" 15a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor#include <algorithm> 16a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor#include <set> 17a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 18a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregorusing namespace clang; 19a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 20a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor/// \brief Computes the set of declarations referenced by these base 21a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor/// paths. 22a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregorvoid CXXBasePaths::ComputeDeclsFound() { 23a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor assert(NumDeclsFound == 0 && !DeclsFound && 24a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor "Already computed the set of declarations"); 25a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 26a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor std::set<NamedDecl *> Decls; 27a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor for (CXXBasePaths::paths_iterator Path = begin(), PathEnd = end(); 28a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Path != PathEnd; ++Path) 29a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Decls.insert(*Path->Decls.first); 30a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 31a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor NumDeclsFound = Decls.size(); 32a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor DeclsFound = new NamedDecl * [NumDeclsFound]; 33a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor std::copy(Decls.begin(), Decls.end(), DeclsFound); 34a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor} 35a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 36a8f32e0965ee19ecc53cd796e34268377a20357cDouglas GregorCXXBasePaths::decl_iterator CXXBasePaths::found_decls_begin() { 37a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor if (NumDeclsFound == 0) 38a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor ComputeDeclsFound(); 39a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return DeclsFound; 40a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor} 41a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 42a8f32e0965ee19ecc53cd796e34268377a20357cDouglas GregorCXXBasePaths::decl_iterator CXXBasePaths::found_decls_end() { 43a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor if (NumDeclsFound == 0) 44a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor ComputeDeclsFound(); 45a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return DeclsFound + NumDeclsFound; 46a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor} 47a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 48a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor/// isAmbiguous - Determines whether the set of paths provided is 49a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor/// ambiguous, i.e., there are two or more paths that refer to 50a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor/// different base class subobjects of the same type. BaseType must be 51a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor/// an unqualified, canonical class type. 52a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregorbool CXXBasePaths::isAmbiguous(QualType BaseType) { 53467b27b9a24bdc823218ad1ad0e37673b6cc1e83John McCall assert(BaseType.isCanonical() && "Base type must be the canonical type"); 54a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor assert(BaseType.hasQualifiers() == 0 && "Base type must be unqualified"); 55a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType]; 56a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return Subobjects.second + (Subobjects.first? 1 : 0) > 1; 57a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor} 58a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 59a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor/// clear - Clear out all prior path information. 60a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregorvoid CXXBasePaths::clear() { 61a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Paths.clear(); 62a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor ClassSubobjects.clear(); 63a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor ScratchPath.clear(); 64a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor DetectedVirtual = 0; 65a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor} 66a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 67a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor/// @brief Swaps the contents of this CXXBasePaths structure with the 68a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor/// contents of Other. 69a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregorvoid CXXBasePaths::swap(CXXBasePaths &Other) { 70a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor std::swap(Origin, Other.Origin); 71a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Paths.swap(Other.Paths); 72a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor ClassSubobjects.swap(Other.ClassSubobjects); 73a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor std::swap(FindAmbiguities, Other.FindAmbiguities); 74a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor std::swap(RecordPaths, Other.RecordPaths); 75a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor std::swap(DetectVirtual, Other.DetectVirtual); 76a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor std::swap(DetectedVirtual, Other.DetectedVirtual); 77a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor} 78a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 79af8e6ed61b5e80ab95632b63f583af79dcb62590John McCallbool CXXRecordDecl::isDerivedFrom(CXXRecordDecl *Base) const { 80a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false, 81a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor /*DetectVirtual=*/false); 82a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return isDerivedFrom(Base, Paths); 83a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor} 84a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 85af8e6ed61b5e80ab95632b63f583af79dcb62590John McCallbool CXXRecordDecl::isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) const { 86a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor if (getCanonicalDecl() == Base->getCanonicalDecl()) 87a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return false; 88a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 89af8e6ed61b5e80ab95632b63f583af79dcb62590John McCall Paths.setOrigin(const_cast<CXXRecordDecl*>(this)); 90a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return lookupInBases(&FindBaseClass, Base->getCanonicalDecl(), Paths); 91a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor} 92a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 93e8174bc483615e79614d9284a50ac94831e8b7c6John McCallstatic bool BaseIsNot(const CXXRecordDecl *Base, void *OpaqueTarget) { 94e8174bc483615e79614d9284a50ac94831e8b7c6John McCall // OpaqueTarget is a CXXRecordDecl*. 95e8174bc483615e79614d9284a50ac94831e8b7c6John McCall return Base->getCanonicalDecl() != (const CXXRecordDecl*) OpaqueTarget; 96e8174bc483615e79614d9284a50ac94831e8b7c6John McCall} 97e8174bc483615e79614d9284a50ac94831e8b7c6John McCall 98e8174bc483615e79614d9284a50ac94831e8b7c6John McCallbool CXXRecordDecl::isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const { 99e8174bc483615e79614d9284a50ac94831e8b7c6John McCall return forallBases(BaseIsNot, (void*) Base->getCanonicalDecl()); 100e8174bc483615e79614d9284a50ac94831e8b7c6John McCall} 101e8174bc483615e79614d9284a50ac94831e8b7c6John McCall 102e8174bc483615e79614d9284a50ac94831e8b7c6John McCallbool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches, 103e8174bc483615e79614d9284a50ac94831e8b7c6John McCall void *OpaqueData, 104e8174bc483615e79614d9284a50ac94831e8b7c6John McCall bool AllowShortCircuit) const { 105e8174bc483615e79614d9284a50ac94831e8b7c6John McCall ASTContext &Context = getASTContext(); 106e8174bc483615e79614d9284a50ac94831e8b7c6John McCall llvm::SmallVector<const CXXRecordDecl*, 8> Queue; 107e8174bc483615e79614d9284a50ac94831e8b7c6John McCall 108e8174bc483615e79614d9284a50ac94831e8b7c6John McCall const CXXRecordDecl *Record = this; 109e8174bc483615e79614d9284a50ac94831e8b7c6John McCall bool AllMatches = true; 110e8174bc483615e79614d9284a50ac94831e8b7c6John McCall while (true) { 111e8174bc483615e79614d9284a50ac94831e8b7c6John McCall for (CXXRecordDecl::base_class_const_iterator 112e8174bc483615e79614d9284a50ac94831e8b7c6John McCall I = Record->bases_begin(), E = Record->bases_end(); I != E; ++I) { 113e8174bc483615e79614d9284a50ac94831e8b7c6John McCall const RecordType *Ty = I->getType()->getAs<RecordType>(); 114e8174bc483615e79614d9284a50ac94831e8b7c6John McCall if (!Ty) { 115e8174bc483615e79614d9284a50ac94831e8b7c6John McCall if (AllowShortCircuit) return false; 116e8174bc483615e79614d9284a50ac94831e8b7c6John McCall AllMatches = false; 117e8174bc483615e79614d9284a50ac94831e8b7c6John McCall continue; 118e8174bc483615e79614d9284a50ac94831e8b7c6John McCall } 119e8174bc483615e79614d9284a50ac94831e8b7c6John McCall 120ca910e84ea026a898c7184d3f3608403005b9bc0Anders Carlsson CXXRecordDecl *Base = 121ca910e84ea026a898c7184d3f3608403005b9bc0Anders Carlsson cast_or_null<CXXRecordDecl>(Ty->getDecl()->getDefinition(Context)); 122e8174bc483615e79614d9284a50ac94831e8b7c6John McCall if (!Base) { 123e8174bc483615e79614d9284a50ac94831e8b7c6John McCall if (AllowShortCircuit) return false; 124e8174bc483615e79614d9284a50ac94831e8b7c6John McCall AllMatches = false; 125e8174bc483615e79614d9284a50ac94831e8b7c6John McCall continue; 126e8174bc483615e79614d9284a50ac94831e8b7c6John McCall } 127e8174bc483615e79614d9284a50ac94831e8b7c6John McCall 128ca910e84ea026a898c7184d3f3608403005b9bc0Anders Carlsson Queue.push_back(Base); 129ca910e84ea026a898c7184d3f3608403005b9bc0Anders Carlsson if (!BaseMatches(Base, OpaqueData)) { 130e8174bc483615e79614d9284a50ac94831e8b7c6John McCall if (AllowShortCircuit) return false; 131e8174bc483615e79614d9284a50ac94831e8b7c6John McCall AllMatches = false; 132e8174bc483615e79614d9284a50ac94831e8b7c6John McCall continue; 133e8174bc483615e79614d9284a50ac94831e8b7c6John McCall } 134e8174bc483615e79614d9284a50ac94831e8b7c6John McCall } 135e8174bc483615e79614d9284a50ac94831e8b7c6John McCall 136e8174bc483615e79614d9284a50ac94831e8b7c6John McCall if (Queue.empty()) break; 137e8174bc483615e79614d9284a50ac94831e8b7c6John McCall Record = Queue.back(); // not actually a queue. 138e8174bc483615e79614d9284a50ac94831e8b7c6John McCall Queue.pop_back(); 139e8174bc483615e79614d9284a50ac94831e8b7c6John McCall } 140e8174bc483615e79614d9284a50ac94831e8b7c6John McCall 141e8174bc483615e79614d9284a50ac94831e8b7c6John McCall return AllMatches; 142e8174bc483615e79614d9284a50ac94831e8b7c6John McCall} 143e8174bc483615e79614d9284a50ac94831e8b7c6John McCall 144a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregorbool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches, 145a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor void *UserData, 146af8e6ed61b5e80ab95632b63f583af79dcb62590John McCall CXXBasePaths &Paths) const { 147a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor bool FoundPath = false; 14846460a68f6508775e98c19b4bb8454bb471aac24John McCall 14992f883177b162928a8e632e4e3b93fafd2b26072John McCall // The access of the path down to this record. 15092f883177b162928a8e632e4e3b93fafd2b26072John McCall AccessSpecifier AccessToHere = Paths.ScratchPath.Access; 15192f883177b162928a8e632e4e3b93fafd2b26072John McCall bool IsFirstStep = Paths.ScratchPath.empty(); 15292f883177b162928a8e632e4e3b93fafd2b26072John McCall 153a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor ASTContext &Context = getASTContext(); 154af8e6ed61b5e80ab95632b63f583af79dcb62590John McCall for (base_class_const_iterator BaseSpec = bases_begin(), 155af8e6ed61b5e80ab95632b63f583af79dcb62590John McCall BaseSpecEnd = bases_end(); BaseSpec != BaseSpecEnd; ++BaseSpec) { 156a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // Find the record of the base class subobjects for this type. 157a4923eb7c4b04d360cb2747641a5e92818edf804Douglas Gregor QualType BaseType = Context.getCanonicalType(BaseSpec->getType()) 158a4923eb7c4b04d360cb2747641a5e92818edf804Douglas Gregor .getUnqualifiedType(); 159a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 160a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // C++ [temp.dep]p3: 161a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // In the definition of a class template or a member of a class template, 162a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // if a base class of the class template depends on a template-parameter, 163a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // the base class scope is not examined during unqualified name lookup 164a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // either at the point of definition of the class template or member or 165a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // during an instantiation of the class tem- plate or member. 166a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor if (BaseType->isDependentType()) 167a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor continue; 168a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 169a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // Determine whether we need to visit this base class at all, 170a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // updating the count of subobjects appropriately. 171a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor std::pair<bool, unsigned>& Subobjects = Paths.ClassSubobjects[BaseType]; 172a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor bool VisitBase = true; 173a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor bool SetVirtual = false; 174a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor if (BaseSpec->isVirtual()) { 175a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor VisitBase = !Subobjects.first; 176a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Subobjects.first = true; 177a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor if (Paths.isDetectingVirtual() && Paths.DetectedVirtual == 0) { 178a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // If this is the first virtual we find, remember it. If it turns out 179a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // there is no base path here, we'll reset it later. 180a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Paths.DetectedVirtual = BaseType->getAs<RecordType>(); 181a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor SetVirtual = true; 182a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } 183a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } else 184a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor ++Subobjects.second; 185a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 186a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor if (Paths.isRecordingPaths()) { 187a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // Add this base specifier to the current path. 188a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor CXXBasePathElement Element; 189a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Element.Base = &*BaseSpec; 190a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Element.Class = this; 191a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor if (BaseSpec->isVirtual()) 192a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Element.SubobjectNumber = 0; 193a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor else 194a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Element.SubobjectNumber = Subobjects.second; 195a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Paths.ScratchPath.push_back(Element); 19646460a68f6508775e98c19b4bb8454bb471aac24John McCall 19792f883177b162928a8e632e4e3b93fafd2b26072John McCall // Calculate the "top-down" access to this base class. 19892f883177b162928a8e632e4e3b93fafd2b26072John McCall // The spec actually describes this bottom-up, but top-down is 19992f883177b162928a8e632e4e3b93fafd2b26072John McCall // equivalent because the definition works out as follows: 20092f883177b162928a8e632e4e3b93fafd2b26072John McCall // 1. Write down the access along each step in the inheritance 20192f883177b162928a8e632e4e3b93fafd2b26072John McCall // chain, followed by the access of the decl itself. 20292f883177b162928a8e632e4e3b93fafd2b26072John McCall // For example, in 20392f883177b162928a8e632e4e3b93fafd2b26072John McCall // class A { public: int foo; }; 20492f883177b162928a8e632e4e3b93fafd2b26072John McCall // class B : protected A {}; 20592f883177b162928a8e632e4e3b93fafd2b26072John McCall // class C : public B {}; 20692f883177b162928a8e632e4e3b93fafd2b26072John McCall // class D : private C {}; 20792f883177b162928a8e632e4e3b93fafd2b26072John McCall // we would write: 20892f883177b162928a8e632e4e3b93fafd2b26072John McCall // private public protected public 20992f883177b162928a8e632e4e3b93fafd2b26072John McCall // 2. If 'private' appears anywhere except far-left, access is denied. 21092f883177b162928a8e632e4e3b93fafd2b26072John McCall // 3. Otherwise, overall access is determined by the most restrictive 21192f883177b162928a8e632e4e3b93fafd2b26072John McCall // access in the sequence. 21292f883177b162928a8e632e4e3b93fafd2b26072John McCall if (IsFirstStep) 21392f883177b162928a8e632e4e3b93fafd2b26072John McCall Paths.ScratchPath.Access = BaseSpec->getAccessSpecifier(); 21492f883177b162928a8e632e4e3b93fafd2b26072John McCall else 21592f883177b162928a8e632e4e3b93fafd2b26072John McCall Paths.ScratchPath.Access 21692f883177b162928a8e632e4e3b93fafd2b26072John McCall = MergeAccess(AccessToHere, BaseSpec->getAccessSpecifier()); 217a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } 218a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 219a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor if (BaseMatches(BaseSpec, Paths.ScratchPath, UserData)) { 22092f883177b162928a8e632e4e3b93fafd2b26072John McCall // We've found a path that terminates at this base. 221a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor FoundPath = true; 222a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor if (Paths.isRecordingPaths()) { 223a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // We have a path. Make a copy of it before moving on. 224a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Paths.Paths.push_back(Paths.ScratchPath); 225a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } else if (!Paths.isFindingAmbiguities()) { 226a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // We found a path and we don't care about ambiguities; 227a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // return immediately. 228a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return FoundPath; 229a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } 230a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } else if (VisitBase) { 231a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor CXXRecordDecl *BaseRecord 232a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor = cast<CXXRecordDecl>(BaseSpec->getType()->getAs<RecordType>() 233a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor ->getDecl()); 234a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor if (BaseRecord->lookupInBases(BaseMatches, UserData, Paths)) { 235a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // C++ [class.member.lookup]p2: 236a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // A member name f in one sub-object B hides a member name f in 237a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // a sub-object A if A is a base class sub-object of B. Any 238a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // declarations that are so hidden are eliminated from 239a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // consideration. 240a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 241a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // There is a path to a base class that meets the criteria. If we're 242a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // not collecting paths or finding ambiguities, we're done. 243a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor FoundPath = true; 244a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor if (!Paths.isFindingAmbiguities()) 245a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return FoundPath; 246a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } 247a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } 248a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 249a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // Pop this base specifier off the current path (if we're 250a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // collecting paths). 25146460a68f6508775e98c19b4bb8454bb471aac24John McCall if (Paths.isRecordingPaths()) { 252a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Paths.ScratchPath.pop_back(); 25346460a68f6508775e98c19b4bb8454bb471aac24John McCall } 25446460a68f6508775e98c19b4bb8454bb471aac24John McCall 255a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // If we set a virtual earlier, and this isn't a path, forget it again. 256a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor if (SetVirtual && !FoundPath) { 257a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Paths.DetectedVirtual = 0; 258a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } 259a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } 26092f883177b162928a8e632e4e3b93fafd2b26072John McCall 26192f883177b162928a8e632e4e3b93fafd2b26072John McCall // Reset the scratch path access. 26292f883177b162928a8e632e4e3b93fafd2b26072John McCall Paths.ScratchPath.Access = AccessToHere; 263a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 264a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return FoundPath; 265a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor} 266a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 267af8e6ed61b5e80ab95632b63f583af79dcb62590John McCallbool CXXRecordDecl::FindBaseClass(const CXXBaseSpecifier *Specifier, 268a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor CXXBasePath &Path, 269a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor void *BaseRecord) { 270a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor assert(((Decl *)BaseRecord)->getCanonicalDecl() == BaseRecord && 271a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor "User data for FindBaseClass is not canonical!"); 272a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return Specifier->getType()->getAs<RecordType>()->getDecl() 273a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor ->getCanonicalDecl() == BaseRecord; 274a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor} 275a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 276af8e6ed61b5e80ab95632b63f583af79dcb62590John McCallbool CXXRecordDecl::FindTagMember(const CXXBaseSpecifier *Specifier, 277a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor CXXBasePath &Path, 278a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor void *Name) { 279a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl(); 280a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 281a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor DeclarationName N = DeclarationName::getFromOpaquePtr(Name); 282a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor for (Path.Decls = BaseRecord->lookup(N); 283a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Path.Decls.first != Path.Decls.second; 284a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor ++Path.Decls.first) { 285a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor if ((*Path.Decls.first)->isInIdentifierNamespace(IDNS_Tag)) 286a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return true; 287a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } 288a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 289a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return false; 290a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor} 291a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 292af8e6ed61b5e80ab95632b63f583af79dcb62590John McCallbool CXXRecordDecl::FindOrdinaryMember(const CXXBaseSpecifier *Specifier, 293a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor CXXBasePath &Path, 294a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor void *Name) { 295a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl(); 296a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 297a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor const unsigned IDNS = IDNS_Ordinary | IDNS_Tag | IDNS_Member; 298a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor DeclarationName N = DeclarationName::getFromOpaquePtr(Name); 299a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor for (Path.Decls = BaseRecord->lookup(N); 300a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Path.Decls.first != Path.Decls.second; 301a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor ++Path.Decls.first) { 302a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor if ((*Path.Decls.first)->isInIdentifierNamespace(IDNS)) 303a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return true; 304a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } 305a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 306a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return false; 307a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor} 308a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 309af8e6ed61b5e80ab95632b63f583af79dcb62590John McCallbool CXXRecordDecl:: 310af8e6ed61b5e80ab95632b63f583af79dcb62590John McCallFindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier, 311af8e6ed61b5e80ab95632b63f583af79dcb62590John McCall CXXBasePath &Path, 312af8e6ed61b5e80ab95632b63f583af79dcb62590John McCall void *Name) { 313a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl(); 314a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 315a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor DeclarationName N = DeclarationName::getFromOpaquePtr(Name); 316a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor for (Path.Decls = BaseRecord->lookup(N); 317a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Path.Decls.first != Path.Decls.second; 318a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor ++Path.Decls.first) { 319a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // FIXME: Refactor the "is it a nested-name-specifier?" check 320a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor if (isa<TypedefDecl>(*Path.Decls.first) || 321a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor (*Path.Decls.first)->isInIdentifierNamespace(IDNS_Tag)) 322a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return true; 323a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } 324a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 325a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return false; 32682109bd64a8494c801263c11f4d2294f47e21807Mike Stump} 327