]> granicus.if.org Git - clang/commitdiff
Implement template instantiation for implicit property references in
authorDouglas Gregor <dgregor@apple.com>
Mon, 26 Apr 2010 21:04:54 +0000 (21:04 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 26 Apr 2010 21:04:54 +0000 (21:04 +0000)
Objective-C++. This is the last bit of (non-blocks-related) template
instantiation logic for Objective-C++. Yay!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102382 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 406b905888dc26d35ec69e8dfb0dbf8ad93b2896..8a09f4e9a6a9256b0c9807d84571f954cb3d4e60 100644 (file)
@@ -299,7 +299,8 @@ public:
                  QualType t,
                  ObjCMethodDecl *setter,
                  SourceLocation l, Expr *base)
-    : Expr(ObjCImplicitSetterGetterRefExprClass, t, false, false),
+    : Expr(ObjCImplicitSetterGetterRefExprClass, t, /*TypeDependent=*/false, 
+           base->isValueDependent()),
       Setter(setter), Getter(getter), MemberLoc(l), Base(base),
       InterfaceDecl(0), ClassLoc(SourceLocation()) {
     }
index 946496ae12ca634851b907226c166899883b038e..cded16cd60dccfd8a8ded0183adc9cda6dd8e974 100644 (file)
@@ -1860,6 +1860,26 @@ public:
                                               /*TemplateArgs=*/0);
   }
   
+  /// \brief Build a new Objective-C implicit setter/getter reference 
+  /// expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.  
+  OwningExprResult RebuildObjCImplicitSetterGetterRefExpr(
+                                                        ObjCMethodDecl *Getter,
+                                                          QualType T,
+                                                        ObjCMethodDecl *Setter,
+                                                        SourceLocation NameLoc,
+                                                          ExprArg Base) {
+    // Since these expressions can only be value-dependent, we do not need to
+    // perform semantic analysis again.
+    return getSema().Owned(
+             new (getSema().Context) ObjCImplicitSetterGetterRefExpr(Getter, T,
+                                                                     Setter,
+                                                                     NameLoc,
+                                                          Base.takeAs<Expr>()));
+  }
+
   /// \brief Build a new Objective-C "isa" expression.
   ///
   /// By default, performs semantic analysis to build the new expression.
@@ -5916,9 +5936,30 @@ template<typename Derived>
 Sema::OwningExprResult
 TreeTransform<Derived>::TransformObjCImplicitSetterGetterRefExpr(
                                           ObjCImplicitSetterGetterRefExpr *E) {
-  // FIXME: Implement this!
-  assert(false && "Cannot transform Objective-C expressions yet");
-  return SemaRef.Owned(E->Retain());
+  // If this implicit setter/getter refers to class methods, it cannot have any
+  // dependent parts. Just retain the existing declaration.
+  if (E->getInterfaceDecl())
+    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 getters/setters; they 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().RebuildObjCImplicitSetterGetterRefExpr(
+                                                          E->getGetterMethod(),
+                                                             E->getType(),
+                                                          E->getSetterMethod(),
+                                                             E->getLocation(),
+                                                             move(Base));
+                                                             
 }
 
 template<typename Derived>
index c480ecfa8873f1c80318730303202ad6f8aea590..08be5f7b91102a58426ca3ba0aa020c6ac7c87f9 100644 (file)
@@ -49,3 +49,25 @@ void f3(U ptr) {
 
 template void f3<Class>(id);
 template void f3<int>(id); // expected-note{{instantiation of}}
+
+// Implicit setter/getter
+@interface B
+- (int)foo;
+- (void)setFoo:(int)value;
+@end
+
+template<typename T>
+void f4(B *b, T value) {
+  b.foo = value; // expected-error{{assigning to 'int' from incompatible type 'int *'}}
+}
+
+template void f4(B*, int);
+template void f4(B*, int*); // expected-note{{in instantiation of function template specialization 'f4<int *>' requested here}}
+
+template<typename T, typename U>
+void f5(T ptr, U value) {
+  ptr.foo = value; // expected-error{{assigning to 'int' from incompatible type 'int *'}}
+}
+
+template void f5(B*, int);
+template void f5(B*, int*); // expected-note{{in instantiation of function template specialization 'f5<B *, int *>' requested here}}