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 | ddabf1a94614f895d0de595e6145bda07d30a2ef (patch) | |
tree | 6cc8193eb34d35a2144d0c9cfbe0606464461c35 /clang/lib/AST/CXXInheritance.cpp | |
parent | 80888c7b38bdfc0925893ba74c06c10606a1a535 (diff) | |
download | bcm5719-llvm-ddabf1a94614f895d0de595e6145bda07d30a2ef.tar.gz bcm5719-llvm-ddabf1a94614f895d0de595e6145bda07d30a2ef.zip |
Add CXXRecordDecl::forallBases to walk an inheritance hierarchy with non-lookup
semantics and CXXRecordDecl::isProvablyNotDerivedFrom to assist with
pre-instantiation diagnostics.
llvm-svn: 90842
Diffstat (limited to 'clang/lib/AST/CXXInheritance.cpp')
-rw-r--r-- | clang/lib/AST/CXXInheritance.cpp | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/clang/lib/AST/CXXInheritance.cpp b/clang/lib/AST/CXXInheritance.cpp index 023bca43633..e5300f82847 100644 --- a/clang/lib/AST/CXXInheritance.cpp +++ b/clang/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 { |