https://github.com/mizvekov updated 
https://github.com/llvm/llvm-project/pull/124313

>From 7a7950dd8fd6a01cdc0d1351b86962798d300ea6 Mon Sep 17 00:00:00 2001
From: Matheus Izvekov <mizve...@gmail.com>
Date: Sun, 12 Jan 2025 14:45:24 -0300
Subject: [PATCH] [clang] disallow narrowing when matching template template
 parameters

This fixes the core issue described in P3579, following the design
intent of P0522 to not introduce any new cases where a template
template parameter match is allowed for a template which is not valid
for all possible uses.

With this patch, narrowing conversions is disallowed for TTP matching.

This reuses the existing machinery for diagnosing narrowing in
a converted constant expression.
Since P0522 is a DR and we apply it all the way back to C++98,
this brings that machinery to use in older standards, in this
very narrow scope of TTP matching.

This still doesn't solve the ambiguity when partial ordering NTTPs of
different integral types, this is blocked by a different bug which will
be fixed in a subsequent patch.
---
 clang/docs/ReleaseNotes.rst                   |  3 +
 .../clang/Basic/DiagnosticSemaKinds.td        |  4 +-
 clang/include/clang/Sema/Sema.h               |  3 +
 clang/lib/Sema/SemaLookup.cpp                 |  2 +-
 clang/lib/Sema/SemaOverload.cpp               | 23 ++++---
 clang/lib/Sema/SemaTemplate.cpp               | 43 +++++++------
 clang/lib/Sema/SemaTemplateDeduction.cpp      |  4 +-
 clang/lib/Sema/SemaTemplateInstantiate.cpp    |  7 ++-
 clang/test/CXX/drs/cwg0xx.cpp                 |  6 +-
 clang/test/CXX/drs/cwg12xx.cpp                |  2 +
 clang/test/CXX/drs/cwg3xx.cpp                 | 16 +++--
 clang/test/CXX/expr/expr.const/p3-0x.cpp      |  8 ++-
 .../CXX/temp/temp.arg/temp.arg.nontype/p1.cpp | 15 +++--
 .../temp/temp.arg/temp.arg.template/p3-0x.cpp | 16 ++---
 clang/test/Modules/cxx-templates.cpp          |  5 +-
 clang/test/SemaObjCXX/noescape.mm             |  7 +--
 clang/test/SemaTemplate/cwg2398.cpp           | 63 +++++++++++++++++--
 clang/test/SemaTemplate/default-arguments.cpp | 28 +++++----
 .../instantiate-template-template-parm.cpp    |  4 +-
 .../SemaTemplate/instantiation-default-2.cpp  |  6 +-
 clang/test/SemaTemplate/nested-template.cpp   |  6 +-
 .../SemaTemplate/temp_arg_nontype_cxx1z.cpp   |  8 +--
 .../SemaTemplate/temp_arg_nontype_cxx20.cpp   |  4 +-
 clang/test/SemaTemplate/temp_arg_template.cpp |  7 +--
 .../SemaTemplate/temp_arg_template_p0522.cpp  |  5 +-
 25 files changed, 198 insertions(+), 97 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f110b8cf765075..b89d055304f4a6 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -329,6 +329,9 @@ C++17 Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
 - The implementation of the relaxed template template argument matching rules 
is
   more complete and reliable, and should provide more accurate diagnostics.
+  This implements:
+  - `P3310R5: Solving issues introduced by relaxed template template parameter 
matching <https://wg21.link/p3310r5>`_.
+  - `P3579R0: Fix matching of non-type template parameters when matching 
template template parameters <https://wg21.link/p3579r0>`_.
 
 Resolutions to C++ Defect Reports
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 774e5484cfa0e7..6be67a36b9fe7d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -82,11 +82,11 @@ def err_typecheck_converted_constant_expression_indirect : 
Error<
   "conversion from %0 to %1 in converted constant expression would "
   "bind reference to a temporary">;
 def err_expr_not_cce : Error<
-  "%select{case value|enumerator value|non-type template argument|"
+  "%select{case value|enumerator value|non-type template argument|non-type 
parameter of template template parameter|"
   "array size|explicit specifier argument|noexcept specifier argument|"
   "call to 'size()'|call to 'data()'}0 is not a constant expression">;
 def ext_cce_narrowing : ExtWarn<
