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.

llvm-svn: 52676
This commit is contained in:
Ted Kremenek 2008-06-24 15:50:53 +00:00
parent a2509a1a48
commit a3a37ae8c8
3 changed files with 71 additions and 12 deletions

View File

@ -227,6 +227,9 @@ public:
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 @@ class ObjCMessageExpr : public Expr {
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 @@ public:
/// 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 @@ public:
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; }

View File

@ -1131,7 +1131,7 @@ ObjCMessageExpr::ObjCMessageExpr(IdentifierInfo *clsName, Selector selInfo,
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 @@ ObjCMessageExpr::ObjCMessageExpr(IdentifierInfo *clsName, Selector selInfo,
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);

View File

@ -202,8 +202,16 @@ Sema::ExprResult Sema::ActOnClassMessage(
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.