[cfe-commits] r95167 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaCXXCast.cpp lib/Sema/SemaCodeComplete.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaExprObjC.cpp lib/Sema/SemaStmt.cpp test/Sema/block-return.c test/SemaCXX/comma.cpp test/SemaCXX/enum.cpp test/SemaCXX/reinterpret-cast.cpp

Douglas Gregor dgregor at apple.com
Tue Feb 2 16:27:59 PST 2010


Author: dgregor
Date: Tue Feb  2 18:27:59 2010
New Revision: 95167

URL: http://llvm.org/viewvc/llvm-project?rev=95167&view=rev
Log:
Implement the lvalue-to-rvalue conversion where needed. The
lvalue-to-rvalue conversion adjusts lvalues of qualified, non-class
type to rvalue expressions of the unqualified variant of that
type. For example, given:

  const int i;
  (void)(i + 17);

the lvalue-to-rvalue conversion for the subexpression "i" will turn it
from an lvalue expression (a DeclRefExpr) with type 'const int' into
an rvalue expression with type 'int'. Both C and C++ mandate this
conversion, and somehow we've slid through without implementing it. 

We now have both DefaultFunctionArrayConversion and
DefaultFunctionArrayLvalueConversion, and which gets used depends on
whether we do the lvalue-to-rvalue conversion or not. Generally, we do
the lvalue-to-rvalue conversion, but there are a few notable
exceptions:
  - the left-hand side of a '.' operator
  - the left-hand side of an assignment
  - a C++ throw expression
  - a subscript expression that's subscripting a vector

Making this change exposed two issues with blocks:
  - we were deducing const-qualified return types of non-class type
  from a block return, which doesn't fit well
  - we weren't always setting the known return type of a block when it
  was provided with the ^return-type syntax

Fixes the current Clang-on-Clang compile failure and PR6076.


Added:
    cfe/trunk/test/SemaCXX/comma.cpp   (with props)
Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaCXXCast.cpp
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/lib/Sema/SemaStmt.cpp
    cfe/trunk/test/Sema/block-return.c
    cfe/trunk/test/SemaCXX/enum.cpp
    cfe/trunk/test/SemaCXX/reinterpret-cast.cpp

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=95167&r1=95166&r2=95167&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Feb  2 18:27:59 2010
@@ -3617,6 +3617,11 @@
   // to their respective pointers (C99 6.3.2.1).
   void DefaultFunctionArrayConversion(Expr *&expr);
 
