]> granicus.if.org Git - clang/commitdiff
Fix <rdar://problem/5879237> clang objc rewriter: ivars not accessible in structure...
authorSteve Naroff <snaroff@apple.com>
Tue, 6 May 2008 23:20:07 +0000 (23:20 +0000)
committerSteve Naroff <snaroff@apple.com>
Tue, 6 May 2008 23:20:07 +0000 (23:20 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50781 91177308-0d34-0410-b5e6-96231b3b80d8

Driver/RewriteObjC.cpp

index e50ba66761434ba64c3f3033ec06ef8d1bee6dae..fc64b5d9123c4e94f47d0b0e000b37d84629e31c 100644 (file)
@@ -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;
 }