[cfe-commits] r124505 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/CXXInheritance.cpp lib/Sema/SemaExprCXX.cpp test/SemaCXX/type-traits.cpp

John McCall rjmccall at apple.com
Fri Jan 28 14:02:36 PST 2011


Author: rjmccall
Date: Fri Jan 28 16:02:36 2011
New Revision: 124505

URL: http://llvm.org/viewvc/llvm-project?rev=124505&view=rev
Log:
Fix some corner cases in the __is_base_of logic.


Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/CXXInheritance.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/test/SemaCXX/type-traits.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=124505&r1=124504&r2=124505&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Fri Jan 28 16:02:36 2011
@@ -811,7 +811,7 @@
   /// \param Base the base class we are searching for.
   ///
   /// \returns true if this class is derived from Base, false otherwise.
-  bool isDerivedFrom(CXXRecordDecl *Base) const;
+  bool isDerivedFrom(const CXXRecordDecl *Base) const;
   
   /// \brief Determine whether this class is derived from the type \p Base.
   ///
@@ -829,7 +829,7 @@
   ///
   /// \todo add a separate paramaeter to configure IsDerivedFrom, rather than 
   /// tangling input and output in \p Paths  
-  bool isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) const;
+  bool isDerivedFrom(const CXXRecordDecl *Base, CXXBasePaths &Paths) const;
 
   /// \brief Determine whether this class is virtually derived from
   /// the class \p Base.

Modified: cfe/trunk/lib/AST/CXXInheritance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CXXInheritance.cpp?rev=124505&r1=124504&r2=124505&view=diff
==============================================================================
--- cfe/trunk/lib/AST/CXXInheritance.cpp (original)
+++ cfe/trunk/lib/AST/CXXInheritance.cpp Fri Jan 28 16:02:36 2011
@@ -76,18 +76,21 @@
   std::swap(DetectedVirtual, Other.DetectedVirtual);
 }
 
-bool CXXRecordDecl::isDerivedFrom(CXXRecordDecl *Base) const {
+bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base) const {
   CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false,
                      /*DetectVirtual=*/false);
   return isDerivedFrom(Base, Paths);
 }
 
