summaryrefslogtreecommitdiffstats
path: root/lib/Frontend/RewriteObjC.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Frontend/RewriteObjC.cpp')
-rw-r--r--lib/Frontend/RewriteObjC.cpp312
1 files changed, 235 insertions, 77 deletions
diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp
index 710fa55..df85c13 100644
--- a/lib/Frontend/RewriteObjC.cpp
+++ b/lib/Frontend/RewriteObjC.cpp
@@ -255,7 +255,10 @@ namespace {
Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);
- void WarnAboutReturnGotoContinueOrBreakStmts(Stmt *S);
+ void WarnAboutReturnGotoStmts(Stmt *S);
+ void HasReturnStmts(Stmt *S, bool &hasReturns);
+ void RewriteTryReturnStmts(Stmt *S);
+ void RewriteSyncReturnStmts(Stmt *S, std::string buf);
Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);
Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);
Stmt *RewriteObjCCatchStmt(ObjCAtCatchStmt *S);
@@ -328,11 +331,16 @@ namespace {
const char *funcName, std::string Tag);
std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
const char *funcName, std::string Tag);
- std::string SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
- bool hasCopyDisposeHelpers);
+ std::string SynthesizeBlockImpl(BlockExpr *CE,
+ std::string Tag, std::string Desc);
+ std::string SynthesizeBlockDescriptor(std::string DescTag,
+ std::string ImplTag,
+ int i, const char *funcName,
+ unsigned hasCopy);
Stmt *SynthesizeBlockCall(CallExpr *Exp);
void SynthesizeBlockLiterals(SourceLocation FunLocStart,
const char *FunName);
+ void RewriteRecordBody(RecordDecl *RD);
void CollectBlockDeclRefInfo(BlockExpr *Exp);
void GetBlockCallExprs(Stmt *S);
@@ -547,14 +555,21 @@ void RewriteObjC::Initialize(ASTContext &context) {
Preamble += "struct __block_impl {\n";
Preamble += " void *isa;\n";
Preamble += " int Flags;\n";
- Preamble += " int Size;\n";
+ Preamble += " int Reserved;\n";
Preamble += " void *FuncPtr;\n";
Preamble += "};\n";
Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";
- Preamble += "__OBJC_RW_STATICIMPORT void _Block_object_assign(void *, const void *, const int);\n";
- Preamble += "__OBJC_RW_STATICIMPORT void _Block_object_dispose(const void *, const int);\n";
- Preamble += "__OBJC_RW_STATICIMPORT void *_NSConcreteGlobalBlock[32];\n";
- Preamble += "__OBJC_RW_STATICIMPORT void *_NSConcreteStackBlock[32];\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_dispose(const void *, const int);\n";
+ Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
+ Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
+ Preamble += "#else\n";
+ Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
+ Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
+ Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
+ Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
+ Preamble += "#endif\n";
Preamble += "#endif\n";
if (LangOpts.Microsoft) {
Preamble += "#undef __OBJC_RW_DLLIMPORT\n";
@@ -1325,7 +1340,12 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
// type elem;
NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());
QualType ElementType = cast<ValueDecl>(D)->getType();
- elementTypeAsString = ElementType.getAsString();
+ if (ElementType->isObjCQualifiedIdType() ||
+ ElementType->isObjCQualifiedInterfaceType())
+ // Simply use 'id' for all qualified types.
+ elementTypeAsString = "id";
+ else
+ elementTypeAsString = ElementType.getAsString();
buf += elementTypeAsString;
buf += " ";
elementName = D->getNameAsCString();
@@ -1335,8 +1355,13 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
else {
DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());
elementName = DR->getDecl()->getNameAsCString();
- elementTypeAsString
- = cast<ValueDecl>(DR->getDecl())->getType().getAsString();
+ ValueDecl *VD = cast<ValueDecl>(DR->getDecl());
+ if (VD->getType()->isObjCQualifiedIdType() ||
+ VD->getType()->isObjCQualifiedInterfaceType())
+ // Simply use 'id' for all qualified types.
+ elementTypeAsString = "id";
+ else
+ elementTypeAsString = VD->getType().getAsString();
}
// struct __objcFastEnumerationState enumState = { 0 };
@@ -1502,7 +1527,9 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
buf += "}\n";
buf += "{ /* implicit finally clause */\n";
buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
- buf += " objc_sync_exit(";
+
+ std::string syncBuf;
+ syncBuf += " objc_sync_exit(";
Expr *syncExpr = new (Context) CStyleCastExpr(Context->getObjCIdType(),
CastExpr::CK_Unknown,
S->getSynchExpr(),
@@ -1513,31 +1540,102 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
llvm::raw_string_ostream syncExprBuf(syncExprBufS);
syncExpr->printPretty(syncExprBuf, *Context, 0,
PrintingPolicy(LangOpts));
- buf += syncExprBuf.str();
- buf += ");\n";
- buf += " if (_rethrow) objc_exception_throw(_rethrow);\n";
+ syncBuf += syncExprBuf.str();
+ syncBuf += ");";
+
+ buf += syncBuf;
+ buf += "\n if (_rethrow) objc_exception_throw(_rethrow);\n";
buf += "}\n";
buf += "}";
ReplaceText(lastCurlyLoc, 1, buf.c_str(), buf.size());
+
+ bool hasReturns = false;
+ HasReturnStmts(S->getSynchBody(), hasReturns);
+ if (hasReturns)
+ RewriteSyncReturnStmts(S->getSynchBody(), syncBuf);
+
return 0;
}
-void RewriteObjC::WarnAboutReturnGotoContinueOrBreakStmts(Stmt *S) {
+void RewriteObjC::WarnAboutReturnGotoStmts(Stmt *S)
+{
// Perform a bottom up traversal of all children.
for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
CI != E; ++CI)
if (*CI)
- WarnAboutReturnGotoContinueOrBreakStmts(*CI);
+ WarnAboutReturnGotoStmts(*CI);
- if (isa<ReturnStmt>(S) || isa<ContinueStmt>(S) ||
- isa<BreakStmt>(S) || isa<GotoStmt>(S)) {
+ if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
Diags.Report(Context->getFullLoc(S->getLocStart()),
TryFinallyContainsReturnDiag);
}
return;
}
+void RewriteObjC::HasReturnStmts(Stmt *S, bool &hasReturns)
+{
+ // Perform a bottom up traversal of all children.
+ for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
+ CI != E; ++CI)
+ if (*CI)
+ HasReturnStmts(*CI, hasReturns);
+
+ if (isa<ReturnStmt>(S))
+ hasReturns = true;
+ return;
+}
+
+void RewriteObjC::RewriteTryReturnStmts(Stmt *S) {
+ // Perform a bottom up traversal of all children.
+ for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
+ CI != E; ++CI)
+ if (*CI) {
+ RewriteTryReturnStmts(*CI);
+ }
+ if (isa<ReturnStmt>(S)) {
+ SourceLocation startLoc = S->getLocStart();
+ const char *startBuf = SM->getCharacterData(startLoc);
+
+ const char *semiBuf = strchr(startBuf, ';');
+ assert((*semiBuf == ';') && "RewriteTryReturnStmts: can't find ';'");
+ SourceLocation onePastSemiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf+1);
+
+ std::string buf;
+ buf = "{ objc_exception_try_exit(&_stack); return";
+
+ ReplaceText(startLoc, 6, buf.c_str(), buf.size());
+ InsertText(onePastSemiLoc, "}", 1);
+ }
+ return;
+}
+
+void RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) {
+ // Perform a bottom up traversal of all children.
+ for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
+ CI != E; ++CI)
+ if (*CI) {
+ RewriteSyncReturnStmts(*CI, syncExitBuf);
+ }
+ if (isa<ReturnStmt>(S)) {
+ SourceLocation startLoc = S->getLocStart();
+ const char *startBuf = SM->getCharacterData(startLoc);
+
+ const char *semiBuf = strchr(startBuf, ';');
+ assert((*semiBuf == ';') && "RewriteSyncReturnStmts: can't find ';'");
+ SourceLocation onePastSemiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf+1);
+
+ std::string buf;
+ buf = "{ objc_exception_try_exit(&_stack);";
+ buf += syncExitBuf;
+ buf += " return";
+
+ ReplaceText(startLoc, 6, buf.c_str(), buf.size());
+ InsertText(onePastSemiLoc, "}", 1);
+ }
+ return;
+}
+
Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
// Get the start location and compute the semi location.
SourceLocation startLoc = S->getLocStart();
@@ -1689,13 +1787,21 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
lastCurlyLoc = body->getLocEnd();
// Now check for any return/continue/go statements within the @try.
- WarnAboutReturnGotoContinueOrBreakStmts(S->getTryBody());
+ WarnAboutReturnGotoStmts(S->getTryBody());
} else { /* no finally clause - make sure we synthesize an implicit one */
buf = "{ /* implicit finally clause */\n";
buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
buf += " if (_rethrow) objc_exception_throw(_rethrow);\n";
buf += "}";
ReplaceText(lastCurlyLoc, 1, buf.c_str(), buf.size());
+
+ // Now check for any return/continue/go statements within the @try.
+ // The implicit finally clause won't called if the @try contains any
+ // jump statements.
+ bool hasReturns = false;
+ HasReturnStmts(S->getTryBody(), hasReturns);
+ if (hasReturns)
+ RewriteTryReturnStmts(S->getTryBody());
}
// Now emit the final closing curly brace...
lastCurlyLoc = lastCurlyLoc.getFileLocWithOffset(1);
@@ -1878,6 +1984,10 @@ void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) {
return;
Type = proto->getResultType();
}
+ else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {
+ Loc = FD->getLocation();
+ Type = FD->getType();
+ }
else
return;
@@ -2134,8 +2244,7 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
PrintingPolicy(LangOpts));
Preamble += prettyBuf.str();
Preamble += ",";
- // The minus 2 removes the begin/end double quotes.
- Preamble += utostr(prettyBuf.str().size()-2) + "};\n";
+ Preamble += utostr(Exp->getString()->getByteLength()) + "};\n";
VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
&Context->Idents.get(S.c_str()), strType, 0,
@@ -2569,7 +2678,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
// Build sizeof(returnType)
SizeOfAlignOfExpr *sizeofExpr = new (Context) SizeOfAlignOfExpr(true,
- Context->getTrivialDeclaratorInfo(returnType),
+ Context->getTrivialTypeSourceInfo(returnType),
Context->getSizeType(),
SourceLocation(), SourceLocation());
// (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
@@ -2609,12 +2718,12 @@ Stmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {
// typedef struct objc_object Protocol;
QualType RewriteObjC::getProtocolType() {
if (!ProtocolTypeDecl) {
- DeclaratorInfo *DInfo
- = Context->getTrivialDeclaratorInfo(Context->getObjCIdType());
+ TypeSourceInfo *TInfo
+ = Context->getTrivialTypeSourceInfo(Context->getObjCIdType());
ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl,
SourceLocation(),
&Context->Idents.get("Protocol"),
- DInfo);
+ TInfo);
}
return Context->getTypeDeclType(ProtocolTypeDecl);
}
@@ -2737,7 +2846,7 @@ void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl,
ReplaceText(LocStart, endHeader-startBuf, Result.c_str(), Result.size());
} else {
// rewrite the original header *without* disturbing the '{'
- ReplaceText(LocStart, cursor-startBuf-1, Result.c_str(), Result.size());
+ ReplaceText(LocStart, cursor-startBuf, Result.c_str(), Result.size());
}
if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {
Result = "\n struct ";
@@ -3689,20 +3798,18 @@ std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
return S;
}
-std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
- bool hasCopyDisposeHelpers) {
+std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
+ std::string Desc) {
std::string S = "\nstruct " + Tag;
std::string Constructor = " " + Tag;
S += " {\n struct __block_impl impl;\n";
+ S += " struct " + Desc;
+ S += "* Desc;\n";
- if (hasCopyDisposeHelpers)
- S += " void *copy;\n void *dispose;\n";
-
- Constructor += "(void *fp";
-
- if (hasCopyDisposeHelpers)
- Constructor += ", void *copyHelp, void *disposeHelp";
+ Constructor += "(void *fp, "; // Invoke function pointer.
+ Constructor += "struct " + Desc; // Descriptor pointer.
+ Constructor += " *desc";
if (BlockDeclRefs.size()) {
// Output all "by copy" declarations.
@@ -3765,11 +3872,9 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";
else
Constructor += " impl.isa = &_NSConcreteStackBlock;\n";
- Constructor += " impl.Size = sizeof(";
- Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n";
+ Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";
- if (hasCopyDisposeHelpers)
- Constructor += " copy = copyHelp;\n dispose = disposeHelp;\n";
+ Constructor += " Desc = desc;\n";
// Initialize all "by copy" arguments.
for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
@@ -3800,10 +3905,8 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";
else
Constructor += " impl.isa = &_NSConcreteStackBlock;\n";
- Constructor += " impl.Size = sizeof(";
- Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n";
- if (hasCopyDisposeHelpers)
- Constructor += " copy = copyHelp;\n dispose = disposeHelp;\n";
+ Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";
+ Constructor += " Desc = desc;\n";
}
Constructor += " ";
Constructor += "}\n";
@@ -3812,6 +3915,29 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
return S;
}
+std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag,
+ std::string ImplTag, int i,
+ const char *FunName,
+ unsigned hasCopy) {
+ std::string S = "\nstatic struct " + DescTag;
+
+ S += " {\n unsigned long reserved;\n";
+ S += " unsigned long Block_size;\n";
+ if (hasCopy) {
+ S += " void *copy;\n void *dispose;\n";
+ }
+ S += "} ";
+
+ S += DescTag + "_DATA = { 0, sizeof(struct ";
+ S += ImplTag + ")";
+ if (hasCopy) {
+ S += ", __" + std::string(FunName) + "_block_copy_" + utostr(i);
+ S += ", __" + std::string(FunName) + "_block_dispose_" + utostr(i);
+ }
+ S += "};\n";
+ return S;
+}
+
void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
const char *FunName) {
// Insert closures that were part of the function.
@@ -3819,21 +3945,24 @@ void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
CollectBlockDeclRefInfo(Blocks[i]);
- std::string Tag = "__" + std::string(FunName) + "_block_impl_" + utostr(i);
+ std::string ImplTag = "__" + std::string(FunName) + "_block_impl_" + utostr(i);
+ std::string DescTag = "__" + std::string(FunName) + "_block_desc_" + utostr(i);
- std::string CI = SynthesizeBlockImpl(Blocks[i], Tag,
- ImportedBlockDecls.size() > 0);
+ std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);
InsertText(FunLocStart, CI.c_str(), CI.size());
- std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, Tag);
+ std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);
InsertText(FunLocStart, CF.c_str(), CF.size());
if (ImportedBlockDecls.size()) {
- std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, Tag);
+ std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);
InsertText(FunLocStart, HF.c_str(), HF.size());
}
+ std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,
+ ImportedBlockDecls.size() > 0);
+ InsertText(FunLocStart, BD.c_str(), BD.size());
BlockDeclRefs.clear();
BlockByRefDecls.clear();
@@ -4243,25 +4372,21 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) {
SourceLocation());
InitExprs.push_back(castExpr);
- if (ImportedBlockDecls.size()) {
- std::string Buf = "__" + FuncName + "_block_copy_" + BlockNumber;
- FD = SynthBlockInitFunctionDecl(Buf.c_str());
- Arg = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation());
- castExpr = new (Context) CStyleCastExpr(Context->VoidPtrTy,
- CastExpr::CK_Unknown, Arg,
- Context->VoidPtrTy, SourceLocation(),
- SourceLocation());
- InitExprs.push_back(castExpr);
-
- Buf = "__" + FuncName + "_block_dispose_" + BlockNumber;
- FD = SynthBlockInitFunctionDecl(Buf.c_str());
- Arg = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation());
- castExpr = new (Context) CStyleCastExpr(Context->VoidPtrTy,
- CastExpr::CK_Unknown, Arg,
- Context->VoidPtrTy, SourceLocation(),
- SourceLocation());
- InitExprs.push_back(castExpr);
- }
+ // Initialize the block descriptor.
+ std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA";
+
+ VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
+ &Context->Idents.get(DescData.c_str()),
+ Context->VoidPtrTy, 0,
+ VarDecl::Static);
+ UnaryOperator *DescRefExpr = new (Context) UnaryOperator(
+ new (Context) DeclRefExpr(NewVD,
+ Context->VoidPtrTy, SourceLocation()),
+ UnaryOperator::AddrOf,
+ Context->getPointerType(Context->VoidPtrTy),
+ SourceLocation());
+ InitExprs.push_back(DescRefExpr);
+
// Add initializers for any closure decl refs.
if (BlockDeclRefs.size()) {
Expr *Exp;
@@ -4297,6 +4422,17 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) {
InitExprs.push_back(Exp);
}
}
+ if (ImportedBlockDecls.size()) { // generate "1<<25" to indicate we have helper functions.
+ unsigned IntSize =
+ static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
+ BinaryOperator *Exp = new (Context) BinaryOperator(
+ new (Context) IntegerLiteral(llvm::APInt(IntSize, 1),
+ Context->IntTy,SourceLocation()),
+ new (Context) IntegerLiteral(llvm::APInt(IntSize, 25),
+ Context->IntTy, SourceLocation()),
+ BinaryOperator::Shl, Context->IntTy, SourceLocation());
+ InitExprs.push_back(Exp);
+ }
NewRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], InitExprs.size(),
FType, SourceLocation());
NewRep = new (Context) UnaryOperator(NewRep, UnaryOperator::AddrOf,
@@ -4486,7 +4622,14 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
// FIXME: What we're doing here is modifying the type-specifier that
// precedes the first Decl. In the future the DeclGroup should have
// a separate type-specifier that we can rewrite.
- RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());
+ // NOTE: We need to avoid rewriting the DeclStmt if it is within
+ // the context of an ObjCForCollectionStmt. For example:
+ // NSArray *someArray;
+ // for (id <FooProtocol> index in someArray) ;
+ // This is because RewriteObjCForCollectionStmt() does textual rewriting
+ // and it depends on the original text locations/positions.
+ if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
+ RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());
// Blocks rewrite rules.
for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
@@ -4552,6 +4695,18 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
return S;
}
+void RewriteObjC::RewriteRecordBody(RecordDecl *RD) {
+ for (RecordDecl::field_iterator i = RD->field_begin(),
+ e = RD->field_end(); i != e; ++i) {
+ FieldDecl *FD = *i;
+ if (isTopLevelBlockPointerType(FD->getType()))
+ RewriteBlockPointerDecl(FD);
+ if (FD->getType()->isObjCQualifiedIdType() ||
+ FD->getType()->isObjCQualifiedInterfaceType())
+ RewriteObjCQualifiedInterfaceTypes(FD);
+ }
+}
+
/// HandleDeclInMainFile - This is called for each top-level decl defined in the
/// main file of the input.
void RewriteObjC::HandleDeclInMainFile(Decl *D) {
@@ -4618,6 +4773,10 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) {
RewriteCastExpr(CE);
}
}
+ } else if (VD->getType()->isRecordType()) {
+ RecordDecl *RD = VD->getType()->getAs<RecordType>()->getDecl();
+ if (RD->isDefinition())
+ RewriteRecordBody(RD);
}
if (VD->getInit()) {
GlobalVarDecl = VD;
@@ -4645,17 +4804,16 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) {
RewriteBlockPointerDecl(TD);
else if (TD->getUnderlyingType()->isFunctionPointerType())
CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
+ else if (TD->getUnderlyingType()->isRecordType()) {
+ RecordDecl *RD = TD->getUnderlyingType()->getAs<RecordType>()->getDecl();
+ if (RD->isDefinition())
+ RewriteRecordBody(RD);
+ }
return;
}
if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
- if (RD->isDefinition()) {
- for (RecordDecl::field_iterator i = RD->field_begin(),
- e = RD->field_end(); i != e; ++i) {
- FieldDecl *FD = *i;
- if (isTopLevelBlockPointerType(FD->getType()))
- RewriteBlockPointerDecl(FD);
- }
- }
+ if (RD->isDefinition())
+ RewriteRecordBody(RD);
return;
}
// Nothing yet.
OpenPOWER on IntegriCloud