-  "%select{case value|enumerator value|non-type template argument|"
+  "%select{case value|enumerator value|non-type template argument|non-type 
parameter of template template parameter|"
   "array size|explicit specifier argument|noexcept specifier argument|"
   "call to 'size()'|call to 'data()'}0 %select{cannot be narrowed from "
   "type %2 to %3|evaluates to %2, which cannot be narrowed to type %3}1">,
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 4d6e02fe2956e0..1ea7c62cb36f05 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9999,6 +9999,7 @@ class Sema final : public SemaBase {
     CCEK_CaseValue,    ///< Expression in a case label.
     CCEK_Enumerator,   ///< Enumerator value with fixed underlying type.
     CCEK_TemplateArg,  ///< Value of a non-type template parameter.
+    CCEK_InjectedTTP,  ///< Injected parameter of a template template 
parameter.
     CCEK_ArrayBound,   ///< Array bound in array declarator or new-expression.
     CCEK_ExplicitBool, ///< Condition in an explicit(bool) specifier.
     CCEK_Noexcept,     ///< Condition in a noexcept(bool) specifier.
@@ -11682,6 +11683,7 @@ class Sema final : public SemaBase {
                         SmallVectorImpl<TemplateArgument> &SugaredConverted,
                         SmallVectorImpl<TemplateArgument> &CanonicalConverted,
                         CheckTemplateArgumentKind CTAK, bool PartialOrdering,
+                        bool PartialOrderingTTP,
                         bool *MatchedPackOnParmToNonPackOnArg);
 
   /// Check that the given template arguments can be provided to
@@ -11755,6 +11757,7 @@ class Sema final : public SemaBase {
                                    QualType InstantiatedParamType, Expr *Arg,
                                    TemplateArgument &SugaredConverted,
                                    TemplateArgument &CanonicalConverted,
+                                   bool PartialOrderingTTP,
                                    CheckTemplateArgumentKind CTAK);
 
   /// Check a template argument against its corresponding
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 2ed8d3608d49ec..26f53532a1491f 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -3676,7 +3676,7 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
           if (CheckTemplateArgument(
                   Params->getParam(0), Arg, FD, R.getNameLoc(), R.getNameLoc(),
                   0, SugaredChecked, CanonicalChecked, CTAK_Specified,
-                  /*PartialOrdering=*/false,
+                  /*PartialOrdering=*/false, /*PartialOrderingTTP=*/false,
                   /*MatchedPackOnParmToNonPackOnArg=*/nullptr) ||
               Trap.hasErrorOccurred())
             IsTemplate = false;
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 6ae9c51c06b315..20eaf494e90bb8 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -6151,8 +6151,8 @@ static ExprResult BuildConvertedConstantExpression(Sema 
&S, Expr *From,
                                                    Sema::CCEKind CCE,
                                                    NamedDecl *Dest,
                                                    APValue &PreNarrowingValue) 
{
-  assert(S.getLangOpts().CPlusPlus11 &&
-         "converted constant expression outside C++11");
+  assert((S.getLangOpts().CPlusPlus11 || CCE == Sema::CCEK_InjectedTTP) &&
+         "converted constant expression outside C++11 or TTP matching");
 
   if (checkPlaceholderForOverload(S, From))
     return ExprError();
@@ -6221,8 +6221,10 @@ static ExprResult BuildConvertedConstantExpression(Sema 
&S, Expr *From,
   // earlier, but that's not guaranteed to work when initializing an object of
   // class type.
   ExprResult Result;
+  bool IsTemplateArgument =
+      CCE == Sema::CCEK_TemplateArg || CCE == Sema::CCEK_InjectedTTP;
   if (T->isRecordType()) {
-    assert(CCE == Sema::CCEK_TemplateArg &&
+    assert(IsTemplateArgument &&
            "unexpected class type converted constant expr");
     Result = S.PerformCopyInitialization(
         InitializedEntity::InitializeTemplateParameter(
@@ -6239,7 +6241,7 @@ static ExprResult BuildConvertedConstantExpression(Sema 
&S, Expr *From,
   //   A full-expression is [...] a constant-expression [...]
   Result = S.ActOnFinishFullExpr(Result.get(), From->getExprLoc(),
                                  /*DiscardedValue=*/false, 
/*IsConstexpr=*/true,
-                                 CCE == Sema::CCEKind::CCEK_TemplateArg);
+                                 IsTemplateArgument);
   if (Result.isInvalid())
     return Result;
 
@@ -6248,9 +6250,6 @@ static ExprResult BuildConvertedConstantExpression(Sema 
&S, Expr *From,
   QualType PreNarrowingType;
   switch (SCS->getNarrowingKind(S.Context, Result.get(), PreNarrowingValue,
                                 PreNarrowingType)) {
-  case NK_Dependent_Narrowing:
-    // Implicit conversion to a narrower type, but the expression is
-    // value-dependent so we can't tell whether it's actually narrowing.
   case NK_Variable_Narrowing:
     // Implicit conversion to a narrower type, and the value is not a constant
     // expression. We'll diagnose this in a moment.
@@ -6271,6 +6270,14 @@ static ExprResult BuildConvertedConstantExpression(Sema 
&S, Expr *From,
         << PreNarrowingValue.getAsString(S.Context, PreNarrowingType) << T;
     break;
 
+  case NK_Dependent_Narrowing:
+    // Implicit conversion to a narrower type, but the expression is
+    // value-dependent so we can't tell whether it's actually narrowing.
+    // For matching the parameters of a TTP, the conversion is ill-formed
+    // if it may narrow.
+    if (CCE != Sema::CCEK_InjectedTTP)
+      break;
+    [[fallthrough]];
   case NK_Type_Narrowing:
     // FIXME: It would be better to diagnose that the expression is not a
     // constant expression.
@@ -6343,6 +6350,8 @@ Sema::EvaluateConvertedConstantExpression(Expr *E, 
QualType T, APValue &Value,
   Expr::EvalResult Eval;
   Eval.Diag = &Notes;
 
+  assert(CCE != Sema::CCEK_InjectedTTP && "unnexpected CCE Kind");
+
   ConstantExprKind Kind;
   if (CCE == Sema::CCEK_TemplateArg && T->isRecordType())
     Kind = ConstantExprKind::ClassTemplateArgument;
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 38196c5c2bc125..f3d7749c32f918 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -5205,7 +5205,7 @@ bool Sema::CheckTemplateArgument(
     SmallVectorImpl<TemplateArgument> &SugaredConverted,
     SmallVectorImpl<TemplateArgument> &CanonicalConverted,
     CheckTemplateArgumentKind CTAK, bool PartialOrdering,
-    bool *MatchedPackOnParmToNonPackOnArg) {
+    bool PartialOrderingTTP, bool *MatchedPackOnParmToNonPackOnArg) {
   // Check template type parameters.
   if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
     return CheckTemplateTypeArgument(TTP, Arg, SugaredConverted,
@@ -5260,8 +5260,9 @@ bool Sema::CheckTemplateArgument(
       Expr *E = Arg.getArgument().getAsExpr();
       TemplateArgument SugaredResult, CanonicalResult;
       unsigned CurSFINAEErrors = NumSFINAEErrors;
-      ExprResult Res = CheckTemplateArgument(NTTP, NTTPType, E, SugaredResult,
-                                             CanonicalResult, CTAK);
+      ExprResult Res =
+          CheckTemplateArgument(NTTP, NTTPType, E, SugaredResult,
+                                CanonicalResult, PartialOrderingTTP, CTAK);
       if (Res.isInvalid())
         return true;
       // If the current template argument causes an error, give up now.
@@ -5326,7 +5327,8 @@ bool Sema::CheckTemplateArgument(
 
         TemplateArgument SugaredResult, CanonicalResult;
         E = CheckTemplateArgument(NTTP, NTTPType, E.get(), SugaredResult,
-                                  CanonicalResult, CTAK_Specified);
+                                  CanonicalResult, 
/*PartialOrderingTTP=*/false,
+                                  CTAK_Specified);
         if (E.isInvalid())
           return true;
 
@@ -5585,11 +5587,11 @@ bool Sema::CheckTemplateArgumentList(
               getExpandedPackSize(*Param))
             Arg = Arg.getPackExpansionPattern();
           TemplateArgumentLoc NewArgLoc(Arg, ArgLoc.getLocInfo());
-          if (CheckTemplateArgument(*Param, NewArgLoc, Template, TemplateLoc,
-                                    RAngleLoc, SugaredArgumentPack.size(),
-                                    SugaredConverted, CanonicalConverted,
-                                    CTAK_Specified, /*PartialOrdering=*/false,
-                                    MatchedPackOnParmToNonPackOnArg))
+          if (CheckTemplateArgument(
+                  *Param, NewArgLoc, Template, TemplateLoc, RAngleLoc,
+                  SugaredArgumentPack.size(), SugaredConverted,
+                  CanonicalConverted, CTAK_Specified, 
/*PartialOrdering=*/false,
+                  /*PartialOrderingTTP=*/true, 
MatchedPackOnParmToNonPackOnArg))
             return true;
           Arg = NewArgLoc.getArgument();
           CanonicalConverted.back().setIsDefaulted(
@@ -5601,11 +5603,11 @@ bool Sema::CheckTemplateArgumentList(
             TemplateArgumentLoc(TemplateArgument::CreatePackCopy(Context, 
Args),
                                 ArgLoc.getLocInfo());
       } else {
-        if (CheckTemplateArgument(*Param, ArgLoc, Template, TemplateLoc,
-                                  RAngleLoc, SugaredArgumentPack.size(),
-                                  SugaredConverted, CanonicalConverted,
-                                  CTAK_Specified, /*PartialOrdering=*/false,
-                                  MatchedPackOnParmToNonPackOnArg))
+        if (CheckTemplateArgument(
+                *Param, ArgLoc, Template, TemplateLoc, RAngleLoc,
+                SugaredArgumentPack.size(), SugaredConverted,
+                CanonicalConverted, CTAK_Specified, /*PartialOrdering=*/false,
+                PartialOrderingTTP, MatchedPackOnParmToNonPackOnArg))
           return true;
         CanonicalConverted.back().setIsDefaulted(
             clang::isSubstitutedDefaultArgument(Context, ArgLoc.getArgument(),
@@ -5753,6 +5755,7 @@ bool Sema::CheckTemplateArgumentList(
     if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc, RAngleLoc, 0,
                               SugaredConverted, CanonicalConverted,
                               CTAK_Specified, /*PartialOrdering=*/false,
+                              /*PartialOrderingTTP=*/false,
                               /*MatchedPackOnParmToNonPackOnArg=*/nullptr))
       return true;
 
@@ -6740,6 +6743,7 @@ ExprResult 
Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
                                        QualType ParamType, Expr *Arg,
                                        TemplateArgument &SugaredConverted,
                                        TemplateArgument &CanonicalConverted,
+                                       bool PartialOrderingTTP,
                                        CheckTemplateArgumentKind CTAK) {
   SourceLocation StartLoc = Arg->getBeginLoc();
 
@@ -6930,17 +6934,20 @@ ExprResult 
Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
     IsConvertedConstantExpression = false;
   }
 
-  if (getLangOpts().CPlusPlus17) {
+  if (getLangOpts().CPlusPlus17 || PartialOrderingTTP) {
     // C++17 [temp.arg.nontype]p1:
     //   A template-argument for a non-type template parameter shall be
     //   a converted constant expression of the type of the template-parameter.
     APValue Value;
     ExprResult ArgResult;
     if (IsConvertedConstantExpression) {
-      ArgResult = BuildConvertedConstantExpression(Arg, ParamType,
-                                                   CCEK_TemplateArg, Param);
-      if (ArgResult.isInvalid())
+      ArgResult = BuildConvertedConstantExpression(
+          Arg, ParamType,
+          PartialOrderingTTP ? CCEK_InjectedTTP : CCEK_TemplateArg, Param);
+      if (ArgResult.isInvalid()) {
+        NoteTemplateParameterLocation(*Param);
         return ExprError();
+      }
     } else {
       ArgResult = Arg;
     }
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 7882d7a755d345..2b96692727a7c8 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -2979,7 +2979,8 @@ static bool ConvertDeducedTemplateArgument(
             ? (Arg.wasDeducedFromArrayBound() ? 
Sema::CTAK_DeducedFromArrayBound
                                               : Sema::CTAK_Deduced)
             : Sema::CTAK_Specified,
-        PartialOrdering, &MatchedPackOnParmToNonPackOnArg);
+        PartialOrdering, /*PartialOrderingTTP=*/false,
+        &MatchedPackOnParmToNonPackOnArg);
     if (MatchedPackOnParmToNonPackOnArg)
       Info.setMatchedPackOnParmToNonPackOnArg();
     return Res;
@@ -3179,6 +3180,7 @@ static TemplateDeductionResult 
ConvertDeducedTemplateArguments(
             Param, DefArg, TD, TD->getLocation(), 
TD->getSourceRange().getEnd(),
             /*ArgumentPackIndex=*/0, SugaredBuilder, CanonicalBuilder,
             Sema::CTAK_Specified, /*PartialOrdering=*/false,
+            /*PartialOrderingTTP=*/false,
             /*MatchedPackOnParmToNonPackOnArg=*/nullptr)) {
       Info.Param = makeTemplateParameter(
                          const_cast<NamedDecl *>(TemplateParams->getParam(I)));
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp 
b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 3dc5696bd38216..862086a0c53408 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2399,9 +2399,10 @@ 
TemplateInstantiator::TransformSubstNonTypeTemplateParmExpr(
   // The call to CheckTemplateArgument here produces the ImpCast.
   TemplateArgument SugaredConverted, CanonicalConverted;
   if (SemaRef
-          .CheckTemplateArgument(E->getParameter(), SubstType,
-                                 SubstReplacement.get(), SugaredConverted,
-                                 CanonicalConverted, Sema::CTAK_Specified)
+          .CheckTemplateArgument(
+              E->getParameter(), SubstType, SubstReplacement.get(),
+              SugaredConverted, CanonicalConverted,
+              /*PartialOrderingTTP=*/false, Sema::CTAK_Specified)
           .isInvalid())
     return true;
   return transformNonTypeTemplateParmRef(E->getAssociatedDecl(),
diff --git a/clang/test/CXX/drs/cwg0xx.cpp b/clang/test/CXX/drs/cwg0xx.cpp
index 15f469440c66f2..44a0eb520af221 100644
--- a/clang/test/CXX/drs/cwg0xx.cpp
+++ b/clang/test/CXX/drs/cwg0xx.cpp
@@ -521,12 +521,12 @@ namespace example1 {
   namespace A {
     int i;
   }
-  
+
   namespace A1 {
     using A::i;
     using A::i;
   }
-  
+
   void f()
   {
     using A::i;
@@ -1371,7 +1371,7 @@ namespace cwg92 { // cwg92: 4 c++17
   // considered in this context. In C++17, we *do* perform an implicit
   // conversion (which performs initialization), and the exception 
specification
   // is part of the type of the parameter, so this is invalid.
-  template<void() throw()> struct X {};
+  template<void() throw()> struct X {}; // since-cxx17-note {{template 
parameter is declared here}}
   X<&f> xp;
   // since-cxx17-error@-1 {{value of type 'void (*)() throw(int, float)' is 
not implicitly convertible to 'void (*)() throw()'}}
 
diff --git a/clang/test/CXX/drs/cwg12xx.cpp b/clang/test/CXX/drs/cwg12xx.cpp
index 344adb6d720231..e02a7e11b80b2a 100644
--- a/clang/test/CXX/drs/cwg12xx.cpp
+++ b/clang/test/CXX/drs/cwg12xx.cpp
@@ -155,6 +155,8 @@ namespace cwg1295 { // cwg1295: 4
   // cxx98-14-error@-1 {{non-type template argument does not refer to any 
declaration}}
   //   cxx98-14-note@#cwg1295-Y {{template parameter is declared here}}
   // since-cxx17-error@#cwg1295-y {{reference cannot bind to bit-field in 
converted constant expression}}
+  //   since-cxx17-note@#cwg1295-Y {{template parameter is declared here}}
+
 
 #if __cplusplus >= 201103L
   const unsigned other = 0;
diff --git a/clang/test/CXX/drs/cwg3xx.cpp b/clang/test/CXX/drs/cwg3xx.cpp
index b5e07a66bb4eda..6c420ecd4c91db 100644
--- a/clang/test/CXX/drs/cwg3xx.cpp
+++ b/clang/test/CXX/drs/cwg3xx.cpp
@@ -444,7 +444,7 @@ namespace cwg329 { // cwg329: 3.5
     //   expected-note@#cwg329-b {{in instantiation of template class 
'cwg329::A<char>' requested here}}
     //   expected-note@#cwg329-i {{previous definition is here}}
   };
-  A<int> a; 
+  A<int> a;
   A<char> b; // #cwg329-b
 
   void test() {
@@ -688,9 +688,9 @@ namespace cwg341 { // cwg341: sup 1708
   namespace B {
     extern "C" int &cwg341_a = cwg341_a;
     // expected-error@-1 {{redefinition of 'cwg341_a'}}
-    //   expected-note@#cwg341_a {{previous definition is here}} 
+    //   expected-note@#cwg341_a {{previous definition is here}}
   }
-  extern "C" void cwg341_b(); // #cwg341_b 
+  extern "C" void cwg341_b(); // #cwg341_b
 }
 int cwg341_a;
 // expected-error@-1 {{declaration of 'cwg341_a' in global scope conflicts 
with declaration with C language linkage}}
@@ -708,7 +708,7 @@ namespace cwg341 {
   // expected-error@-1 {{declaration of 'cwg341_d' with C language linkage 
conflicts with declaration in global scope}}
   //   expected-note@#cwg341_d {{declared in global scope here}}
 
-  namespace A { extern "C" int cwg341_e; } // #cwg341_e 
+  namespace A { extern "C" int cwg341_e; } // #cwg341_e
   namespace B { extern "C" void cwg341_e(); }
   // expected-error@-1 {{redefinition of 'cwg341_e' as different kind of 
symbol}}
   //   expected-note@#cwg341_e {{previous definition is here}}
@@ -960,6 +960,7 @@ namespace cwg354 { // cwg354: 3.1 c++11
   // cxx11-14-error@#cwg354-p0 {{null non-type template argument must be cast 
to template parameter type 'int *'}}
   //   cxx11-14-note@#cwg354-ptr {{template parameter is declared here}}
   // since-cxx17-error@#cwg354-p0 {{conversion from 'int' to 'int *' is not 
allowed in a converted constant expression}}
+  //   since-cxx17-note@#cwg354-ptr {{template parameter is declared here}}
   ptr<(int*)0> p1;
   // cxx98-error@-1 {{non-type template argument does not refer to any 
declaration}}
   //   cxx98-note@#cwg354-ptr {{template parameter is declared here}}
@@ -969,12 +970,14 @@ namespace cwg354 { // cwg354: 3.1 c++11
   // cxx11-14-error@#cwg354-p2 {{null non-type template argument of type 
'float *' does not match template parameter of type 'int *'}}
   //   cxx11-14-note@#cwg354-ptr {{template parameter is declared here}}
   // since-cxx17-error@#cwg354-p2 {{value of type 'float *' is not implicitly 
convertible to 'int *'}}
+  //   since-cxx17-note@#cwg354-ptr {{template parameter is declared here}}
   ptr<(int S::*)0> p3; // #cwg354-p3
   // cxx98-error@#cwg354-p3 {{non-type template argument does not refer to any 
declaration}}
   //   cxx98-note@#cwg354-ptr {{template parameter is declared here}}
   // cxx11-14-error@#cwg354-p3 {{null non-type template argument of type 'int 
