[cfe-commits] r44673 - in /cfe/trunk: Driver/RewriteTest.cpp Sema/SemaDecl.cpp Sema/SemaExpr.cpp include/clang/AST/DeclObjC.h

Steve Naroff snaroff at apple.com
Thu Dec 6 19:50:46 PST 2007


Author: snaroff
Date: Thu Dec  6 21:50:46 2007
New Revision: 44673

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

Rewrite 'super' within a class method. This required some minor tweaks to the front-end.


Modified:
    cfe/trunk/Driver/RewriteTest.cpp
    cfe/trunk/Sema/SemaDecl.cpp
    cfe/trunk/Sema/SemaExpr.cpp
    cfe/trunk/include/clang/AST/DeclObjC.h

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

==============================================================================
--- cfe/trunk/Driver/RewriteTest.cpp (original)
+++ cfe/trunk/Driver/RewriteTest.cpp Thu Dec  6 21:50:46 2007
@@ -47,6 +47,7 @@
     FunctionDecl *MsgSendSuperStretFunctionDecl;
     FunctionDecl *MsgSendFpretFunctionDecl;
     FunctionDecl *GetClassFunctionDecl;
+    FunctionDecl *GetMetaClassFunctionDecl;
     FunctionDecl *SelGetUidFunctionDecl;
     FunctionDecl *CFStringFunctionDecl;
       
@@ -69,6 +70,7 @@
       MsgSendSuperStretFunctionDecl = 0;
       MsgSendFpretFunctionDecl = 0;
       GetClassFunctionDecl = 0;
+      GetMetaClassFunctionDecl = 0;
       SelGetUidFunctionDecl = 0;
       CFStringFunctionDecl = 0;
       ConstantStringClassReference = 0;
@@ -103,6 +105,8 @@
                       "(struct objc_object *, struct objc_selector *, ...);\n"
                       "extern struct objc_object *objc_getClass"
                       "(const char *);\n"
+                      "extern struct objc_object *objc_getMetaClass"
+                      "(const char *);\n"
                       "extern void objc_exception_throw(struct objc_object *);\n"
                       "extern void objc_exception_try_enter(void *);\n"
                       "extern void objc_exception_try_exit(void *);\n"
@@ -160,6 +164,7 @@
     void SynthMsgSendFpretFunctionDecl();
     void SynthMsgSendSuperStretFunctionDecl();
     void SynthGetClassFunctionDecl();
+    void SynthGetMetaClassFunctionDecl();
     void SynthCFStringFunctionDecl();
     void SynthSelGetUidFunctionDecl();
       
@@ -1155,6 +1160,20 @@
                                           FunctionDecl::Extern, false, 0);
 }
 
+// SynthGetMetaClassFunctionDecl - id objc_getClass(const char *name);
+void RewriteTest::SynthGetMetaClassFunctionDecl() {
+  IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");
+  llvm::SmallVector<QualType, 16> ArgTys;
+  ArgTys.push_back(Context->getPointerType(
+                     Context->CharTy.getQualifiedType(QualType::Const)));
+  QualType getClassType = Context->getFunctionType(Context->getObjcIdType(),
+                                                   &ArgTys[0], ArgTys.size(),
+                                                   false /*isVariadic*/);
+  GetMetaClassFunctionDecl = new FunctionDecl(SourceLocation(), 
+                                              getClassIdent, getClassType,
+                                              FunctionDecl::Extern, false, 0);
+}
+
 // SynthCFStringFunctionDecl - id __builtin___CFStringMakeConstantString(const char *name);
 void RewriteTest::SynthCFStringFunctionDecl() {
   IdentifierInfo *getClassIdent = &Context->Idents.get("__builtin___CFStringMakeConstantString");
@@ -1226,7 +1245,8 @@
 }
 
 ObjcInterfaceDecl *RewriteTest::isSuperReceiver(Expr *recExpr) {
-  if (CurMethodDecl) { // check if we are sending a message to 'super'
+  // check if we are sending a message to 'super'
+  if (CurMethodDecl && CurMethodDecl->isInstance()) {
     if (CastExpr *CE = dyn_cast<CastExpr>(recExpr)) {
       if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr())) {
         if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
@@ -1242,7 +1262,7 @@
           }
         }
       }
