forked from OSchip/llvm-project
Implement template instantiation for value-dependent Objective-C ivar
references and isa expressions. Also, test template instantiation of unresolved member references to Objective-C ivar references and isa expressions. llvm-svn: 102374
This commit is contained in:
parent
91358585d7
commit
d51d90dd04
|
@ -181,9 +181,10 @@ class ObjCIvarRefExpr : public Expr {
|
|||
|
||||
public:
|
||||
ObjCIvarRefExpr(ObjCIvarDecl *d,
|
||||
QualType t, SourceLocation l, Expr *base=0,
|
||||
QualType t, SourceLocation l, Expr *base,
|
||||
bool arrow = false, bool freeIvar = false) :
|
||||
Expr(ObjCIvarRefExprClass, t, false, false), D(d),
|
||||
Expr(ObjCIvarRefExprClass, t, /*TypeDependent=*/false,
|
||||
base->isValueDependent()), D(d),
|
||||
Loc(l), Base(base), IsArrow(arrow),
|
||||
IsFreeIvar(freeIvar) {}
|
||||
|
||||
|
@ -773,7 +774,8 @@ class ObjCIsaExpr : public Expr {
|
|||
bool IsArrow;
|
||||
public:
|
||||
ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, QualType ty)
|
||||
: Expr(ObjCIsaExprClass, ty, false, false),
|
||||
: Expr(ObjCIsaExprClass, ty, /*TypeDependent=*/false,
|
||||
base->isValueDependent()),
|
||||
Base(base), IsaMemberLoc(l), IsArrow(isarrow) {}
|
||||
|
||||
/// \brief Build an empty expression.
|
||||
|
|
|
@ -1801,6 +1801,62 @@ public:
|
|||
move(Args));
|
||||
}
|
||||
|
||||
/// \brief Build a new Objective-C ivar reference expression.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new expression.
|
||||
/// Subclasses may override this routine to provide different behavior.
|
||||
OwningExprResult RebuildObjCIvarRefExpr(ExprArg BaseArg, ObjCIvarDecl *Ivar,
|
||||
SourceLocation IvarLoc,
|
||||
bool IsArrow, bool IsFreeIvar) {
|
||||
// FIXME: We lose track of the IsFreeIvar bit.
|
||||
CXXScopeSpec SS;
|
||||
Expr *Base = BaseArg.takeAs<Expr>();
|
||||
LookupResult R(getSema(), Ivar->getDeclName(), IvarLoc,
|
||||
Sema::LookupMemberName);
|
||||
OwningExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
|
||||
/*FIME:*/IvarLoc,
|
||||
SS, DeclPtrTy());
|
||||
if (Result.isInvalid())
|
||||
return getSema().ExprError();
|
||||
|
||||
if (Result.get())
|
||||
return move(Result);
|
||||
|
||||
return getSema().BuildMemberReferenceExpr(getSema().Owned(Base),
|
||||
Base->getType(),
|
||||
/*FIXME:*/IvarLoc, 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.
|
||||
/// Subclasses may override this routine to provide different behavior.
|
||||
OwningExprResult RebuildObjCIsaExpr(ExprArg BaseArg, SourceLocation IsaLoc,
|
||||
bool IsArrow) {
|
||||
CXXScopeSpec SS;
|
||||
Expr *Base = BaseArg.takeAs<Expr>();
|
||||
LookupResult R(getSema(), &getSema().Context.Idents.get("isa"), IsaLoc,
|
||||
Sema::LookupMemberName);
|
||||
OwningExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
|
||||
/*FIME:*/IsaLoc,
|
||||
SS, DeclPtrTy());
|
||||
if (Result.isInvalid())
|
||||
return getSema().ExprError();
|
||||
|
||||
if (Result.get())
|
||||
return move(Result);
|
||||
|
||||
return getSema().BuildMemberReferenceExpr(getSema().Owned(Base),
|
||||
Base->getType(),
|
||||
/*FIXME:*/IsaLoc, IsArrow, SS,
|
||||
/*FirstQualifierInScope=*/0,
|
||||
R,
|
||||
/*TemplateArgs=*/0);
|
||||
}
|
||||
|
||||
/// \brief Build a new shuffle vector expression.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new expression.
|
||||
|
@ -5790,9 +5846,21 @@ TreeTransform<Derived>::TransformObjCProtocolExpr(ObjCProtocolExpr *E) {
|
|||
template<typename Derived>
|
||||
Sema::OwningExprResult
|
||||
TreeTransform<Derived>::TransformObjCIvarRefExpr(ObjCIvarRefExpr *E) {
|
||||
// FIXME: Implement this!
|
||||
assert(false && "Cannot transform Objective-C expressions yet");
|
||||
// Transform the base expression.
|
||||
OwningExprResult Base = getDerived().TransformExpr(E->getBase());
|
||||
if (Base.isInvalid())
|
||||
return SemaRef.ExprError();
|
||||
|
||||
// We don't need to transform the ivar; 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().RebuildObjCIvarRefExpr(move(Base), E->getDecl(),
|
||||
E->getLocation(),
|
||||
E->isArrow(), E->isFreeIvar());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
|
@ -5822,9 +5890,18 @@ TreeTransform<Derived>::TransformObjCSuperExpr(ObjCSuperExpr *E) {
|
|||
template<typename Derived>
|
||||
Sema::OwningExprResult
|
||||
TreeTransform<Derived>::TransformObjCIsaExpr(ObjCIsaExpr *E) {
|
||||
// FIXME: Implement this!
|
||||
assert(false && "Cannot transform Objective-C expressions yet");
|
||||
// Transform the base expression.
|
||||
OwningExprResult Base = getDerived().TransformExpr(E->getBase());
|
||||
if (Base.isInvalid())
|
||||
return SemaRef.ExprError();
|
||||
|
||||
// If nothing changed, just retain the existing expression.
|
||||
if (!getDerived().AlwaysRebuild() &&
|
||||
Base.get() == E->getBase())
|
||||
return SemaRef.Owned(E->Retain());
|
||||
|
||||
return getDerived().RebuildObjCIsaExpr(move(Base), E->getIsaMemberLoc(),
|
||||
E->isArrow());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
|
||||
@interface A {
|
||||
@public
|
||||
int ivar;
|
||||
}
|
||||
@end
|
||||
|
||||
typedef struct objc_object {
|
||||
Class isa;
|
||||
} *id;
|
||||
|
||||
// Test instantiation of value-dependent ObjCIvarRefExpr and
|
||||
// ObjCIsaRefExpr nodes.
|
||||
A *get_an_A(unsigned);
|
||||
id get_an_id(unsigned);
|
||||
|
||||
template<unsigned N, typename T, typename U>
|
||||
void f(U value) {
|
||||
get_an_A(N)->ivar = value; // expected-error{{assigning to 'int' from incompatible type 'int *'}}
|
||||
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}}
|
||||
|
||||
// Test instantiation of unresolved member reference expressions to an
|
||||
// ivar reference.
|
||||
template<typename T, typename U>
|
||||
void f2(T ptr, U value) {
|
||||
ptr->ivar = value; // expected-error{{assigning to 'int' from incompatible type 'int *'}}
|
||||
}
|
||||
|
||||
template void f2(A*, int);
|
||||
template void f2(A*, int*); // expected-note{{instantiation of}}
|
||||
|
||||
// Test instantiation of unresolved member referfence expressions to
|
||||
// an isa.
|
||||
template<typename T, typename U>
|
||||
void f3(U ptr) {
|
||||
T c = ptr->isa; // expected-error{{cannot initialize a variable of type 'int' with an lvalue of type 'Class'}}
|
||||
}
|
||||
|
||||
template void f3<Class>(id);
|
||||
template void f3<int>(id); // expected-note{{instantiation of}}
|
Loading…
Reference in New Issue