S::*' does not match template parameter of type 'int *'}}
   //   cxx11-14-note@#cwg354-ptr {{template parameter is declared here}}
   // since-cxx17-error@#cwg354-p3 {{value of type 'int S::*' is not implicitly 
convertible to 'int *'}}
+  //   since-cxx17-note@#cwg354-ptr {{template parameter is declared here}}
 
   template<int*> int both(); // #cwg354-both-int-ptr
   template<int> int both(); // #cwg354-both-int
@@ -991,6 +994,7 @@ namespace cwg354 { // cwg354: 3.1 c++11
   // cxx11-14-error@#cwg354-m0 {{null non-type template argument must be cast 
to template parameter type 'int S::*'}}
   //   cxx11-14-note@#cwg354-ptr_mem {{template parameter is declared here}}
   // since-cxx17-error@#cwg354-m0 {{conversion from 'int' to 'int S::*' is not 
allowed in a converted constant expression}}
+  //   since-cxx17-note@#cwg354-ptr_mem {{template parameter is declared here}}
   ptr_mem<(int S::*)0> m1;
   // cxx98-error@-1 {{non-type template argument is not a pointer to member 
constant}}
   ptr_mem<(float S::*)0> m2; // #cwg354-m2
@@ -999,12 +1003,14 @@ namespace cwg354 { // cwg354: 3.1 c++11
   // cxx11-14-error@#cwg354-m2 {{null non-type template argument of type 
'float S::*' does not match template parameter of type 'int S::*'}}
   //   cxx11-14-note@#cwg354-ptr_mem {{template parameter is declared here}}
   // since-cxx17-error@#cwg354-m2 {{value of type 'float S::*' is not 
