Support for implementation of property in the case where
the synthesis is in an implementation of s subclass of a super class where the property has been declared. llvm-svn: 60792
This commit is contained in:
parent
c13f26873f
commit
3d8552a75d
|
@ -216,7 +216,7 @@ public:
|
|||
/// implict parameters. This must be called prior to using getSelfDecl()
|
||||
/// or getCmdDecl(). The call is ignored if the implicit paramters
|
||||
/// have already been created.
|
||||
void createImplicitParams(ASTContext &Context);
|
||||
void createImplicitParams(ASTContext &Context, const ObjCInterfaceDecl *ID);
|
||||
|
||||
ImplicitParamDecl * getSelfDecl() const { return SelfDecl; }
|
||||
ImplicitParamDecl * getCmdDecl() const { return CmdDecl; }
|
||||
|
|
|
@ -220,13 +220,14 @@ ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C,
|
|||
// Objective-C Decl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void ObjCMethodDecl::createImplicitParams(ASTContext &Context) {
|
||||
void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
|
||||
const ObjCInterfaceDecl *OID) {
|
||||
QualType selfTy;
|
||||
if (isInstance()) {
|
||||
// There may be no interface context due to error in declaration
|
||||
// of the interface (which has been reported). Recover gracefully.
|
||||
if (ObjCInterfaceDecl *OID = getClassInterface()) {
|
||||
selfTy = Context.getObjCInterfaceType(OID);
|
||||
if (OID) {
|
||||
selfTy = Context.getObjCInterfaceType(const_cast<ObjCInterfaceDecl *>(OID));
|
||||
selfTy = Context.getPointerType(selfTy);
|
||||
} else {
|
||||
selfTy = Context.getObjCIdType();
|
||||
|
|
|
@ -137,14 +137,15 @@ void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
|
|||
/// GenerateObjCGetter - Generate an Objective-C property getter
|
||||
/// function. The given Decl must be either an ObjCCategoryImplDecl
|
||||
/// or an ObjCImplementationDecl.
|
||||
void CodeGenFunction::GenerateObjCGetter(const ObjCPropertyImplDecl *PID) {
|
||||
void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
|
||||
const ObjCPropertyImplDecl *PID) {
|
||||
ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
|
||||
const ObjCPropertyDecl *PD = PID->getPropertyDecl();
|
||||
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());
|
||||
OMD->createImplicitParams(getContext(), IMP->getClassInterface());
|
||||
StartObjCMethod(OMD);
|
||||
|
||||
// Determine if we should use an objc_getProperty call for
|
||||
|
@ -173,7 +174,7 @@ void CodeGenFunction::GenerateObjCGetter(const ObjCPropertyImplDecl *PID) {
|
|||
QualType IdTy = getContext().getObjCIdType();
|
||||
llvm::Value *SelfAsId =
|
||||
Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy));
|
||||
llvm::Value *Offset = EmitIvarOffset(OMD->getClassInterface(), Ivar);
|
||||
llvm::Value *Offset = EmitIvarOffset(IMP->getClassInterface(), Ivar);
|
||||
llvm::Value *True =
|
||||
llvm::ConstantInt::get(Types.ConvertTypeForMem(getContext().BoolTy), 1);
|
||||
CallArgList Args;
|
||||
|
@ -204,14 +205,15 @@ void CodeGenFunction::GenerateObjCGetter(const ObjCPropertyImplDecl *PID) {
|
|||
/// GenerateObjCSetter - Generate an Objective-C property setter
|
||||
/// function. The given Decl must be either an ObjCCategoryImplDecl
|
||||
/// or an ObjCImplementationDecl.
|
||||
void CodeGenFunction::GenerateObjCSetter(const ObjCPropertyImplDecl *PID) {
|
||||
void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP,
|
||||
const ObjCPropertyImplDecl *PID) {
|
||||
ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
|
||||
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());
|
||||
OMD->createImplicitParams(getContext(), IMP->getClassInterface());
|
||||
StartObjCMethod(OMD);
|
||||
|
||||
bool IsCopy = PD->getSetterKind() == ObjCPropertyDecl::Copy;
|
||||
|
@ -244,7 +246,7 @@ void CodeGenFunction::GenerateObjCSetter(const ObjCPropertyImplDecl *PID) {
|
|||
QualType IdTy = getContext().getObjCIdType();
|
||||
llvm::Value *SelfAsId =
|
||||
Builder.CreateBitCast(LoadObjCSelf(), Types.ConvertType(IdTy));
|
||||
llvm::Value *Offset = EmitIvarOffset(OMD->getClassInterface(), Ivar);
|
||||
llvm::Value *Offset = EmitIvarOffset(IMP->getClassInterface(), Ivar);
|
||||
llvm::Value *Arg = LocalDeclMap[OMD->getParamDecl(0)];
|
||||
llvm::Value *ArgAsId =
|
||||
Builder.CreateBitCast(Builder.CreateLoad(Arg, "arg"),
|
||||
|
|
|
@ -45,6 +45,7 @@ namespace clang {
|
|||
class ObjCInterfaceDecl;
|
||||
class ObjCIvarDecl;
|
||||
class ObjCMethodDecl;
|
||||
class ObjCImplementationDecl;
|
||||
class ObjCPropertyImplDecl;
|
||||
class TargetInfo;
|
||||
class VarDecl;
|
||||
|
@ -176,11 +177,13 @@ public:
|
|||
|
||||
/// GenerateObjCGetter - Synthesize an Objective-C property getter
|
||||
/// function.
|
||||
void GenerateObjCGetter(const ObjCPropertyImplDecl *PID);
|
||||
void GenerateObjCGetter(ObjCImplementationDecl *IMP,
|
||||
const ObjCPropertyImplDecl *PID);
|
||||
|
||||
/// GenerateObjCSetter - Synthesize an Objective-C property setter
|
||||
/// function for the given property.
|
||||
void GenerateObjCSetter(const ObjCPropertyImplDecl *PID);
|
||||
void GenerateObjCSetter(ObjCImplementationDecl *IMP,
|
||||
const ObjCPropertyImplDecl *PID);
|
||||
|
||||
void GenerateCode(const FunctionDecl *FD,
|
||||
llvm::Function *Fn);
|
||||
|
|
|
@ -980,10 +980,12 @@ void CodeGenModule::EmitObjCPropertyImplementations(const
|
|||
// property. What we want to know is if the method is defined in
|
||||
// this implementation.
|
||||
if (!D->getInstanceMethod(PD->getGetterName()))
|
||||
CodeGenFunction(*this).GenerateObjCGetter(PID);
|
||||
CodeGenFunction(*this).GenerateObjCGetter(
|
||||
const_cast<ObjCImplementationDecl *>(D), PID);
|
||||
if (!PD->isReadOnly() &&
|
||||
!D->getInstanceMethod(PD->getSetterName()))
|
||||
CodeGenFunction(*this).GenerateObjCSetter(PID);
|
||||
CodeGenFunction(*this).GenerateObjCSetter(
|
||||
const_cast<ObjCImplementationDecl *>(D), PID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ void Sema::ObjCActOnStartOfMethodDef(Scope *FnBodyScope, DeclTy *D) {
|
|||
// binding to their use.
|
||||
|
||||
// Insert the invisible arguments, self and _cmd!
|
||||
MDecl->createImplicitParams(Context);
|
||||
MDecl->createImplicitParams(Context, MDecl->getClassInterface());
|
||||
|
||||
PushOnScopeChains(MDecl->getSelfDecl(), FnBodyScope);
|
||||
PushOnScopeChains(MDecl->getCmdDecl(), FnBodyScope);
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
// RUN: clang -fnext-runtime --emit-llvm -o %t %s
|
||||
|
||||
@interface Object
|
||||
- (id) new;
|
||||
@end
|
||||
|
||||
@interface Tester : Object
|
||||
@property char PropertyAtomic_char;
|
||||
@property short PropertyAtomic_short;
|
||||
@property int PropertyAtomic_int;
|
||||
@property long PropertyAtomic_long;
|
||||
@property long long PropertyAtomic_longlong;
|
||||
@property float PropertyAtomic_float;
|
||||
@property double PropertyAtomic_double;
|
||||
@property(assign) id PropertyAtomic_id;
|
||||
@property(retain) id PropertyAtomicRetained_id;
|
||||
@property(copy) id PropertyAtomicRetainedCopied_id;
|
||||
@property(retain) id PropertyAtomicRetainedGCOnly_id;
|
||||
@property(copy) id PropertyAtomicRetainedCopiedGCOnly_id;
|
||||
@end
|
||||
|
||||
@implementation Tester
|
||||
@dynamic PropertyAtomic_char;
|
||||
@dynamic PropertyAtomic_short;
|
||||
@dynamic PropertyAtomic_int;
|
||||
@dynamic PropertyAtomic_long;
|
||||
@dynamic PropertyAtomic_longlong;
|
||||
@dynamic PropertyAtomic_float;
|
||||
@dynamic PropertyAtomic_double;
|
||||
@dynamic PropertyAtomic_id;
|
||||
@dynamic PropertyAtomicRetained_id;
|
||||
@dynamic PropertyAtomicRetainedCopied_id;
|
||||
@dynamic PropertyAtomicRetainedGCOnly_id;
|
||||
@dynamic PropertyAtomicRetainedCopiedGCOnly_id;
|
||||
@end
|
||||
|
||||
@interface SubClass : Tester
|
||||
{
|
||||
char PropertyAtomic_char;
|
||||
short PropertyAtomic_short;
|
||||
int PropertyAtomic_int;
|
||||
long PropertyAtomic_long;
|
||||
long long PropertyAtomic_longlong;
|
||||
float PropertyAtomic_float;
|
||||
double PropertyAtomic_double;
|
||||
id PropertyAtomic_id;
|
||||
id PropertyAtomicRetained_id;
|
||||
id PropertyAtomicRetainedCopied_id;
|
||||
id PropertyAtomicRetainedGCOnly_id;
|
||||
id PropertyAtomicRetainedCopiedGCOnly_id;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation SubClass
|
||||
@synthesize PropertyAtomic_char;
|
||||
@synthesize PropertyAtomic_short;
|
||||
@synthesize PropertyAtomic_int;
|
||||
@synthesize PropertyAtomic_long;
|
||||
@synthesize PropertyAtomic_longlong;
|
||||
@synthesize PropertyAtomic_float;
|
||||
@synthesize PropertyAtomic_double;
|
||||
@synthesize PropertyAtomic_id;
|
||||
@synthesize PropertyAtomicRetained_id;
|
||||
@synthesize PropertyAtomicRetainedCopied_id;
|
||||
@synthesize PropertyAtomicRetainedGCOnly_id;
|
||||
@synthesize PropertyAtomicRetainedCopiedGCOnly_id;
|
||||
@end
|
||||
|
||||
int main()
|
||||
{
|
||||
SubClass *f = [SubClass new];
|
||||
f.PropertyAtomic_int = 1;
|
||||
|
||||
f.PropertyAtomic_int += 3;
|
||||
|
||||
f.PropertyAtomic_int -= 4;
|
||||
return f.PropertyAtomic_int;
|
||||
}
|
Loading…
Reference in New Issue