[cfe-commits] r102374 - in /cfe/trunk: include/clang/AST/ExprObjC.h lib/Sema/TreeTransform.h test/SemaObjCXX/instantiate-expr.mm

Douglas Gregor dgregor at apple.com
Mon Apr 26 13:11:03 PDT 2010


Author: dgregor
Date: Mon Apr 26 15:11:03 2010
New Revision: 102374

URL: http://llvm.org/viewvc/llvm-project?rev=102374&view=rev
Log:
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.

Added:
    cfe/trunk/test/SemaObjCXX/instantiate-expr.mm
Modified:
    cfe/trunk/include/clang/AST/ExprObjC.h
    cfe/trunk/lib/Sema/TreeTransform.h

Modified: cfe/trunk/include/clang/AST/ExprObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprObjC.h?rev=102374&r1=102373&r2=102374&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprObjC.h (original)
+++ cfe/trunk/include/clang/AST/ExprObjC.h Mon Apr 26 15:11:03 2010
@@ -181,11 +181,12 @@
 
 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),
-    Loc(l), Base(base), IsArrow(arrow),
-    IsFreeIvar(freeIvar) {}
+    Expr(ObjCIvarRefExprClass, t, /*TypeDependent=*/false,
+         base->isValueDependent()), D(d),
+         Loc(l), Base(base), IsArrow(arrow),
+         IsFreeIvar(freeIvar) {}
 
   explicit ObjCIvarRefExpr(EmptyShell Empty)
     : Expr(ObjCIvarRefExprClass, Empty) {}
@@ -773,7 +774,8 @@
   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.

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=102374&r1=102373&r2=102374&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Mon Apr 26 15:11:03 2010
@@ -1801,6 +1801,62 @@
                                         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 @@
 template<typename Derived>
 Sema::OwningExprResult
 TreeTransform<Derived>::TransformObjCIvarRefExpr(ObjCIvarRefExpr *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 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 @@
 template<typename Derived>
 Sema::OwningExprResult
 TreeTransform<Derived>::TransformObjCIsaExpr(ObjCIsaExpr *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();
+  
+  // 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>

Added: cfe/trunk/test/SemaObjCXX/instantiate-expr.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/instantiate-expr.mm?rev=102374&view=auto
==============================================================================
--- cfe/trunk/test/SemaObjCXX/instantiate-expr.mm (added)
+++ cfe/trunk/test/SemaObjCXX/instantiate-expr.mm Mon Apr 26 15:11:03 2010
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+ at interface A {
+ at public
+  int ivar;
+}
+ at 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}}





More information about the cfe-commits mailing list