CXXInheritance.cpp revision 4e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4
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 934e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregorbool CXXRecordDecl::isVirtuallyDerivedFrom(CXXRecordDecl *Base) const { 944e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false, 954e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor /*DetectVirtual=*/false); 964e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor 974e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor if (getCanonicalDecl() == Base->getCanonicalDecl()) 984e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor return false; 994e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor 1004e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor Paths.setOrigin(const_cast<CXXRecordDecl*>(this)); 1014e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor return lookupInBases(&FindVirtualBaseClass, Base->getCanonicalDecl(), Paths); 1024e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor} 1034e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor 104e8174bc483615e79614d9284a50ac94831e8b7c6John McCallstatic bool BaseIsNot(const CXXRecordDecl *Base, void *OpaqueTarget) { 105e8174bc483615e79614d9284a50ac94831e8b7c6John McCall // OpaqueTarget is a CXXRecordDecl*. 106e8174bc483615e79614d9284a50ac94831e8b7c6John McCall return Base->getCanonicalDecl() != (const CXXRecordDecl*) OpaqueTarget; 107e8174bc483615e79614d9284a50ac94831e8b7c6John McCall} 108e8174bc483615e79614d9284a50ac94831e8b7c6John McCall 109e8174bc483615e79614d9284a50ac94831e8b7c6John McCallbool CXXRecordDecl::isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const { 110e8174bc483615e79614d9284a50ac94831e8b7c6John McCall return forallBases(BaseIsNot, (void*) Base->getCanonicalDecl()); 111e8174bc483615e79614d9284a50ac94831e8b7c6John McCall} 112e8174bc483615e79614d9284a50ac94831e8b7c6John McCall 113e8174bc483615e79614d9284a50ac94831e8b7c6John McCallbool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches, 114e8174bc483615e79614d9284a50ac94831e8b7c6John McCall void *OpaqueData, 115e8174bc483615e79614d9284a50ac94831e8b7c6John McCall bool AllowShortCircuit) const { 116e8174bc483615e79614d9284a50ac94831e8b7c6John McCall llvm::SmallVector<const CXXRecordDecl*, 8> Queue; 117e8174bc483615e79614d9284a50ac94831e8b7c6John McCall 118e8174bc483615e79614d9284a50ac94831e8b7c6John McCall const CXXRecordDecl *Record = this; 119e8174bc483615e79614d9284a50ac94831e8b7c6John McCall bool AllMatches = true; 120e8174bc483615e79614d9284a50ac94831e8b7c6John McCall while (true) { 121e8174bc483615e79614d9284a50ac94831e8b7c6John McCall for (CXXRecordDecl::base_class_const_iterator 122e8174bc483615e79614d9284a50ac94831e8b7c6John McCall I = Record->bases_begin(), E = Record->bases_end(); I != E; ++I) { 123e8174bc483615e79614d9284a50ac94831e8b7c6John McCall const RecordType *Ty = I->getType()->getAs<RecordType>(); 124e8174bc483615e79614d9284a50ac94831e8b7c6John McCall if (!Ty) { 125e8174bc483615e79614d9284a50ac94831e8b7c6John McCall if (AllowShortCircuit) return false; 126e8174bc483615e79614d9284a50ac94831e8b7c6John McCall AllMatches = false; 127e8174bc483615e79614d9284a50ac94831e8b7c6John McCall continue; 128e8174bc483615e79614d9284a50ac94831e8b7c6John McCall } 129e8174bc483615e79614d9284a50ac94831e8b7c6John McCall 130ca910e84ea026a898c7184d3f3608403005b9bc0Anders Carlsson CXXRecordDecl *Base = 131952b017601f9c82b51119c3a1600f1312a833db9Douglas Gregor cast_or_null<CXXRecordDecl>(Ty->getDecl()->getDefinition()); 132e8174bc483615e79614d9284a50ac94831e8b7c6John McCall if (!Base) { 133e8174bc483615e79614d9284a50ac94831e8b7c6John McCall if (AllowShortCircuit) return false; 134e8174bc483615e79614d9284a50ac94831e8b7c6John McCall AllMatches = false; 135e8174bc483615e79614d9284a50ac94831e8b7c6John McCall continue; 136e8174bc483615e79614d9284a50ac94831e8b7c6John McCall } 137e8174bc483615e79614d9284a50ac94831e8b7c6John McCall 138ca910e84ea026a898c7184d3f3608403005b9bc0Anders Carlsson Queue.push_back(Base); 139ca910e84ea026a898c7184d3f3608403005b9bc0Anders Carlsson if (!BaseMatches(Base, OpaqueData)) { 140e8174bc483615e79614d9284a50ac94831e8b7c6John McCall if (AllowShortCircuit) return false; 141e8174bc483615e79614d9284a50ac94831e8b7c6John McCall AllMatches = false; 142e8174bc483615e79614d9284a50ac94831e8b7c6John McCall continue; 143e8174bc483615e79614d9284a50ac94831e8b7c6John McCall } 144e8174bc483615e79614d9284a50ac94831e8b7c6John McCall } 145e8174bc483615e79614d9284a50ac94831e8b7c6John McCall 146e8174bc483615e79614d9284a50ac94831e8b7c6John McCall if (Queue.empty()) break; 147e8174bc483615e79614d9284a50ac94831e8b7c6John McCall Record = Queue.back(); // not actually a queue. 148e8174bc483615e79614d9284a50ac94831e8b7c6John McCall Queue.pop_back(); 149e8174bc483615e79614d9284a50ac94831e8b7c6John McCall } 150e8174bc483615e79614d9284a50ac94831e8b7c6John McCall 151e8174bc483615e79614d9284a50ac94831e8b7c6John McCall return AllMatches; 152e8174bc483615e79614d9284a50ac94831e8b7c6John McCall} 153e8174bc483615e79614d9284a50ac94831e8b7c6John McCall 15489b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregorbool CXXBasePaths::lookupInBases(ASTContext &Context, 15589b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor const CXXRecordDecl *Record, 15689b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor CXXRecordDecl::BaseMatchesCallback *BaseMatches, 15789b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor void *UserData) { 158a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor bool FoundPath = false; 15946460a68f6508775e98c19b4bb8454bb471aac24John McCall 16092f883177b162928a8e632e4e3b93fafd2b26072John McCall // The access of the path down to this record. 16189b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor AccessSpecifier AccessToHere = ScratchPath.Access; 16289b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor bool IsFirstStep = ScratchPath.empty(); 16392f883177b162928a8e632e4e3b93fafd2b26072John McCall 16489b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor for (CXXRecordDecl::base_class_const_iterator BaseSpec = Record->bases_begin(), 16589b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor BaseSpecEnd = Record->bases_end(); 16689b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor BaseSpec != BaseSpecEnd; 16789b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor ++BaseSpec) { 168a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // Find the record of the base class subobjects for this type. 169a4923eb7c4b04d360cb2747641a5e92818edf804Douglas Gregor QualType BaseType = Context.getCanonicalType(BaseSpec->getType()) 170a4923eb7c4b04d360cb2747641a5e92818edf804Douglas Gregor .getUnqualifiedType(); 171a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 172a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // C++ [temp.dep]p3: 173a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // In the definition of a class template or a member of a class template, 174a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // if a base class of the class template depends on a template-parameter, 175a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // the base class scope is not examined during unqualified name lookup 176a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // either at the point of definition of the class template or member or 177a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // during an instantiation of the class tem- plate or member. 178a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor if (BaseType->isDependentType()) 179a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor continue; 180a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 181a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // Determine whether we need to visit this base class at all, 182a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // updating the count of subobjects appropriately. 18389b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType]; 184a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor bool VisitBase = true; 185a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor bool SetVirtual = false; 186a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor if (BaseSpec->isVirtual()) { 187a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor VisitBase = !Subobjects.first; 188a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Subobjects.first = true; 18989b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor if (isDetectingVirtual() && DetectedVirtual == 0) { 190a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // If this is the first virtual we find, remember it. If it turns out 191a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // there is no base path here, we'll reset it later. 19289b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor DetectedVirtual = BaseType->getAs<RecordType>(); 193a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor SetVirtual = true; 194a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } 195a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } else 196a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor ++Subobjects.second; 197a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 19889b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor if (isRecordingPaths()) { 199a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // Add this base specifier to the current path. 200a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor CXXBasePathElement Element; 201a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Element.Base = &*BaseSpec; 20289b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor Element.Class = Record; 203a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor if (BaseSpec->isVirtual()) 204a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Element.SubobjectNumber = 0; 205a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor else 206a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Element.SubobjectNumber = Subobjects.second; 20789b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor ScratchPath.push_back(Element); 20846460a68f6508775e98c19b4bb8454bb471aac24John McCall 20992f883177b162928a8e632e4e3b93fafd2b26072John McCall // Calculate the "top-down" access to this base class. 21092f883177b162928a8e632e4e3b93fafd2b26072John McCall // The spec actually describes this bottom-up, but top-down is 21192f883177b162928a8e632e4e3b93fafd2b26072John McCall // equivalent because the definition works out as follows: 21292f883177b162928a8e632e4e3b93fafd2b26072John McCall // 1. Write down the access along each step in the inheritance 21392f883177b162928a8e632e4e3b93fafd2b26072John McCall // chain, followed by the access of the decl itself. 21492f883177b162928a8e632e4e3b93fafd2b26072John McCall // For example, in 21592f883177b162928a8e632e4e3b93fafd2b26072John McCall // class A { public: int foo; }; 21692f883177b162928a8e632e4e3b93fafd2b26072John McCall // class B : protected A {}; 21792f883177b162928a8e632e4e3b93fafd2b26072John McCall // class C : public B {}; 21892f883177b162928a8e632e4e3b93fafd2b26072John McCall // class D : private C {}; 21992f883177b162928a8e632e4e3b93fafd2b26072John McCall // we would write: 22092f883177b162928a8e632e4e3b93fafd2b26072John McCall // private public protected public 22192f883177b162928a8e632e4e3b93fafd2b26072John McCall // 2. If 'private' appears anywhere except far-left, access is denied. 22292f883177b162928a8e632e4e3b93fafd2b26072John McCall // 3. Otherwise, overall access is determined by the most restrictive 22392f883177b162928a8e632e4e3b93fafd2b26072John McCall // access in the sequence. 22492f883177b162928a8e632e4e3b93fafd2b26072John McCall if (IsFirstStep) 22589b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor ScratchPath.Access = BaseSpec->getAccessSpecifier(); 22692f883177b162928a8e632e4e3b93fafd2b26072John McCall else 22789b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor ScratchPath.Access = CXXRecordDecl::MergeAccess(AccessToHere, 22889b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor BaseSpec->getAccessSpecifier()); 229a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } 230ed814cc4cd2bd4d32cbb4bfde3cc59ccae723a92John McCall 231ed814cc4cd2bd4d32cbb4bfde3cc59ccae723a92John McCall // Track whether there's a path involving this specific base. 232ed814cc4cd2bd4d32cbb4bfde3cc59ccae723a92John McCall bool FoundPathThroughBase = false; 233ed814cc4cd2bd4d32cbb4bfde3cc59ccae723a92John McCall 23489b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor if (BaseMatches(BaseSpec, ScratchPath, UserData)) { 23592f883177b162928a8e632e4e3b93fafd2b26072John McCall // We've found a path that terminates at this base. 236ed814cc4cd2bd4d32cbb4bfde3cc59ccae723a92John McCall FoundPath = FoundPathThroughBase = true; 23789b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor if (isRecordingPaths()) { 238a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // We have a path. Make a copy of it before moving on. 23989b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor Paths.push_back(ScratchPath); 24089b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor } else if (!isFindingAmbiguities()) { 241a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // We found a path and we don't care about ambiguities; 242a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // return immediately. 243a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return FoundPath; 244a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } 245a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } else if (VisitBase) { 246a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor CXXRecordDecl *BaseRecord 247a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor = cast<CXXRecordDecl>(BaseSpec->getType()->getAs<RecordType>() 248a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor ->getDecl()); 24989b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor if (lookupInBases(Context, BaseRecord, BaseMatches, UserData)) { 250a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // C++ [class.member.lookup]p2: 251a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // A member name f in one sub-object B hides a member name f in 252a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // a sub-object A if A is a base class sub-object of B. Any 253a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // declarations that are so hidden are eliminated from 254a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // consideration. 255a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 256a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // There is a path to a base class that meets the criteria. If we're 257a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // not collecting paths or finding ambiguities, we're done. 258ed814cc4cd2bd4d32cbb4bfde3cc59ccae723a92John McCall FoundPath = FoundPathThroughBase = true; 25989b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor if (!isFindingAmbiguities()) 260a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return FoundPath; 261a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } 262a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } 263a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 264a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // Pop this base specifier off the current path (if we're 265a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // collecting paths). 26689b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor if (isRecordingPaths()) { 26789b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor ScratchPath.pop_back(); 26846460a68f6508775e98c19b4bb8454bb471aac24John McCall } 26946460a68f6508775e98c19b4bb8454bb471aac24John McCall 270a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // If we set a virtual earlier, and this isn't a path, forget it again. 271ed814cc4cd2bd4d32cbb4bfde3cc59ccae723a92John McCall if (SetVirtual && !FoundPathThroughBase) { 27289b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor DetectedVirtual = 0; 273a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } 274a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } 27592f883177b162928a8e632e4e3b93fafd2b26072John McCall 27692f883177b162928a8e632e4e3b93fafd2b26072John McCall // Reset the scratch path access. 27789b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor ScratchPath.Access = AccessToHere; 278a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 279a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return FoundPath; 280a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor} 281a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 28289b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregorbool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches, 28389b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor void *UserData, 28489b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor CXXBasePaths &Paths) const { 2854e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor // If we didn't find anything, report that. 2864e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor if (!Paths.lookupInBases(getASTContext(), this, BaseMatches, UserData)) 2874e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor return false; 2884e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor 2894e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor // If we're not recording paths or we won't ever find ambiguities, 2904e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor // we're done. 2914e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor if (!Paths.isRecordingPaths() || !Paths.isFindingAmbiguities()) 2924e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor return true; 2934e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor 2944e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor // C++ [class.member.lookup]p6: 2954e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor // When virtual base classes are used, a hidden declaration can be 2964e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor // reached along a path through the sub-object lattice that does 2974e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor // not pass through the hiding declaration. This is not an 2984e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor // ambiguity. The identical use with nonvirtual base classes is an 2994e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor // ambiguity; in that case there is no unique instance of the name 3004e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor // that hides all the others. 3014e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor // 3024e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor // FIXME: This is an O(N^2) algorithm, but DPG doesn't see an easy 3034e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor // way to make it any faster. 3044e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor for (CXXBasePaths::paths_iterator P = Paths.begin(), PEnd = Paths.end(); 3054e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor P != PEnd; /* increment in loop */) { 3064e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor bool Hidden = false; 3074e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor 3084e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor for (CXXBasePath::iterator PE = P->begin(), PEEnd = P->end(); 3094e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor PE != PEEnd && !Hidden; ++PE) { 3104e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor if (PE->Base->isVirtual()) { 3114e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor CXXRecordDecl *VBase = 0; 3124e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor if (const RecordType *Record = PE->Base->getType()->getAs<RecordType>()) 3134e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor VBase = cast<CXXRecordDecl>(Record->getDecl()); 3144e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor if (!VBase) 3154e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor break; 3164e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor 3174e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor // The declaration(s) we found along this path were found in a 3184e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor // subobject of a virtual base. Check whether this virtual 3194e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor // base is a subobject of any other path; if so, then the 3204e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor // declaration in this path are hidden by that patch. 3214e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor for (CXXBasePaths::paths_iterator HidingP = Paths.begin(), 3224e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor HidingPEnd = Paths.end(); 3234e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor HidingP != HidingPEnd; 3244e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor ++HidingP) { 3254e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor CXXRecordDecl *HidingClass = 0; 3264e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor if (const RecordType *Record 3274e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor = HidingP->back().Base->getType()->getAs<RecordType>()) 3284e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor HidingClass = cast<CXXRecordDecl>(Record->getDecl()); 3294e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor if (!HidingClass) 3304e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor break; 3314e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor 3324e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor if (HidingClass->isVirtuallyDerivedFrom(VBase)) { 3334e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor Hidden = true; 3344e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor break; 3354e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor } 3364e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor } 3374e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor } 3384e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor } 3394e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor 3404e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor if (Hidden) 3414e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor P = Paths.Paths.erase(P); 3424e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor else 3434e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor ++P; 3444e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor } 3454e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor 3464e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor return true; 34789b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor} 34889b7702c9a64e12093ed34fc02dc3cfbb6eb133aDouglas Gregor 349af8e6ed61b5e80ab95632b63f583af79dcb62590John McCallbool CXXRecordDecl::FindBaseClass(const CXXBaseSpecifier *Specifier, 350a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor CXXBasePath &Path, 351a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor void *BaseRecord) { 352a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor assert(((Decl *)BaseRecord)->getCanonicalDecl() == BaseRecord && 353a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor "User data for FindBaseClass is not canonical!"); 354a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return Specifier->getType()->getAs<RecordType>()->getDecl() 355a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor ->getCanonicalDecl() == BaseRecord; 356a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor} 357a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 3584e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregorbool CXXRecordDecl::FindVirtualBaseClass(const CXXBaseSpecifier *Specifier, 3594e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor CXXBasePath &Path, 3604e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor void *BaseRecord) { 3614e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor assert(((Decl *)BaseRecord)->getCanonicalDecl() == BaseRecord && 3624e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor "User data for FindBaseClass is not canonical!"); 3634e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor return Specifier->isVirtual() && 3644e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor Specifier->getType()->getAs<RecordType>()->getDecl() 3654e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor ->getCanonicalDecl() == BaseRecord; 3664e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor} 3674e6ba4be8ddeca2978da6b9bae02cbe9594f2ef4Douglas Gregor 368af8e6ed61b5e80ab95632b63f583af79dcb62590John McCallbool CXXRecordDecl::FindTagMember(const CXXBaseSpecifier *Specifier, 369a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor CXXBasePath &Path, 370a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor void *Name) { 371a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl(); 372a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 373a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor DeclarationName N = DeclarationName::getFromOpaquePtr(Name); 374a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor for (Path.Decls = BaseRecord->lookup(N); 375a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Path.Decls.first != Path.Decls.second; 376a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor ++Path.Decls.first) { 377a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor if ((*Path.Decls.first)->isInIdentifierNamespace(IDNS_Tag)) 378a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return true; 379a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } 380a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 381a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return false; 382a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor} 383a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 384af8e6ed61b5e80ab95632b63f583af79dcb62590John McCallbool CXXRecordDecl::FindOrdinaryMember(const CXXBaseSpecifier *Specifier, 385a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor CXXBasePath &Path, 386a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor void *Name) { 387a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl(); 388a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 389a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor const unsigned IDNS = IDNS_Ordinary | IDNS_Tag | IDNS_Member; 390a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor DeclarationName N = DeclarationName::getFromOpaquePtr(Name); 391a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor for (Path.Decls = BaseRecord->lookup(N); 392a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Path.Decls.first != Path.Decls.second; 393a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor ++Path.Decls.first) { 394a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor if ((*Path.Decls.first)->isInIdentifierNamespace(IDNS)) 395a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return true; 396a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } 397a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 398a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return false; 399a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor} 400a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 401af8e6ed61b5e80ab95632b63f583af79dcb62590John McCallbool CXXRecordDecl:: 402af8e6ed61b5e80ab95632b63f583af79dcb62590John McCallFindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier, 403af8e6ed61b5e80ab95632b63f583af79dcb62590John McCall CXXBasePath &Path, 404af8e6ed61b5e80ab95632b63f583af79dcb62590John McCall void *Name) { 405a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl(); 406a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 407a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor DeclarationName N = DeclarationName::getFromOpaquePtr(Name); 408a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor for (Path.Decls = BaseRecord->lookup(N); 409a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor Path.Decls.first != Path.Decls.second; 410a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor ++Path.Decls.first) { 411a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor // FIXME: Refactor the "is it a nested-name-specifier?" check 412a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor if (isa<TypedefDecl>(*Path.Decls.first) || 413a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor (*Path.Decls.first)->isInIdentifierNamespace(IDNS_Tag)) 414a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return true; 415a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor } 416a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor 417a8f32e0965ee19ecc53cd796e34268377a20357cDouglas Gregor return false; 41882109bd64a8494c801263c11f4d2294f47e21807Mike Stump} 419