92a93,143
> 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;
> }
>
> CXXRecordDecl *Base =
> cast_or_null<CXXRecordDecl>(Ty->getDecl()->getDefinition(Context));
> if (!Base) {
> if (AllowShortCircuit) return false;
> AllMatches = false;
> continue;
> }
>
> Queue.push_back(Base);
> if (!BaseMatches(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;
> }
>
> 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;
> }
>
> CXXRecordDecl *Base =
> cast_or_null<CXXRecordDecl>(Ty->getDecl()->getDefinition(Context));
> if (!Base) {
> if (AllowShortCircuit) return false;
> AllMatches = false;
> continue;
> }
>
> Queue.push_back(Base);
> if (!BaseMatches(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;
> }
>