implicitly convertible to 'int S::*'}}
+  //   since-cxx17-note@#cwg354-ptr_mem {{template parameter is declared here}}
   ptr_mem<(int *)0> m3; // #cwg354-m3
   // cxx98-error@#cwg354-m3 {{non-type template argument of type 'int *' 
cannot be converted to a value of type 'int S::*'}}
   //   cxx98-note@#cwg354-ptr_mem {{template parameter is declared here}}
   // cxx11-14-error@#cwg354-m3 {{null non-type template argument of type 'int 
*' does not match template parameter of type 'int S::*'}}
   //   cxx11-14-note@#cwg354-ptr_mem {{template parameter is declared here}}
   // since-cxx17-error@#cwg354-m3 {{value of type 'int *' is not implicitly 
convertible to 'int S::*'}}
+  //   since-cxx17-note@#cwg354-ptr_mem {{template parameter is declared here}}
 } // namespace cwg354
 
 struct cwg355_S; // cwg355: 2.7
@@ -1116,7 +1122,7 @@ namespace cwg364 { // cwg364: 2.7
 } // namespace cwg364
 
 namespace cwg366 { // cwg366: 2.7
-#if "foo" // expected-error {{invalid token at start of a preprocessor 
expression}} 
+#if "foo" // expected-error {{invalid token at start of a preprocessor 
expression}}
 #endif
 } // namespace cwg366
 