+  // DefaultFunctionArrayLvalueConversion - converts functions and
+  // arrays to their respective pointers and performs the
+  // lvalue-to-rvalue conversion.
+  void DefaultFunctionArrayLvalueConversion(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/SemaCXXCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXCast.cpp?rev=95167&r1=95166&r2=95167&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXCast.cpp Tue Feb  2 18:27:59 2010
@@ -388,7 +388,7 @@
 CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
                const SourceRange &OpRange, const SourceRange &DestRange) {
   if (!DestType->isLValueReferenceType())
-    Self.DefaultFunctionArrayConversion(SrcExpr);
+    Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
 
   unsigned msg = diag::err_bad_cxx_cast_generic;
   if (TryConstCast(Self, SrcExpr, DestType, /*CStyle*/false, msg) != TC_Success
@@ -407,7 +407,7 @@
                      const SourceRange &OpRange, const SourceRange &DestRange,
                      CastExpr::CastKind &Kind) {
   if (!DestType->isLValueReferenceType())
-    Self.DefaultFunctionArrayConversion(SrcExpr);
+    Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
 
   unsigned msg = diag::err_bad_cxx_cast_generic;
   if (TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange,
@@ -434,7 +434,7 @@
   }
 
   if (!DestType->isLValueReferenceType() && !DestType->isRecordType())
-    Self.DefaultFunctionArrayConversion(SrcExpr);
+    Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
 
   unsigned msg = diag::err_bad_cxx_cast_generic;
   if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg,
@@ -1197,7 +1197,7 @@
     return false;
 
   if (!CastTy->isLValueReferenceType() && !CastTy->isRecordType())
-    DefaultFunctionArrayConversion(CastExpr);
+    DefaultFunctionArrayLvalueConversion(CastExpr);
 
   // C++ [expr.cast]p5: The conversions performed by
   //   - a const_cast,

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=95167&r1=95166&r2=95167&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Tue Feb  2 18:27:59 2010
@@ -2978,7 +2978,7 @@
   
   // If necessary, apply function/array conversion to the receiver.
   // C99 6.7.5.3p[7,8].
-  DefaultFunctionArrayConversion(RecExpr);
+  DefaultFunctionArrayLvalueConversion(RecExpr);
   QualType ReceiverType = RecExpr->getType();
   
   if (ReceiverType->isObjCIdType() || ReceiverType->isBlockPointerType()) {

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=95167&r1=95166&r2=95167&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Feb  2 18:27:59 2010
@@ -200,6 +200,28 @@
   }
 }
 
+void Sema::DefaultFunctionArrayLvalueConversion(Expr *&E) {
+  DefaultFunctionArrayConversion(E);
+  
+  QualType Ty = E->getType();
+  assert(!Ty.isNull() && "DefaultFunctionArrayLvalueConversion - missing type");
+  if (!Ty->isDependentType() && Ty.hasQualifiers() &&
+      (!getLangOptions().CPlusPlus || !Ty->isRecordType()) &&
+      E->isLvalue(Context) == Expr::LV_Valid) {
+    // C++ [conv.lval]p1:
+    //   [...] If T is a non-class type, the type of the rvalue 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.
+    ImpCastExprToType(E, Ty.getUnqualifiedType(), CastExpr::CK_NoOp);
+  }
+}
+
+
 /// UsualUnaryConversions - Performs various conversions that are common to most
 /// operators (C99 6.3). The conversions of array and function types are
 /// sometimes surpressed. For example, the array->pointer conversion doesn't
@@ -233,7 +255,7 @@
     return Expr;
   }
 
-  DefaultFunctionArrayConversion(Expr);
+  DefaultFunctionArrayLvalueConversion(Expr);
   return Expr;
 }
 
@@ -2033,8 +2055,9 @@
   Expr *RHSExp = static_cast<Expr*>(Idx.get());
 
   // Perform default conversions.
-  DefaultFunctionArrayConversion(LHSExp);
-  DefaultFunctionArrayConversion(RHSExp);
+  if (!LHSExp->getType()->getAs<VectorType>())
+      DefaultFunctionArrayLvalueConversion(LHSExp);
+  DefaultFunctionArrayLvalueConversion(RHSExp);
 
   QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType();
 
