]> granicus.if.org Git - clang/commitdiff
Implement template instantiation for ObjCPropertyRefExpr.
authorDouglas Gregor <dgregor@apple.com>
Mon, 26 Apr 2010 20:47:02 +0000 (20:47 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 26 Apr 2010 20:47:02 +0000 (20:47 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102379 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ExprObjC.h
lib/Sema/TreeTransform.h
test/SemaObjCXX/instantiate-expr.mm

index c62e91e31b3555f8460181d60827617b4b5d8545..406b905888dc26d35ec69e8dfb0dbf8ad93b2896 100644 (file)
@@ -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)
index 695ff6e524258819e1768e0211a0ddcf9e7ea8eb..946496ae12ca634851b907226c166899883b038e 100644 (file)
@@ -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>
index 264ea634e87dda09bb0fc10474564250b95348c9..c480ecfa8873f1c80318730303202ad6f8aea590 100644 (file)
@@ -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.