diff --git a/clang/test/CXX/expr/expr.const/p3-0x.cpp 
b/clang/test/CXX/expr/expr.const/p3-0x.cpp
index 5bd70c5250b598..3eedef3cf7712f 100644
--- a/clang/test/CXX/expr/expr.const/p3-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p3-0x.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
-// RUN: %clang_cc1 -fsyntax-only -std=c++1z -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify=expected,cxx11 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify=expected,cxx17 %s
 
 // A converted constant expression of type T is a core constant expression,
 int nonconst = 8; // expected-note 3 {{here}}
@@ -66,7 +66,8 @@ enum class EEE : unsigned short {
   e = 123456, // expected-error {{enumerator value evaluates to 123456, which 
cannot be narrowed to type 'unsigned short'}}
   f = -3 // expected-error {{enumerator value evaluates to -3, which cannot be 
narrowed to type 'unsigned short'}}
 };
-template<unsigned char> using A = int;
+template<unsigned char> using A = int; // cxx17-note 2{{template parameter is 
declared here}}
+
 using Int = A<E6>;
 using Int = A<EE::EE32>; // expected-error {{not implicitly convertible}}
 using Int = A<(int)EE::EE32>;
@@ -78,6 +79,7 @@ using Int = A<-3>; // expected-error {{template argument 
evaluates to -3, which
 // integral conversions as well as boolean conversions.
 // FIXME: Per core issue 1407, this is not correct.
 template<typename T, T v> struct Val { static constexpr T value = v; };
+// cxx17-note@-1 2{{template parameter is declared here}}
 static_assert(Val<bool, E1>::value == 1, ""); // ok
 static_assert(Val<bool, '\0'>::value == 0, ""); // ok
 static_assert(Val<bool, U'\1'>::value == 1, ""); // ok
diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp 
b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp
index 7fce6155169245..629000d88acc37 100644
--- a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp
+++ b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp
@@ -8,7 +8,7 @@
 //   be one of:
 //   -- an integral constant expression; or
 //   -- the name of a non-type template-parameter ; or
-#ifndef CPP11ONLY 
+#ifndef CPP11ONLY
 
 namespace non_type_tmpl_param {
   template <int N> struct X0 { X0(); };
@@ -31,15 +31,18 @@ namespace non_type_tmpl_param {
 //      omitted if the name refers to a function or array and shall be omitted
 //      if the corresopnding template-parameter is a reference; or
 namespace addr_of_obj_or_func {
-  template <int* p> struct X0 { }; // precxx17-note 5{{here}}
+  template <int* p> struct X0 { }; // expected-note 5{{here}}
 #if __cplusplus >= 201103L
   // precxx17-note@-2 2{{template parameter is declared here}}
 #endif
 
-  template <int (*fp)(int)> struct X1 { };
-  template <int &p> struct X2 { }; // precxx17-note 4{{here}}
-  template <const int &p> struct X2k { }; // precxx17-note {{here}}
-  template <int (&fp)(int)> struct X3 { }; // precxx17-note 4{{here}}
+  template <int (*fp)(int)> struct X1 { }; // cxx17-note {{here}}
+#if __cplusplus <= 199711L
+  // precxx17-note@-2 {{here}}
+#endif
+  template <int &p> struct X2 { }; // expected-note 4{{here}}
+  template <const int &p> struct X2k { }; // expected-note {{here}}
+  template <int (&fp)(int)> struct X3 { }; // expected-note 4{{here}}
 
   int i = 42;
 #if __cplusplus >= 201103L
diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp 
b/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp
index 54fcfccad6f520..3caed045c6688b 100644
--- a/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp
+++ b/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp
@@ -18,8 +18,9 @@ eval<D<int, 17>> eD; // expected-error{{implicit 
instantiation of undefined temp
 eval<E<int, float>> eE; // expected-error{{implicit instantiation of undefined 
template 'eval<E<int, float>>}}
 
 template<
-  template <int ...N> // expected-error{{deduced non-type template argument 
does not have the same type as the corresponding template parameter ('int' vs 
'void *')}}
-  class TT // expected-note {{previous template template parameter is here}}
+  template <int ...N> // expected-error {{cannot be narrowed from type 'int' 
to 'short'}}
+                      // expected-error@-1 {{conversion from 'int' to 'void *' 
is not allowed in a converted constant expression}}
+  class TT // expected-note 2{{previous template template parameter is here}}
 > struct X0 { };
 
 template<int I, int J, int ...Rest> struct X0a;
@@ -31,12 +32,13 @@ template<int I, void *J> struct X0e; // 
expected-note{{template parameter is dec
 X0<X0a> inst_x0a;
 X0<X0b> inst_x0b;
 X0<X0c> inst_x0c;
-X0<X0d> inst_x0d;
+X0<X0d> inst_x0d; // expected-note {{has different template parameters}}
 X0<X0e> inst_x0e; // expected-note{{template template argument has different 
template parameters than its corresponding template template parameter}}
 
 template<typename T,
-         template <T ...N> // expected-error{{deduced non-type template 
argument does not have the same type as the corresponding template parameter 
('short' vs 'void *')}}
-         class TT // expected-note {{previous template template parameter is 
here}}
+         template <T ...N> // expected-error {{conversion from 'short' to 
'void *' is not allowed in a converted constant expression}}
+                           // expected-error@-1 {{cannot be narrowed from type 
'int' to 'short'}}
+         class TT // expected-note 2{{previous template template parameter is 
here}}
 > struct X1 { };
 
 template<int I, int J, int ...Rest> struct X1a;
