diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-04-26 20:47:02 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-04-26 20:47:02 +0000 |
commit | 9faee21f67f7e8afa8e191f6e1132e91c3eff512 (patch) | |
tree | af6a5cacc912f4673d1cbd73e413df6778a2e108 /clang | |
parent | 137d90c763200b85018e0cde4986d7306b8a15b0 (diff) | |
download | bcm5719-llvm-9faee21f67f7e8afa8e191f6e1132e91c3eff512.tar.gz bcm5719-llvm-9faee21f67f7e8afa8e191f6e1132e91c3eff512.zip |
Implement template instantiation for ObjCPropertyRefExpr.
llvm-svn: 102379
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/AST/ExprObjC.h | 5 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 49 | ||||
-rw-r--r-- | clang/test/SemaObjCXX/instantiate-expr.mm | 27 |
3 files changed, 64 insertions, 17 deletions
diff --git a/clang/include/clang/AST/ExprObjC.h b/clang/include/clang/AST/ExprObjC.h index c62e91e31b3..406b905888d 100644 --- a/clang/include/clang/AST/ExprObjC.h +++ b/clang/include/clang/AST/ExprObjC.h @@ -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) diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 695ff6e5242..946496ae12c 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -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> diff --git a/clang/test/SemaObjCXX/instantiate-expr.mm b/clang/test/SemaObjCXX/instantiate-expr.mm index 264ea634e87..c480ecfa887 100644 --- a/clang/test/SemaObjCXX/instantiate-expr.mm +++ b/clang/test/SemaObjCXX/instantiate-expr.mm @@ -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. |