forked from OSchip/llvm-project
Implement template instantiation for ObjCPropertyRefExpr.
llvm-svn: 102379
This commit is contained in:
parent
137d90c763
commit
9faee21f67
|
@ -233,8 +233,9 @@ private:
|
|||
public:
|
||||
ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
|
||||
SourceLocation l, Expr *base)
|
||||
: Expr(ObjCPropertyRefExprClass, t, false, false), AsProperty(PD),
|
||||
IdLoc(l), Base(base) {
|
||||
: Expr(ObjCPropertyRefExprClass, t, /*TypeDependent=*/false,
|
||||
base->isValueDependent()),
|
||||
AsProperty(PD), IdLoc(l), Base(base) {
|
||||
}
|
||||
|
||||
explicit ObjCPropertyRefExpr(EmptyShell Empty)
|
||||
|
|
|
@ -1829,7 +1829,37 @@ public:
|
|||
R,
|
||||
/*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.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new expression.
|
||||
|
@ -5866,9 +5896,20 @@ TreeTransform<Derived>::TransformObjCIvarRefExpr(ObjCIvarRefExpr *E) {
|
|||
template<typename Derived>
|
||||
Sema::OwningExprResult
|
||||
TreeTransform<Derived>::TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
|
||||
// FIXME: Implement this!
|
||||
assert(false && "Cannot transform Objective-C expressions yet");
|
||||
return SemaRef.Owned(E->Retain());
|
||||
// Transform the base expression.
|
||||
OwningExprResult Base = getDerived().TransformExpr(E->getBase());
|
||||
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>
|
||||
|
|
|
@ -4,36 +4,41 @@
|
|||
@public
|
||||
int ivar;
|
||||
}
|
||||
@property int prop;
|
||||
@end
|
||||
|
||||
typedef struct objc_object {
|
||||
Class isa;
|
||||
} *id;
|
||||
|
||||
// Test instantiation of value-dependent ObjCIvarRefExpr and
|
||||
// ObjCIsaRefExpr nodes.
|
||||
// Test instantiation of value-dependent ObjCIvarRefExpr,
|
||||
// ObjCIsaRefExpr, and ObjCPropertyRefExpr nodes.
|
||||
A *get_an_A(unsigned);
|
||||
id get_an_id(unsigned);
|
||||
|
||||
template<unsigned N, typename T, typename U>
|
||||
void f(U value) {
|
||||
template<unsigned N, typename T, typename U, typename V>
|
||||
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).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'}}
|
||||
}
|
||||
|
||||
template void f<6, Class>(int);
|
||||
template void f<7, Class>(int*); // expected-note{{in instantiation of}}
|
||||
template void f<8, int>(int); // expected-note{{in instantiation of}}
|
||||
template void f<6, Class>(int, int);
|
||||
template void f<7, Class>(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
|
||||
// ivar reference.
|
||||
template<typename T, typename U>
|
||||
void f2(T ptr, U value) {
|
||||
template<typename T, typename U, typename V>
|
||||
void f2(T ptr, U value, V value2) {
|
||||
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*); // expected-note{{instantiation of}}
|
||||
template void f2(A*, int, int);
|
||||
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
|
||||
// an isa.
|
||||
|
|
Loading…
Reference in New Issue