Implement the special template argument deduction rule for T&& in a
call (C++0x [temp.deduct.call]p3).

As part of this, start improving the reference-binding implementation
used in the computation of implicit conversion sequences (for overload
resolution) to reflect C++0x semantics. It still needs more work and
testing, of course.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123966 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index c6150d9..e1318f9 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -3013,8 +3013,7 @@
   // qualifier.
   // This is also the point where rvalue references and lvalue inits no longer
   // go together.
-  if ((!isRValRef && !T1.isConstQualified()) ||
-      (isRValRef && InitCategory.isLValue()))
+  if (!isRValRef && !T1.isConstQualified())
     return ICS;
 
   //       -- If T1 is a function type, then
@@ -3073,8 +3072,17 @@
         !S.RequireCompleteType(DeclLoc, T2, 0) && 
         FindConversionForRefInit(S, ICS, DeclType, DeclLoc,
                                  Init, T2, /*AllowRvalues=*/true,
-                                 AllowExplicit))
+                                 AllowExplicit)) {
+      // In the second case, if the reference is an rvalue reference
+      // and the second standard conversion sequence of the
+      // user-defined conversion sequence includes an lvalue-to-rvalue
+      // conversion, the program is ill-formed.
+      if (ICS.isUserDefined() && isRValRef && 
+          ICS.UserDefined.After.First == ICK_Lvalue_To_Rvalue)
+        ICS.setBad(BadConversionSequence::no_conversion, Init, DeclType);
+
       return ICS;
+    }
   }
   
   //       -- Otherwise, a temporary of type "cv1 T1" is created and
@@ -3101,6 +3109,12 @@
       (T1->isRecordType() || T2->isRecordType()))
     return ICS;
 
+  // If T1 is reference-related to T2 and the reference is an rvalue
+  // reference, the initializer expression shall not be an lvalue.
+  if (RefRelationship >= Sema::Ref_Related &&
+      isRValRef && Init->Classify(S.Context).isLValue())
+    return ICS;
+
   // C++ [over.ics.ref]p2:
   //   When a parameter of reference type is not bound directly to
   //   an argument expression, the conversion sequence is the one
@@ -3123,6 +3137,7 @@
     ICS.UserDefined.After.ReferenceBinding = true;
     ICS.UserDefined.After.RRefBinding = isRValRef;
   }
+
   return ICS;
 }
 
@@ -4005,6 +4020,16 @@
       Candidate.FailureKind = ovl_fail_final_conversion_not_exact;
     }
       
+    // C++0x [dcl.init.ref]p5:
+    //    In the second case, if the reference is an rvalue reference and
+    //    the second standard conversion sequence of the user-defined
+    //    conversion sequence includes an lvalue-to-rvalue conversion, the
+    //    program is ill-formed.
+    if (ToType->isRValueReferenceType() && 
+        ICS.Standard.First == ICK_Lvalue_To_Rvalue) {
+      Candidate.Viable = false;
+      Candidate.FailureKind = ovl_fail_bad_final_conversion;
+    }
     break;
 
   case ImplicitConversionSequence::BadConversion:
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index fc48039..333eb32 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -2399,6 +2399,18 @@
     ParamType = ParamType.getLocalUnqualifiedType();
   const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>();
   if (ParamRefType) {
+    //   [C++0x] If P is an rvalue reference to a cv-unqualified
+    //   template parameter and the argument is an lvalue, the type
+    //   "lvalue reference to A" is used in place of A for type
+    //   deduction.
+    if (const RValueReferenceType *RValueRef
+                                   = dyn_cast<RValueReferenceType>(ParamType)) {
+      if (!RValueRef->getPointeeType().getQualifiers() &&
+          isa<TemplateTypeParmType>(RValueRef->getPointeeType()) &&
+          Arg->Classify(S.Context).isLValue())
+        ArgType = S.Context.getLValueReferenceType(ArgType);
+    }
+
     //   [...] If P is a reference type, the type referred to by P is used
     //   for type deduction.
     ParamType = ParamRefType->getPointeeType();