diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index 6a34696462c3..72c8e025a811 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -1066,6 +1066,8 @@ public: 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/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index 459121003226..4f46eaa02842 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -492,15 +492,21 @@ DIAG(error_missing_property_context, ERROR, 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/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index ede0edb354ac..0c5cf20ef8eb 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -1077,7 +1077,11 @@ Parser::DeclTy *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { 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/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 21130a04fa02..45d877778568 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -952,10 +952,11 @@ Sema::DeclTy *Sema::ActOnPropertyImplDecl(SourceLocation AtLoc, if (ObjCImplementationDecl *IC = dyn_cast(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 @@ Sema::DeclTy *Sema::ActOnPropertyImplDecl(SourceLocation AtLoc, } else if (ObjCCategoryImplDecl* CatImplClass = dyn_cast(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 @@ Sema::DeclTy *Sema::ActOnPropertyImplDecl(SourceLocation AtLoc, // 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 @@ Sema::DeclTy *Sema::ActOnPropertyImplDecl(SourceLocation AtLoc, 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/clang/test/Sema/objc-property-1.m b/clang/test/Sema/objc-property-1.m new file mode 100644 index 000000000000..d307d13022f9 --- /dev/null +++ b/clang/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 + + +