[cfe-commits] r123918 - in /cfe/trunk: lib/Sema/SemaInit.cpp test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp

Douglas Gregor dgregor at apple.com
Thu Jan 20 08:44:54 PST 2011


Author: dgregor
Date: Thu Jan 20 10:44:54 2011
New Revision: 123918

URL: http://llvm.org/viewvc/llvm-project?rev=123918&view=rev
Log:
Start refactoring reference binding to more closely match the C++0x
working paper's structure. The only functional change here is that we
now handling binding to array rvalues, which we would previously reject.

Modified:
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=123918&r1=123917&r2=123918&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Thu Jan 20 10:44:54 2011
@@ -2597,13 +2597,17 @@
     return;
   }
 
-  //       - [If T1 is not a function type], if T2 is a class type and
-  if (!T1Function && T2->isRecordType()) {
-    bool isXValue = InitCategory.isXValue();
-    //       - the initializer expression is an rvalue and "cv1 T1" is 
-    //         reference-compatible with "cv2 T2", or
-    if (InitCategory.isRValue() && 
-        RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
+  //    - If the initializer expression
+  //      - is an xvalue, class prvalue, array prvalue, or function lvalue and
+  //        "cv1 T1" is reference-compatible with "cv2 T2"
+  // Note: functions are handled below.
+  if (!T1Function &&
+      RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification &&
+      (InitCategory.isXValue() ||
+       (InitCategory.isPRValue() && T2->isRecordType()) ||
+       (InitCategory.isPRValue() && T2->isArrayType()))) {
+    ExprValueKind ValueKind = InitCategory.isXValue()? VK_XValue : VK_RValue;
+    if (InitCategory.isPRValue() && T2->isRecordType()) {
       // The corresponding bullet in C++03 [dcl.init.ref]p5 gives the
       // compiler the freedom to perform a copy here or bind to the
       // object, while C++0x requires that we bind directly to the
@@ -2615,27 +2619,30 @@
       //   be callable whether or not the copy is actually done.
       if (!S.getLangOptions().CPlusPlus0x && !S.getLangOptions().Microsoft)
         Sequence.AddExtraneousCopyToTemporary(cv2T2);
-
-      if (DerivedToBase)
-        Sequence.AddDerivedToBaseCastStep(
-                         S.Context.getQualifiedType(T1, T2Quals), 
-                         isXValue ? VK_XValue : VK_RValue);
-      else if (ObjCConversion)
-        Sequence.AddObjCObjectConversionStep(
-                                     S.Context.getQualifiedType(T1, T2Quals));
-
-      if (T1Quals != T2Quals)
-        Sequence.AddQualificationConversionStep(cv1T1,
-                                            isXValue ? VK_XValue : VK_RValue);
-      Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/!isXValue);
-      return;
     }
-
-    //       - T1 is not reference-related to T2 and the initializer expression
-    //         can be implicitly converted to an rvalue of type "cv3 T3" (this
-    //         conversion is selected by enumerating the applicable conversion
-    //         functions (13.3.1.6) and choosing the best one through overload 
-    //         resolution (13.3)),
+        
+    if (DerivedToBase)
+      Sequence.AddDerivedToBaseCastStep(S.Context.getQualifiedType(T1, T2Quals),
+                                        ValueKind);
+    else if (ObjCConversion)
+      Sequence.AddObjCObjectConversionStep(
+                                       S.Context.getQualifiedType(T1, T2Quals));
+      
+    if (T1Quals != T2Quals)
+      Sequence.AddQualificationConversionStep(cv1T1, ValueKind);
+    Sequence.AddReferenceBindingStep(cv1T1, 
+         /*bindingTemporary=*/(InitCategory.isPRValue() && !T2->isArrayType()));
+    return;      
+  }
+  
+  //       - has a class type (i.e., T2 is a class type), where T1 is not 
+  //         reference-related to T2, and can be implicitly converted to an 
+  //         xvalue, class prvalue, or function lvalue of type "cv3 T3",
+  //         where "cv1 T1" is reference-compatible with "cv3 T3",
+  //
+  // FIXME: Need to handle xvalue, class prvalue, etc. cases in 
+  // TryRefInitWithConversionFunction.
+  if (T2->isRecordType()) {
     if (RefRelationship == Sema::Ref_Incompatible) {
       ConvOvlResult = TryRefInitWithConversionFunction(S, Entity,
                                                        Kind, Initializer,
@@ -2652,13 +2659,7 @@
     Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
     return;
   }
-  
-  //      - If the initializer expression is an rvalue, with T2 an array type,
-  //        and "cv1 T1" is reference-compatible with "cv2 T2," the reference
-  //        is bound to the object represented by the rvalue (see 3.10).
-  // FIXME: How can an array type be reference-compatible with anything?
-  // Don't we mean the element types of T1 and T2?
-  
+    
   //      - Otherwise, a temporary of type “cv1 T1” is created and initialized
   //        from the initializer expression using the rules for a non-reference
   //        copy initialization (8.5). The reference is then bound to the 

Modified: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp?rev=123918&r1=123917&r2=123918&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp (original)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp Thu Jan 20 10:44:54 2011
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify -pedantic %s
 
 // Test the C++0x-specific reference initialization rules, e.g., the
 // rules for rvalue references.
@@ -30,9 +30,28 @@
   Base&& base2 = prvalue<Base>();
   Base&& base3 = prvalue<Derived>();
 
-  // FIXME: array prvalue case
-  //  int (&&array0)[5] = HasArray().array;
+  // array prvalue case
+  int (&&array0)[5] = HasArray().array;
 
   // function lvalue case
   int (&&function0)(int) = f;
 }
+
+class NonCopyable {
+  NonCopyable(const NonCopyable&);
+};
+
+class NonCopyableDerived : public NonCopyable {
+  NonCopyableDerived(const NonCopyableDerived&);
+};
+
+void test_direct_binding() {
+  NonCopyable &&nc0 = prvalue<NonCopyable>();
+  NonCopyable &&nc1 = prvalue<NonCopyableDerived>();
+  NonCopyable &&nc2 = xvalue<NonCopyable>();
+  NonCopyable &&nc3 = xvalue<NonCopyableDerived>();
+  const NonCopyable &nc4 = prvalue<NonCopyable>();
+  const NonCopyable &nc5 = prvalue<NonCopyableDerived>();
+  const NonCopyable &nc6 = xvalue<NonCopyable>();
+  const NonCopyable &nc7 = xvalue<NonCopyableDerived>();
+}





More information about the cfe-commits mailing list