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
This commit is contained in:
John McCall 2009-12-08 07:42:38 +00:00
Родитель ceb9bb3038
Коммит e8174bc483
2 изменённых файлов: 73 добавлений и 0 удалений

Просмотреть файл

@ -704,6 +704,30 @@ public:
/// \todo add a separate paramaeter to configure IsDerivedFrom, rather than
/// tangling input and output in \p Paths
bool isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) const;
/// \brief Determine whether this class is provably not derived from
/// the type \p Base.
bool isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const;
/// \brief Function type used by forallBases() as a callback.
///
/// \param Base the definition of the base class
///
/// \returns true if this base matched the search criteria
typedef bool ForallBasesCallback(const CXXRecordDecl *BaseDefinition,
void *UserData);
/// \brief Determines if the given callback holds for all the direct
/// or indirect base classes of this type.
///
/// The class itself does not count as a base class. This routine
/// returns false if the class has non-computable base classes.
///
/// \param AllowShortCircuit if false, forces the callback to be called
/// for every base class, even if a dependent or non-matching base was
/// found.
bool forallBases(ForallBasesCallback *BaseMatches, void *UserData,
bool AllowShortCircuit = true) const;
/// \brief Function type used by lookupInBases() to determine whether a
/// specific base class subobject matches the lookup criteria.

Просмотреть файл

@ -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 {