Fix bug where template argument deduction of a non-type template parameter used
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 28 Sep 2016 22:08:38 +0000 (22:08 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 28 Sep 2016 22:08:38 +0000 (22:08 +0000)
as a template argument in a template-id, from a null non-type template
argument, failed.

Extracted from a patch by James Touton!

llvm-svn: 282641

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

index f8e825f..2311b2b 100644 (file)
@@ -285,7 +285,7 @@ checkDeducedTemplateArguments(ASTContext &Context,
 }
 
 /// \brief Deduce the value of the given non-type template parameter
-/// from the given constant.
+/// from the given integral constant.
 static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
     Sema &S, NonTypeTemplateParmDecl *NTTP, const llvm::APSInt &Value,
     QualType ValueType, bool DeducedFromArrayBound, TemplateDeductionInfo &Info,
@@ -310,6 +310,32 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(
 }
 
 /// \brief Deduce the value of the given non-type template parameter
+/// from the given null pointer template argument type.
+static Sema::TemplateDeductionResult DeduceNullPtrTemplateArgument(
+    Sema &S, NonTypeTemplateParmDecl *NTTP, QualType NullPtrType,
+    TemplateDeductionInfo &Info,
+    SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
+  Expr *Value =
+      S.ImpCastExprToType(new (S.Context) CXXNullPtrLiteralExpr(
+                              S.Context.NullPtrTy, NTTP->getLocation()),
+                          NullPtrType, CK_NullToPointer)
+          .get();
+  DeducedTemplateArgument NewDeduced(Value);
+  DeducedTemplateArgument Result = checkDeducedTemplateArguments(
+      S.Context, Deduced[NTTP->getIndex()], NewDeduced);
+
+  if (Result.isNull()) {
+    Info.Param = NTTP;
+    Info.FirstArg = Deduced[NTTP->getIndex()];
+    Info.SecondArg = NewDeduced;
+    return Sema::TDK_Inconsistent;
+  }
+
+  Deduced[NTTP->getIndex()] = Result;
+  return Sema::TDK_Success;
+}
+
+/// \brief Deduce the value of the given non-type template parameter
 /// from the given type- or value-dependent expression.
 ///
 /// \returns true if deduction succeeded, false otherwise.
@@ -1758,6 +1784,9 @@ DeduceTemplateArguments(Sema &S,
                                              Arg.getIntegralType(),
                                              /*ArrayBound=*/false,
                                              Info, Deduced);
+      if (Arg.getKind() == TemplateArgument::NullPtr)
+        return DeduceNullPtrTemplateArgument(S, NTTP, Arg.getNullPtrType(),
+                                             Info, Deduced);
       if (Arg.getKind() == TemplateArgument::Expression)
         return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsExpr(),
                                              Info, Deduced);
index d024c31..7c7b0ab 100644 (file)
@@ -264,4 +264,12 @@ int main() {
   return 0;
 }
 } // end ns2 
-}
\ No newline at end of file
+}
+
+namespace nullptr_deduction {
+  template<typename T, T v> struct X {};
+  template<typename T, T v> void f(X<T, v>) {
+    static_assert(!v, "");
+  }
+  void g() { f(X<int*, nullptr>()); }
+}
index 548f7f8..98b3aa4 100644 (file)
@@ -122,7 +122,7 @@ namespace DeduceDifferentType {
   int a_exp = a<3>(A<3>());
 
   template<decltype(nullptr)> struct B {};
-  template<int *P> int b(B<P>); // expected-note {{could not match}} expected-note {{not implicitly convertible}}
+  template<int *P> int b(B<P>); // expected-note {{does not have the same type}} expected-note {{not implicitly convertible}}
   int b_imp = b(B<nullptr>()); // expected-error {{no matching function}}
   int b_exp = b<nullptr>(B<nullptr>()); // expected-error {{no matching function}}