[cfe-commits] r121035 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaExpr.cpp

John McCall rjmccall at apple.com
Mon Dec 6 12:48:59 PST 2010


Author: rjmccall
Date: Mon Dec  6 14:48:59 2010
New Revision: 121035

URL: http://llvm.org/viewvc/llvm-project?rev=121035&view=rev
Log:
Split out a function to do lvalue conversion on objects;  this is basically
FunctionArrayLvalueConversion but without the function/array decay.  Generally
this is only appropriate for use sites that know the type of the expression
and thus that it can't be subject to the decays.

Also make sure we do lvalue-to-rvalue on the bases of ivar references.


Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExpr.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=121035&r1=121034&r2=121035&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Dec  6 14:48:59 2010
@@ -4003,6 +4003,12 @@
   // lvalue-to-rvalue conversion.
   void DefaultFunctionArrayLvalueConversion(Expr *&expr);
 
+  // DefaultLvalueConversion - performs lvalue-to-rvalue conversion on
+  // the operand.  This is DefaultFunctionArrayLvalueConversion,
+  // except that it assumes the operand isn't of function or array
+  // type.
+  void DefaultLvalueConversion(Expr *&expr);
+
   // DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
   // do not have a prototype. Integer promotions are performed on each
   // argument, and arguments that have type float are promoted to double.

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=121035&r1=121034&r2=121035&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Dec  6 14:48:59 2010
@@ -244,53 +244,57 @@
   }
 }
 
-void Sema::DefaultFunctionArrayLvalueConversion(Expr *&E) {
-  DefaultFunctionArrayConversion(E);
-  
+void Sema::DefaultLvalueConversion(Expr *&E) {
   // C++ [conv.lval]p1:
   //   A glvalue of a non-function, non-array type T can be
   //   converted to a prvalue.
-  if (E->isGLValue()) {
-    QualType T = E->getType();
-    assert(!T.isNull() && "r-value conversion on typeless expression?");
+  if (!E->isGLValue()) return;
 
-    // Create a load out of an ObjCProperty l-value, if necessary.
-    if (E->getObjectKind() == OK_ObjCProperty) {
-      ConvertPropertyForRValue(E);
-      if (!E->isGLValue())
-        return;
-    }
+  QualType T = E->getType();
+  assert(!T.isNull() && "r-value conversion on typeless expression?");
 
-    // We don't want to throw lvalue-to-rvalue casts on top of
-    // expressions of certain types in C++.
-    if (getLangOptions().CPlusPlus &&
-        (E->getType() == Context.OverloadTy ||
-         T->isDependentType() ||
-         T->isRecordType()))
+  // Create a load out of an ObjCProperty l-value, if necessary.
+  if (E->getObjectKind() == OK_ObjCProperty) {
+    ConvertPropertyForRValue(E);
+    if (!E->isGLValue())
       return;
+  }
 
-    // The C standard is actually really unclear on this point, and
-    // DR106 tells us what the result should be but not why.  It's
-    // generally best to say that void just doesn't undergo
-    // lvalue-to-rvalue at all.
-    if (T->isVoidType())
-      return;
+  // We don't want to throw lvalue-to-rvalue casts on top of
+  // expressions of certain types in C++.
+  if (getLangOptions().CPlusPlus &&
+      (E->getType() == Context.OverloadTy ||
+       T->isDependentType() ||
+       T->isRecordType()))
+    return;
 
-    // C++ [conv.lval]p1:
-    //   [...] If T is a non-class type, the type of the prvalue is the
-    //   cv-unqualified version of T. Otherwise, the type of the
-    //   rvalue is T.
-    //
-    // C99 6.3.2.1p2:
-    //   If the lvalue has qualified type, the value has the unqualified
-    //   version of the type of the lvalue; otherwise, the value has the
-    //   type of the lvalue.    
-    if (T.hasQualifiers())
-      T = T.getUnqualifiedType();
+  // The C standard is actually really unclear on this point, and
+  // DR106 tells us what the result should be but not why.  It's
+  // generally best to say that void types just doesn't undergo
+  // lvalue-to-rvalue at all.  Note that expressions of unqualified
+  // 'void' type are never l-values, but qualified void can be.
+  if (T->isVoidType())
+    return;
 
-    E = ImplicitCastExpr::Create(Context, T, CK_LValueToRValue,
-                                 E, 0, VK_RValue);
-  }
+  // C++ [conv.lval]p1:
+  //   [...] If T is a non-class type, the type of the prvalue is the
+  //   cv-unqualified version of T. Otherwise, the type of the
+  //   rvalue is T.
+  //
+  // C99 6.3.2.1p2:
+  //   If the lvalue has qualified type, the value has the unqualified
+  //   version of the type of the lvalue; otherwise, the value has the
+  //   type of the lvalue.    
+  if (T.hasQualifiers())
+    T = T.getUnqualifiedType();
+
+  E = ImplicitCastExpr::Create(Context, T, CK_LValueToRValue,
+                               E, 0, VK_RValue);
+}
+
+void Sema::DefaultFunctionArrayLvalueConversion(Expr *&E) {
+  DefaultFunctionArrayConversion(E);
+  DefaultLvalueConversion(E);
 }
 
 
@@ -1722,10 +1726,13 @@
       if (SelfExpr.isInvalid())
         return ExprError();
 
+      Expr *SelfE = SelfExpr.take();
+      DefaultLvalueConversion(SelfE);
+
       MarkDeclarationReferenced(Loc, IV);
       return Owned(new (Context)
                    ObjCIvarRefExpr(IV, IV->getType(), Loc,
-                                   SelfExpr.takeAs<Expr>(), true, true));
+                                   SelfE, true, true));
     }
   } else if (CurMethod->isInstanceMethod()) {
     // We should warn if a local variable hides an ivar.
@@ -2672,7 +2679,7 @@
 
   // _Real and _Imag are only l-values for normal l-values.
   if (V->getObjectKind() != OK_Ordinary)
-    S.DefaultFunctionArrayLvalueConversion(V);
+    S.DefaultLvalueConversion(V);
 
   // These operators return the element type of a complex type.
   if (const ComplexType *CT = V->getType()->getAs<ComplexType>())
@@ -3712,6 +3719,8 @@
               << IV->getDeclName();
         }
 
+        if (IsArrow) DefaultLvalueConversion(BaseExpr);
+
         return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(),
                                                    MemberLoc, BaseExpr,
                                                    IsArrow));
@@ -3725,7 +3734,7 @@
   if (!IsArrow && (BaseType->isObjCIdType() ||
                    BaseType->isObjCQualifiedIdType())) {
     // This actually uses the base as an r-value.
-    DefaultFunctionArrayLvalueConversion(BaseExpr);
+    DefaultLvalueConversion(BaseExpr);
     assert(Context.hasSameUnqualifiedType(BaseType, BaseExpr->getType()));
 
     const ObjCObjectPointerType *QIdTy = BaseType->getAs<ObjCObjectPointerType>();
@@ -3779,7 +3788,7 @@
     if (const ObjCObjectPointerType *OPT =
           BaseType->getAsObjCInterfacePointerType()) {
       // This actually uses the base as an r-value.
-      DefaultFunctionArrayLvalueConversion(BaseExpr);      
+      DefaultLvalueConversion(BaseExpr);      
       return HandleExprPropertyRefExpr(OPT, BaseExpr, MemberName, MemberLoc,
                                        SourceLocation(), QualType(), false);
     }





More information about the cfe-commits mailing list