@@ -2076,7 +2099,7 @@
     ResultType = VTy->getElementType();
   } else if (LHSTy->isArrayType()) {
     // If we see an array that wasn't promoted by
-    // DefaultFunctionArrayConversion, it must be an array that
+    // DefaultFunctionArrayLvalueConversion, it must be an array that
     // wasn't promoted because of the C90 rule that doesn't
     // allow promoting non-lvalue arrays.  Warn, then
     // force the promotion here.
@@ -3777,7 +3800,7 @@
     return CXXCheckCStyleCast(TyR, castType, castExpr, Kind, FunctionalStyle,
                               ConversionDecl);
 
-  DefaultFunctionArrayConversion(castExpr);
+  DefaultFunctionArrayLvalueConversion(castExpr);
 
   // C99 6.5.4p2: the cast type needs to be void or scalar and the expression
   // type needs to be scalar.
@@ -4814,7 +4837,7 @@
   //
   // Suppress this for references: C++ 8.5.3p5.
   if (!lhsType->isReferenceType())
-    DefaultFunctionArrayConversion(rExpr);
+    DefaultFunctionArrayLvalueConversion(rExpr);
 
   Sema::AssignConvertType result =
     CheckAssignmentConstraints(lhsType, rExpr->getType());
@@ -5777,7 +5800,9 @@
 // C99 6.5.17
 QualType Sema::CheckCommaOperands(Expr *LHS, Expr *&RHS, SourceLocation Loc) {
   // Comma performs lvalue conversion (C99 6.3.2.1), but not unary conversions.
-  DefaultFunctionArrayConversion(RHS);
+  // C++ does not perform this conversion (C++ [expr.comma]p1).
+  if (!getLangOptions().CPlusPlus)
+    DefaultFunctionArrayLvalueConversion(RHS);
 
   // FIXME: Check that RHS type is complete in C mode (it's legal for it to be
   // incomplete in C++).
@@ -6383,7 +6408,7 @@
     resultType = CheckAddressOfOperand(Input, OpLoc);
     break;
   case UnaryOperator::Deref:
-    DefaultFunctionArrayConversion(Input);
+    DefaultFunctionArrayLvalueConversion(Input);
     resultType = CheckIndirectionOperand(Input, OpLoc);
     break;
   case UnaryOperator::Plus:
@@ -6420,7 +6445,7 @@
     break;
   case UnaryOperator::LNot: // logical negation
     // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5).
-    DefaultFunctionArrayConversion(Input);
+    DefaultFunctionArrayLvalueConversion(Input);
     resultType = Input->getType();
     if (resultType->isDependentType())
       break;
@@ -6590,7 +6615,7 @@
 
         // Promote the array so it looks more like a normal array subscript
         // expression.
-        DefaultFunctionArrayConversion(Res);
+        DefaultFunctionArrayLvalueConversion(Res);
 
         // C99 6.5.2.1p1
         Expr *Idx = static_cast<Expr*>(OC.U.E);
@@ -6767,6 +6792,8 @@
            diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy;
       return;
     }
+
+    CurBlock->ReturnType = RetTy;
     return;
   }
 
@@ -7385,7 +7412,7 @@
   DiagnoseAssignmentAsCondition(E);
 
   if (!E->isTypeDependent()) {
-    DefaultFunctionArrayConversion(E);
+    DefaultFunctionArrayLvalueConversion(E);
 
     QualType T = E->getType();
 

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=95167&r1=95166&r2=95167&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Feb  2 18:27:59 2010
@@ -1678,8 +1678,8 @@
   if (LVoid || RVoid) {
     //   ... then the [l2r] conversions are performed on the second and third
     //   operands ...
-    DefaultFunctionArrayConversion(LHS);
-    DefaultFunctionArrayConversion(RHS);
+    DefaultFunctionArrayLvalueConversion(LHS);
+    DefaultFunctionArrayLvalueConversion(RHS);
     LTy = LHS->getType();
     RTy = RHS->getType();
 
@@ -1765,8 +1765,8 @@
   // C++0x 5.16p6
   //   LValue-to-rvalue, array-to-pointer, and function-to-pointer standard
   //   conversions are performed on the second and third operands.
-  DefaultFunctionArrayConversion(LHS);
-  DefaultFunctionArrayConversion(RHS);
+  DefaultFunctionArrayLvalueConversion(LHS);
+  DefaultFunctionArrayLvalueConversion(RHS);
   LTy = LHS->getType();
   RTy = RHS->getType();
 

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=95167&r1=95166&r2=95167&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Tue Feb  2 18:27:59 2010
@@ -492,7 +492,7 @@
 
   // If necessary, apply function/array conversion to the receiver.
   // C99 6.7.5.3p[7,8].
-  DefaultFunctionArrayConversion(RExpr);
+  DefaultFunctionArrayLvalueConversion(RExpr);
 
   QualType returnType;
   QualType ReceiverCType =

Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=95167&r1=95166&r2=95167&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Tue Feb  2 18:27:59 2010
@@ -873,7 +873,7 @@
           << FirstType << First->getSourceRange();
   }
   if (Second) {
-    DefaultFunctionArrayConversion(Second);
+    DefaultFunctionArrayLvalueConversion(Second);
     QualType SecondType = Second->getType();
     if (!SecondType->isObjCObjectPointerType())
       Diag(ForLoc, diag::err_collection_expr_type)
@@ -947,7 +947,7 @@
     if (RetValExp) {
       // Don't call UsualUnaryConversions(), since we don't want to do
       // integer promotions here.
-      DefaultFunctionArrayConversion(RetValExp);
+      DefaultFunctionArrayLvalueConversion(RetValExp);
       CurBlock->ReturnType = RetValExp->getType();
       if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(RetValExp)) {
         // We have to remove a 'const' added to copied-in variable which was
@@ -1258,7 +1258,7 @@
       }
     }
 
-    DefaultFunctionArrayConversion(Exprs[i]);
+    DefaultFunctionArrayLvalueConversion(Exprs[i]);
 
     InputConstraintInfos.push_back(Info);
   }