-bool CXXRecordDecl::isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) const {
+bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base,
+                                  CXXBasePaths &Paths) const {
   if (getCanonicalDecl() == Base->getCanonicalDecl())
     return false;
   
   Paths.setOrigin(const_cast<CXXRecordDecl*>(this));
-  return lookupInBases(&FindBaseClass, Base->getCanonicalDecl(), Paths);
+  return lookupInBases(&FindBaseClass,
+                       const_cast<CXXRecordDecl*>(Base->getCanonicalDecl()),
+                       Paths);
 }
 
 bool CXXRecordDecl::isVirtuallyDerivedFrom(CXXRecordDecl *Base) const {

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=124505&r1=124504&r2=124505&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri Jan 28 16:02:36 2011
@@ -2487,17 +2487,36 @@
          "Cannot evaluate traits for dependent types.");
 
   switch(BTT) {
-  case BTT_IsBaseOf:
+  case BTT_IsBaseOf: {
     // C++0x [meta.rel]p2
-    // Base is a base class of Derived  without regard to cv-qualifiers or
+    // Base is a base class of Derived without regard to cv-qualifiers or
     // Base and Derived are not unions and name the same class type without
     // regard to cv-qualifiers.
-    if (Self.IsDerivedFrom(RhsT, LhsT) ||
-        (!LhsT->isUnionType() &&  !RhsT->isUnionType()
-         && LhsT->getAsCXXRecordDecl() == RhsT->getAsCXXRecordDecl()))
-      return true;
 
-    return false;
+    const RecordType *lhsRecord = LhsT->getAs<RecordType>();
+    if (!lhsRecord) return false;
+
+    const RecordType *rhsRecord = RhsT->getAs<RecordType>();
+    if (!rhsRecord) return false;
+
+    assert(Self.Context.hasSameUnqualifiedType(LhsT, RhsT)
+             == (lhsRecord == rhsRecord));
+
+    if (lhsRecord == rhsRecord)
+      return !lhsRecord->getDecl()->isUnion();
+
+    // C++0x [meta.rel]p2:
+    //   If Base and Derived are class types and are different types
+    //   (ignoring possible cv-qualifiers) then Derived shall be a
+    //   complete type.
+    if (Self.RequireCompleteType(KeyLoc, RhsT, 
+                          diag::err_incomplete_type_used_in_type_trait_expr))
+      return false;
+
+    return cast<CXXRecordDecl>(rhsRecord->getDecl())
+      ->isDerivedFrom(cast<CXXRecordDecl>(lhsRecord->getDecl()));
+  }
+
   case BTT_TypeCompatible:
     return Self.Context.typesAreCompatible(LhsT.getUnqualifiedType(),
                                            RhsT.getUnqualifiedType());
@@ -2560,19 +2579,7 @@
   QualType LhsT = LhsTSInfo->getType();
   QualType RhsT = RhsTSInfo->getType();
 
-  if (BTT == BTT_IsBaseOf) {
-    // C++0x [meta.rel]p2
-    // If Base and Derived are class types and are different types
-    // (ignoring possible cv-qualifiers) then Derived shall be a complete
-    // type. []
-    CXXRecordDecl *LhsDecl = LhsT->getAsCXXRecordDecl();
-    CXXRecordDecl *RhsDecl = RhsT->getAsCXXRecordDecl();
-    if (!LhsT->isDependentType() && !RhsT->isDependentType() &&
-        LhsDecl && RhsDecl && LhsT != RhsT &&
-        RequireCompleteType(KWLoc, RhsT,
-                            diag::err_incomplete_type_used_in_type_trait_expr))
-      return ExprError();
-  } else if (BTT == BTT_TypeCompatible) {
+  if (BTT == BTT_TypeCompatible) {
     if (getLangOptions().CPlusPlus) {
       Diag(KWLoc, diag::err_types_compatible_p_in_cplusplus)
         << SourceRange(KWLoc, RParen);

Modified: cfe/trunk/test/SemaCXX/type-traits.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type-traits.cpp?rev=124505&r1=124504&r2=124505&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/type-traits.cpp (original)
+++ cfe/trunk/test/SemaCXX/type-traits.cpp Fri Jan 28 16:02:36 2011
@@ -469,6 +469,9 @@
   int t[F(__is_base_of(Base, Derived))];
 };
 
+template <class T> class DerivedTemp : Base {};
+template <class T> class NonderivedTemp {};
+template <class T> class UndefinedTemp; // expected-note {{declared here}}
 
 void is_base_of() {
   int t01[T(__is_base_of(Base, Derived))];
@@ -486,7 +489,14 @@
   int t13[F(__is_base_of(Union, Union))];
   int t14[T(__is_base_of(Empty, Empty))];
   int t15[T(__is_base_of(class_forward, class_forward))];
-  int t16[F(__is_base_of(Empty, class_forward))]; // expected-error {{incomplete type 'class_forward' used in type trait expression}}   
+  int t16[F(__is_base_of(Empty, class_forward))]; // expected-error {{incomplete type 'class_forward' used in type trait expression}}
+  int t17[F(__is_base_of(Base&, Derived&))];
+  int t18[F(__is_base_of(Base[10], Derived[10]))];
+  int t19[F(__is_base_of(int, int))];
+  int t20[F(__is_base_of(long, int))];
+  int t21[T(__is_base_of(Base, DerivedTemp<int>))];
+  int t22[F(__is_base_of(Base, NonderivedTemp<int>))];
+  int t23[F(__is_base_of(Base, UndefinedTemp<int>))]; // expected-error {{implicit instantiation of undefined template 'UndefinedTemp<int>'}}
 
   isBaseOfT<Base, Derived>();
   isBaseOfF<Derived, Base>();





More information about the cfe-commits mailing list