-    } 
+    }
   }
   return 0;
 }
@@ -1284,6 +1304,8 @@
     SynthMsgSendFpretFunctionDecl();
   if (!GetClassFunctionDecl)
     SynthGetClassFunctionDecl();
+  if (!GetMetaClassFunctionDecl)
+    SynthGetMetaClassFunctionDecl();
   
   // default to objc_msgSend().
   FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
@@ -1304,19 +1326,62 @@
   
   // Derive/push the receiver/selector, 2 implicit arguments to objc_msgSend().
   if (clsName) { // class message.
-    llvm::SmallVector<Expr*, 8> ClsExprs;
-    QualType argType = Context->getPointerType(Context->CharTy);
-    ClsExprs.push_back(new StringLiteral(clsName->getName(), 
-                                         clsName->getLength(),
-                                         false, argType, SourceLocation(),
-                                         SourceLocation()));
-    CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
-                                                 &ClsExprs[0], ClsExprs.size());
-    MsgExprs.push_back(Cls);
+    if (!strcmp(clsName->getName(), "super")) {
+      MsgSendFlavor = MsgSendSuperFunctionDecl;
+      if (MsgSendStretFlavor)
+        MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
+      assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
+      
+      ObjcInterfaceDecl *SuperDecl = 
+        CurMethodDecl->getClassInterface()->getSuperClass();
+
+      llvm::SmallVector<Expr*, 4> InitExprs;
+      
+      // set the receiver to self, the first argument to all methods.
+      InitExprs.push_back(new DeclRefExpr(CurMethodDecl->getSelfDecl(), 
+                                          Context->getObjcIdType(),
+                                          SourceLocation())); 
+      llvm::SmallVector<Expr*, 8> ClsExprs;
+      QualType argType = Context->getPointerType(Context->CharTy);
+      ClsExprs.push_back(new StringLiteral(SuperDecl->getIdentifier()->getName(), 
+                                           SuperDecl->getIdentifier()->getLength(),
+                                           false, argType, SourceLocation(),
+                                           SourceLocation()));
+      CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
+                                                   &ClsExprs[0], 
+                                                   ClsExprs.size());
+      // To turn off a warning, type-cast to 'id'
+      InitExprs.push_back(
+        new CastExpr(Context->getObjcIdType(), 
+        Cls, SourceLocation())); // 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 {
+      llvm::SmallVector<Expr*, 8> ClsExprs;
+      QualType argType = Context->getPointerType(Context->CharTy);
+      ClsExprs.push_back(new StringLiteral(clsName->getName(), 
+                                           clsName->getLength(),
+                                           false, argType, SourceLocation(),
+                                           SourceLocation()));
+      CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
+                                                   &ClsExprs[0], 
+                                                   ClsExprs.size());
+      MsgExprs.push_back(Cls);
+    }
   } else { // instance message.
     Expr *recExpr = Exp->getReceiver();
 
-    if (ObjcInterfaceDecl *ID = isSuperReceiver(recExpr)) {
+    if (ObjcInterfaceDecl *SuperDecl = isSuperReceiver(recExpr)) {
       MsgSendFlavor = MsgSendSuperFunctionDecl;
       if (MsgSendStretFlavor)
         MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
@@ -1330,8 +1395,8 @@
       
       llvm::SmallVector<Expr*, 8> ClsExprs;
       QualType argType = Context->getPointerType(Context->CharTy);
-      ClsExprs.push_back(new StringLiteral(ID->getIdentifier()->getName(), 
-                                           ID->getIdentifier()->getLength(),
+      ClsExprs.push_back(new StringLiteral(SuperDecl->getIdentifier()->getName(), 
+                                           SuperDecl->getIdentifier()->getLength(),
                                            false, argType, SourceLocation(),
                                            SourceLocation()));
       CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,

Modified: cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaDecl.cpp?rev=44673&r1=44672&r2=44673&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Thu Dec  6 21:50:46 2007
@@ -977,7 +977,7 @@
     PI.TypeInfo = selfTy.getAsOpaquePtr();
   } else
     PI.TypeInfo = Context.getObjcIdType().getAsOpaquePtr();
-  ActOnParamDeclarator(PI, FnBodyScope);
+  CurMethodDecl->setSelfDecl(ActOnParamDeclarator(PI, FnBodyScope));
   
   PI.Ident = &Context.Idents.get("_cmd");
   PI.TypeInfo = Context.getObjcSelType().getAsOpaquePtr();

Modified: cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaExpr.cpp?rev=44673&r1=44672&r2=44673&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/Sema/SemaExpr.cpp Thu Dec  6 21:50:46 2007
@@ -2140,23 +2140,24 @@
   if (!strcmp(receiverName->getName(), "super") && CurMethodDecl) {
     ClassDecl = CurMethodDecl->getClassInterface()->getSuperClass();
     if (ClassDecl && CurMethodDecl->isInstance()) {
+      // Synthesize a cast to the super class. This hack allows us to loosely
+      // represent super without creating a special expression node.
       IdentifierInfo &II = Context.Idents.get("self");
-      ExprResult ReceiverExpr = ActOnIdentifierExpr(S, lbrac, II, 
-                                                    false);
+      ExprResult ReceiverExpr = ActOnIdentifierExpr(S, lbrac, II, false);
       QualType superTy = Context.getObjcInterfaceType(ClassDecl);
       superTy = Context.getPointerType(superTy);
       ReceiverExpr = ActOnCastExpr(SourceLocation(), superTy.getAsOpaquePtr(),
                                    SourceLocation(), ReceiverExpr.Val);
-      
+      // We are really in an instance method, redirect.
       return ActOnInstanceMessage(ReceiverExpr.Val, Sel, lbrac, rbrac,
                                   Args, NumArgs);
     }
-    // class method
-    if (ClassDecl)
-      receiverName = ClassDecl->getIdentifier();
-  }
-  else
+    // We are sending a message to 'super' within a class method. Do nothing,
+    // the receiver will pass through as 'super' (how convenient:-).
+  } else
     ClassDecl = getObjCInterfaceDecl(receiverName);
+  
+  // FIXME: can ClassDecl ever be null?
   ObjcMethodDecl *Method = ClassDecl->lookupClassMethod(Sel);
   QualType returnType;
   

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=44673&r1=44672&r2=44673&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Thu Dec  6 21:50:46 2007
@@ -650,9 +650,12 @@
   /// List of attributes for this method declaration.
   AttributeList *MethodAttrs;
   
-  Stmt *Body;  // Null if a prototype.
-  
   SourceLocation EndLoc; // the location of the ';' or '{'.
+  
+  // The following are only used for method definitions, null otherwise.
+  // FIXME: space savings opportunity, consider a sub-class.
+  Stmt *Body;
+  ParmVarDecl *SelfDecl;
 public:
   ObjcMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
                  Selector SelInfo, QualType T,
@@ -668,7 +671,7 @@
     MethodContext(static_cast<NamedDecl*>(contextDecl)),
     SelName(SelInfo), MethodDeclType(T), 
     ParamInfo(paramInfo), NumMethodParams(numParams),
-    MethodAttrs(M), EndLoc(endLoc) {}
+    MethodAttrs(M), EndLoc(endLoc), Body(0), SelfDecl(0) {}
   virtual ~ObjcMethodDecl();
   
   ObjcDeclQualifier getObjcDeclQualifier() const { return objcDeclQualifier; }
@@ -718,6 +721,9 @@
   }
   Stmt *const getBody() const { return Body; }
   void setBody(Stmt *B) { Body = B; }
+
+  ParmVarDecl *const getSelfDecl() const { return SelfDecl; }
+  void setSelfDecl(ParmVarDecl *PVD) { SelfDecl = PVD; }
   
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return D->getKind() == ObjcMethod; }





More information about the cfe-commits mailing list