Support rewriting of property synthesis with retain/copy

attributes. Fixes radar 7214439.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97203 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Fariborz Jahanian 2010-02-26 01:42:20 +00:00
Родитель 692f85c1d2
Коммит 7c63fddad6
2 изменённых файлов: 120 добавлений и 25 удалений

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

@ -256,6 +256,8 @@ namespace {
void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl); void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl);
void RewriteImplementationDecl(Decl *Dcl); void RewriteImplementationDecl(Decl *Dcl);
void RewriteObjCMethodDecl(ObjCMethodDecl *MDecl, std::string &ResultStr); void RewriteObjCMethodDecl(ObjCMethodDecl *MDecl, std::string &ResultStr);
void RewriteTypeIntoString(QualType T, std::string &ResultStr,
const FunctionType *&FPRetType);
void RewriteByRefString(std::string &ResultStr, const std::string &Name, void RewriteByRefString(std::string &ResultStr, const std::string &Name,
ValueDecl *VD); ValueDecl *VD);
void RewriteCategoryDecl(ObjCCategoryDecl *Dcl); void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);
@ -349,7 +351,7 @@ namespace {
std::string &Result); std::string &Result);
void SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, void SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl,
std::string &Result); std::string &Result);
void SynthesizeIvarOffsetComputation(ObjCImplementationDecl *IDecl, void SynthesizeIvarOffsetComputation(ObjCContainerDecl *IDecl,
ObjCIvarDecl *ivar, ObjCIvarDecl *ivar,
std::string &Result); std::string &Result);
void RewriteImplementations(); void RewriteImplementations();
@ -617,7 +619,8 @@ void RewriteObjC::Initialize(ASTContext &context) {
Preamble += "};\n"; Preamble += "};\n";
Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n"; Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";
Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n"; Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n";
Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_assign(void *, const void *, const int);\n"; Preamble += "extern \"C\" __declspec(dllexport) "
"void _Block_object_assign(void *, const void *, const int);\n";
Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n"; Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n"; Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n"; Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
@ -638,6 +641,7 @@ void RewriteObjC::Initialize(ASTContext &context) {
Preamble += "#define __block\n"; Preamble += "#define __block\n";
Preamble += "#define __weak\n"; Preamble += "#define __weak\n";
} }
Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long) &((TYPE *)0)->MEMBER)\n";
} }
@ -761,6 +765,8 @@ static std::string getIvarAccessString(ObjCInterfaceDecl *ClassDecl,
void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
ObjCImplementationDecl *IMD, ObjCImplementationDecl *IMD,
ObjCCategoryImplDecl *CID) { ObjCCategoryImplDecl *CID) {
static bool objcGetPropertyDefined = false;
static bool objcSetPropertyDefined = false;
SourceLocation startLoc = PID->getLocStart(); SourceLocation startLoc = PID->getLocStart();
InsertText(startLoc, "// "); InsertText(startLoc, "// ");
const char *startBuf = SM->getCharacterData(startLoc); const char *startBuf = SM->getCharacterData(startLoc);
@ -780,14 +786,54 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
if (!OID) if (!OID)
return; return;
unsigned Attributes = PD->getPropertyAttributes();
bool GenGetProperty = !(Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) &&
(Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
ObjCPropertyDecl::OBJC_PR_copy));
std::string Getr; std::string Getr;
if (GenGetProperty && !objcGetPropertyDefined) {
objcGetPropertyDefined = true;
// FIXME. Is this attribute correct in all cases?
Getr = "\nextern \"C\" __declspec(dllimport) "
"id objc_getProperty(id, SEL, long, bool);\n";
}
RewriteObjCMethodDecl(PD->getGetterMethodDecl(), Getr); RewriteObjCMethodDecl(PD->getGetterMethodDecl(), Getr);
Getr += "{ "; Getr += "{ ";
// Synthesize an explicit cast to gain access to the ivar. // Synthesize an explicit cast to gain access to the ivar.
// FIXME: deal with code generation implications for various property
// attributes (copy, retain, nonatomic).
// See objc-act.c:objc_synthesize_new_getter() for details. // See objc-act.c:objc_synthesize_new_getter() for details.
if (GenGetProperty) {
// return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)
Getr += "typedef ";
const FunctionType *FPRetType = 0;
RewriteTypeIntoString(PD->getGetterMethodDecl()->getResultType(), Getr,
FPRetType);
Getr += " _TYPE";
if (FPRetType) {
Getr += ")"; // close the precedence "scope" for "*".
// Now, emit the argument types (if any).
if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) {
Getr += "(";
for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) {
if (i) Getr += ", ";
std::string ParamStr = FT->getArgType(i).getAsString();
Getr += ParamStr;
}
if (FT->isVariadic()) {
if (FT->getNumArgs()) Getr += ", ";
Getr += "...";
}
Getr += ")";
} else
Getr += "()";
}
Getr += ";\n";
Getr += "return (_TYPE)";
Getr += "objc_getProperty(self, _cmd, ";
SynthesizeIvarOffsetComputation(ClassDecl, OID, Getr);
Getr += ", 1)";
}
else
Getr += "return " + getIvarAccessString(ClassDecl, OID); Getr += "return " + getIvarAccessString(ClassDecl, OID);
Getr += "; }"; Getr += "; }";
InsertText(onePastSemiLoc, Getr); InsertText(onePastSemiLoc, Getr);
@ -796,14 +842,38 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
// Generate the 'setter' function. // Generate the 'setter' function.
std::string Setr; std::string Setr;
bool GenSetProperty = Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
ObjCPropertyDecl::OBJC_PR_copy);
if (GenSetProperty && !objcSetPropertyDefined) {
objcSetPropertyDefined = true;
// FIXME. Is this attribute correct in all cases?
Setr = "\nextern \"C\" __declspec(dllimport) "
"void objc_setProperty (id, SEL, long, id, bool, bool);\n";
}
RewriteObjCMethodDecl(PD->getSetterMethodDecl(), Setr); RewriteObjCMethodDecl(PD->getSetterMethodDecl(), Setr);
Setr += "{ "; Setr += "{ ";
// Synthesize an explicit cast to initialize the ivar. // Synthesize an explicit cast to initialize the ivar.
// FIXME: deal with code generation implications for various property
// attributes (copy, retain, nonatomic).
// See objc-act.c:objc_synthesize_new_setter() for details. // See objc-act.c:objc_synthesize_new_setter() for details.
if (GenSetProperty) {
Setr += "objc_setProperty (self, _cmd, ";
SynthesizeIvarOffsetComputation(ClassDecl, OID, Setr);
Setr += ", (id)";
Setr += PD->getNameAsCString();
Setr += ", ";
if (Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic)
Setr += "0, ";
else
Setr += "1, ";
if (Attributes & ObjCPropertyDecl::OBJC_PR_copy)
Setr += "1)";
else
Setr += "0)";
}
else {
Setr += getIvarAccessString(ClassDecl, OID) + " = "; Setr += getIvarAccessString(ClassDecl, OID) + " = ";
Setr += PD->getNameAsCString(); Setr += PD->getNameAsCString();
}
Setr += "; }"; Setr += "; }";
InsertText(onePastSemiLoc, Setr); InsertText(onePastSemiLoc, Setr);
} }
@ -940,18 +1010,15 @@ void RewriteObjC::RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *PDecl) {
ReplaceText(LocStart, 0, "// "); ReplaceText(LocStart, 0, "// ");
} }
void RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl *OMD, void RewriteObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr,
std::string &ResultStr) { const FunctionType *&FPRetType) {
//fprintf(stderr,"In RewriteObjCMethodDecl\n"); if (T->isObjCQualifiedIdType())
const FunctionType *FPRetType = 0;
ResultStr += "\nstatic ";
if (OMD->getResultType()->isObjCQualifiedIdType())
ResultStr += "id"; ResultStr += "id";
else if (OMD->getResultType()->isFunctionPointerType() || else if (T->isFunctionPointerType() ||
OMD->getResultType()->isBlockPointerType()) { T->isBlockPointerType()) {
// needs special handling, since pointer-to-functions have special // needs special handling, since pointer-to-functions have special
// syntax (where a decaration models use). // syntax (where a decaration models use).
QualType retType = OMD->getResultType(); QualType retType = T;
QualType PointeeTy; QualType PointeeTy;
if (const PointerType* PT = retType->getAs<PointerType>()) if (const PointerType* PT = retType->getAs<PointerType>())
PointeeTy = PT->getPointeeType(); PointeeTy = PT->getPointeeType();
@ -962,7 +1029,15 @@ void RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl *OMD,
ResultStr += "(*"; ResultStr += "(*";
} }
} else } else
ResultStr += OMD->getResultType().getAsString(); ResultStr += T.getAsString();
}
void RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl *OMD,
std::string &ResultStr) {
//fprintf(stderr,"In RewriteObjCMethodDecl\n");
const FunctionType *FPRetType = 0;
ResultStr += "\nstatic ";
RewriteTypeIntoString(OMD->getResultType(), ResultStr, FPRetType);
ResultStr += " "; ResultStr += " ";
// Unique method name // Unique method name
@ -3509,7 +3584,7 @@ void RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
/// SynthesizeIvarOffsetComputation - This rutine synthesizes computation of /// SynthesizeIvarOffsetComputation - This rutine synthesizes computation of
/// ivar offset. /// ivar offset.
void RewriteObjC::SynthesizeIvarOffsetComputation(ObjCImplementationDecl *IDecl, void RewriteObjC::SynthesizeIvarOffsetComputation(ObjCContainerDecl *IDecl,
ObjCIvarDecl *ivar, ObjCIvarDecl *ivar,
std::string &Result) { std::string &Result) {
if (ivar->isBitField()) { if (ivar->isBitField()) {
@ -3808,8 +3883,6 @@ void RewriteObjC::SynthesizeMetaDataIntoBuffer(std::string &Result) {
int ClsDefCount = ClassImplementation.size(); int ClsDefCount = ClassImplementation.size();
int CatDefCount = CategoryImplementation.size(); int CatDefCount = CategoryImplementation.size();
// This is needed for determining instance variable offsets.
Result += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long) &((TYPE *)0)->MEMBER)\n";
// For each implemented class, write out all its meta data. // For each implemented class, write out all its meta data.
for (int i = 0; i < ClsDefCount; i++) for (int i = 0; i < ClsDefCount; i++)
RewriteObjCClassMetaData(ClassImplementation[i], Result); RewriteObjCClassMetaData(ClassImplementation[i], Result);

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

@ -0,0 +1,22 @@
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp
// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
// radar 7214439
typedef void (^void_block_t)(void);
@interface Y {
void_block_t __completion;
Y* YVAR;
id ID;
}
@property (copy) void_block_t completionBlock;
@property (retain) Y* Yblock;
@property (copy) id ID;
@end
@implementation Y
@synthesize completionBlock=__completion;
@synthesize Yblock = YVAR;
@synthesize ID;
@end