[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