From: Steve Naroff Date: Tue, 6 May 2008 23:20:07 +0000 (+0000) Subject: Fix clang objc rewriter: ivars not accessible in structure... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9f525970bec0e29f32cec6141aa3baa245c5ae82;p=clang Fix clang objc rewriter: ivars not accessible in structure generated for class git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50781 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Driver/RewriteObjC.cpp b/Driver/RewriteObjC.cpp index e50ba66761..fc64b5d912 100644 --- a/Driver/RewriteObjC.cpp +++ b/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(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; }