[cfe-commits] r52676 - in /cfe/trunk: include/clang/AST/ExprObjC.h lib/AST/Expr.cpp lib/Sema/SemaExprObjC.cpp

Ted Kremenek kremenek at apple.com
Tue Jun 24 08:50:53 PDT 2008


Author: kremenek
Date: Tue Jun 24 10:50:53 2008
New Revision: 52676

URL: http://llvm.org/viewvc/llvm-project?rev=52676&view=rev
Log:
ObjCMessageExpr objects that represent messages to class methods now can contain the ObjCInterfaceDecl* of the target class if it was available when the ObjCMessageExpr object was constructed.  The original interfaces of the class has been preserved (requiring no functionality changes from clients), but now a "getClasSInfo" method returns both the ObjCInterfaceDecl* and IdentifierInfo* of the target class.

Modified:
    cfe/trunk/include/clang/AST/ExprObjC.h
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/Sema/SemaExprObjC.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/ExprObjC.h (original)
+++ cfe/trunk/include/clang/AST/ExprObjC.h Tue Jun 24 10:50:53 2008
@@ -227,6 +227,9 @@
 class ObjCMessageExpr : public Expr {
   enum { RECEIVER=0, ARGS_START=1 };
 
+  // Bit-swizziling flags.
+  enum { IsInstMeth=0, IsClsMethDeclUnknown, IsClsMethDeclKnown, Flags=0x3 };
+
   Stmt **SubExprs;
   
   unsigned NumArgs;
@@ -249,12 +252,21 @@
     MethodProto(NULL), LBracloc(LBrac), RBracloc(RBrac) {}
   
 public:
-  // constructor for class messages. 
-  // FIXME: clsName should be typed to ObjCInterfaceType
+  /// This constructor is used to represent class messages where the
+  /// ObjCInterfaceDecl* of the receiver is not known.
   ObjCMessageExpr(IdentifierInfo *clsName, Selector selInfo,
                   QualType retType, ObjCMethodDecl *methDecl,
                   SourceLocation LBrac, SourceLocation RBrac,
                   Expr **ArgExprs, unsigned NumArgs);
+
+  /// This constructor is used to represent class messages where the
+  /// ObjCInterfaceDecl* of the receiver is known.
+  // FIXME: clsName should be typed to ObjCInterfaceType
+  ObjCMessageExpr(ObjCInterfaceDecl *cls, Selector selInfo,
+                  QualType retType, ObjCMethodDecl *methDecl,
+                  SourceLocation LBrac, SourceLocation RBrac,
+                  Expr **ArgExprs, unsigned NumArgs);
+  
   // constructor for instance messages.
   ObjCMessageExpr(Expr *receiver, Selector selInfo,
                   QualType retType, ObjCMethodDecl *methDecl,
@@ -270,7 +282,7 @@
   ///  class methods, use getClassName.
   Expr *getReceiver() { 
     uintptr_t x = (uintptr_t) SubExprs[RECEIVER];
-    return x & 0x1 ? NULL : (Expr*) x;
+    return (x & Flags) == IsInstMeth ? (Expr*) x : 0;
   }  
   const Expr *getReceiver() const {
     return const_cast<ObjCMessageExpr*>(this)->getReceiver();
@@ -280,16 +292,21 @@
 
   const ObjCMethodDecl *getMethodDecl() const { return MethodProto; }
   ObjCMethodDecl *getMethodDecl() { return MethodProto; }
+
+  typedef std::pair<ObjCInterfaceDecl*, IdentifierInfo*> ClassInfo;
+  
+  /// getClassInfo - For class methods, this returns both the ObjCInterfaceDecl*
+  ///  and IdentifierInfo* of the invoked class.  Both can be NULL if this
+  ///  is an instance message, and the ObjCInterfaceDecl* can be NULL if none
+  ///  was available when this ObjCMessageExpr object was constructed.  
+  ClassInfo getClassInfo() const;  
   
   /// getClassName - For class methods, this returns the invoked class,
   ///  and returns NULL otherwise.  For instance methods, use getReceiver.  
-  IdentifierInfo *getClassName() {
-    uintptr_t x = (uintptr_t) SubExprs[RECEIVER];
-    return x & 0x1 ? (IdentifierInfo*) (x & ~0x1) : NULL;
-  }  
-  const IdentifierInfo *getClassName() const {
-    return const_cast<ObjCMessageExpr*>(this)->getClassName();
+  IdentifierInfo *getClassName() const {
+    return getClassInfo().second;
   }
+
   
   /// getNumArgs - Return the number of actual arguments to this call.
   unsigned getNumArgs() const { return NumArgs; }

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=52676&r1=52675&r2=52676&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Tue Jun 24 10:50:53 2008
@@ -1131,7 +1131,7 @@
     MethodProto(mproto) {
   NumArgs = nargs;
   SubExprs = new Stmt*[NumArgs+1];
-  SubExprs[RECEIVER] = (Expr*) ((uintptr_t) clsName | 0x1);
+  SubExprs[RECEIVER] = (Expr*) ((uintptr_t) clsName | IsClsMethDeclUnknown);
   if (NumArgs) {
     for (unsigned i = 0; i != NumArgs; ++i)
       SubExprs[i+ARGS_START] = static_cast<Expr *>(ArgExprs[i]);
@@ -1140,6 +1140,40 @@
   RBracloc = RBrac;
 }
 
+// constructor for class messages. 
+ObjCMessageExpr::ObjCMessageExpr(ObjCInterfaceDecl *cls, Selector selInfo,
+                                 QualType retType, ObjCMethodDecl *mproto,
+                                 SourceLocation LBrac, SourceLocation RBrac,
+                                 Expr **ArgExprs, unsigned nargs)
+: Expr(ObjCMessageExprClass, retType), SelName(selInfo), 
+MethodProto(mproto) {
+  NumArgs = nargs;
+  SubExprs = new Stmt*[NumArgs+1];
+  SubExprs[RECEIVER] = (Expr*) ((uintptr_t) cls | IsClsMethDeclKnown);
+  if (NumArgs) {
+    for (unsigned i = 0; i != NumArgs; ++i)
+      SubExprs[i+ARGS_START] = static_cast<Expr *>(ArgExprs[i]);
+  }
+  LBracloc = LBrac;
+  RBracloc = RBrac;
+}
+
+ObjCMessageExpr::ClassInfo ObjCMessageExpr::getClassInfo() const {
+  uintptr_t x = (uintptr_t) SubExprs[RECEIVER];
+  switch (x & Flags) {
+    default:
+      assert(false && "Invalid ObjCMessageExpr.");
+    case IsInstMeth:
+      return ClassInfo(0, 0);
+    case IsClsMethDeclUnknown:
+      return ClassInfo(0, (IdentifierInfo*) (x & ~Flags));
+    case IsClsMethDeclKnown: {
+      ObjCInterfaceDecl* D = (ObjCInterfaceDecl*) (x & ~Flags);
+      return ClassInfo(D, D->getIdentifier());
+    }
+  }
+}
+
 bool ChooseExpr::isConditionTrue(ASTContext &C) const {
   llvm::APSInt CondVal(32);
   bool IsConst = getCond()->isIntegerConstantExpr(CondVal, C);

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=52676&r1=52675&r2=52676&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Tue Jun 24 10:50:53 2008
@@ -202,8 +202,16 @@
         return true;
     }
   }
-  return new ObjCMessageExpr(receiverName, Sel, returnType, Method,
-                             lbrac, rbrac, ArgExprs, NumArgs);
+
+  // If we have the ObjCInterfaceDecl* for the class that is receiving
+  // the message, use that to construct the ObjCMessageExpr.  Otherwise
+  // pass on the IdentifierInfo* for the class.
+  if (ClassDecl)
+    return new ObjCMessageExpr(ClassDecl, Sel, returnType, Method,
+                               lbrac, rbrac, ArgExprs, NumArgs);
+  else
+    return new ObjCMessageExpr(receiverName, Sel, returnType, Method,
+                               lbrac, rbrac, ArgExprs, NumArgs);
 }
 
 // ActOnInstanceMessage - used for both unary and keyword messages.





More information about the cfe-commits mailing list