[cfe-commits] r44168 - /cfe/trunk/Driver/RewriteTest.cpp

Steve Naroff snaroff at apple.com
Thu Nov 15 02:28:21 PST 2007


Author: snaroff
Date: Thu Nov 15 04:28:18 2007
New Revision: 44168

URL: http://llvm.org/viewvc/llvm-project?rev=44168&view=rev
Log:

Rewrite for messaging 'super'.

The code gen. results in some spurious warnings...a cast is forthcoming.

Modified:
    cfe/trunk/Driver/RewriteTest.cpp

Modified: cfe/trunk/Driver/RewriteTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/RewriteTest.cpp?rev=44168&r1=44167&r2=44168&view=diff

==============================================================================
--- cfe/trunk/Driver/RewriteTest.cpp (original)
+++ cfe/trunk/Driver/RewriteTest.cpp Thu Nov 15 04:28:18 2007
@@ -20,6 +20,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "clang/Lex/Lexer.h"
+#include <sstream>
 using namespace clang;
 using llvm::utostr;
 
@@ -37,6 +38,7 @@
     llvm::DenseMap<ObjcMethodDecl*, std::string> MethodInternalNames;
     
     FunctionDecl *MsgSendFunctionDecl;
+    FunctionDecl *MsgSendSuperFunctionDecl;
     FunctionDecl *GetClassFunctionDecl;
     FunctionDecl *SelGetUidFunctionDecl;
     FunctionDecl *CFStringFunctionDecl;
@@ -45,6 +47,10 @@
     FileVarDecl *ConstantStringClassReference;
     RecordDecl *NSStringRecord;
     
+    // Needed for super.
+    ObjcMethodDecl *CurMethodDecl;
+    RecordDecl *SuperStructDecl;
+    
     static const int OBJC_ABI_VERSION =7 ;
   public:
     void Initialize(ASTContext &context, unsigned mainFileID) {
@@ -52,17 +58,24 @@
       SM = &Context->SourceMgr;
       MainFileID = mainFileID;
       MsgSendFunctionDecl = 0;
+      MsgSendSuperFunctionDecl = 0;
       GetClassFunctionDecl = 0;
       SelGetUidFunctionDecl = 0;
       CFStringFunctionDecl = 0;
       ConstantStringClassReference = 0;
       NSStringRecord = 0;
+      CurMethodDecl = 0;
+      SuperStructDecl = 0;
+      
       Rewrite.setSourceMgr(Context->SourceMgr);
       // declaring objc_selector outside the parameter list removes a silly
       // scope related warning...
       const char *s = "struct objc_selector; struct objc_class;\n"
                       "extern struct objc_object *objc_msgSend"
                       "(struct objc_object *, struct objc_selector *, ...);\n"
+                      "struct objc_super { struct objc_object *receiver; struct objc_class *super; };\n"
+                      "extern struct objc_object *objc_msgSendSuper"
+                      "(struct objc_super *, struct objc_selector *, ...);\n"
                       "extern struct objc_object *objc_getClass"
                       "(const char *);\n"
                       "extern void objc_exception_throw(struct objc_object *);\n"
@@ -99,6 +112,8 @@
     void RewriteObjcQualifiedInterfaceTypes(
         const FunctionTypeProto *proto, FunctionDecl *FD);
     bool needToScanForQualifiers(QualType T);
+    ObjcInterfaceDecl *isSuperReceiver(Expr *recExpr);
+    QualType getSuperStructType();
     
     // Expression Rewriting.
     Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
@@ -114,6 +129,7 @@
     CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD, 
                                            Expr **args, unsigned nargs);
     void SynthMsgSendFunctionDecl();
+    void SynthMsgSendSuperFunctionDecl();
     void SynthGetClassFunctionDecl();
     void SynthCFStringFunctionDecl();
       