@@ -49,8 +51,8 @@ X1<int, X1a> inst_x1a;
 X1<long, X1b> inst_x1b;
 X1<short, X1c> inst_x1c;
 X1<short, X1d> inst_sx1d;
-X1<int, X1d> inst_ix1d;
-X1<short, X1e> inst_x1e; // expected-note{{template template argument has 
different template parameters than its corresponding template template 
parameter}}
+X1<int, X1d> inst_ix1d;  // expected-note {{has different template parameters}}
+X1<short, X1e> inst_x1e; // expected-note {{has different template parameters}}
 
 template <int> class X2; // expected-note{{template is declared here}} \
                          // expected-note{{template is declared here}}
diff --git a/clang/test/Modules/cxx-templates.cpp 
b/clang/test/Modules/cxx-templates.cpp
index b197f319e0d153..f587af4beb7ceb 100644
--- a/clang/test/Modules/cxx-templates.cpp
+++ b/clang/test/Modules/cxx-templates.cpp
@@ -40,7 +40,10 @@ void g() {
 
   template_param_kinds_1<0>(); // ok, from cxx-templates-a.h
   template_param_kinds_1<int>(); // ok, from cxx-templates-b.h
-  template_param_kinds_2<Tmpl_T_C>(); // ok, from cxx-templates-b.h
+
+  template_param_kinds_2<Tmpl_T_C>(); // expected-error {{no matching function 
for call}}
+  // expected-note@Inputs/cxx-templates-a.h:11 {{candidate}}
+  // expected-note@Inputs/cxx-templates-b.h:11 {{candidate}}
 
   template_param_kinds_2<Tmpl_T_I_I>(); // expected-error {{ambiguous}}
   // expected-note@Inputs/cxx-templates-a.h:11 {{candidate}}
diff --git a/clang/test/SemaObjCXX/noescape.mm 
b/clang/test/SemaObjCXX/noescape.mm
index 999a91b87300b7..4484e3b955ac03 100644
--- a/clang/test/SemaObjCXX/noescape.mm
+++ b/clang/test/SemaObjCXX/noescape.mm
@@ -77,12 +77,11 @@ -(void) m0:(int*) p {}
 void (*fnptr0)(int *);
 void (*fnptr1)(__attribute__((noescape)) int *);
 template<void (*fn)(int*)> struct S4 {};
-template<void (*fn)(int* __attribute__((noescape)))> struct S5 {};
-
 #if __cplusplus < 201406
-  // expected-note@-4 {{template parameter is declared here}}
-  // expected-note@-4 {{template parameter is declared here}}
+// expected-note@-2 {{template parameter is declared here}}
 #endif
+template<void (*fn)(int* __attribute__((noescape)))> struct S5 {};
+// expected-note@-1 {{template parameter is declared here}}
 
 void test0() {
   fnptr0 = &func0;
diff --git a/clang/test/SemaTemplate/cwg2398.cpp 
b/clang/test/SemaTemplate/cwg2398.cpp
index 21a1b89ce79b4e..888ae59f687ef5 100644
--- a/clang/test/SemaTemplate/cwg2398.cpp
+++ b/clang/test/SemaTemplate/cwg2398.cpp
@@ -362,15 +362,17 @@ namespace classes {
 
 namespace packs {
   namespace t1 {
-    // FIXME: This should be rejected
     template<template<int, int...> class> struct A {};
-    // old-note@-1 {{previous non-type template parameter with type 'int' is 
here}}
+    // new-error@-1 {{non-type parameter of template template parameter cannot 
be narrowed from type 'int' to 'char'}}
+    // new-note@-2 {{previous template template parameter is here}}
+    // old-note@-3 {{previous non-type template parameter with type 'int' is 
here}}
 
     template<char> struct B;
     // old-note@-1 {{template non-type parameter has a different type 'char' 
in template argument}}
 
     template struct A<B>;
-    // old-error@-1 {{has different template parameters}}
+    // new-note@-1 {{has different template parameters}}
+    // old-error@-2 {{has different template parameters}}
   } // namespace t1
   namespace t2 {
     template<template<char, int...> class> struct A {};
@@ -383,15 +385,17 @@ namespace packs {
     // old-error@-1 {{has different template parameters}}
   } // namespace t2
   namespace t3 {
-    // FIXME: This should be rejected
     template<template<int...> class> struct A {};
-    // old-note@-1 {{previous non-type template parameter with type 'int' is 
here}}
+    // new-error@-1 {{non-type parameter of template template parameter cannot 
be narrowed from type 'int' to 'char'}}
+    // new-note@-2 {{previous template template parameter is here}}
+    // old-note@-3 {{previous non-type template parameter with type 'int' is 
here}}
 
     template<char> struct B;
     // old-note@-1 {{template non-type parameter has a different type 'char' 
in template argument}}
 
     template struct A<B>;
-    // old-error@-1 {{has different template parameters}}
+    // new-note@-1 {{has different template parameters}}
+    // old-error@-2 {{has different template parameters}}
   } // namespace t3
   namespace t4 {
     template<template<char...> class> struct A {};
@@ -648,3 +652,50 @@ namespace nttp_auto {
     // new-note@-1 {{different template parameters}}
   } // namespace t3
 } // namespace nttp_auto
