[cfe-commits] r97203 - in /cfe/trunk: lib/Frontend/RewriteObjC.cpp test/Rewriter/rewrite-property-attributes.mm
Fariborz Jahanian
fjahanian at apple.com
Thu Feb 25 17:42:20 PST 2010
Author: fjahanian
Date: Thu Feb 25 19:42:20 2010
New Revision: 97203
URL: http://llvm.org/viewvc/llvm-project?rev=97203&view=rev
Log:
Support rewriting of property synthesis with retain/copy
attributes. Fixes radar 7214439.
Added:
cfe/trunk/test/Rewriter/rewrite-property-attributes.mm
Modified:
cfe/trunk/lib/Frontend/RewriteObjC.cpp
Modified: cfe/trunk/lib/Frontend/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/RewriteObjC.cpp?rev=97203&r1=97202&r2=97203&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/RewriteObjC.cpp (original)
+++ cfe/trunk/lib/Frontend/RewriteObjC.cpp Thu Feb 25 19:42:20 2010
@@ -256,6 +256,8 @@
void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl);
void RewriteImplementationDecl(Decl *Dcl);
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,
ValueDecl *VD);
void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);
@@ -349,7 +351,7 @@
std::string &Result);
void SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl,
std::string &Result);
- void SynthesizeIvarOffsetComputation(ObjCImplementationDecl *IDecl,
+ void SynthesizeIvarOffsetComputation(ObjCContainerDecl *IDecl,
ObjCIvarDecl *ivar,
std::string &Result);
void RewriteImplementations();
@@ -558,7 +560,7 @@
Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
} else
- Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";
+ Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";
Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend";
Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper";
@@ -617,7 +619,8 @@
Preamble += "};\n";
Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\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 *_NSConcreteGlobalBlock[32];\n";
Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
@@ -638,6 +641,7 @@
Preamble += "#define __block\n";
Preamble += "#define __weak\n";
}
+ Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long) &((TYPE *)0)->MEMBER)\n";
}
@@ -761,6 +765,8 @@
void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
ObjCImplementationDecl *IMD,
ObjCCategoryImplDecl *CID) {
+ static bool objcGetPropertyDefined = false;
+ static bool objcSetPropertyDefined = false;
SourceLocation startLoc = PID->getLocStart();
InsertText(startLoc, "// ");
const char *startBuf = SM->getCharacterData(startLoc);
@@ -780,15 +786,55 @@
if (!OID)
return;
-
+ unsigned Attributes = PD->getPropertyAttributes();
+ bool GenGetProperty = !(Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) &&
+ (Attributes & (ObjCPropertyDecl::OBJC_PR_retain |
+ ObjCPropertyDecl::OBJC_PR_copy));
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);
Getr += "{ ";
// 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.
- Getr += "return " + getIvarAccessString(ClassDecl, OID);
+ 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 += "; }";
InsertText(onePastSemiLoc, Getr);
if (PD->isReadOnly())
@@ -796,14 +842,38 @@
// Generate the 'setter' function.
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);
Setr += "{ ";
// 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.
- Setr += getIvarAccessString(ClassDecl, OID) + " = ";
- Setr += PD->getNameAsCString();
+ 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 += PD->getNameAsCString();
+ }
Setr += "; }";
InsertText(onePastSemiLoc, Setr);
}
@@ -940,18 +1010,15 @@
ReplaceText(LocStart, 0, "// ");
}
-void RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl *OMD,
- std::string &ResultStr) {
- //fprintf(stderr,"In RewriteObjCMethodDecl\n");
- const FunctionType *FPRetType = 0;
- ResultStr += "\nstatic ";
- if (OMD->getResultType()->isObjCQualifiedIdType())
+void RewriteObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr,
+ const FunctionType *&FPRetType) {
+ if (T->isObjCQualifiedIdType())
ResultStr += "id";
- else if (OMD->getResultType()->isFunctionPointerType() ||
- OMD->getResultType()->isBlockPointerType()) {
+ else if (T->isFunctionPointerType() ||
+ T->isBlockPointerType()) {
// needs special handling, since pointer-to-functions have special
// syntax (where a decaration models use).
- QualType retType = OMD->getResultType();
+ QualType retType = T;
QualType PointeeTy;
if (const PointerType* PT = retType->getAs<PointerType>())
PointeeTy = PT->getPointeeType();
@@ -962,7 +1029,15 @@
ResultStr += "(*";
}
} 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 += " ";
// Unique method name
@@ -3509,7 +3584,7 @@
/// SynthesizeIvarOffsetComputation - This rutine synthesizes computation of
/// ivar offset.
-void RewriteObjC::SynthesizeIvarOffsetComputation(ObjCImplementationDecl *IDecl,
+void RewriteObjC::SynthesizeIvarOffsetComputation(ObjCContainerDecl *IDecl,
ObjCIvarDecl *ivar,
std::string &Result) {
if (ivar->isBitField()) {
@@ -3807,9 +3882,7 @@
void RewriteObjC::SynthesizeMetaDataIntoBuffer(std::string &Result) {
int ClsDefCount = ClassImplementation.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 (int i = 0; i < ClsDefCount; i++)
RewriteObjCClassMetaData(ClassImplementation[i], Result);
Added: cfe/trunk/test/Rewriter/rewrite-property-attributes.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Rewriter/rewrite-property-attributes.mm?rev=97203&view=auto
==============================================================================
--- cfe/trunk/test/Rewriter/rewrite-property-attributes.mm (added)
+++ cfe/trunk/test/Rewriter/rewrite-property-attributes.mm Thu Feb 25 19:42:20 2010
@@ -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);
+
+ at interface Y {
+ void_block_t __completion;
+ Y* YVAR;
+ id ID;
+}
+ at property (copy) void_block_t completionBlock;
+ at property (retain) Y* Yblock;
+ at property (copy) id ID;
+ at end
+
+ at implementation Y
+ at synthesize completionBlock=__completion;
+ at synthesize Yblock = YVAR;
+ at synthesize ID;
+ at end
+
More information about the cfe-commits
mailing list