Initial work for property implementation declarations.

Mostly semantic checking in this patch. This is on going
and incomplete.

llvm-svn: 49882
This commit is contained in:
Fariborz Jahanian 2008-04-18 00:19:30 +00:00
parent be89ba0c38
commit ffe97a3925
6 changed files with 178 additions and 7 deletions

View File

@ -27,6 +27,7 @@ class ObjCMethodDecl;
class ObjCProtocolDecl;
class ObjCCategoryDecl;
class ObjCPropertyDecl;
class ObjCPropertyImplDecl;
/// ObjCMethodDecl - Represents an instance or class method declaration.
/// ObjC methods can be declared within 4 contexts: class interfaces,
@ -807,6 +808,9 @@ class ObjCCategoryImplDecl : public NamedDecl {
/// implemented class methods
llvm::SmallVector<ObjCMethodDecl*, 32> ClassMethods;
/// Propertys' being implemented
llvm::SmallVector<ObjCPropertyImplDecl*, 8> PropertyImplementations;
SourceLocation EndLoc;
@ -829,13 +833,20 @@ public:
}
void addClassMethod(ObjCMethodDecl *method) {
ClassMethods.push_back(method);
}
}
// Get the instance method definition for this implementation.
ObjCMethodDecl *getInstanceMethod(Selector Sel);
// Get the class method definition for this implementation.
ObjCMethodDecl *getClassMethod(Selector Sel);
void addPropertyImplementation(ObjCPropertyImplDecl *property) {
PropertyImplementations.push_back(property);
}
unsigned getNumPropertyImplementations() const
{ return PropertyImplementations.size(); }
typedef llvm::SmallVector<ObjCMethodDecl*, 32>::const_iterator
instmeth_iterator;
instmeth_iterator instmeth_begin() const { return InstanceMethods.begin(); }
@ -888,6 +899,9 @@ class ObjCImplementationDecl : public NamedDecl {
/// implemented class methods
llvm::SmallVector<ObjCMethodDecl*, 32> ClassMethods;
/// Propertys' being implemented
llvm::SmallVector<ObjCPropertyImplDecl*, 8> PropertyImplementations;
SourceLocation EndLoc;
ObjCImplementationDecl(SourceLocation L, IdentifierInfo *Id,
@ -912,6 +926,11 @@ public:
void addClassMethod(ObjCMethodDecl *method) {
ClassMethods.push_back(method);
}
void addPropertyImplementation(ObjCPropertyImplDecl *property) {
PropertyImplementations.push_back(property);
}
// Location information, modeled after the Stmt API.
SourceLocation getLocStart() const { return getLocation(); }
SourceLocation getLocEnd() const { return EndLoc; }
@ -926,6 +945,9 @@ public:
unsigned getNumInstanceMethods() const { return InstanceMethods.size(); }
unsigned getNumClassMethods() const { return ClassMethods.size(); }
unsigned getNumPropertyImplementations() const
{ return PropertyImplementations.size(); }
typedef llvm::SmallVector<ObjCMethodDecl*, 32>::const_iterator
instmeth_iterator;
@ -1041,14 +1063,15 @@ public:
OBJC_PR_IMPL_DYNAMIC
};
private:
SourceLocation AtLoc; // location of @syntheisze or @dynamic
/// Property declaration being implemented
ObjCPropertyDecl *PropertyDecl;
PropertyImplKind PropertyImplementation;
/// Null for @dynamic. Required for @synthesize.
ObjCIvarDecl *PropertyIvarDecl;
public:
ObjCPropertyImplDecl(SourceLocation L)
: Decl(ObjCPropertyImpl, L), PropertyDecl(0),
ObjCPropertyImplDecl(SourceLocation atLoc, SourceLocation L)
: Decl(ObjCPropertyImpl, L), AtLoc(atLoc), PropertyDecl(0),
PropertyImplementation(OBJC_PR_IMPL_None), PropertyIvarDecl(0) {}
void setPropertyDecl(ObjCPropertyDecl *property) { PropertyDecl = property; }

View File

@ -487,6 +487,20 @@ DIAG(error_bad_receiver_type, ERROR,
"bad receiver type '%0'")
DIAG(error_no_super_class, ERROR,
"no super class declared in @interface for '%0'")
DIAG(error_missing_property_context, ERROR,
"missing context for property implementation declaration")
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'")
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")
DIAG(error_missing_property_ivar_decl, ERROR,
"property synthesize requires a previously declared ivar")
//===----------------------------------------------------------------------===//
// Semantic Analysis

View File

@ -626,6 +626,18 @@ public:
SourceLocation CatLoc) {
return 0;
}
// ActOnPropertyImplDecl - called for every property implementation
virtual DeclTy *ActOnPropertyImplDecl(
SourceLocation AtLoc, // location of the @syntheize/@dynamic
SourceLocation PropertyNameLoc, // location for the property name
bool ImplKind, // true for @synthesize, false for
// @dynamic
DeclTy *ClassImplDecl, // class or category implementation
IdentifierInfo *propertyId, // name of property
IdentifierInfo *propertyIvar) { // name of the ivar
return 0;
}
// ActOnMethodDeclaration - called for all method declarations.
virtual DeclTy *ActOnMethodDeclaration(
SourceLocation BeginLoc, // location of the + or -.

View File

@ -1031,13 +1031,15 @@ Parser::DeclTy *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
Parser::DeclTy *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
assert(Tok.isObjCAtKeyword(tok::objc_synthesize) &&
"ParseObjCPropertyDynamic(): Expected '@synthesize'");
SourceLocation loc = ConsumeToken(); // consume dynamic
SourceLocation loc = ConsumeToken(); // consume synthesize
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
return 0;
}
while (Tok.is(tok::identifier)) {
ConsumeToken(); // consume property name
IdentifierInfo *propertyIvar = 0;
IdentifierInfo *propertyId = Tok.getIdentifierInfo();
SourceLocation propertyLoc = ConsumeToken(); // consume property name
if (Tok.is(tok::equal)) {
// property '=' ivar-name
ConsumeToken(); // consume '='
@ -1045,8 +1047,11 @@ Parser::DeclTy *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
Diag(Tok, diag::err_expected_ident);
break;
}
propertyIvar = Tok.getIdentifierInfo();
ConsumeToken(); // consume ivar-name
}
Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, true, ObjCImpDecl,
propertyId, propertyIvar);
if (Tok.isNot(tok::comma))
break;
ConsumeToken(); // consume ','