@@ -197,8 +213,12 @@
       FD->setBody(RewriteFunctionBodyOrGlobalInitializer(Body));
 	  
   if (ObjcMethodDecl *MD = dyn_cast<ObjcMethodDecl>(D)) {
-    if (Stmt *Body = MD->getBody())
+    if (Stmt *Body = MD->getBody()) {
+      //Body->dump();
+      CurMethodDecl = MD;
       MD->setBody(RewriteFunctionBodyOrGlobalInitializer(Body));
+      CurMethodDecl = 0;
+    }
   }
   if (ObjcImplementationDecl *CI = dyn_cast<ObjcImplementationDecl>(D))
     ClassImplementation.push_back(CI);
@@ -631,7 +651,20 @@
 
   if (ObjcAtThrowStmt *StmtThrow = dyn_cast<ObjcAtThrowStmt>(S))
     return RewriteObjcThrowStmt(StmtThrow);
-    
+#if 0
+  if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
+    CastExpr *Replacement = new CastExpr(ICE->getType(), ICE->getSubExpr(), SourceLocation());
+    // Get the new text.
+    std::ostringstream Buf;
+    Replacement->printPretty(Buf);
+    const std::string &Str = Buf.str();
+
+    printf("CAST = %s\n", &Str[0]);
+    Rewrite.InsertText(ICE->getSubExpr()->getLocStart(), &Str[0], Str.size());
+    delete S;
+    return Replacement;
+  }
+#endif
   // Return this stmt unmodified.
   return S;
 }
@@ -954,6 +987,26 @@
                                          FunctionDecl::Extern, false, 0);
 }
 
+// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...);
+void RewriteTest::SynthMsgSendSuperFunctionDecl() {
+  IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper");
+  llvm::SmallVector<QualType, 16> ArgTys;
+  RecordDecl *RD = new RecordDecl(Decl::Struct, SourceLocation(),
+                                  &Context->Idents.get("objc_super"), 0);
+  QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
+  assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
+  ArgTys.push_back(argT);
+  argT = Context->getObjcSelType();
+  assert(!argT.isNull() && "Can't find 'SEL' type");
+  ArgTys.push_back(argT);
+  QualType msgSendType = Context->getFunctionType(Context->getObjcIdType(),
+                                                  &ArgTys[0], ArgTys.size(),
+                                                  true /*isVariadic*/);
+  MsgSendSuperFunctionDecl = new FunctionDecl(SourceLocation(), 
+                                              msgSendIdent, msgSendType,
+                                              FunctionDecl::Extern, false, 0);
+}
+
 // SynthGetClassFunctionDecl - id objc_getClass(const char *name);
 void RewriteTest::SynthGetClassFunctionDecl() {
   IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");
@@ -1038,13 +1091,62 @@
 #endif
 }
 
+ObjcInterfaceDecl *RewriteTest::isSuperReceiver(Expr *recExpr) {
+  if (CurMethodDecl) { // check if we are sending a message to 'super'
+    if (CastExpr *CE = dyn_cast<CastExpr>(recExpr)) {
+      if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr())) {
+        if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
+          if (!strcmp(PVD->getName(), "self")) {
+            if (const PointerType *PT = CE->getType()->getAsPointerType()) {
+              if (ObjcInterfaceType *IT = 
+                    dyn_cast<ObjcInterfaceType>(PT->getPointeeType())) {
+                if (IT->getDecl() == 
+                    CurMethodDecl->getClassInterface()->getSuperClass())
+                  return IT->getDecl();
+              }
+            }
+          }
+        }
+      }
+    } 
+  }
+  return 0;
+}
+
+// struct objc_super { struct objc_object *receiver; struct objc_class *super; };
+QualType RewriteTest::getSuperStructType() {
+  if (!SuperStructDecl) {
+    SuperStructDecl = new RecordDecl(Decl::Struct, SourceLocation(), 
+                                     &Context->Idents.get("objc_super"), 0);
+    QualType FieldTypes[2];
+  
+    // struct objc_object *receiver;
+    FieldTypes[0] = Context->getObjcIdType();  
+    // struct objc_class *super;
+    FieldTypes[1] = Context->getObjcClassType();  
+    // Create fields
+    FieldDecl *FieldDecls[2];
+  
+    for (unsigned i = 0; i < 2; ++i)
+      FieldDecls[i] = new FieldDecl(SourceLocation(), 0, FieldTypes[i]);
+  
+    SuperStructDecl->defineBody(FieldDecls, 4);
+  }
+  return Context->getTagDeclType(SuperStructDecl);
+}
+
 Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
   assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");
   if (!MsgSendFunctionDecl)
     SynthMsgSendFunctionDecl();
