aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDeclCXX.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2012-11-10 07:24:09 +0000
committerDouglas Gregor <dgregor@apple.com>2012-11-10 07:24:09 +0000
commit229d47aef27e6f65fe4dc3beb22f622dd81104ad (patch)
treef36e3c95a4e160a0bdc651cd679d657bd836e0dc /lib/Sema/SemaDeclCXX.cpp
parent463eb89d5e36b05d74c14b937384076d745b3b84 (diff)
Rework my implementation of circular-reference finding to not use
CXXRecordDecl::forallBases, which does *not* do what I need. Fixes the failure introduced in r167651. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@167668 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r--lib/Sema/SemaDeclCXX.cpp41
1 files changed, 34 insertions, 7 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 1c3d4f2052..16eddf80ae 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1018,12 +1018,39 @@ bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *,
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.
@@ -1062,7 +1089,7 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
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);