]> granicus.if.org Git - clang/commitdiff
Rework my implementation of circular-reference finding to not use
authorDouglas Gregor <dgregor@apple.com>
Sat, 10 Nov 2012 07:24:09 +0000 (07:24 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 10 Nov 2012 07:24:09 +0000 (07:24 +0000)
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

include/clang/AST/DeclCXX.h
lib/AST/CXXInheritance.cpp
lib/Sema/SemaDeclCXX.cpp
test/SemaTemplate/dependent-names.cpp

index d5d66fcd963a26f5de1289fda8416595d0139a7e..9cb56e2b3ccc214736fcf9ebce96a511f93cca53 100644 (file)
@@ -1322,12 +1322,8 @@ public:
   /// \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.
index 6e91f3f9105ba946d9cd699ce240aacdf4e4a4d4..213b214a4e4c22a99860bac5a21fd9466b6739dd 100644 (file)
@@ -123,8 +123,7 @@ bool CXXRecordDecl::isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const {
 
 bool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches,
                                 void *OpaqueData,
-                                bool AllowShortCircuit,
-                                bool VisitDependent) const {
+                                bool AllowShortCircuit) const {
   SmallVector<const CXXRecordDecl*, 8> Queue;
 
   const CXXRecordDecl *Record = this;
@@ -132,14 +131,15 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches,
   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;
index 1c3d4f2052cf881584c92338ec8104d17ede3039..16eddf80ae5bffea67ae8115b5eec6e04809347e 100644 (file)
@@ -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);
 
index 4e322d909d6fff382da428d66228f1d97dbb1d8f..efa4d28723d832ca94347fbe650f1ecbdaa0a265 100644 (file)
@@ -336,6 +336,9 @@ namespace rdar12629723 {
       virtual void foo() { }
     };
     struct B;
+
+    struct D : T::foo { };
+    struct E : D { };
   };
 
   template<class T>