View File

@ -656,7 +656,13 @@ public:
DeclTy **allProperties = 0, unsigned pNum = 0);
virtual DeclTy *ActOnProperty(Scope *S, SourceLocation AtLoc,
FieldDeclarator &FD, ObjCDeclSpec &ODS);
FieldDeclarator &FD, ObjCDeclSpec &ODS);
virtual DeclTy *ActOnPropertyImplDecl(SourceLocation AtLoc,
SourceLocation PropertyLoc,
bool ImplKind, DeclTy *ClassImplDecl,
IdentifierInfo *PropertyId,
IdentifierInfo *PropertyIvar);
virtual DeclTy *ActOnMethodDeclaration(
SourceLocation BeginLoc, // location of the + or -.
SourceLocation EndLoc, // location of the ; or {.

View File

@ -929,5 +929,116 @@ Sema::DeclTy *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
return PDecl;
}
/// ActOnPropertyImplDecl - This routine performas semantic checks and
/// build the AST node for a property implementation declaration; declared
/// as @synthesize ot @dynamic
///
Sema::DeclTy *Sema::ActOnPropertyImplDecl(SourceLocation AtLoc,
SourceLocation PropertyLoc,
bool Synthesize,
DeclTy *ClassCatImpDecl,
IdentifierInfo *PropertyId,
IdentifierInfo *PropertyIvar) {
Decl *ClassImpDecl = static_cast<Decl*>(ClassCatImpDecl);
// Make sure we have a context for the property implementation declaration.
if (!ClassImpDecl) {
Diag(AtLoc, diag::error_missing_property_context);
return 0;
}
ObjCPropertyDecl *property = 0;
ObjCInterfaceDecl* IDecl = 0;
// Find the class or category class where this property must have
// a declaration.
if (ObjCImplementationDecl *IC =
dyn_cast<ObjCImplementationDecl>(ClassImpDecl)) {
IDecl = getObjCInterfaceDecl(IC->getIdentifier());
if (!IDecl) {
Diag(AtLoc, diag::error_missing_property_interface);
return 0;
}
// Look for this property declaration in the @implementation's @interface
ObjCInterfaceDecl::classprop_iterator I,E;
for (I = IDecl->classprop_begin(),
E = IDecl->classprop_end(); I != E; ++I) {
property = *I;
if (property->getIdentifier() == PropertyId)
break;
}
if (I == E) {
Diag(PropertyLoc, diag::error_bad_property_decl, IDecl->getName());
return 0;
}
}
else if (ObjCCategoryImplDecl* CatImplClass =
dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl)) {
IDecl = CatImplClass->getClassInterface();
if (!IDecl) {
Diag(AtLoc, diag::error_missing_property_interface);
return 0;
}
ObjCCategoryDecl *Categories;
for (ObjCCategoryDecl *Categories = IDecl->getCategoryList();
Categories; Categories = Categories->getNextClassCategory())
if (Categories->getIdentifier() == CatImplClass->getIdentifier())
break;
// If category for this implementation not found, it is an error which
// has already been reported eralier.
if (!Categories)
return 0;
// Look for this property declaration in @implementation's category
ObjCCategoryDecl::classprop_iterator I,E;
for (I = Categories->classprop_begin(),
E = Categories->classprop_end(); I != E; ++I) {
property = *I;
if (property->getIdentifier() == PropertyId)
break;
}
if (I == E) {
Diag(PropertyLoc, diag::error_bad_property_decl,
Categories->getName());
return 0;
}
}
else {
Diag(AtLoc, diag::error_bad_property_context);
return 0;
}
// Check that we have a valid, previously declared ivar for @synthesize
if (Synthesize) {
// @synthesize
if (!PropertyIvar) {
Diag(PropertyLoc, diag::error_property_ivar_decl);
return 0;
}
// Check that this is a previously declared 'ivar' in 'IDecl' interface
ObjCInterfaceDecl::ivar_iterator IVI, IVE;
for (IVI = IDecl->ivar_begin(), IVE = IDecl->ivar_end();
IVI != IVE; ++IVI) {
ObjCIvarDecl* ImplIvar = (*IVI);
if (ImplIvar->getIdentifier() == PropertyIvar)
break;
}
if (IVI == IVE) {
Diag(PropertyLoc, diag::error_missing_property_ivar_decl);
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
#if 0
ObjCCategoryImplDecl *PIDecl =
ObjCCategoryImplDecl::Create(AtLoc, PropertyLoc, property,
Synthesize ? ObjCPropertyImplDecl::OBJC_PR_IMPL_SYNTHSIZE
: ObjCPropertyImplDecl::OBJC_PR_IMPL_DYNAMIC,
PropertyId, PropertyIvar);
#endif
return 0;
}