forked from OSchip/llvm-project
Fix ObjCPropertRefExpr to be able to encode all the information for
uses which refer to methods not properties. - Not yet wired in Sema. llvm-svn: 55681
This commit is contained in:
parent
b530f08122
commit
c5d330400f
|
@ -20,6 +20,8 @@
|
|||
namespace clang {
|
||||
class IdentifierInfo;
|
||||
class ASTContext;
|
||||
class ObjCMethodDecl;
|
||||
class ObjCPropertyDecl;
|
||||
|
||||
/// ObjCStringLiteral, used for Objective-C string literals
|
||||
/// i.e. @"foo".
|
||||
|
@ -189,18 +191,70 @@ public:
|
|||
static ObjCIvarRefExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
|
||||
};
|
||||
|
||||
/// ObjCPropertyRefExpr - A reference to an ObjC property.
|
||||
/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC
|
||||
/// property. Note that dot-syntax can also be used to access
|
||||
/// "implicit" properties (i.e. methods following the property naming
|
||||
/// convention). Additionally, sema is not yet smart enough to know if
|
||||
/// a property reference is to a getter or a setter, so the expr must
|
||||
/// have access to both methods.
|
||||
///
|
||||
// FIXME: Consider splitting these into separate Expr classes.
|
||||
class ObjCPropertyRefExpr : public Expr {
|
||||
class Decl *D; // an ObjCMethodDecl or ObjCPropertyDecl
|
||||
public:
|
||||
enum Kind {
|
||||
PropertyRef, // This expressions references a declared property.
|
||||
MethodRef // This expressions references methods.
|
||||
};
|
||||
|
||||
private:
|
||||
// A dot-syntax reference via methods must always have a getter. We
|
||||
// avoid storing the kind explicitly by relying on this invariant
|
||||
// and assuming this is a MethodRef iff Getter is non-null. Setter
|
||||
// can be null in situations which access a read-only property.
|
||||
union {
|
||||
ObjCPropertyDecl *AsProperty;
|
||||
struct {
|
||||
ObjCMethodDecl *Setter;
|
||||
ObjCMethodDecl *Getter;
|
||||
} AsMethod;
|
||||
} Referent;
|
||||
SourceLocation Loc;
|
||||
Stmt *Base;
|
||||
|
||||
public:
|
||||
ObjCPropertyRefExpr(Decl *d, QualType t, SourceLocation l, Expr *base) :
|
||||
Expr(ObjCPropertyRefExprClass, t), D(d), Loc(l), Base(base) {}
|
||||
|
||||
Decl *getDecl() { return D; }
|
||||
const Decl *getDecl() const { return D; }
|
||||
ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
|
||||
SourceLocation l, Expr *base)
|
||||
: Expr(ObjCPropertyRefExprClass, t), Loc(l), Base(base) {
|
||||
Referent.AsMethod.Getter = Referent.AsMethod.Setter = NULL;
|
||||
Referent.AsProperty = PD;
|
||||
}
|
||||
ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
|
||||
QualType t,
|
||||
SourceLocation l, Expr *base)
|
||||
: Expr(ObjCPropertyRefExprClass, t), Loc(l), Base(base) {
|
||||
Referent.AsMethod.Getter = Getter;
|
||||
Referent.AsMethod.Setter = Setter;
|
||||
}
|
||||
|
||||
Kind getKind() const {
|
||||
return Referent.AsMethod.Getter ? MethodRef : PropertyRef;
|
||||
}
|
||||
|
||||
ObjCPropertyDecl *getProperty() const {
|
||||
assert(getKind() == PropertyRef &&
|
||||
"Cannot get property from an ObjCPropertyRefExpr using methods");
|
||||
return Referent.AsProperty;
|
||||
}
|
||||
ObjCMethodDecl *getGetterMethod() const {
|
||||
assert(getKind() == MethodRef &&
|
||||
"Cannot get method from an ObjCPropertyRefExpr using a property");
|
||||
return Referent.AsMethod.Getter;
|
||||
}
|
||||
ObjCMethodDecl *getSetterMethod() const {
|
||||
assert(getKind() == MethodRef &&
|
||||
"Cannot get method from an ObjCPropertyRefExpr using a property");
|
||||
return Referent.AsMethod.Setter;
|
||||
}
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(getBase()->getLocStart(), Loc);
|
||||
|
|
|
@ -453,12 +453,15 @@ void StmtDumper::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) {
|
|||
|
||||
void StmtDumper::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
|
||||
DumpExpr(Node);
|
||||
|
||||
if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(Node->getDecl())) {
|
||||
fprintf(F, " MethodDecl=\"%s\"", MD->getSelector().getName().c_str());
|
||||
|
||||
if (Node->getKind() == ObjCPropertyRefExpr::MethodRef) {
|
||||
ObjCMethodDecl *Getter = Node->getGetterMethod();
|
||||
ObjCMethodDecl *Setter = Node->getSetterMethod();
|
||||
fprintf(F, " Kind=MethodRef Getter=\"%s\" Setter=\"%s\"",
|
||||
Getter->getSelector().getName().c_str(),
|
||||
Setter ? Setter->getSelector().getName().c_str() : "(null)");
|
||||
} else {
|
||||
ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(Node->getDecl());
|
||||
fprintf(F, " PropertyDecl=\"%s\"", PD->getName());
|
||||
fprintf(F, " Kind=PropertyRef Property=\"%s\"", Node->getProperty()->getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -998,7 +998,14 @@ ObjCIvarRefExpr* ObjCIvarRefExpr::CreateImpl(Deserializer& D, ASTContext& C) {
|
|||
void ObjCPropertyRefExpr::EmitImpl(Serializer& S) const {
|
||||
S.Emit(Loc);
|
||||
S.Emit(getType());
|
||||
S.EmitPtr(getDecl());
|
||||
unsigned Kind = getKind();
|
||||
S.Emit(Kind);
|
||||
if (Kind == PropertyRef) {
|
||||
S.EmitPtr(getProperty());
|
||||
} else {
|
||||
S.EmitPtr(getGetterMethod());
|
||||
S.EmitPtr(getSetterMethod());
|
||||
}
|
||||
}
|
||||
|
||||
ObjCPropertyRefExpr* ObjCPropertyRefExpr::CreateImpl(Deserializer& D,
|
||||
|
@ -1006,7 +1013,13 @@ ObjCPropertyRefExpr* ObjCPropertyRefExpr::CreateImpl(Deserializer& D,
|
|||
SourceLocation Loc = SourceLocation::ReadVal(D);
|
||||
QualType T = QualType::ReadVal(D);
|
||||
ObjCPropertyRefExpr* dr = new ObjCPropertyRefExpr(NULL,T,Loc,0);
|
||||
D.ReadPtr(dr->D,false);
|
||||
unsigned Kind = D.ReadInt();
|
||||
if (Kind == PropertyRef) {
|
||||
D.ReadPtr(dr->Referent.AsProperty,false);
|
||||
} else {
|
||||
D.ReadPtr(dr->Referent.AsMethod.Setter,false);
|
||||
D.ReadPtr(dr->Referent.AsMethod.Getter,false);
|
||||
}
|
||||
return dr;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "CodeGenModule.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
|
||||
using namespace clang;
|
||||
|
@ -231,10 +232,10 @@ llvm::Value *CodeGenFunction::LoadObjCSelf(void) {
|
|||
RValue CodeGenFunction::EmitObjCPropertyGet(const ObjCPropertyRefExpr *E) {
|
||||
// Determine getter selector.
|
||||
Selector S;
|
||||
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(E->getDecl())) {
|
||||
S = MD->getSelector();
|
||||
if (E->getKind() == ObjCPropertyRefExpr::MethodRef) {
|
||||
S = E->getGetterMethod()->getSelector();
|
||||
} else {
|
||||
S = cast<ObjCPropertyDecl>(E->getDecl())->getGetterName();
|
||||
S = E->getProperty()->getGetterName();
|
||||
}
|
||||
|
||||
return CGM.getObjCRuntime().
|
||||
|
@ -246,12 +247,21 @@ RValue CodeGenFunction::EmitObjCPropertyGet(const ObjCPropertyRefExpr *E) {
|
|||
void CodeGenFunction::EmitObjCPropertySet(const ObjCPropertyRefExpr *E,
|
||||
RValue Src) {
|
||||
Selector S;
|
||||
if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(E->getDecl())) {
|
||||
S = PD->getSetterName();
|
||||
if (E->getKind() == ObjCPropertyRefExpr::MethodRef) {
|
||||
ObjCMethodDecl *Setter = E->getSetterMethod();
|
||||
|
||||
if (Setter) {
|
||||
S = Setter->getSelector();
|
||||
} else {
|
||||
// FIXME: This should be diagnosed by sema.
|
||||
SourceRange Range = E->getSourceRange();
|
||||
CGM.getDiags().Report(getContext().getFullLoc(E->getLocStart()),
|
||||
diag::err_typecheck_assign_const, 0, 0,
|
||||
&Range, 1);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// FIXME: How can we have a method decl here?
|
||||
ErrorUnsupported(E, "Objective-C property setter call");
|
||||
return;
|
||||
S = E->getProperty()->getSetterName();
|
||||
}
|
||||
|
||||
CallArgList Args;
|
||||
|
|
|
@ -499,9 +499,8 @@ CodeGen::RValue CGObjCMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
|
|||
ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
|
||||
|
||||
// FIXME: This is a hack, we are implicitly coordinating with
|
||||
// EmitCallExprExt, which will move the return type to the first
|
||||
// parameter and set the structure return flag. See
|
||||
// getMessageSendFn().
|
||||
// EmitCall, which will move the return type to the first parameter
|
||||
// and set the structure return flag. See getMessageSendFn().
|
||||
|
||||
const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(ResultType);
|
||||
return CGF.EmitCall(ObjCTypes.getMessageSendFn(IsSuper, ReturnTy),
|
||||
|
|
Loading…
Reference in New Issue