+  if (!MsgSendSuperFunctionDecl)
+    SynthMsgSendSuperFunctionDecl();
   if (!GetClassFunctionDecl)
     SynthGetClassFunctionDecl();
 
+  // default to objc_msgSend().
+  FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; 
+  
   // Synthesize a call to objc_msgSend().
   llvm::SmallVector<Expr*, 8> MsgExprs;
   IdentifierInfo *clsName = Exp->getClassName();
@@ -1062,9 +1164,40 @@
     MsgExprs.push_back(Cls);
   } else { // instance message.
     Expr *recExpr = Exp->getReceiver();
-    
-    recExpr = new CastExpr(Context->getObjcIdType(), recExpr, SourceLocation());
-    MsgExprs.push_back(recExpr);
+
+    if (ObjcInterfaceDecl *ID = isSuperReceiver(recExpr)) {
+      MsgSendFlavor = MsgSendSuperFunctionDecl;
+      assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
+      
+      llvm::SmallVector<Expr*, 4> InitExprs;
+      
+      InitExprs.push_back(recExpr); // set the 'receiver'.
+      
+      llvm::SmallVector<Expr*, 8> ClsExprs;
+      QualType argType = Context->getPointerType(Context->CharTy);
+      ClsExprs.push_back(new StringLiteral(ID->getIdentifier()->getName(), 
+                                           ID->getIdentifier()->getLength(),
+                                           false, argType, SourceLocation(),
+                                           SourceLocation()));
+      CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
+                                                   &ClsExprs[0], ClsExprs.size());
+      InitExprs.push_back(Cls); // set 'super class', using objc_getClass().
+      // struct objc_super
+      QualType superType = getSuperStructType();
+      // (struct objc_super) { <exprs from above> }
+      InitListExpr *ILE = new InitListExpr(SourceLocation(), 
+                                           &InitExprs[0], InitExprs.size(), 
+                                           SourceLocation());
+      CompoundLiteralExpr *SuperRep = new CompoundLiteralExpr(superType, ILE);
+      // struct objc_super *
+      Expr *Unop = new UnaryOperator(SuperRep, UnaryOperator::AddrOf,
+                               Context->getPointerType(SuperRep->getType()), 
+                               SourceLocation());
+      MsgExprs.push_back(Unop);
+    } else {
+      recExpr = new CastExpr(Context->getObjcIdType(), recExpr, SourceLocation());
+      MsgExprs.push_back(recExpr);
+    }
   }
   // Create a call to sel_registerName("selName"), it will be the 2nd argument.
   llvm::SmallVector<Expr*, 8> SelExprs;
@@ -1109,10 +1242,10 @@
     returnType = Context->getObjcIdType();
   }
   // Get the type, we will need to reference it in a couple spots.
-  QualType msgSendType = MsgSendFunctionDecl->getType();
+  QualType msgSendType = MsgSendFlavor->getType();
   
   // Create a reference to the objc_msgSend() declaration.
-  DeclRefExpr *DRE = new DeclRefExpr(MsgSendFunctionDecl, msgSendType, SourceLocation());
+  DeclRefExpr *DRE = new DeclRefExpr(MsgSendFlavor, msgSendType, SourceLocation());
 
   // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid). 
   // If we don't do this cast, we get the following bizarre warning/note:





More information about the cfe-commits mailing list