[cfe-commits] r90842 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/CXXInheritance.cpp

John McCall rjmccall at apple.com
Mon Dec 7 23:42:39 PST 2009


Author: rjmccall
Date: Tue Dec  8 01:42:38 2009
New Revision: 90842

URL: http://llvm.org/viewvc/llvm-project?rev=90842&view=rev
Log:
Add CXXRecordDecl::forallBases to walk an inheritance hierarchy with non-lookup
semantics and CXXRecordDecl::isProvablyNotDerivedFrom to assist with
pre-instantiation diagnostics.


Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/CXXInheritance.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=90842&r1=90841&r2=90842&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Tue Dec  8 01:42:38 2009
@@ -704,6 +704,30 @@
   /// \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.

Modified: cfe/trunk/lib/AST/CXXInheritance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CXXInheritance.cpp?rev=90842&r1=90841&r2=90842&view=diff

==============================================================================
--- cfe/trunk/lib/AST/CXXInheritance.cpp (original)
+++ cfe/trunk/lib/AST/CXXInheritance.cpp Tue Dec  8 01:42:38 2009
@@ -90,6 +90,55 @@
   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 {





More information about the cfe-commits mailing list