]> granicus.if.org Git - clang/commitdiff
Implement the rvalue-reference deduction transformation (from T&& ->
authorDouglas Gregor <dgregor@apple.com>
Tue, 25 Jan 2011 17:19:08 +0000 (17:19 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 25 Jan 2011 17:19:08 +0000 (17:19 +0000)
T) when taking the address of an overloaded function or matching a
specialization to a template (C++0x [temp.deduct.type]p10). Fixes
PR9044.

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

lib/Sema/SemaTemplateDeduction.cpp
test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p10-0x.cpp [new file with mode: 0644]

index 5c899ebdea365070fd3f0e82b5053efdbc8846ab..00d92bc6b535e7da4ac8e2ee1318adeb49fd678d 100644 (file)
@@ -49,7 +49,10 @@ namespace clang {
     /// \brief Allow non-dependent types to differ, e.g., when performing
     /// template argument deduction from a function call where conversions
     /// may apply.
-    TDF_SkipNonDependent = 0x08
+    TDF_SkipNonDependent = 0x08,
+    /// \brief Whether we are performing template argument deduction for
+    /// parameters and arguments in a top-level template argument 
+    TDF_TopLevelParameterTypeList = 0x10
   };
 }
 
@@ -763,9 +766,9 @@ DeduceTemplateArguments(Sema &S,
       
       // Deduce template arguments from the pattern.
       if (Sema::TemplateDeductionResult Result 
-          = DeduceTemplateArguments(S, TemplateParams, Pattern, Args[ArgIdx],
-                                    Info, Deduced, PartialOrdering,
-                                    RefParamComparisons))
+            = DeduceTemplateArguments(S, TemplateParams, Pattern, Args[ArgIdx],
+                                      Info, Deduced, TDF, PartialOrdering,
+                                      RefParamComparisons))
         return Result;
       
       // Capture the deduced template arguments for each parameter pack expanded
@@ -898,6 +901,29 @@ DeduceTemplateArguments(Sema &S,
                              Arg.getCVRQualifiers());
       Param = S.Context.getQualifiedType(UnqualParam, Quals);
     }
+    
+    if ((TDF & TDF_TopLevelParameterTypeList) && !Param->isFunctionType()) {
+      // C++0x [temp.deduct.type]p10:
+      //   If P and A are function types that originated from deduction when
+      //   taking the address of a function template (14.8.2.2) or when deducing
+      //   template arguments from a function declaration (14.8.2.6) and Pi and
+      //   Ai are parameters of the top-level parameter-type-list of P and A, 
+      //   respectively, Pi is adjusted if it is an rvalue reference to a 
+      //   cv-unqualified template parameter and Ai is an lvalue reference, in 
+      //   which case the type of Pi is changed to be the template parameter 
+      //   type (i.e., T&& is changed to simply T). [ Note: As a result, when
+      //   Pi is T&& and Ai is X&, the adjusted Pi will be T, causing T to be
+      //   deduced as X&. — end note ]
+      TDF &= ~TDF_TopLevelParameterTypeList;
+      
+      if (const RValueReferenceType *ParamRef
+                                        = Param->getAs<RValueReferenceType>()) {
+        if (isa<TemplateTypeParmType>(ParamRef->getPointeeType()) &&
+            !ParamRef->getPointeeType().getQualifiers())
+          if (Arg->isLValueReferenceType())
+            Param = ParamRef->getPointeeType();
+      }
+    }
   }
   
   // If the parameter type is not dependent, there is nothing to deduce.
@@ -1119,6 +1145,7 @@ DeduceTemplateArguments(Sema &S,
     //     T(*)()
     //     T(*)(T)
     case Type::FunctionProto: {
+      unsigned SubTDF = TDF & TDF_TopLevelParameterTypeList;
       const FunctionProtoType *FunctionProtoArg =
         dyn_cast<FunctionProtoType>(Arg);
       if (!FunctionProtoArg)
@@ -1147,7 +1174,7 @@ DeduceTemplateArguments(Sema &S,
                                      FunctionProtoParam->getNumArgs(),
                                      FunctionProtoArg->arg_type_begin(),
                                      FunctionProtoArg->getNumArgs(),
-                                     Info, Deduced, 0);
+                                     Info, Deduced, SubTDF);
     }
 
     case Type::InjectedClassName: {
@@ -2767,7 +2794,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
     if (TemplateDeductionResult Result
           = ::DeduceTemplateArguments(*this, TemplateParams,
                                       FunctionType, ArgFunctionType, Info,
-                                      Deduced, 0))
+                                      Deduced, TDF_TopLevelParameterTypeList))
       return Result;
   }
 
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p10-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p10-0x.cpp
new file mode 100644 (file)
index 0000000..9d342c8
--- /dev/null
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+template<typename T> void f(T&&);
+template<> void f(int&) { }
+void (*fp)(int&) = &f;