Modified: cfe/trunk/test/Sema/block-return.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/block-return.c?rev=95167&r1=95166&r2=95167&view=diff

==============================================================================
--- cfe/trunk/test/Sema/block-return.c (original)
+++ cfe/trunk/test/Sema/block-return.c Tue Feb  2 18:27:59 2010
@@ -109,7 +109,7 @@
 
 void foo7()
 {
- const int (^BB) (void) = ^{ const int i = 1; return i; }; // OK 
+ const int (^BB) (void) = ^{ const int i = 1; return i; }; // expected-error{{incompatible block pointer types initializing 'int (^)(void)', expected 'int const (^)(void)'}}
  const int (^CC) (void)  = ^const int{ const int i = 1; return i; }; // OK
 
   int i;
@@ -123,9 +123,8 @@
   __block const int k;
   const int cint = 100;
 
-  int (^MM) (void)  = ^{ return k; }; // expected-error {{incompatible block pointer types initializing 'int const (^)(void)', expected 'int (^)(void)'}}
-  int (^NN) (void)  = ^{ return cint; }; // expected-error {{incompatible block pointer types initializing 'int const (^)(void)', expected 'int (^)(void)'}}
-
+  int (^MM) (void)  = ^{ return k; };
+  int (^NN) (void)  = ^{ return cint; };
 }
 
 

Added: cfe/trunk/test/SemaCXX/comma.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/comma.cpp?rev=95167&view=auto

==============================================================================
--- cfe/trunk/test/SemaCXX/comma.cpp (added)
+++ cfe/trunk/test/SemaCXX/comma.cpp Tue Feb  2 18:27:59 2010
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// PR6076
+void f();
+void (&g)() = (void(), f);
+
+int a[1];
+int (&b)[1] = (void(), a);

Propchange: cfe/trunk/test/SemaCXX/comma.cpp

------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/SemaCXX/comma.cpp

------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/SemaCXX/comma.cpp

------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/test/SemaCXX/enum.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/enum.cpp?rev=95167&r1=95166&r2=95167&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/enum.cpp (original)
+++ cfe/trunk/test/SemaCXX/enum.cpp Tue Feb  2 18:27:59 2010
@@ -67,3 +67,7 @@
     enum { id }; 
   };
 }
+
+namespace Conditional {
+  enum a { A }; a x(const enum a x) { return 1?x:A; }
+}

Modified: cfe/trunk/test/SemaCXX/reinterpret-cast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/reinterpret-cast.cpp?rev=95167&r1=95166&r2=95167&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/reinterpret-cast.cpp (original)
+++ cfe/trunk/test/SemaCXX/reinterpret-cast.cpp Tue Feb  2 18:27:59 2010
@@ -47,7 +47,7 @@
   // Invalid: T1 const* -> T2*
   (void)reinterpret_cast<int*>(icp); // expected-error {{reinterpret_cast from 'int const *' to 'int *' casts away constness}}
   // Invalid: T1*** -> T2 const* const**
-  int const *const **icpcpp = reinterpret_cast<int const* const**>(ipppc); // expected-error {{reinterpret_cast from 'int ***const' to 'int const *const **' casts away constness}}
+  int const *const **icpcpp = reinterpret_cast<int const* const**>(ipppc); // expected-error {{reinterpret_cast from 'int ***' to 'int const *const **' casts away constness}}
   // Valid: T1* -> T2*
   int *ip = reinterpret_cast<int*>(icpcpp);
   // Valid: T* -> T const*





More information about the cfe-commits mailing list