diff options
| author | Steve Naroff <snaroff@apple.com> | 2008-05-06 23:20:07 +0000 |
|---|---|---|
| committer | Steve Naroff <snaroff@apple.com> | 2008-05-06 23:20:07 +0000 |
| commit | 29ce4e5d78f781298dc4e6617fdbdd797362aef5 (patch) | |
| tree | a1d17084aa51fb076737dd06d8dd37058025fe8e | |
| parent | 51b2a1808471c95ef35f61842028be5b7c81fbf3 (diff) | |
| download | bcm5719-llvm-29ce4e5d78f781298dc4e6617fdbdd797362aef5.tar.gz bcm5719-llvm-29ce4e5d78f781298dc4e6617fdbdd797362aef5.zip | |
Fix <rdar://problem/5879237> clang objc rewriter: ivars not accessible in structure generated for class
llvm-svn: 50781
| -rw-r--r-- | clang/Driver/RewriteObjC.cpp | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/clang/Driver/RewriteObjC.cpp b/clang/Driver/RewriteObjC.cpp index e50ba667614..fc64b5d9123 100644 --- a/clang/Driver/RewriteObjC.cpp +++ b/clang/Driver/RewriteObjC.cpp @@ -850,9 +850,35 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { } } } else { // we are outside a method. - if (IV->isFreeIvar()) - assert(1 && "Cannot have a free standing ivar outside a method"); - // Explicit ivar refs do not need to be rewritten. Do nothing. + assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method"); + + // Explicit ivar refs need to have a cast inserted. + // FIXME: consider sharing some of this code with the code above. + if (const PointerType *pType = IV->getBase()->getType()->getAsPointerType()) { + ObjCInterfaceType *intT = dyn_cast<ObjCInterfaceType>(pType->getPointeeType()); + // lookup which class implements the instance variable. + ObjCInterfaceDecl *clsDeclared = 0; + intT->getDecl()->lookupInstanceVariable(D->getIdentifier(), clsDeclared); + assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); + + // Synthesize an explicit cast to gain access to the ivar. + std::string RecName = clsDeclared->getIdentifier()->getName(); + RecName += "_IMPL"; + IdentifierInfo *II = &Context->Idents.get(RecName.c_str()); + RecordDecl *RD = RecordDecl::Create(*Context, Decl::Struct, TUDecl, + SourceLocation(), II, 0); + assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); + QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); + CastExpr *castExpr = new CastExpr(castT, IV->getBase(), SourceLocation()); + // Don't forget the parens to enforce the proper binding. + ParenExpr *PE = new ParenExpr(SourceLocation(), SourceLocation(), castExpr); + ReplaceStmt(IV->getBase(), PE); + // Cannot delete IV->getBase(), since PE points to it. + // Replace the old base with the cast. This is important when doing + // embedded rewrites. For example, [newInv->_container addObject:0]. + IV->setBase(PE); + return IV; + } } return IV; } |

