зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
ceb9bb3038
Коммит
e8174bc483
|
@ -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 {
|
||||
|
|
Загрузка…
Ссылка в новой задаче