diff options
author | John McCall <rjmccall@apple.com> | 2009-12-08 07:42:38 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2009-12-08 07:42:38 +0000 |
commit | e8174bc483615e79614d9284a50ac94831e8b7c6 (patch) | |
tree | d15bdff46e5f0ce8eddbf099cbfc34b064aab280 /lib/AST/CXXInheritance.cpp | |
parent | ceb9bb3038c830f446bd761568e724fa9c0e0d69 (diff) |
Add CXXRecordDecl::forallBases to walk an inheritance hierarchy with non-lookup
semantics and CXXRecordDecl::isProvablyNotDerivedFrom to assist with
pre-instantiation diagnostics.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90842 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/CXXInheritance.cpp')
-rw-r--r-- | lib/AST/CXXInheritance.cpp | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp index 023bca4363..e5300f8284 100644 --- a/lib/AST/CXXInheritance.cpp +++ b/lib/AST/CXXInheritance.cpp @@ -90,6 +90,55 @@ bool CXXRecordDecl::isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) cons return lookupInBases(&FindBaseClass, Base->getCanonicalDecl(), Paths); } +static bool BaseIsNot(const CXXRecordDecl *Base, void *OpaqueTarget) { + // OpaqueTarget is a CXXRecordDecl*. + return Base->getCanonicalDecl() != (const CXXRecordDecl*) OpaqueTarget; +} + +bool CXXRecordDecl::isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const { + return forallBases(BaseIsNot, (void*) Base->getCanonicalDecl()); +} + +bool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches, + void *OpaqueData, + bool AllowShortCircuit) const { + ASTContext &Context = getASTContext(); + llvm::SmallVector<const CXXRecordDecl*, 8> Queue; + + const CXXRecordDecl *Record = this; + bool AllMatches = true; + while (true) { + for (CXXRecordDecl::base_class_const_iterator + I = Record->bases_begin(), E = Record->bases_end(); I != E; ++I) { + const RecordType *Ty = I->getType()->getAs<RecordType>(); + if (!Ty) { + if (AllowShortCircuit) return false; + AllMatches = false; + continue; + } + + RecordDecl *Base = Ty->getDecl()->getDefinition(Context); + if (!Base) { + if (AllowShortCircuit) return false; + AllMatches = false; + continue; + } + + if (!BaseMatches(cast<CXXRecordDecl>(Base), OpaqueData)) { + if (AllowShortCircuit) return false; + AllMatches = false; + continue; + } + } + + if (Queue.empty()) break; + Record = Queue.back(); // not actually a queue. + Queue.pop_back(); + } + + return AllMatches; +} + bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches, void *UserData, CXXBasePaths &Paths) const { |