Patch for objc2's property ASTs, as well as pretty-priting the ASTs.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43778 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Fariborz Jahanian 2007-11-06 22:01:00 +00:00
Родитель 2ebc89f6cb
Коммит 82a5fe3d1c
10 изменённых файлов: 292 добавлений и 16 удалений

Просмотреть файл

@ -36,6 +36,7 @@ static unsigned nIvarDecls = 0;
static unsigned nObjcImplementationDecls = 0;
static unsigned nObjcCategoryImpl = 0;
static unsigned nObjcCompatibleAlias = 0;
static unsigned nObjcPropertyDecl = 0;
static bool StatSwitch = false;
@ -146,6 +147,10 @@ void Decl::PrintStats() {
nObjcCompatibleAlias, (int)sizeof(ObjcCompatibleAliasDecl),
int(nObjcCompatibleAlias*sizeof(ObjcCompatibleAliasDecl)));
fprintf(stderr, " %d property decls, %d each (%d bytes)\n",
nObjcPropertyDecl, (int)sizeof(ObjcPropertyDecl),
int(nObjcPropertyDecl*sizeof(ObjcPropertyDecl)));
fprintf(stderr, "Total bytes = %d\n",
int(nFuncs*sizeof(FunctionDecl)+nBlockVars*sizeof(BlockVarDecl)+
nFileVars*sizeof(FileVarDecl)+nParmVars*sizeof(ParmVarDecl)+
@ -215,6 +220,9 @@ void Decl::addDeclKind(const Kind k) {
case CompatibleAlias:
nObjcCompatibleAlias++;
break;
case PropertyDecl:
nObjcPropertyDecl++;
break;
}
}

Просмотреть файл

@ -103,10 +103,78 @@ static void PrintObjcInterfaceDecl(ObjcInterfaceDecl *OID) {
fprintf(stderr, "\t%s %s;\n", Ivars[i]->getType().getAsString().c_str(),
Ivars[i]->getName());
}
fprintf(stderr, "}\n@end\n");
fprintf(stderr, "}\n");
}
else
fprintf(stderr,"@end\n");
int NumProperties = OID->getNumPropertyDecl();
if (NumProperties > 0) {
for (int i = 0; i < NumProperties; i++) {
ObjcPropertyDecl *PDecl = OID->getPropertyDecl()[i];
fprintf(stderr, "@property");
if (PDecl->getPropertyAttributes() != ObjcPropertyDecl::OBJC_PR_noattr) {
bool first = true;
fprintf(stderr, " (");
if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_readonly)
{
fprintf(stderr, "%creadonly", first ? ' ' : ',');
first = false;
}
if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_getter)
{
fprintf(stderr, "%cgetter = %s", first ? ' ' : ','
, PDecl->getGetterName()->getName());
first = false;
}
if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_setter)
{
fprintf(stderr, "%csetter = %s:", first ? ' ' : ','
, PDecl->getSetterName()->getName());
first = false;
}
if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_assign)
{
fprintf(stderr, "%cassign", first ? ' ' : ',');
first = false;
}
if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_readwrite)
{
fprintf(stderr, "%creadwrite", first ? ' ' : ',');
first = false;
}
if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_retain)
{
fprintf(stderr, "%cretain", first ? ' ' : ',');
first = false;
}
if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_copy)
{
fprintf(stderr, "%ccopy", first ? ' ' : ',');
first = false;
}
if (PDecl->getPropertyAttributes() & ObjcPropertyDecl::OBJC_PR_nonatomic)
{
fprintf(stderr, "%cnonatomic", first ? ' ' : ',');
first = false;
}
fprintf(stderr, " )");
}
ObjcIvarDecl **IDecl = PDecl->getPropertyDecls();
fprintf(stderr, " %s %s", IDecl[0]->getType().getAsString().c_str(),
IDecl[0]->getName());
for (int j = 1; j < PDecl->getNumPropertyDecls(); j++) {
fprintf(stderr, ", %s", IDecl[j]->getName());
}
fprintf(stderr, ";\n");
}
}
fprintf(stderr,"@end\n");
// FIXME: implement the rest...
}

