Implement template instantiation for ObjCPropertyRefExpr.

llvm-svn: 102379
This commit is contained in:
Douglas Gregor 2010-04-26 20:47:02 +00:00
parent 137d90c763
commit 9faee21f67
3 changed files with 64 additions and 17 deletions

View File

@ -233,8 +233,9 @@ private:
public: public:
ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
SourceLocation l, Expr *base) SourceLocation l, Expr *base)
: Expr(ObjCPropertyRefExprClass, t, false, false), AsProperty(PD), : Expr(ObjCPropertyRefExprClass, t, /*TypeDependent=*/false,
IdLoc(l), Base(base) { base->isValueDependent()),
AsProperty(PD), IdLoc(l), Base(base) {
} }
explicit ObjCPropertyRefExpr(EmptyShell Empty) explicit ObjCPropertyRefExpr(EmptyShell Empty)

View File

@ -1829,7 +1829,37 @@ public:
R, R,
/*TemplateArgs=*/0); /*TemplateArgs=*/0);
} }
/// \brief Build a new Objective-C property reference expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
OwningExprResult RebuildObjCPropertyRefExpr(ExprArg BaseArg,
ObjCPropertyDecl *Property,
SourceLocation PropertyLoc) {
CXXScopeSpec SS;
Expr *Base = BaseArg.takeAs<Expr>();
LookupResult R(getSema(), Property->getDeclName(), PropertyLoc,
Sema::LookupMemberName);
bool IsArrow = false;
OwningExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
/*FIME:*/PropertyLoc,
SS, DeclPtrTy());
if (Result.isInvalid())
return getSema().ExprError();
if (Result.get())
return move(Result);
return getSema().BuildMemberReferenceExpr(getSema().Owned(Base),
Base->getType(),
/*FIXME:*/PropertyLoc, IsArrow,
SS,
/*FirstQualifierInScope=*/0,
R,
/*TemplateArgs=*/0);
}
/// \brief Build a new Objective-C "isa" expression. /// \brief Build a new Objective-C "isa" expression.
/// ///
/// By default, performs semantic analysis to build the new expression. /// By default, performs semantic analysis to build the new expression.
@ -5866,9 +5896,20 @@ TreeTransform<Derived>::TransformObjCIvarRefExpr(ObjCIvarRefExpr *E) {
template<typename Derived> template<typename Derived>
Sema::OwningExprResult Sema::OwningExprResult
TreeTransform<Derived>::TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { TreeTransform<Derived>::TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
// FIXME: Implement this! // Transform the base expression.
assert(false && "Cannot transform Objective-C expressions yet"); OwningExprResult Base = getDerived().TransformExpr(E->getBase());
return SemaRef.Owned(E->Retain()); if (Base.isInvalid())
return SemaRef.ExprError();
// We don't need to transform the property; it will never change.
// If nothing changed, just retain the existing expression.
if (!getDerived().AlwaysRebuild() &&
Base.get() == E->getBase())
return SemaRef.Owned(E->Retain());
return getDerived().RebuildObjCPropertyRefExpr(move(Base), E->getProperty(),
E->getLocation());
} }
template<typename Derived> template<typename Derived>

View File

@ -4,36 +4,41 @@
@public @public
int ivar; int ivar;
} }
@property int prop;
@end @end
typedef struct objc_object { typedef struct objc_object {
Class isa; Class isa;
} *id; } *id;
// Test instantiation of value-dependent ObjCIvarRefExpr and // Test instantiation of value-dependent ObjCIvarRefExpr,
// ObjCIsaRefExpr nodes. // ObjCIsaRefExpr, and ObjCPropertyRefExpr nodes.
A *get_an_A(unsigned); A *get_an_A(unsigned);
id get_an_id(unsigned); id get_an_id(unsigned);
template<unsigned N, typename T, typename U> template<unsigned N, typename T, typename U, typename V>
void f(U value) { void f(U value, V value2) {
get_an_A(N)->ivar = value; // expected-error{{assigning to 'int' from incompatible type 'int *'}} get_an_A(N)->ivar = value; // expected-error{{assigning to 'int' from incompatible type 'int *'}}
get_an_A(N).prop = value2; // expected-error{{assigning to 'int' from incompatible type 'double *'}}
T c = get_an_id(N)->isa; // expected-error{{cannot initialize a variable of type 'int' with an lvalue of type 'Class'}} T c = get_an_id(N)->isa; // expected-error{{cannot initialize a variable of type 'int' with an lvalue of type 'Class'}}
} }
template void f<6, Class>(int); template void f<6, Class>(int, int);
template void f<7, Class>(int*); // expected-note{{in instantiation of}} template void f<7, Class>(int*, int); // expected-note{{in instantiation of}}
template void f<8, int>(int); // expected-note{{in instantiation of}} template void f<8, Class>(int, double*); // expected-note{{in instantiation of}}
template void f<9, int>(int, int); // expected-note{{in instantiation of}}
// Test instantiation of unresolved member reference expressions to an // Test instantiation of unresolved member reference expressions to an
// ivar reference. // ivar reference.
template<typename T, typename U> template<typename T, typename U, typename V>
void f2(T ptr, U value) { void f2(T ptr, U value, V value2) {
ptr->ivar = value; // expected-error{{assigning to 'int' from incompatible type 'int *'}} ptr->ivar = value; // expected-error{{assigning to 'int' from incompatible type 'int *'}}
ptr.prop = value2; // expected-error{{assigning to 'int' from incompatible type 'double *'}}
} }
template void f2(A*, int); template void f2(A*, int, int);
template void f2(A*, int*); // expected-note{{instantiation of}} template void f2(A*, int*, int); // expected-note{{instantiation of}}
template void f2(A*, int, double*); // expected-note{{instantiation of}}
// Test instantiation of unresolved member referfence expressions to // Test instantiation of unresolved member referfence expressions to
// an isa. // an isa.