This patch deals with Sema Part of Setter/Getter synthesis
of properties which are of C++ objects. Code Gen to follow (Radar 7468090). llvm-svn: 103123
This commit is contained in:
parent
245b169212
commit
25491a22af
|
@ -1421,13 +1421,21 @@ private:
|
|||
|
||||
/// Null for @dynamic. Required for @synthesize.
|
||||
ObjCIvarDecl *PropertyIvarDecl;
|
||||
|
||||
/// Null for @dynamic. Non-null if property must be copy-constructed in getter
|
||||
Expr *GetterCXXConstructor;
|
||||
|
||||
/// Null for @dynamic. Non-null if property has assignment operator to call
|
||||
/// in Setter synthesis.
|
||||
Expr *SetterCXXAssignment;
|
||||
|
||||
ObjCPropertyImplDecl(DeclContext *DC, SourceLocation atLoc, SourceLocation L,
|
||||
ObjCPropertyDecl *property,
|
||||
Kind PK,
|
||||
ObjCIvarDecl *ivarDecl)
|
||||
: Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc),
|
||||
PropertyDecl(property), PropertyIvarDecl(ivarDecl) {
|
||||
PropertyDecl(property), PropertyIvarDecl(ivarDecl),
|
||||
GetterCXXConstructor(0), SetterCXXAssignment(0) {
|
||||
assert (PK == Dynamic || PropertyIvarDecl);
|
||||
}
|
||||
|
||||
|
@ -1457,7 +1465,21 @@ public:
|
|||
return PropertyIvarDecl;
|
||||
}
|
||||
void setPropertyIvarDecl(ObjCIvarDecl *Ivar) { PropertyIvarDecl = Ivar; }
|
||||
|
||||
Expr *getGetterCXXConstructor() const {
|
||||
return GetterCXXConstructor;
|
||||
}
|
||||
void setGetterCXXConstructor(Expr *getterCXXConstructor) {
|
||||
GetterCXXConstructor = getterCXXConstructor;
|
||||
}
|
||||
|
||||
Expr *getSetterCXXAssignment() const {
|
||||
return SetterCXXAssignment;
|
||||
}
|
||||
void setSetterCXXAssignment(Expr *setterCXXAssignment) {
|
||||
SetterCXXAssignment = setterCXXAssignment;
|
||||
}
|
||||
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const ObjCPropertyImplDecl *D) { return true; }
|
||||
static bool classofKind(Decl::Kind K) { return K == ObjCPropertyImpl; }
|
||||
|
|
|
@ -2303,6 +2303,7 @@ public:
|
|||
}
|
||||
// ActOnPropertyImplDecl - called for every property implementation
|
||||
virtual DeclPtrTy ActOnPropertyImplDecl(
|
||||
Scope *S,
|
||||
SourceLocation AtLoc, // location of the @synthesize/@dynamic
|
||||
SourceLocation PropertyNameLoc, // location for the property name
|
||||
bool ImplKind, // true for @synthesize, false for
|
||||
|
@ -2346,7 +2347,7 @@ public:
|
|||
// protocols, categories), the parser passes all methods/properties.
|
||||
// For class implementations, these values default to 0. For implementations,
|
||||
// methods are processed incrementally (by ActOnMethodDeclaration above).
|
||||
virtual void ActOnAtEnd(SourceRange AtEnd,
|
||||
virtual void ActOnAtEnd(Scope *S, SourceRange AtEnd,
|
||||
DeclPtrTy classDecl,
|
||||
DeclPtrTy *allMethods = 0,
|
||||
unsigned allNum = 0,
|
||||
|
|
|
@ -157,9 +157,6 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
|
|||
!(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic);
|
||||
ObjCMethodDecl *OMD = PD->getGetterMethodDecl();
|
||||
assert(OMD && "Invalid call to generate getter (empty method)");
|
||||
// FIXME: This is rather murky, we create this here since they will not have
|
||||
// been created by Sema for us.
|
||||
OMD->createImplicitParams(getContext(), IMP->getClassInterface());
|
||||
StartObjCMethod(OMD, IMP->getClassInterface());
|
||||
|
||||
// Determine if we should use an objc_getProperty call for
|
||||
|
@ -274,9 +271,6 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP,
|
|||
const ObjCPropertyDecl *PD = PID->getPropertyDecl();
|
||||
ObjCMethodDecl *OMD = PD->getSetterMethodDecl();
|
||||
assert(OMD && "Invalid call to generate setter (empty method)");
|
||||
// FIXME: This is rather murky, we create this here since they will not have
|
||||
// been created by Sema for us.
|
||||
OMD->createImplicitParams(getContext(), IMP->getClassInterface());
|
||||
StartObjCMethod(OMD, IMP->getClassInterface());
|
||||
|
||||
bool IsCopy = PD->getSetterKind() == ObjCPropertyDecl::Copy;
|
||||
|
|
|
@ -394,6 +394,7 @@ void PCHDeclReader::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
|
|||
cast_or_null<ObjCPropertyDecl>(Reader.GetDecl(Record[Idx++])));
|
||||
D->setPropertyIvarDecl(
|
||||
cast_or_null<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++])));
|
||||
// FIXME. read GetterCXXConstructor and SetterCXXAssignment
|
||||
}
|
||||
|
||||
void PCHDeclReader::VisitFieldDecl(FieldDecl *FD) {
|
||||
|
|
|
@ -370,6 +370,7 @@ void PCHDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
|
|||
Writer.AddSourceLocation(D->getLocStart(), Record);
|
||||
Writer.AddDeclRef(D->getPropertyDecl(), Record);
|
||||
Writer.AddDeclRef(D->getPropertyIvarDecl(), Record);
|
||||
// FIXME. write GetterCXXConstructor and SetterCXXAssignment.
|
||||
Code = pch::DECL_OBJC_PROPERTY_IMPL;
|
||||
}
|
||||
|
||||
|
|
|
@ -446,7 +446,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
|
|||
|
||||
// Insert collected methods declarations into the @interface object.
|
||||
// This passes in an invalid SourceLocation for AtEndLoc when EOF is hit.
|
||||
Actions.ActOnAtEnd(AtEnd, interfaceDecl,
|
||||
Actions.ActOnAtEnd(CurScope, AtEnd, interfaceDecl,
|
||||
allMethods.data(), allMethods.size(),
|
||||
allProperties.data(), allProperties.size(),
|
||||
allTUVariables.data(), allTUVariables.size());
|
||||
|
@ -1277,7 +1277,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) {
|
|||
DeclPtrTy Result = ObjCImpDecl;
|
||||
ConsumeToken(); // the "end" identifier
|
||||
if (ObjCImpDecl) {
|
||||
Actions.ActOnAtEnd(atEnd, ObjCImpDecl);
|
||||
Actions.ActOnAtEnd(CurScope, atEnd, ObjCImpDecl);
|
||||
ObjCImpDecl = DeclPtrTy();
|
||||
PendingObjCImpDecl.pop_back();
|
||||
}
|
||||
|
@ -1292,7 +1292,7 @@ Parser::DeclGroupPtrTy Parser::RetrievePendingObjCImpDecl() {
|
|||
if (PendingObjCImpDecl.empty())
|
||||
return Actions.ConvertDeclToDeclGroup(DeclPtrTy());
|
||||
DeclPtrTy ImpDecl = PendingObjCImpDecl.pop_back_val();
|
||||
Actions.ActOnAtEnd(SourceRange(), ImpDecl);
|
||||
Actions.ActOnAtEnd(CurScope, SourceRange(), ImpDecl);
|
||||
return Actions.ConvertDeclToDeclGroup(ImpDecl);
|
||||
}
|
||||
|
||||
|
@ -1371,7 +1371,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
|
|||
propertyIvar = Tok.getIdentifierInfo();
|
||||
ConsumeToken(); // consume ivar-name
|
||||
}
|
||||
Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, true, ObjCImpDecl,
|
||||
Actions.ActOnPropertyImplDecl(CurScope, atLoc, propertyLoc, true, ObjCImpDecl,
|
||||
propertyId, propertyIvar);
|
||||
if (Tok.isNot(tok::comma))
|
||||
break;
|
||||
|
@ -1411,7 +1411,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
|
|||
|
||||
IdentifierInfo *propertyId = Tok.getIdentifierInfo();
|
||||
SourceLocation propertyLoc = ConsumeToken(); // consume property name
|
||||
Actions.ActOnPropertyImplDecl(atLoc, propertyLoc, false, ObjCImpDecl,
|
||||
Actions.ActOnPropertyImplDecl(CurScope, atLoc, propertyLoc, false, ObjCImpDecl,
|
||||
propertyId, 0);
|
||||
|
||||
if (Tok.isNot(tok::comma))
|
||||
|
|
|
@ -1528,13 +1528,13 @@ public:
|
|||
|
||||
/// ImplMethodsVsClassMethods - This is main routine to warn if any method
|
||||
/// remains unimplemented in the class or category @implementation.
|
||||
void ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl,
|
||||
void ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
|
||||
ObjCContainerDecl* IDecl,
|
||||
bool IncompleteImpl = false);
|
||||
|
||||
/// DiagnoseUnimplementedProperties - This routine warns on those properties
|
||||
/// which must be implemented by this implementation.
|
||||
void DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl,
|
||||
void DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
|
||||
ObjCContainerDecl *CDecl,
|
||||
const llvm::DenseSet<Selector>& InsMap);
|
||||
|
||||
|
@ -3858,7 +3858,7 @@ public:
|
|||
void MatchOneProtocolPropertiesInClass(Decl *CDecl,
|
||||
ObjCProtocolDecl *PDecl);
|
||||
|
||||
virtual void ActOnAtEnd(SourceRange AtEnd,
|
||||
virtual void ActOnAtEnd(Scope *S, SourceRange AtEnd,
|
||||
DeclPtrTy classDecl,
|
||||
DeclPtrTy *allMethods = 0, unsigned allNum = 0,
|
||||
DeclPtrTy *allProperties = 0, unsigned pNum = 0,
|
||||
|
@ -3871,7 +3871,8 @@ public:
|
|||
bool *OverridingProperty,
|
||||
tok::ObjCKeywordKind MethodImplKind);
|
||||
|
||||
virtual DeclPtrTy ActOnPropertyImplDecl(SourceLocation AtLoc,
|
||||
virtual DeclPtrTy ActOnPropertyImplDecl(Scope *S,
|
||||
SourceLocation AtLoc,
|
||||
SourceLocation PropertyLoc,
|
||||
bool ImplKind,DeclPtrTy ClassImplDecl,
|
||||
IdentifierInfo *PropertyId,
|
||||
|
|
|
@ -925,7 +925,7 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap,
|
|||
}
|
||||
}
|
||||
|
||||
void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl,
|
||||
void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
|
||||
ObjCContainerDecl* CDecl,
|
||||
bool IncompleteImpl) {
|
||||
llvm::DenseSet<Selector> InsMap;
|
||||
|
@ -939,7 +939,7 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl,
|
|||
// an implementation or 2) there is a @synthesize/@dynamic implementation
|
||||
// of the property in the @implementation.
|
||||
if (isa<ObjCInterfaceDecl>(CDecl))
|
||||
DiagnoseUnimplementedProperties(IMPDecl, CDecl, InsMap);
|
||||
DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, InsMap);
|
||||
|
||||
llvm::DenseSet<Selector> ClsMap;
|
||||
for (ObjCImplementationDecl::classmeth_iterator
|
||||
|
@ -968,7 +968,7 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl,
|
|||
for (ObjCCategoryDecl *Categories = I->getCategoryList();
|
||||
Categories; Categories = Categories->getNextClassCategory()) {
|
||||
if (Categories->IsClassExtension()) {
|
||||
ImplMethodsVsClassMethods(IMPDecl, Categories, IncompleteImpl);
|
||||
ImplMethodsVsClassMethods(S, IMPDecl, Categories, IncompleteImpl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -990,7 +990,7 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl,
|
|||
I = IMP->instmeth_begin(), E = IMP->instmeth_end(); I!=E; ++I)
|
||||
InsMap.insert((*I)->getSelector());
|
||||
}
|
||||
DiagnoseUnimplementedProperties(IMPDecl, CDecl, InsMap);
|
||||
DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, InsMap);
|
||||
}
|
||||
} else
|
||||
assert(false && "invalid ObjCContainerDecl type.");
|
||||
|
@ -1326,7 +1326,7 @@ void Sema::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID,
|
|||
|
||||
// Note: For class/category implemenations, allMethods/allProperties is
|
||||
// always null.
|
||||
void Sema::ActOnAtEnd(SourceRange AtEnd,
|
||||
void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
|
||||
DeclPtrTy classDecl,
|
||||
DeclPtrTy *allMethods, unsigned allNum,
|
||||
DeclPtrTy *allProperties, unsigned pNum,
|
||||
|
@ -1433,7 +1433,7 @@ void Sema::ActOnAtEnd(SourceRange AtEnd,
|
|||
if (ObjCImplementationDecl *IC=dyn_cast<ObjCImplementationDecl>(ClassDecl)) {
|
||||
IC->setAtEndRange(AtEnd);
|
||||
if (ObjCInterfaceDecl* IDecl = IC->getClassInterface()) {
|
||||
ImplMethodsVsClassMethods(IC, IDecl);
|
||||
ImplMethodsVsClassMethods(S, IC, IDecl);
|
||||
AtomicPropertySetterGetterRules(IC, IDecl);
|
||||
if (LangOpts.ObjCNonFragileABI2)
|
||||
while (IDecl->getSuperClass()) {
|
||||
|
@ -1452,7 +1452,7 @@ void Sema::ActOnAtEnd(SourceRange AtEnd,
|
|||
for (ObjCCategoryDecl *Categories = IDecl->getCategoryList();
|
||||
Categories; Categories = Categories->getNextClassCategory()) {
|
||||
if (Categories->getIdentifier() == CatImplClass->getIdentifier()) {
|
||||
ImplMethodsVsClassMethods(CatImplClass, Categories);
|
||||
ImplMethodsVsClassMethods(S, CatImplClass, Categories);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Sema.h"
|
||||
#include "SemaInit.h"
|
||||
#include "clang/AST/ExprObjC.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
|
@ -275,7 +277,8 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
|
|||
/// builds the AST node for a property implementation declaration; declared
|
||||
/// as @synthesize or @dynamic.
|
||||
///
|
||||
Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc,
|
||||
Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(Scope *S,
|
||||
SourceLocation AtLoc,
|
||||
SourceLocation PropertyLoc,
|
||||
bool Synthesize,
|
||||
DeclPtrTy ClassCatImpDecl,
|
||||
|
@ -427,6 +430,54 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc,
|
|||
ObjCPropertyImplDecl::Synthesize
|
||||
: ObjCPropertyImplDecl::Dynamic),
|
||||
Ivar);
|
||||
if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) {
|
||||
getterMethod->createImplicitParams(Context, IDecl);
|
||||
if (getLangOptions().CPlusPlus && Synthesize) {
|
||||
// For Objective-C++, need to synthesize the AST for the IVAR object to be
|
||||
// returned by the getter as it must conform to C++'s copy-return rules.
|
||||
// FIXME. Eventually we want to do this for Objective-C as well.
|
||||
ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl();
|
||||
DeclRefExpr *SelfExpr =
|
||||
new (Context) DeclRefExpr(SelfDecl,SelfDecl->getType(),
|
||||
SourceLocation());
|
||||
Expr *IvarRefExpr =
|
||||
new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc,
|
||||
SelfExpr, true, true);
|
||||
OwningExprResult Res =
|
||||
PerformCopyInitialization(InitializedEntity::InitializeResult(
|
||||
SourceLocation(),
|
||||
getterMethod->getResultType()),
|
||||
SourceLocation(),
|
||||
Owned(IvarRefExpr));
|
||||
if (!Res.isInvalid()) {
|
||||
Expr *ResExpr = Res.takeAs<Expr>();
|
||||
if (ResExpr)
|
||||
ResExpr = MaybeCreateCXXExprWithTemporaries(ResExpr);
|
||||
PIDecl->setGetterCXXConstructor(ResExpr);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) {
|
||||
setterMethod->createImplicitParams(Context, IDecl);
|
||||
if (getLangOptions().CPlusPlus && Synthesize) {
|
||||
// FIXME. Eventually we want to do this for Objective-C as well.
|
||||
ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl();
|
||||
DeclRefExpr *SelfExpr =
|
||||
new (Context) DeclRefExpr(SelfDecl,SelfDecl->getType(),
|
||||
SourceLocation());
|
||||
Expr *lhs =
|
||||
new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc,
|
||||
SelfExpr, true, true);
|
||||
ObjCMethodDecl::param_iterator P = setterMethod->param_begin();
|
||||
ParmVarDecl *Param = (*P);
|
||||
Expr *rhs = new (Context) DeclRefExpr(Param,Param->getType(),
|
||||
SourceLocation());
|
||||
OwningExprResult Res = BuildBinOp(S, SourceLocation(),
|
||||
BinaryOperator::Assign, lhs, rhs);
|
||||
PIDecl->setSetterCXXAssignment(Res.takeAs<Expr>());
|
||||
}
|
||||
}
|
||||
|
||||
if (IC) {
|
||||
if (Synthesize)
|
||||
if (ObjCPropertyImplDecl *PPIDecl =
|
||||
|
@ -818,7 +869,7 @@ ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl,
|
|||
}
|
||||
|
||||
|
||||
void Sema::DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl,
|
||||
void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
|
||||
ObjCContainerDecl *CDecl,
|
||||
const llvm::DenseSet<Selector>& InsMap) {
|
||||
llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap;
|
||||
|
@ -841,7 +892,7 @@ void Sema::DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl,
|
|||
PropImplMap.count(Prop))
|
||||
continue;
|
||||
if (LangOpts.ObjCNonFragileABI2 && !isa<ObjCCategoryImplDecl>(IMPDecl)) {
|
||||
ActOnPropertyImplDecl(IMPDecl->getLocation(),
|
||||
ActOnPropertyImplDecl(S, IMPDecl->getLocation(),
|
||||
IMPDecl->getLocation(),
|
||||
true, DeclPtrTy::make(IMPDecl),
|
||||
Prop->getIdentifier(),
|
||||
|
|
Loading…
Reference in New Issue