]> granicus.if.org Git - clang/commitdiff
restore fix for 18645, buildbot apparently gave a false positive.
authorNathan Sidwell <nathan@acm.org>
Fri, 16 Jan 2015 15:20:14 +0000 (15:20 +0000)
committerNathan Sidwell <nathan@acm.org>
Fri, 16 Jan 2015 15:20:14 +0000 (15:20 +0000)
Correct logic concerning 'T &&' deduction against lvalues.

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

lib/Sema/SemaTemplateDeduction.cpp
test/SemaTemplate/deduction.cpp

index dd2a4d26979e6ff802474425c1f86a41d1979e00..90384f0b0a922f9565185afe63ed846de1ebd19b 100644 (file)
@@ -3136,34 +3136,16 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
   //   are ignored for type deduction.
   if (ParamType.hasQualifiers())
     ParamType = ParamType.getUnqualifiedType();
-  const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>();
-  if (ParamRefType) {
-    QualType PointeeType = ParamRefType->getPointeeType();
-
-    // If the argument has incomplete array type, try to complete its type.
-    if (ArgType->isIncompleteArrayType() && !S.RequireCompleteExprType(Arg, 0))
-      ArgType = Arg->getType();
-
-    //   [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 (isa<RValueReferenceType>(ParamType)) {
-      if (!PointeeType.getQualifiers() &&
-          isa<TemplateTypeParmType>(PointeeType) &&
-          Arg->Classify(S.Context).isLValue() &&
-          Arg->getType() != S.Context.OverloadTy &&
-          Arg->getType() != S.Context.BoundMemberTy)
-        ArgType = S.Context.getLValueReferenceType(ArgType);
-    }
 
-    //   [...] If P is a reference type, the type referred to by P is used
-    //   for type deduction.
-    ParamType = PointeeType;
-  }
+  //   [...] If P is a reference type, the type referred to by P is
+  //   used for type deduction.
+  const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>();
+  if (ParamRefType)
+    ParamType = ParamRefType->getPointeeType();
 
-  // Overload sets usually make this parameter an undeduced
-  // context, but there are sometimes special circumstances.
+  // Overload sets usually make this parameter an undeduced context,
+  // but there are sometimes special circumstances.  Typically
+  // involving a template-id-expr.
   if (ArgType == S.Context.OverloadTy) {
     ArgType = ResolveOverloadForDeduction(S, TemplateParams,
                                           Arg, ParamType,
@@ -3173,12 +3155,17 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
   }
 
   if (ParamRefType) {
+    // If the argument has incomplete array type, try to complete its type.
+    if (ArgType->isIncompleteArrayType() && !S.RequireCompleteExprType(Arg, 0))
+      ArgType = Arg->getType();
+
     // C++0x [temp.deduct.call]p3:
-    //   [...] If P is of the form T&&, where T is a template parameter, and
-    //   the argument is an lvalue, the type A& is used in place of A for
-    //   type deduction.
+    //   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 (ParamRefType->isRValueReferenceType() &&
-        ParamRefType->getAs<TemplateTypeParmType>() &&
+        !ParamType.getQualifiers() &&
+        isa<TemplateTypeParmType>(ParamType) &&
         Arg->isLValue())
       ArgType = S.Context.getLValueReferenceType(ArgType);
   } else {
index c59f10dbb12e1c69295d5287a098211a6abd5e8c..e33d1576da58b94b750465976d39b321e73d4d44 100644 (file)
@@ -202,3 +202,8 @@ namespace PR19372 {
     using T = S<int, int>;
   }
 }
+
+namespace PR18645 {
+  template<typename F> F Quux(F &&f);
+  auto Baz = Quux(Quux<float>);
+}