]> granicus.if.org Git - clang/commitdiff
Improve support for 'decltype(auto)' in template template parameter matching.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 22 Feb 2017 20:01:55 +0000 (20:01 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 22 Feb 2017 20:01:55 +0000 (20:01 +0000)
A 'decltype(auto)' parameter can match any other kind of non-type template
parameter, so should be usable in place of any other parameter in a template
template argument. The standard is sadly extremely unclear on how this is
supposed to work, but this seems like the obviously-correct result.

It's less clear whether an 'auto' parameter should be able to match
'decltype(auto)', since the former cannot be used if the latter turns out to be
used for a reference type, but if we disallow that then consistency suggests we
should also disallow 'auto' matching 'T' for the same reason, defeating
intended use cases of the feature.

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

lib/Sema/SemaTemplate.cpp
test/SemaTemplate/temp_arg_template_cxx1z.cpp

index ad7b9e54f90e62346a15bffe72657b66d6ebf7d7..f6c6ccbd4100a1ea08f498e5c0db6fbd04aa0658 100644 (file)
@@ -5666,6 +5666,19 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
 
   // If the parameter type somehow involves auto, deduce the type now.
   if (getLangOpts().CPlusPlus1z && ParamType->isUndeducedType()) {
+    // During template argument deduction, we allow 'decltype(auto)' to
+    // match an arbitrary dependent argument.
+    // FIXME: The language rules don't say what happens in this case.
+    // FIXME: We get an opaque dependent type out of decltype(auto) if the
+    // expression is merely instantiation-dependent; is this enough?
+    if (CTAK == CTAK_Deduced && Arg->isTypeDependent()) {
+      auto *AT = dyn_cast<AutoType>(ParamType);
+      if (AT && AT->isDecltypeAuto()) {
+        Converted = TemplateArgument(Arg);
+        return Arg;
+      }
+    }
+
     // When checking a deduced template argument, deduce from its type even if
     // the type is dependent, in order to check the types of non-type template
     // arguments line up properly in partial ordering.
index 703935dcd5c19bfa76e6634a02fa379b11c19462..e3f228e7efb7493b7ef0f961380d5d40ee9b1a5a 100644 (file)
@@ -103,12 +103,13 @@ namespace Auto {
   TDecltypeAuto<Int> dai; // expected-error {{different template parameters}}
   TDecltypeAuto<IntPtr> daip; // expected-error {{different template parameters}}
 
-  // FIXME: It's completely unclear what should happen here. A case can be made
-  // that 'auto' is more specialized, because it's always a prvalue, whereas
-  // 'decltype(auto)' could have any value category. Under that interpretation,
-  // we get the following results entirely backwards:
-  TAuto<DecltypeAuto> ada; // expected-error {{different template parameters}}
-  TAutoPtr<DecltypeAuto> apda; // expected-error {{different template parameters}}
+  // FIXME: It's completely unclear what should happen here, but these results
+  // seem at least plausible:
+  TAuto<DecltypeAuto> ada;
+  TAutoPtr<DecltypeAuto> apda;
+  // Perhaps this case should be invalid, as there are valid 'decltype(auto)'
+  // parameters (such as 'user-defined-type &') that are not valid 'auto'
+  // parameters.
   TDecltypeAuto<Auto> daa;
   TDecltypeAuto<AutoPtr> daa; // expected-error {{different template parameters}}