Support for @dynamic AST build.
More property semantics checking.
First test case for ObjC2's property implementation.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50057 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index 6a34696..72c8e02 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -1066,6 +1066,8 @@
static ObjCPropertyDecl *Create(ASTContext &C, SourceLocation L,
IdentifierInfo *Id, QualType T);
QualType getType() const { return DeclType; }
+ QualType getCanonicalType() const { return DeclType.getCanonicalType(); }
+
PropertyAttributeKind getPropertyAttributes() const {
return PropertyAttributeKind(PropertyAttributes);
}
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def
index 4591210..4f46eaa 100644
--- a/include/clang/Basic/DiagnosticKinds.def
+++ b/include/clang/Basic/DiagnosticKinds.def
@@ -492,15 +492,21 @@
DIAG(error_bad_property_context, ERROR,
"property implementation must be in a class or category implementation")
DIAG(error_bad_property_decl, ERROR,
- "property implementation must have the declaration in the class '%0'")
+ "property implementation must have its declaration in the class '%0'")
+DIAG(error_bad_category_property_decl, ERROR,
+ "property implementation must have its declaration in the category '%0'")
DIAG(error_property_ivar_decl, ERROR,
"property synthesize requires specification of an ivar")
DIAG(error_dynamic_property_ivar_decl, ERROR,
"dynamic property can not have ivar specification")
DIAG(error_missing_property_interface, ERROR,
- "property implementation in a class/category implementation with no interface")
+ "property implementation in a category with no category declaration")
DIAG(error_missing_property_ivar_decl, ERROR,
"property synthesize requires a previously declared ivar")
+DIAG(error_synthesize_category_decl, ERROR,
+ "@synthesize not allowed in a category's implementation")
+DIAG(error_property_ivar_type, ERROR,
+ "type of property '%0' does not match type of ivar '%1'")
//===----------------------------------------------------------------------===//
// Semantic Analysis
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index ede0edb..0c5cf20 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -1077,7 +1077,11 @@
return 0;
}
while (Tok.is(tok::identifier)) {
- ConsumeToken(); // consume property name
+ IdentifierInfo *propertyId = Tok.getIdentifierInfo();
+ SourceLocation propertyLoc = ConsumeToken(); // consume property name
+ Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, false, ObjCImpDecl,
+ propertyId, 0);
+
if (Tok.isNot(tok::comma))
break;
ConsumeToken(); // consume ','
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 21130a04..45d8777 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -952,10 +952,11 @@
if (ObjCImplementationDecl *IC =
dyn_cast<ObjCImplementationDecl>(ClassImpDecl)) {
IDecl = getObjCInterfaceDecl(IC->getIdentifier());
- if (!IDecl) {
- Diag(AtLoc, diag::error_missing_property_interface);
- return 0;
- }
+ // We always synthesize an interface for an implementation
+ // without an interface decl. So, IDecl is always non-zero.
+ assert(IDecl &&
+ "ActOnPropertyImplDecl - @implementation without @interface");
+
// Look for this property declaration in the @implementation's @interface
property = IDecl->FindPropertyDeclaration(PropertyId);
if (!property) {
@@ -965,6 +966,10 @@
}
else if (ObjCCategoryImplDecl* CatImplClass =
dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl)) {
+ if (Synthesize) {
+ Diag(AtLoc, diag::error_synthesize_category_decl);
+ return 0;
+ }
IDecl = CatImplClass->getClassInterface();
if (!IDecl) {
Diag(AtLoc, diag::error_missing_property_interface);
@@ -980,7 +985,7 @@
// Look for this property declaration in @implementation's category
property = Category->FindPropertyDeclaration(PropertyId);
if (!property) {
- Diag(PropertyLoc, diag::error_bad_property_decl,
+ Diag(PropertyLoc, diag::error_bad_category_property_decl,
Category->getName());
return 0;
}
@@ -998,16 +1003,23 @@
return 0;
}
// Check that this is a previously declared 'ivar' in 'IDecl' interface
- if (!IDecl->FindIvarDeclaration(PropertyIvar)) {
+ ObjCIvarDecl *Ivar = IDecl->FindIvarDeclaration(PropertyIvar);
+ if (!Ivar) {
Diag(PropertyLoc, diag::error_missing_property_ivar_decl);
return 0;
}
+ // Check that type of property and its ivar match.
+ if (Ivar->getCanonicalType() != property->getCanonicalType()) {
+ Diag(PropertyLoc, diag::error_property_ivar_type, property->getName(),
+ Ivar->getName());
+ return 0;
+ }
+
} else if (PropertyIvar) {
// @dynamic
Diag(PropertyLoc, diag::error_dynamic_property_ivar_decl);
return 0;
}
- // TODO: More diagnostics go here !!
assert (property && "ActOnPropertyImplDecl - property declaration missing");
// TODO: Build the property implementation AST, pushes it into its
// class/cateogory implementation's vector of property implementations
diff --git a/test/Sema/objc-property-1.m b/test/Sema/objc-property-1.m
new file mode 100644
index 0000000..d307d13
--- /dev/null
+++ b/test/Sema/objc-property-1.m
@@ -0,0 +1,36 @@
+// RUN: clang -fsyntax-only -verify %s
+
+@interface I
+{
+ int IVAR;
+}
+@property int d1;
+@property id prop_id;
+@end
+
+@interface I(CAT)
+@property int d1;
+@end
+
+@implementation I
+@synthesize d1; // expected-error {{property synthesize requires specification of an ivar}}
+@dynamic bad; // expected-error {{property implementation must have its declaration in the class 'I'}}
+@synthesize prop_id; // expected-error {{property synthesize requires specification of an ivar}}
+@synthesize prop_id = IVAR; // expected-error {{type of property 'prop_id' does not match type of ivar 'IVAR'}}
+@end
+
+@implementation I(CAT)
+@synthesize d1; // expected-error {{@synthesize not allowed in a category's implementation}}
+@dynamic bad; // expected-error {{property implementation must have its declaration in the category 'CAT'}}
+@end
+
+@implementation E // expected-warning {{cannot find interface declaration for 'E'}}
+@dynamic d; // expected-error {{property implementation must have its declaration in the class 'E'}}
+@end
+
+@implementation Q(MYCAT) // expected-error {{cannot find interface declaration for 'Q'}}
+@dynamic d; // expected-error {{property implementation in a category with no category declaration}}
+@end
+
+
+