/// \param AllowShortCircuit if false, forces the callback to be called
/// for every base class, even if a dependent or non-matching base was
/// found.
- ///
- /// \param VisitDependent whether we should also visit dependent bases
- /// that can be resolved to CXXRecordDecls.
bool forallBases(ForallBasesCallback *BaseMatches, void *UserData,
- bool AllowShortCircuit = true,
- bool VisitDependent = false) const;
+ bool AllowShortCircuit = true) const;
/// \brief Function type used by lookupInBases() to determine whether a
/// specific base class subobject matches the lookup criteria.
bool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches,
void *OpaqueData,
- bool AllowShortCircuit,
- bool VisitDependent) const {
+ bool AllowShortCircuit) const {
SmallVector<const CXXRecordDecl*, 8> Queue;
const CXXRecordDecl *Record = this;
while (true) {
for (CXXRecordDecl::base_class_const_iterator
I = Record->bases_begin(), E = Record->bases_end(); I != E; ++I) {
- CXXRecordDecl *Base = I->getType()->getAsCXXRecordDecl();
- if (!Base || (!VisitDependent && I->getType()->isDependentType())) {
+ const RecordType *Ty = I->getType()->getAs<RecordType>();
+ if (!Ty) {
if (AllowShortCircuit) return false;
AllMatches = false;
continue;
}
- Base = Base->getDefinition();
+ CXXRecordDecl *Base =
+ cast_or_null<CXXRecordDecl>(Ty->getDecl()->getDefinition());
if (!Base) {
if (AllowShortCircuit) return false;
AllMatches = false;
return false;
}
-/// \brief Determine whether we have the same C++ record definition.
-///
-/// Used as a helper function in Sema::CheckBaseSpecifier, below.
-static bool sameCXXRecordDef(const CXXRecordDecl *BaseDefinition,
- void *UserData) {
- return (CXXRecordDecl *)UserData != BaseDefinition;
+/// \brief Determine whether the given class is a base class of the given
+/// class, including looking at dependent bases.
+static bool findCircularInheritance(const CXXRecordDecl *Class,
+ const CXXRecordDecl *Current) {
+ SmallVector<const CXXRecordDecl*, 8> Queue;
+
+ Class = Class->getCanonicalDecl();
+ while (true) {
+ for (CXXRecordDecl::base_class_const_iterator I = Current->bases_begin(),
+ E = Current->bases_end();
+ I != E; ++I) {
+ CXXRecordDecl *Base = I->getType()->getAsCXXRecordDecl();
+ if (!Base)
+ continue;
+
+ Base = Base->getDefinition();
+ if (!Base)
+ continue;
+
+ if (Base->getCanonicalDecl() == Class)
+ return true;
+
+ Queue.push_back(Base);
+ }
+
+ if (Queue.empty())
+ return false;
+
+ Current = Queue.back();
+ Queue.pop_back();
+ }
+
+ return false;
}
/// \brief Check the validity of a C++ base class specifier.
if (CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl()) {
if (BaseDecl->getCanonicalDecl() == Class->getCanonicalDecl() ||
((BaseDecl = BaseDecl->getDefinition()) &&
- !BaseDecl->forallBases(&sameCXXRecordDef, Class))) {
+ findCircularInheritance(Class, BaseDecl))) {
Diag(BaseLoc, diag::err_circular_inheritance)
<< BaseType << Context.getTypeDeclType(Class);