+
+namespace nttp_partial_order {
+  namespace t1 {
+    // FIXME: This should pick the second overload.
+    template<template<short> class TT1> void f(TT1<0>);
+    // new-note@-1 {{here}}
+    template<template<int>   class TT2> void f(TT2<0>) {};
+    // new-note@-1 {{here}}
+    template<int> struct B {};
+    template void f<B>(B<0>);
+    // new-error@-1 {{ambiguous}}
+  } // namespace t1
+  namespace t2 {
+    // FIXME: This should pick the second overload.
+    struct A {} a;
+    template<template<A&>       class TT1> void f(TT1<a>);
+    // new-note@-1 {{here}}
+    template<template<const A&> class TT2> void f(TT2<a>) {};
+    // new-note@-1 {{here}}
+    template<const A&> struct B {};
+    template void f<B>(B<a>);
+    // new-error@-1 {{ambiguous}}
+  } // namespace t2
+  namespace t3 {
+    // FIXME: This should pick the second overload.
+    struct A {} a;
+    template<template<A*>       class TT1> void f(TT1<&a>);
+    // new-note@-1 {{here}}
+    template<template<const A*> class TT2> void f(TT2<&a>) {};
+    // new-note@-1 {{here}}
+    template<const A*> struct B {};
+    template void f<B>(B<&a>);
+    // new-error@-1 {{ambiguous}}
+  } // namespace t3
+  namespace t4 {
+    // FIXME: This should pick the second overload.
+    struct A {};
+    using nullptr_t = decltype(nullptr);
+    template<template<nullptr_t> class TT2> void f(TT2<nullptr>);
+    // new-note@-1 {{here}}
+    template<template<A*>        class TT1> void f(TT1<nullptr>) {};
+    // new-note@-1 {{here}}
+    template<A*> struct B {};
+    template void f<B>(B<nullptr>);
+    // new-error@-1 {{ambiguous}}
+  } // namespace t4
+} // namespace nttp_partial_order
diff --git a/clang/test/SemaTemplate/default-arguments.cpp 
b/clang/test/SemaTemplate/default-arguments.cpp
index 3b1fbda414c12b..5ea34c0254ec1c 100644
--- a/clang/test/SemaTemplate/default-arguments.cpp
+++ b/clang/test/SemaTemplate/default-arguments.cpp
@@ -52,20 +52,20 @@ struct X2 {
   template<typename U = typename X1<T>::type> // expected-error{{no type named 
'type' in 'X1<int>'}} \
                                               // expected-error{{no type named 
'type' in 'X1<char>'}}
   struct Inner1 { }; // expected-note{{template is declared here}}
-  
+
   template<T Value = X1<T>::value> // expected-error{{no member named 'value' 
in 'X1<int>'}} \
                                    // expected-error{{no member named 'value' 
in 'X1<char>'}}
   struct NonType1 { }; // expected-note{{template is declared here}}
-  
+
   template<T Value>
   struct Inner2 { };
-  
+
   template<typename U>
   struct Inner3 {
     template<typename X = T, typename V = U>
     struct VeryInner { };
-    
-    template<T Value1 = sizeof(T), T Value2 = sizeof(U), 
+
+    template<T Value1 = sizeof(T), T Value2 = sizeof(U),
              T Value3 = Value1 + Value2>
     struct NonType2 { };
   };
@@ -89,11 +89,11 @@ struct is_same { static const bool value = false; };
 template<typename T>
 struct is_same<T, T> { static const bool value = true; };
 
-int array1[is_same<__typeof__(vi), 
+int array1[is_same<__typeof__(vi),
                X2<int>::Inner3<float>::VeryInner<int, float> >::value? 1 : -1];
 
 int array2[is_same<__typeof(x2_deep_nontype),
-                   X2<char>::Inner3<int>::NonType2<sizeof(char), sizeof(int), 
+                   X2<char>::Inner3<int>::NonType2<sizeof(char), sizeof(int),
                                     sizeof(char)+sizeof(int)> >::value? 1 : 
-1];
 
 // Template template parameter defaults
@@ -109,18 +109,20 @@ struct add_pointer {
 
 template<typename T, template<typename> class X = T::template apply>
   struct X4;
-int array4[is_same<X4<add_pointer>, 
+int array4[is_same<X4<add_pointer>,
                    X4<add_pointer, add_pointer::apply> >::value? 1 : -1];
 
 template<int> struct X5 {};
-template<long> struct X5b {};
-template<typename T, 
-         template<T> class B = X5>
+template<long long> struct X5b {};
+template<typename T,
+         template<T> class B = X5> // expected-error {{cannot be narrowed from 
type 'long long' to 'int'}}
+                                   // expected-note@-1 {{has different 
template parameters}}
+                                   // expected-note@-2 {{previous template 
template parameter is here}}
   struct X6 {};
 
 X6<int> x6a;
-X6<long> x6b;
-X6<long, X5b> x6c;
+X6<long long> x6b; // expected-note {{while checking a default template 
argument used here}}
+X6<long long, X5b> x6c;
 
 
 template<template<class> class X = B<int> > struct X7; // expected-error{{must 
be a class template}}
diff --git a/clang/test/SemaTemplate/instantiate-template-template-parm.cpp 
b/clang/test/SemaTemplate/instantiate-template-template-parm.cpp
index 39aeeb1c1a6a32..dce30aa2af4ee3 100644
--- a/clang/test/SemaTemplate/instantiate-template-template-parm.cpp
+++ b/clang/test/SemaTemplate/instantiate-template-template-parm.cpp
@@ -24,11 +24,13 @@ template<int> struct B;
 
 template<typename T,
          template<T Value> class X> // expected-error{{cannot have type 
'float'}}
+                                    // expected-error@-1 {{cannot be narrowed 
from type 'long long' to 'int'}}
+                                    // expected-note@-2 {{previous template 
template parameter is here}}
 struct X0 { };
 
 X0<int, B> x0b1;
 X0<float, B> x0b2; // expected-note{{while substituting}}
-X0<long, B> x0b3;
+X0<long long, B> x0b3; // expected-note {{has different template parameters}}
 
 template<template<int V> class TT>
 struct X1 { };
diff --git a/clang/test/SemaTemplate/instantiation-default-2.cpp 
b/clang/test/SemaTemplate/instantiation-default-2.cpp
index 99c25000bcb0b0..ffa77cf1ee5678 100644
--- a/clang/test/SemaTemplate/instantiation-default-2.cpp
+++ b/clang/test/SemaTemplate/instantiation-default-2.cpp
@@ -2,8 +2,10 @@
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx17,precxx20 -std=c++17 %s
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx20 %std_cxx20- %s
 
-template<typename T, T Value> struct Constant; // precxx17-note{{template 
parameter is declared here}} \
-// FIXME: bad location precxx20-error{{a non-type template parameter cannot 
have type 'float'}}
+template<typename T, T Value> struct Constant;
+// FIXME: bad location precxx20-error@-1 {{a non-type template parameter 
cannot have type 'float'}}
+// expected-note@-2 {{template parameter is declared here}}
+// cxx20-note@-3 {{template parameter is declared here}}
 
 Constant<int, 5> *c1;
 
diff --git a/clang/test/SemaTemplate/nested-template.cpp 
b/clang/test/SemaTemplate/nested-template.cpp
index a54992a3971878..4d7f2d9c5c9469 100644
--- a/clang/test/SemaTemplate/nested-template.cpp
+++ b/clang/test/SemaTemplate/nested-template.cpp
@@ -112,7 +112,9 @@ template struct X1<int>::B<bool>;
 // Template template parameters
 template<typename T>
 struct X2 {
-  template<template<class U, T Value> class>  // expected-error{{cannot have 
type 'float'}}
+  template<template<class U, T Value> class>  // expected-error {{cannot have 
type 'float'}}
+                                              // expected-error@-1 {{cannot be 
narrowed from type 'long long' to 'int'}}
+                                              // expected-note@-2 {{previous 
template template parameter is here}}
     struct Inner { };
 };
 
