]> granicus.if.org Git - clang/commitdiff
Allow pseudo-destructor calls on forward-declared Objective-C class pointers.
authorJohn McCall <rjmccall@apple.com>
Mon, 14 Dec 2015 19:12:54 +0000 (19:12 +0000)
committerJohn McCall <rjmccall@apple.com>
Mon, 14 Dec 2015 19:12:54 +0000 (19:12 +0000)
rdar://18522255

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

lib/Sema/SemaExprCXX.cpp
test/SemaObjCXX/pseudo-destructor.mm [new file with mode: 0644]

index da34791395be172f6f950f5d88560031525081a0..b6c5d792b6dd1057b34bf78c197f024b6410caf6 100644 (file)
@@ -5736,9 +5736,14 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base,
   //
   // This also indicates that we could be parsing a pseudo-destructor-name.
   // Note that Objective-C class and object types can be pseudo-destructor
-  // expressions or normal member (ivar or property) access expressions.
+  // expressions or normal member (ivar or property) access expressions, and
+  // it's legal for the type to be incomplete if this is a pseudo-destructor
+  // call.  We'll do more incomplete-type checks later in the lookup process,
+  // so just skip this check for ObjC types.
   if (BaseType->isObjCObjectOrInterfaceType()) {
+    ObjectType = ParsedType::make(BaseType);
     MayBePseudoDestructor = true;
+    return Base;
   } else if (!BaseType->isRecordType()) {
     ObjectType = ParsedType();
     MayBePseudoDestructor = true;
diff --git a/test/SemaObjCXX/pseudo-destructor.mm b/test/SemaObjCXX/pseudo-destructor.mm
new file mode 100644 (file)
index 0000000..06570c1
--- /dev/null
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+__attribute__((objc_root_class))
+@interface Root
+@end
+
+@class Forward;
+
+template <class T> void destroyPointer(T *t) {
+  t->~T();
+}
+
+template <class T> void destroyReference(T &t) {
+  t.~T();
+}
+
+template void destroyPointer<Root*>(Root **);
+template void destroyReference<Root*>(Root *&);
+
+// rdar://18522255
+template void destroyPointer<Forward*>(Forward **);
+template void destroyReference<Forward*>(Forward *&);