aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2012-08-16 22:38:41 +0000
committerFariborz Jahanian <fjahanian@apple.com>2012-08-16 22:38:41 +0000
commit7f90b531818ad772f6e407f88101dc618c738fa4 (patch)
treecebafeeaaa0a2a0d42c01a7f9fbc8f5e9b6d1749
parenteeff8ce11d687429d545cb6ce9bdaa44319ca72f (diff)
objective-C++: issue diagnostic when ivar type is
an abstract c++ class. // rdar://12095239 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162052 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--include/clang/Sema/Sema.h1
-rw-r--r--lib/Sema/SemaDecl.cpp10
-rw-r--r--test/SemaObjCXX/abstract-class-type-ivar.mm29
4 files changed, 39 insertions, 3 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 4733505a00..bff9a34318 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -815,7 +815,7 @@ def err_friend_def_in_local_class : Error<
"friend function cannot be defined in a local class">;
def err_abstract_type_in_decl : Error<
- "%select{return|parameter|variable|field}0 type %1 is an abstract class">;
+ "%select{return|parameter|variable|field|ivar}0 type %1 is an abstract class">;
def err_allocation_of_abstract_type : Error<
"allocating an object of abstract class type %0">;
def err_throw_abstract_type : Error<
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index b320a2452d..d1a7017fb0 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -4461,6 +4461,7 @@ public:
AbstractParamType,
AbstractVariableType,
AbstractFieldType,
+ AbstractIvarType,
AbstractArrayType
};
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index d37fbf5378..01b2f2c839 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -9913,6 +9913,13 @@ void Sema::ActOnFields(Scope* S,
}
}
}
+ if (isa<ObjCContainerDecl>(EnclosingDecl) &&
+ RequireNonAbstractType(FD->getLocation(), FD->getType(),
+ diag::err_abstract_type_in_decl,
+ AbstractIvarType)) {
+ // Ivars can not have abstract class types
+ FD->setInvalidDecl();
+ }
if (Record && FDTTy->getDecl()->hasObjectMember())
Record->setHasObjectMember(true);
} else if (FDTy->isObjCObjectType()) {
@@ -9921,8 +9928,7 @@ void Sema::ActOnFields(Scope* S,
<< FixItHint::CreateInsertion(FD->getLocation(), "*");
QualType T = Context.getObjCObjectPointerType(FD->getType());
FD->setType(T);
- }
- else if (!getLangOpts().CPlusPlus) {
+ } else if (!getLangOpts().CPlusPlus) {
if (getLangOpts().ObjCAutoRefCount && Record && !ARCErrReported) {
// It's an error in ARC if a field has lifetime.
// We don't want to report this in a system header, though,
diff --git a/test/SemaObjCXX/abstract-class-type-ivar.mm b/test/SemaObjCXX/abstract-class-type-ivar.mm
new file mode 100644
index 0000000000..823e9c197d
--- /dev/null
+++ b/test/SemaObjCXX/abstract-class-type-ivar.mm
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wno-objc-root-class %s
+// rdar://12095239
+
+class CppAbstractBase {
+public:
+ virtual void testA() = 0;
+ virtual void testB() = 0; // expected-note {{unimplemented pure virtual method 'testB' in 'CppConcreteSub}}
+ int a;
+};
+
+class CppConcreteSub : public CppAbstractBase {
+ virtual void testA() { }
+};
+
+@interface Objc {
+ CppConcreteSub _concrete; // expected-error{{ivar type 'CppConcreteSub' is an abstract class}}
+}
+- (CppAbstractBase*)abstract;
+@end
+@implementation Objc
+- (CppAbstractBase*)abstract {
+ return &_concrete;
+}
+@end
+
+class Cpp {
+public:
+ CppConcreteSub sub; // expected-error {{field type 'CppConcreteSub' is an abstract class}}
+};