Support for @dynamic AST build.

More property semantics checking.
First test case for ObjC2's property implementation.

llvm-svn: 50057
This commit is contained in:
Fariborz Jahanian 2008-04-21 21:05:54 +00:00
parent 74a58d780a
commit f2a7d7c949
5 changed files with 70 additions and 10 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -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 ','

View File

@ -952,10 +952,11 @@ Sema::DeclTy *Sema::ActOnPropertyImplDecl(SourceLocation AtLoc,
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 @@ Sema::DeclTy *Sema::ActOnPropertyImplDecl(SourceLocation AtLoc,
}
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 @@ 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

View File

@ -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