@@ -121,7 +123,7 @@ template<typename T, int Value>
 
 X2<int>::Inner<X2_arg> x2i1;
 X2<float> x2a; // expected-note{{instantiation}}
-X2<long>::Inner<X2_arg> x2i3;
+X2<long long>::Inner<X2_arg> x2i3; // expected-note {{has different template 
parameters}}
 
 namespace PR10896 {
   template<typename TN>
diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp 
b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
index 8d9356bb3201cd..c35743b87adbca 100644
--- a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
+++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s
 
-template<typename T, T val> struct A {};
+template<typename T, T val> struct A {}; // expected-note 3{{template 
parameter is declared here}}
 
 template<typename T, typename U> constexpr bool is_same = false;
 template<typename T> constexpr bool is_same<T, T> = true;
@@ -122,13 +122,13 @@ namespace DeduceDifferentType {
   int a_imp = a(A<3>()); // expected-error {{no matching function}}
   int a_exp = a<3>(A<3>());
 
-  template<decltype(nullptr)> struct B {};
+  template<decltype(nullptr)> struct B {}; // expected-note {{template 
parameter is declared here}}
   template<int *P> int b(B<P>); // expected-error {{value of type 'int *' is 
not implicitly convertible to 'decltype(nullptr)'}}
   int b_imp = b(B<nullptr>()); // expected-error {{no matching function}}
   int b_exp = b<nullptr>(B<nullptr>()); // expected-error {{no matching 
function}}
 
   struct X { constexpr operator int() { return 0; } } x;
-  template<X &> struct C {};
+  template<X &> struct C {}; // expected-note {{template parameter is declared 
here}}
   template<int N> int c(C<N>); // expected-error {{value of type 'int' is not 
implicitly convertible to 'X &'}}
   int c_imp = c(C<x>()); // expected-error {{no matching function}}
   int c_exp = c<x>(C<x>()); // expected-error {{no matching function}}
@@ -448,7 +448,7 @@ namespace PR42108 {
   struct R {};
   struct S { constexpr S() {} constexpr S(R) {} };
   struct T { constexpr operator S() { return {}; } };
-  template <const S &> struct A {};
+  template <const S &> struct A {}; // expected-note {{template parameter is 
declared here}}
   void f() {
     A<R{}>(); // expected-error {{would bind reference to a temporary}}
     A<S{}>(); // expected-error {{reference to temporary object}}
diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp 
b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
index ad73daa8e214c3..56ceb7af4ccd93 100644
--- a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
+++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
@@ -101,7 +101,7 @@ namespace ConvertedConstant {
   struct {
     int i : 2;
   } b;
-  template <const int&> struct Y {};
+  template <const int&> struct Y {}; // expected-note {{template parameter is 
declared here}}
   void f(Y<b.i>) {} // expected-error {{reference cannot bind to bit-field in 
converted constant expression}}
 }
 
@@ -238,7 +238,7 @@ namespace UnnamedBitfield {
 }
 
 namespace Temporary {
-  template<const int &> struct A {};
+  template<const int &> struct A {}; // expected-note {{template parameter is 
declared here}}
   A<0> a0; // expected-error {{conversion from 'int' to 'const int &' in 
converted constant expression would bind reference to a temporary}}
 
   A<(const int&)1> a1; // expected-error {{reference to temporary object is 
not allowed in a template argument}}
diff --git a/clang/test/SemaTemplate/temp_arg_template.cpp 
b/clang/test/SemaTemplate/temp_arg_template.cpp
index 9908af5e78669d..aa53dba652050e 100644
--- a/clang/test/SemaTemplate/temp_arg_template.cpp
+++ b/clang/test/SemaTemplate/temp_arg_template.cpp
@@ -7,14 +7,13 @@ template<template<typename T> class X> struct A; // #A
 template<template<typename T, int I> class X> struct B; // 
expected-note{{previous template template parameter is here}}
 
 template<template<int I> class X> struct C;
-// precxx17-error@-1 {{deduced non-type template argument does not have the 
same type as the corresponding template parameter ('int' vs 'const int &')}}
-// cxx17-error@-2 {{conversion from 'int' to 'const int &' in converted 
constant expression would bind reference to a temporary}}
-// expected-note@-3 {{previous template template parameter is here}}
+// expected-error@-1 {{conversion from 'int' to 'const int &' in converted 
constant expression would bind reference to a temporary}}
+// expected-note@-2 {{previous template template parameter is here}}
 
 template<class> struct X; // expected-note {{template is declared here}}
 template<int N> struct Y; // expected-note {{template parameter is declared 
here}}
 template<long N> struct Ylong;
-template<const int &N> struct Yref; // precxx17-note {{template parameter is 
declared here}}
+template<const int &N> struct Yref; // expected-note {{template parameter is 
declared here}}
 
 namespace N {
   template<class> struct Z;
diff --git a/clang/test/SemaTemplate/temp_arg_template_p0522.cpp 
b/clang/test/SemaTemplate/temp_arg_template_p0522.cpp
index dcfc7b5b272880..2e5a36ae6ed082 100644
--- a/clang/test/SemaTemplate/temp_arg_template_p0522.cpp
+++ b/clang/test/SemaTemplate/temp_arg_template_p0522.cpp
@@ -66,8 +66,9 @@ namespace DependentType {
   using ok = Pt<tT0<int, i>, tT0<int, iDi>>;
   using err1 = tT0<int, ii>; // expected-error {{too few template arguments 
for class template 'ii'}}
                              // expected-note@-1 {{different template 
parameters}}
-  using err2 = tT0<short, i>; // FIXME: should this be OK?
-  using err2a = tT0<long long, i>; // FIXME: should this be OK (if long long 
is larger than int)?
+  using err2 = tT0<short, i>;
+  using err2a = tT0<long long, i>; // expected-error@#tT0 {{cannot be narrowed 
from type 'long long' to 'int'}}
+                                   // expected-note@-1 {{different template 
parameters}}
   using err2b = tT0<void*, i>; // expected-error@#tT0 {{value of type 'void *' 
is not implicitly convertible to 'int'}}
                                // expected-note@-1 {{different template 
parameters}}
   using err3 = tT0<short, t0>; // expected-error@#tT0 {{template argument for 
template type parameter must be a type}}

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to