]> granicus.if.org Git - clang/commitdiff
[Sema] Objective-C++ support for type trait __is_base_of
authorErik Pilkington <erik.pilkington@gmail.com>
Wed, 10 May 2017 17:18:56 +0000 (17:18 +0000)
committerErik Pilkington <erik.pilkington@gmail.com>
Wed, 10 May 2017 17:18:56 +0000 (17:18 +0000)
rdar://24308607

Differential revision: https://reviews.llvm.org/D32891

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@302695 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExprCXX.cpp
test/SemaObjCXX/is-base-of.mm [new file with mode: 0644]

index 9b88cddbc9698b0d26f95fdab76b89eb1c96a5d7..ee67df7bac2d0de1529d47a8b99c3b65fc397c70 100644 (file)
@@ -4720,10 +4720,24 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
     // regard to cv-qualifiers.
 
     const RecordType *lhsRecord = LhsT->getAs<RecordType>();
-    if (!lhsRecord) return false;
-
     const RecordType *rhsRecord = RhsT->getAs<RecordType>();
-    if (!rhsRecord) return false;
+    if (!rhsRecord || !lhsRecord) {
+      const ObjCObjectType *LHSObjTy = LhsT->getAs<ObjCObjectType>();
+      const ObjCObjectType *RHSObjTy = RhsT->getAs<ObjCObjectType>();
+      if (!LHSObjTy || !RHSObjTy)
+        return false;
+
+      ObjCInterfaceDecl *BaseInterface = LHSObjTy->getInterface();
+      ObjCInterfaceDecl *DerivedInterface = RHSObjTy->getInterface();
+      if (!BaseInterface || !DerivedInterface)
+        return false;
+
+      if (Self.RequireCompleteType(
+              KeyLoc, RhsT, diag::err_incomplete_type_used_in_type_trait_expr))
+        return false;
+
+      return BaseInterface->isSuperClassOf(DerivedInterface);
+    }
 
     assert(Self.Context.hasSameUnqualifiedType(LhsT, RhsT)
              == (lhsRecord == rhsRecord));
diff --git a/test/SemaObjCXX/is-base-of.mm b/test/SemaObjCXX/is-base-of.mm
new file mode 100644 (file)
index 0000000..9cf1666
--- /dev/null
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+@interface NSObj
+@end
+
+@interface NSChild : NSObj
+@end
+
+static_assert(__is_base_of(NSObj, NSChild), "");
+static_assert(!__is_base_of(NSChild, NSObj), "");
+
+static_assert(__is_base_of(NSObj, NSObj), "");
+
+static_assert(!__is_base_of(NSObj *, NSChild *), "");
+static_assert(!__is_base_of(NSChild *, NSObj *), "");
+
+static_assert(__is_base_of(const volatile NSObj, NSChild), "");
+static_assert(__is_base_of(NSObj, const volatile NSChild), "");
+
+@class NSForward; // expected-note{{forward declaration of class}}
+
+static_assert(!__is_base_of(NSForward, NSObj), "");
+static_assert(!__is_base_of(NSObj, NSForward), ""); // expected-error{{incomplete type 'NSForward'}}
+
+static_assert(!__is_base_of(id, NSObj), "");