]> granicus.if.org Git - clang/commitdiff
Split out a function to do lvalue conversion on objects; this is basically
authorJohn McCall <rjmccall@apple.com>
Mon, 6 Dec 2010 20:48:59 +0000 (20:48 +0000)
committerJohn McCall <rjmccall@apple.com>
Mon, 6 Dec 2010 20:48:59 +0000 (20:48 +0000)
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.

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

include/clang/Sema/Sema.h
lib/Sema/SemaExpr.cpp

index cf770c66eb1a89abb401750c2b7baf6fc8a49110..838e4bc2ffbc927a483ff99c600b4b1f8a2e00e2 100644 (file)
@@ -4003,6 +4003,12 @@ public:
   // 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.
index bc8a7527c85bb183bde54cfe4a95e829269fb5fb..a1ea57ebcfab896e4932c84f7e3e5d96fcb81e0f 100644 (file)
@@ -244,53 +244,57 @@ void Sema::DefaultFunctionArrayConversion(Expr *&E) {
   }
 }
 
-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 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
       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 @@ static QualType CheckRealImagOperand(Sema &S, Expr *&V, SourceLocation Loc,
 
   // _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 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
               << IV->getDeclName();
         }
 
+        if (IsArrow) DefaultLvalueConversion(BaseExpr);
+
         return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(),
                                                    MemberLoc, BaseExpr,
                                                    IsArrow));
@@ -3725,7 +3734,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
   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 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
     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);
     }