Просмотреть файл

@ -225,6 +225,7 @@ Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration(
void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl,
tok::ObjCKeywordKind contextKey) {
llvm::SmallVector<DeclTy*, 32> allMethods;
llvm::SmallVector<DeclTy*, 16> allProperties;
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;
SourceLocation AtEndLoc;
@ -247,7 +248,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl,
if (contextKey != tok::objc_protocol)
Diag(AtLoc, diag::err_objc_protocol_optional);
} else if (ocKind == tok::objc_property) {
ParseObjCPropertyDecl(interfaceDecl);
allProperties.push_back(ParseObjCPropertyDecl(interfaceDecl, AtLoc));
continue;
} else {
Diag(Tok, diag::err_objc_illegal_interface_qual);
@ -277,7 +278,9 @@ void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl,
/// This action is executed even if we don't have any methods (so the @end
/// can be recorded properly).
Actions.ActOnAddMethodsToObjcDecl(CurScope, interfaceDecl, &allMethods[0],
allMethods.size(), AtEndLoc);
allMethods.size(),
&allProperties[0], allProperties.size(),
AtEndLoc);
}
/// Parse property attribute declarations.
@ -296,7 +299,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl,
/// copy
/// nonatomic
///
void Parser::ParseObjCPropertyAttribute (DeclTy *interfaceDecl) {
void Parser::ParseObjCPropertyAttribute (ObjcDeclSpec &DS) {
SourceLocation loc = ConsumeParen(); // consume '('
while (isObjCPropertyAttribute()) {
const IdentifierInfo *II = Tok.getIdentifierInfo();
@ -309,6 +312,8 @@ void Parser::ParseObjCPropertyAttribute (DeclTy *interfaceDecl) {
loc = ConsumeToken();
if (Tok.is(tok::identifier)) {
if (II == ObjcPropertyAttrs[objc_setter]) {
DS.setPropertyAttributes(ObjcDeclSpec::DQ_PR_setter);
DS.setSetterName(Tok.getIdentifierInfo());
loc = ConsumeToken(); // consume method name
if (Tok.isNot(tok::colon)) {
Diag(loc, diag::err_expected_colon);
@ -316,6 +321,10 @@ void Parser::ParseObjCPropertyAttribute (DeclTy *interfaceDecl) {
break;
}
}
else {
DS.setPropertyAttributes(ObjcDeclSpec::DQ_PR_getter);
DS.setGetterName(Tok.getIdentifierInfo());
}
}
else {
Diag(loc, diag::err_expected_ident);
@ -329,6 +338,20 @@ void Parser::ParseObjCPropertyAttribute (DeclTy *interfaceDecl) {
break;
}
}
else if (II == ObjcPropertyAttrs[objc_readonly])
DS.setPropertyAttributes(ObjcDeclSpec::DQ_PR_readonly);
else if (II == ObjcPropertyAttrs[objc_assign])
DS.setPropertyAttributes(ObjcDeclSpec::DQ_PR_assign);
else if (II == ObjcPropertyAttrs[objc_readwrite])
DS.setPropertyAttributes(ObjcDeclSpec::DQ_PR_readwrite);
else if (II == ObjcPropertyAttrs[objc_retain])
DS.setPropertyAttributes(ObjcDeclSpec::DQ_PR_retain);
else if (II == ObjcPropertyAttrs[objc_copy])
DS.setPropertyAttributes(ObjcDeclSpec::DQ_PR_copy);
else if (II == ObjcPropertyAttrs[objc_nonatomic])
DS.setPropertyAttributes(ObjcDeclSpec::DQ_PR_nonatomic);
ConsumeToken(); // consume last attribute token
if (Tok.is(tok::comma)) {
loc = ConsumeToken();
@ -352,17 +375,19 @@ void Parser::ParseObjCPropertyAttribute (DeclTy *interfaceDecl) {
///
/// @property property-attr-decl[opt] property-component-decl ';'
///
void Parser::ParseObjCPropertyDecl(DeclTy *interfaceDecl) {
Parser::DeclTy *Parser::ParseObjCPropertyDecl(DeclTy *interfaceDecl,
SourceLocation AtLoc) {
assert(Tok.isObjCAtKeyword(tok::objc_property) &&
"ParseObjCPropertyDecl(): Expected @property");
ObjcDeclSpec DS;
ConsumeToken(); // the "property" identifier
// Parse property attribute list, if any.
if (Tok.is(tok::l_paren)) {
// property has attribute list.
ParseObjCPropertyAttribute(0/*FIXME*/);
ParseObjCPropertyAttribute(DS);
}
// Parse declaration portion of @property.
llvm::SmallVector<DeclTy*, 32> PropertyDecls;
llvm::SmallVector<DeclTy*, 8> PropertyDecls;
ParseStructDeclaration(interfaceDecl, PropertyDecls);
if (Tok.is(tok::semi))
ConsumeToken();
@ -370,6 +395,8 @@ void Parser::ParseObjCPropertyDecl(DeclTy *interfaceDecl) {
Diag(Tok, diag::err_expected_semi_decl_list);
SkipUntil(tok::r_brace, true, true);
}
return Actions.ActOnAddObjcProperties(AtLoc,
&PropertyDecls[0], PropertyDecls.size(), DS);
}
/// objc-method-proto:
@ -919,6 +946,7 @@ Parser::DeclTy *Parser::ParseObjCAtEndDeclaration(SourceLocation atLoc) {
/// Insert collected methods declarations into the @interface object.
Actions.ActOnAddMethodsToObjcDecl(CurScope, ObjcImpDecl,
&AllImplMethods[0], AllImplMethods.size(),
(DeclTy **)0, 0,
atLoc);
ObjcImpDecl = 0;
AllImplMethods.clear();

Просмотреть файл

@ -531,8 +531,14 @@ public:
virtual void ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *ClassDecl,
DeclTy **allMethods, unsigned allNum,
DeclTy **allProperties, unsigned pNum,
SourceLocation AtEndLoc);
virtual DeclTy *ActOnAddObjcProperties(SourceLocation AtLoc,
DeclTy **allProperties,
unsigned NumProperties,
ObjcDeclSpec &DS);
virtual DeclTy *ActOnMethodDeclaration(
SourceLocation BeginLoc, // location of the + or -.
SourceLocation EndLoc, // location of the ; or {.

Просмотреть файл

@ -1916,6 +1916,7 @@ void Sema::AddFactoryMethodToGlobalPool(ObjcMethodDecl *Method) {
void Sema::ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *classDecl,
DeclTy **allMethods, unsigned allNum,
DeclTy **allProperties, unsigned pNum,
SourceLocation AtEndLoc) {
Decl *ClassDecl = static_cast<Decl *>(classDecl);
@ -1931,11 +1932,19 @@ void Sema::ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *classDecl,
llvm::DenseMap<Selector, const ObjcMethodDecl*> InsMap;
llvm::DenseMap<Selector, const ObjcMethodDecl*> ClsMap;
bool checkDuplicateMethods =
bool isInterfaceDeclKind =
(isa<ObjcInterfaceDecl>(ClassDecl) || isa<ObjcCategoryDecl>(ClassDecl)
|| isa<ObjcProtocolDecl>(ClassDecl));
bool checkIdenticalMethods = isa<ObjcImplementationDecl>(ClassDecl);
// TODO: property declaration in category and protocols.
if (pNum != 0 && isa<ObjcInterfaceDecl>(ClassDecl)) {
ObjcPropertyDecl **properties = new ObjcPropertyDecl*[pNum];
memcpy(properties, allProperties, pNum*sizeof(ObjcPropertyDecl*));
dyn_cast<ObjcInterfaceDecl>(ClassDecl)->setPropertyDecls(properties);
dyn_cast<ObjcInterfaceDecl>(ClassDecl)->setNumPropertyDecl(pNum);
}
for (unsigned i = 0; i < allNum; i++ ) {
ObjcMethodDecl *Method =
cast_or_null<ObjcMethodDecl>(static_cast<Decl*>(allMethods[i]));
@ -1946,7 +1955,7 @@ void Sema::ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *classDecl,
const ObjcMethodDecl *&PrevMethod = InsMap[Method->getSelector()];
bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod)
: false;
if (checkDuplicateMethods && PrevMethod && !match
if (isInterfaceDeclKind && PrevMethod && !match
|| checkIdenticalMethods && match) {
Diag(Method->getLocation(), diag::error_duplicate_method_decl,
Method->getSelector().getName());
@ -1963,7 +1972,7 @@ void Sema::ActOnAddMethodsToObjcDecl(Scope* S, DeclTy *classDecl,
const ObjcMethodDecl *&PrevMethod = ClsMap[Method->getSelector()];
bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod)
: false;
if (checkDuplicateMethods && PrevMethod && !match
if (isInterfaceDeclKind && PrevMethod && !match
|| checkIdenticalMethods && match) {
Diag(Method->getLocation(), diag::error_duplicate_method_decl,
Method->getSelector().getName());
@ -2077,6 +2086,47 @@ Sema::DeclTy *Sema::ActOnMethodDeclaration(
return ObjcMethod;
}
Sema::DeclTy *Sema::ActOnAddObjcProperties(SourceLocation AtLoc,
DeclTy **allProperties, unsigned NumProperties, ObjcDeclSpec &DS) {
ObjcPropertyDecl *PDecl = new ObjcPropertyDecl(AtLoc);
if(DS.getPropertyAttributes() & ObjcDeclSpec::DQ_PR_readonly)
PDecl->setPropertyAttributes(ObjcPropertyDecl::OBJC_PR_readonly);
if(DS.getPropertyAttributes() & ObjcDeclSpec::DQ_PR_getter) {
PDecl->setPropertyAttributes(ObjcPropertyDecl::OBJC_PR_getter);
PDecl->setGetterName(DS.getGetterName());
}
if(DS.getPropertyAttributes() & ObjcDeclSpec::DQ_PR_setter) {
PDecl->setPropertyAttributes(ObjcPropertyDecl::OBJC_PR_setter);
PDecl->setSetterName(DS.getSetterName());
}
if(DS.getPropertyAttributes() & ObjcDeclSpec::DQ_PR_assign)
PDecl->setPropertyAttributes(ObjcPropertyDecl::OBJC_PR_assign);
if(DS.getPropertyAttributes() & ObjcDeclSpec::DQ_PR_readwrite)
PDecl->setPropertyAttributes(ObjcPropertyDecl::OBJC_PR_readwrite);
if(DS.getPropertyAttributes() & ObjcDeclSpec::DQ_PR_retain)
PDecl->setPropertyAttributes(ObjcPropertyDecl::OBJC_PR_retain);
if(DS.getPropertyAttributes() & ObjcDeclSpec::DQ_PR_copy)
PDecl->setPropertyAttributes(ObjcPropertyDecl::OBJC_PR_copy);
if(DS.getPropertyAttributes() & ObjcDeclSpec::DQ_PR_nonatomic)
PDecl->setPropertyAttributes(ObjcPropertyDecl::OBJC_PR_nonatomic);
PDecl->setNumPropertyDecls(NumProperties);
if (NumProperties != 0) {
ObjcIvarDecl **properties = new ObjcIvarDecl*[NumProperties];
memcpy(properties, allProperties, NumProperties*sizeof(ObjcIvarDecl*));
PDecl->setPropertyDecls(properties);
}
return PDecl;
}
Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl,
DeclTy *lastEnumConst,
SourceLocation IdLoc, IdentifierInfo *Id,

Просмотреть файл

@ -48,6 +48,7 @@ public:
ObjcCategoryImpl,
ObjcImplementation,
ObjcProtocol,
PropertyDecl,
// ScopedDecl
CompatibleAlias,
// TypeDecl

Просмотреть файл

@ -26,6 +26,7 @@ class ObjcIvarDecl;
class ObjcMethodDecl;
class ObjcProtocolDecl;
class ObjcCategoryDecl;
class ObjcPropertyDecl;
/// ObjcInterfaceDecl - Represents an ObjC class declaration. For example:
///
@ -71,6 +72,10 @@ class ObjcInterfaceDecl : public TypeDecl {
/// List of categories defined for this class.
ObjcCategoryDecl *CategoryList;
/// class properties
ObjcPropertyDecl **PropertyDecl; // Null if no property
int NumPropertyDecl; // -1 if no property
bool ForwardDecl:1; // declared with @class.
bool InternalInterface:1; // true - no @interface for @implementation
@ -86,7 +91,8 @@ public:
NumIvars(-1),
InstanceMethods(0), NumInstanceMethods(-1),
ClassMethods(0), NumClassMethods(-1),
CategoryList(0), ForwardDecl(FD), InternalInterface(isInternal) {
CategoryList(0), PropertyDecl(0), NumPropertyDecl(-1),
ForwardDecl(FD), InternalInterface(isInternal) {
AllocIntfRefProtocols(numRefProtos);
}
@ -146,6 +152,16 @@ public:
// We also need to record the @end location.
SourceLocation getAtEndLoc() const { return AtEndLoc; }
const int getNumPropertyDecl() const { return NumPropertyDecl; }
int getNumPropertyDecl() { return NumPropertyDecl; }
void setNumPropertyDecl(int num) { NumPropertyDecl = num; }
ObjcPropertyDecl **const getPropertyDecl() const { return PropertyDecl; }
ObjcPropertyDecl **getPropertyDecl() { return PropertyDecl; }
void setPropertyDecls(ObjcPropertyDecl **properties) {
PropertyDecl = properties;
}
/// ImplicitInterfaceDecl - check that this is an implicitely declared
/// ObjcInterfaceDecl node. This is for legacy objective-c @implementation
@ -669,6 +685,61 @@ public:
static bool classof(const ObjcCompatibleAliasDecl *D) { return true; }
};
class ObjcPropertyDecl : public Decl {
public:
enum PrpoertyAttributeKind { OBJC_PR_noattr = 0x0,
OBJC_PR_readonly = 0x01,
OBJC_PR_getter = 0x02,
OBJC_PR_assign = 0x04,
OBJC_PR_readwrite = 0x08,
OBJC_PR_retain = 0x10,
OBJC_PR_copy = 0x20,
OBJC_PR_nonatomic = 0x40,
OBJC_PR_setter = 0x80 };
private:
// List of property name declarations
// FIXME: Property is not an ivar.
ObjcIvarDecl **PropertyDecls;
int NumPropertyDecls;
PrpoertyAttributeKind PropertyAttributes : 8;
IdentifierInfo *GetterName; // getter name of NULL if no getter
IdentifierInfo *SetterName; // setter name of NULL if no setter
public:
ObjcPropertyDecl(SourceLocation L)
: Decl(PropertyDecl, L),
PropertyDecls(0), NumPropertyDecls(-1), PropertyAttributes(OBJC_PR_noattr),
GetterName(0), SetterName(0) {}
ObjcIvarDecl **const getPropertyDecls() const { return PropertyDecls; }
void setPropertyDecls(ObjcIvarDecl **property) { PropertyDecls = property; }
const int getNumPropertyDecls() const { return NumPropertyDecls; }
void setNumPropertyDecls(int num) { NumPropertyDecls = num; }
const PrpoertyAttributeKind getPropertyAttributes() const
{ return PropertyAttributes; }
void setPropertyAttributes(PrpoertyAttributeKind PRVal) {
PropertyAttributes =
(PrpoertyAttributeKind) (PropertyAttributes | PRVal);
}
const IdentifierInfo *getGetterName() const { return GetterName; }
IdentifierInfo *getGetterName() { return GetterName; }
void setGetterName(IdentifierInfo *Id) { GetterName = Id; }
const IdentifierInfo *getSetterName() const { return SetterName; }
IdentifierInfo *getSetterName() { return SetterName; }
void setSetterName(IdentifierInfo *Id) { SetterName = Id; }
static bool classof(const Decl *D) {
return D->getKind() == PropertyDecl;
}
static bool classof(const ObjcPropertyDecl *D) { return true; }
};
} // end namespace clang
#endif

Просмотреть файл

@ -565,9 +565,18 @@ public:
DeclTy *ClassDecl,
DeclTy **allMethods,
unsigned allNum,
DeclTy **allProperties,
unsigned NumProperties,
SourceLocation AtEndLoc) {
return;
}
// ActOnAddObjcProperties - called to build one property AST
virtual DeclTy *ActOnAddObjcProperties (SourceLocation AtLoc,
DeclTy **allProperties, unsigned NumProperties, ObjcDeclSpec &DS) {
return 0;
}
// ActOnClassMessage - used for both unary and keyword messages.
// ArgExprs is optional - if it is present, the number of expressions
// is obtained from Sel.getNumArgs().

Просмотреть файл

@ -292,13 +292,48 @@ public:
DQ_Oneway = 0x20
};
ObjcDeclSpec() : objcDeclQualifier(DQ_None) {}
/// PrpoertyAttributeKind - list of property attributes.
enum ObjcPrpoertyAttributeKind { DQ_PR_noattr = 0x0,
DQ_PR_readonly = 0x01,
DQ_PR_getter = 0x02,
DQ_PR_assign = 0x04,
DQ_PR_readwrite = 0x08,
DQ_PR_retain = 0x10,
DQ_PR_copy = 0x20,
DQ_PR_nonatomic = 0x40,
DQ_PR_setter = 0x80
};
ObjcDeclSpec() : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr)
{}
ObjcDeclQualifier getObjcDeclQualifier() const { return objcDeclQualifier; }
void setObjcDeclQualifier(ObjcDeclQualifier DQVal)
{ objcDeclQualifier = (ObjcDeclQualifier) (objcDeclQualifier | DQVal); }
const ObjcPrpoertyAttributeKind getPropertyAttributes() const
{ return PropertyAttributes; }
void setPropertyAttributes(ObjcPrpoertyAttributeKind PRVal) {
PropertyAttributes =
(ObjcPrpoertyAttributeKind) (PropertyAttributes | PRVal);
}
const IdentifierInfo *getGetterName() const { return GetterName; }
IdentifierInfo *getGetterName() { return GetterName; }
void setGetterName(IdentifierInfo *name) { GetterName = name; }
const IdentifierInfo *getSetterName() const { return SetterName; }
IdentifierInfo *getSetterName() { return SetterName; }
void setSetterName(IdentifierInfo *name) { SetterName = name; }
private:
// FIXME: These two are unrelated and mutially exclusive. So perhaps
// we can put them in a union to reflect their mutual exclusiveness
// (space saving is negligible).
ObjcDeclQualifier objcDeclQualifier : 6;
ObjcPrpoertyAttributeKind PropertyAttributes : 8;
IdentifierInfo *GetterName; // getter name of NULL if no getter
IdentifierInfo *SetterName; // setter name of NULL if no setter
};
/// DeclaratorChunk - One instance of this struct is used for each type in a

Просмотреть файл

@ -298,8 +298,8 @@ private:
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword);
DeclTy *ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType,
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword);
void ParseObjCPropertyAttribute(DeclTy *interfaceDecl);
void ParseObjCPropertyDecl(DeclTy *interfaceDecl);
void ParseObjCPropertyAttribute(ObjcDeclSpec &DS);
DeclTy *ParseObjCPropertyDecl(DeclTy *interfaceDecl, SourceLocation AtLoc);
void ParseObjCInstanceMethodDefinition();
void ParseObjCClassMethodDefinition();