зеркало из https://github.com/microsoft/clang-1.git
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52676 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
0d8ac9a8b1
Коммит
4df728e368
|
@ -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; }
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
Загрузка…
Ссылка в новой задаче