Reland: [clang] Implement evaluation context for checking template parameters

Instead of manually adding a note pointing to the relevant template
parameter to every relevant error, which is very easy to miss,
this patch adds a new instantiation context note, so that this
can work using RAII magic.

This fixes a bunch of places where these notes were missing, and is
more future-proof.

Some diagnostics are reworked to make better use of this note:
- Errors about missing template arguments now refer to the parameter
  which is missing an argument.
- Template Template parameter mismatches now refer to template
  parameters as parameters instead of arguments.

It's likely this will add the note to some diagnostics where the
parameter is not super relevant, but this can be reworked with time
and the decrease in maintenance burden makes up for it.

This bypasses the templight dumper for the new context entry, as the
tests are very hard to update.

This depends on #125453, which is needed to avoid losing the context
note for errors occuring during template argument deduction.

Original PR: #126088
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 98c889c..e942834 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -304,7 +304,11 @@
 - Fixed false positives in ``-Waddress-of-packed-member`` diagnostics when
   potential misaligned members get processed before they can get discarded.
   (#GH144729)
-
+- Clang now more consistently adds a note pointing to the relevant template
+  parameter. Some diagnostics are reworded to better take advantage of this.
+- Template Template Parameter diagnostics now stop referring to template
+  parameters as template arguments, in some circumstances, better hiding
+  from the users template template parameter partial ordering arcana.
 - Clang now emits dignostic with correct message in case of assigning to const reference captured in lambda. (#GH105647)
 
 - Fixed false positive in ``-Wmissing-noreturn`` diagnostic when it was requiring the usage of
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index dc4c6d3..79ef6dd 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5358,19 +5358,14 @@
 def err_template_typedef : Error<"a typedef cannot be a template">;
 def err_template_unnamed_class : Error<
   "cannot declare a class template with no name">;
-def err_template_param_list_different_arity : Error<
-  "%select{too few|too many}0 template parameters in template "
-  "%select{|template parameter }1redeclaration">;
-def note_template_param_list_different_arity : Note<
-  "%select{too few|too many}0 template parameters in template template "
-  "argument">;
+def err_template_param_list_different_arity
+    : Error<"%select{too few|too many}0 template parameters in template "
+            "%select{|template parameter }1redeclaration">;
 def note_template_prev_declaration : Note<
   "previous template %select{declaration|template parameter}0 is here">;
-def err_template_param_different_kind : Error<
-  "template parameter has a different kind in template "
-  "%select{|template parameter }0redeclaration">;
-def note_template_param_different_kind : Note<
-  "template parameter has a different kind in template argument">;
+def err_template_param_different_kind
+    : Error<"template parameter has a different kind in template "
+            "%select{|template parameter }0redeclaration">;
 
 def err_invalid_decl_specifier_in_nontype_parm : Error<
   "invalid declaration specifier in template non-type parameter">;
@@ -5379,8 +5374,6 @@
   "template non-type parameter has a different type %0 in template "
   "%select{|template parameter }1redeclaration">;
 
-def note_template_nontype_parm_different_type : Note<
-  "template non-type parameter has a different type %0 in template argument">;
 def note_template_nontype_parm_prev_declaration : Note<
   "previous non-type template parameter with type %0 is here">;
 def err_template_nontype_parm_bad_type : Error<
@@ -5454,10 +5447,17 @@
   "%select{class template|function template|variable template|alias template|"
   "template template parameter|concept|template}0 %1 requires template "
   "arguments">;
-def err_template_arg_list_different_arity : Error<
-  "%select{too few|too many}0 template arguments for "
-  "%select{class template|function template|variable template|alias template|"
-  "template template parameter|concept|template}1 %2">;
+def err_template_param_missing_arg
+    : Error<"missing template argument for template parameter">;
+def err_template_template_param_missing_param
+    : Error<"no template parameter in this template template parameter "
+            "corresponds to non-defaulted template parameter of argument "
+            "template">;
+def err_template_too_many_args
+    : Error<"too many template arguments for "
+            "%select{class template|function template|variable template|alias "
+            "template|"
+            "template template parameter|concept|template}0 %1">;
 def note_template_decl_here : Note<"template is declared here">;
 def note_template_decl_external : Note<
   "template declaration from hidden source: %0">;
@@ -5500,12 +5500,9 @@
 def note_template_arg_refers_to_template_here
     : Note<"template argument refers to a %select{function template|class "
            "template|variable template|concept}0 %1, here">;
-def err_template_arg_template_params_mismatch : Error<
-  "template template argument has different template parameters than its "
-  "corresponding template template parameter">;
-def note_template_arg_template_params_mismatch : Note<
-  "template template argument has different template parameters than its "
-  "corresponding template template parameter">;
+def note_template_arg_template_params_mismatch
+    : Note<"template template argument is incompatible with its "
+           "corresponding template template parameter">;
 def err_non_deduced_mismatch : Error<
   "could not match %diff{$ against $|types}0,1">;
 def err_inconsistent_deduction : Error<
@@ -5770,8 +5767,10 @@
 def err_constraint_depends_on_self
     : Error<"satisfaction of constraint %0 depends on itself">,
       NoSFINAE;
-def note_template_recursion_depth : Note<
-  "use -ftemplate-depth=N to increase recursive template instantiation depth">;
+def note_template_recursion_depth
+    : Note<"use -ftemplate-depth=N to increase recursive template "
+           "instantiation depth">,
+      NoSFINAE;
 
 def err_template_instantiate_within_definition : Error<
   "%select{implicit|explicit}0 instantiation of template %1 within its"
@@ -6050,14 +6049,11 @@
 def err_template_param_pack_must_be_last_template_parameter : Error<
   "template parameter pack must be the last template parameter">;
 
-def err_template_parameter_pack_non_pack : Error<
-  "%select{template type|non-type template|template template}0 parameter"
-  "%select{| pack}1 conflicts with previous %select{template type|"
-  "non-type template|template template}0 parameter%select{ pack|}1">;
-def note_template_parameter_pack_non_pack : Note<
-  "%select{template type|non-type template|template template}0 parameter"
-  "%select{| pack}1 does not match %select{template type|non-type template"
-  "|template template}0 parameter%select{ pack|}1 in template argument">;
+def err_template_parameter_pack_non_pack
+    : Error<"%select{template type|non-type template|template template}0 "
+            "parameter"
+            "%select{| pack}1 conflicts with previous %select{template type|"
+            "non-type template|template template}0 parameter%select{ pack|}1">;
 def note_template_parameter_pack_here : Note<
   "previous %select{template type|non-type template|template template}0 "
   "parameter%select{| pack}1 declared here">;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 2bd6be2..3e464d9 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -12026,7 +12026,7 @@
                                  bool *ConstraintsNotSatisfied = nullptr);
 
   bool CheckTemplateTypeArgument(
-      TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg,
+      TemplateArgumentLoc &Arg,
       SmallVectorImpl<TemplateArgument> &SugaredConverted,
       SmallVectorImpl<TemplateArgument> &CanonicalConverted);
 
@@ -12066,9 +12066,13 @@
                                                TemplateTemplateParmDecl *Param,
                                                const TemplateArgumentLoc &Arg);
 
+  /// Print the given named declaration to a string,
+  /// using the current PrintingPolicy, except that
+  /// TerseOutput will always be set.
+  SmallString<128> toTerseString(const NamedDecl &D) const;
+
   void NoteTemplateLocation(const NamedDecl &Decl,
                             std::optional<SourceRange> ParamRange = {});
-  void NoteTemplateParameterLocation(const NamedDecl &Decl);
 
   /// Given a non-type template argument that refers to a
   /// declaration and the type of its corresponding non-type template
@@ -12183,15 +12187,13 @@
   bool TemplateParameterListsAreEqual(
       const TemplateCompareNewDeclInfo &NewInstFrom, TemplateParameterList *New,
       const NamedDecl *OldInstFrom, TemplateParameterList *Old, bool Complain,
-      TemplateParameterListEqualKind Kind,
-      SourceLocation TemplateArgLoc = SourceLocation());
+      TemplateParameterListEqualKind Kind);
 
-  bool TemplateParameterListsAreEqual(
-      TemplateParameterList *New, TemplateParameterList *Old, bool Complain,
-      TemplateParameterListEqualKind Kind,
-      SourceLocation TemplateArgLoc = SourceLocation()) {
+  bool TemplateParameterListsAreEqual(TemplateParameterList *New,
+                                      TemplateParameterList *Old, bool Complain,
+                                      TemplateParameterListEqualKind Kind) {
     return TemplateParameterListsAreEqual(nullptr, New, nullptr, Old, Complain,
-                                          Kind, TemplateArgLoc);
+                                          Kind);
   }
 
   /// Check whether a template can be declared within this scope.
@@ -13088,6 +13090,11 @@
 
       /// We are performing partial ordering for template template parameters.
       PartialOrderingTTP,
+
+      /// We are Checking a Template Parameter, so for any diagnostics which
+      /// occur in this scope, we will add a context note which points to this
+      /// template parameter.
+      CheckTemplateParameter,
     } Kind;
 
     /// Was the enclosing context a non-instantiation SFINAE context?
@@ -13318,6 +13325,10 @@
                           PartialOrderingTTP, TemplateDecl *PArg,
                           SourceRange InstantiationRange = SourceRange());
 
+    struct CheckTemplateParameter {};
+    /// \brief Note that we are checking a template parameter.
+    InstantiatingTemplate(Sema &SemaRef, CheckTemplateParameter);
+
     /// Note that we have finished instantiating this template.
     void Clear();
 
@@ -13335,8 +13346,6 @@
     Sema &SemaRef;
     bool Invalid;
     bool AlreadyInstantiating;
-    bool CheckInstantiationDepth(SourceLocation PointOfInstantiation,
-                                 SourceRange InstantiationRange);
 
     InstantiatingTemplate(Sema &SemaRef,
                           CodeSynthesisContext::SynthesisKind Kind,
@@ -13351,6 +13360,30 @@
     InstantiatingTemplate &operator=(const InstantiatingTemplate &) = delete;
   };
 
+  /// For any diagnostics which occur within its scope, adds a context note
+  /// pointing to the declaration of the template parameter.
+  struct CheckTemplateParameterRAII : InstantiatingTemplate {
+    CheckTemplateParameterRAII(Sema &S, NamedDecl *Param = nullptr)
+        : InstantiatingTemplate(S, CheckTemplateParameter()),
+          Context(isInvalid() ? nullptr : &S.CodeSynthesisContexts.back()) {
+      setParam(Param);
+    }
+
+    void setParam(NamedDecl *Param) {
+      assert(!Param || Param->isTemplateParameter());
+      if (isInvalid())
+        return;
+      Context->Entity = Param;
+      Context->PointOfInstantiation =
+          Param ? Param->getLocation() : SourceLocation();
+      Context->InstantiationRange =
+          Param ? Param->getSourceRange() : SourceRange();
+    }
+
+  private:
+    Sema::CodeSynthesisContext *Context;
+  };
+
   bool SubstTemplateArgument(const TemplateArgumentLoc &Input,
                              const MultiLevelTemplateArgumentList &TemplateArgs,
                              TemplateArgumentLoc &Output,
@@ -13529,7 +13562,7 @@
     ~ArgPackSubstIndexRAII() { Self.ArgPackSubstIndex = OldSubstIndex; }
   };
 
-  void pushCodeSynthesisContext(CodeSynthesisContext Ctx);
+  bool pushCodeSynthesisContext(CodeSynthesisContext Ctx);
   void popCodeSynthesisContext();
 
   void PrintContextStack(InstantiationContextDiagFuncRef DiagFunc) {
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index 7424958..a73e0a6 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -418,7 +418,8 @@
   }
 
 private:
-  static std::string toString(CodeSynthesisContext::SynthesisKind Kind) {
+  static std::optional<std::string>
+  toString(CodeSynthesisContext::SynthesisKind Kind) {
     switch (Kind) {
     case CodeSynthesisContext::TemplateInstantiation:
       return "TemplateInstantiation";
@@ -476,8 +477,10 @@
       return "TypeAliasTemplateInstantiation";
     case CodeSynthesisContext::PartialOrderingTTP:
       return "PartialOrderingTTP";
+    case CodeSynthesisContext::CheckTemplateParameter:
+      return std::nullopt;
     }
-    return "";
+    return std::nullopt;
   }
 
   template <bool BeginInstantiation>
@@ -485,12 +488,14 @@
                                     const CodeSynthesisContext &Inst) {
     std::string YAML;
     {
+      std::optional<TemplightEntry> Entry =
+          getTemplightEntry<BeginInstantiation>(TheSema, Inst);
+      if (!Entry)
+        return;
       llvm::raw_string_ostream OS(YAML);
       llvm::yaml::Output YO(OS);
-      TemplightEntry Entry =
-          getTemplightEntry<BeginInstantiation>(TheSema, Inst);
       llvm::yaml::EmptyContext Context;
-      llvm::yaml::yamlize(YO, Entry, true, Context);
+      llvm::yaml::yamlize(YO, *Entry, true, Context);
     }
     Out << "---" << YAML << "\n";
   }
@@ -570,10 +575,13 @@
   }
 
   template <bool BeginInstantiation>
-  static TemplightEntry getTemplightEntry(const Sema &TheSema,
-                                          const CodeSynthesisContext &Inst) {
+  static std::optional<TemplightEntry>
+  getTemplightEntry(const Sema &TheSema, const CodeSynthesisContext &Inst) {
     TemplightEntry Entry;
-    Entry.Kind = toString(Inst.Kind);
+    std::optional<std::string> Kind = toString(Inst.Kind);
+    if (!Kind)
+      return std::nullopt;
+    Entry.Kind = *Kind;
     Entry.Event = BeginInstantiation ? "Begin" : "End";
     llvm::raw_string_ostream OS(Entry.Name);
     printEntryName(TheSema, Inst.Entity, OS);
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index c971293..e79ac26 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -7342,7 +7342,7 @@
 
 void InitializationSequence::PrintInitLocationNote(Sema &S,
                                               const InitializedEntity &Entity) {
-  if (Entity.isParamOrTemplateParamKind() && Entity.getDecl()) {
+  if (Entity.isParameterKind() && Entity.getDecl()) {
     if (Entity.getDecl()->getLocation().isInvalid())
       return;
 
@@ -7351,9 +7351,8 @@
         << Entity.getDecl()->getDeclName();
     else
       S.Diag(Entity.getDecl()->getLocation(), diag::note_parameter_here);
-  }
-  else if (Entity.getKind() == InitializedEntity::EK_RelatedResult &&
-           Entity.getMethodDecl())
+  } else if (Entity.getKind() == InitializedEntity::EK_RelatedResult &&
+             Entity.getMethodDecl())
     S.Diag(Entity.getMethodDecl()->getLocation(),
            diag::note_method_return_type_change)
       << Entity.getMethodDecl()->getDeclName();
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index fbc2e7e..abd030b 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -1525,13 +1525,16 @@
   TemplateParameterList *TemplateParams =
       getGenericLambdaTemplateParameterList(LSI, *this);
   if (TemplateParams) {
-    for (const auto *TP : TemplateParams->asArray()) {
+    CheckTemplateParameterRAII CTP(*this);
+    for (auto *TP : TemplateParams->asArray()) {
       if (!TP->getIdentifier())
         continue;
+      CTP.setParam(TP);
       for (const auto &Capture : Intro.Captures) {
         if (Capture.Id == TP->getIdentifier()) {
           Diag(Capture.Loc, diag::err_template_param_shadow) << Capture.Id;
-          NoteTemplateParameterLocation(*TP);
+          // forget we already emitted this stack.
+          LastEmittedCodeSynthesisContextDepth = 0;
         }
       }
     }
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 25728de..305aab6 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -1613,9 +1613,13 @@
   unsigned N = CodeSynthesisContexts.size();
   for (unsigned I = CodeSynthesisContextLookupModules.size();
        I != N; ++I) {
-    Module *M = CodeSynthesisContexts[I].Entity ?
-                getDefiningModule(*this, CodeSynthesisContexts[I].Entity) :
-                nullptr;
+    auto &Ctx = CodeSynthesisContexts[I];
+    // FIXME: Are there any other context kinds that shouldn't be looked at
+    // here?
+    if (Ctx.Kind == CodeSynthesisContext::PartialOrderingTTP ||
+        Ctx.Kind == CodeSynthesisContext::CheckTemplateParameter)
+      continue;
+    Module *M = Ctx.Entity ? getDefiningModule(*this, Ctx.Entity) : nullptr;
     if (M && !LookupModulesCache.insert(M).second)
       M = nullptr;
     CodeSynthesisContextLookupModules.push_back(M);
@@ -3738,7 +3742,8 @@
       TemplateParameterList *Params = FD->getTemplateParameters();
       if (Params->size() == 1) {
         IsTemplate = true;
-        if (!Params->getParam(0)->isTemplateParameterPack() && !StringLit) {
+        NamedDecl *Param = Params->getParam(0);
+        if (!Param->isTemplateParameterPack() && !StringLit) {
           // Implied but not stated: user-defined integer and floating literals
           // only ever use numeric literal operator templates, not templates
           // taking a parameter of class type.
@@ -3751,6 +3756,7 @@
         if (StringLit) {
           SFINAETrap Trap(*this);
           CheckTemplateArgumentInfo CTAI;
+          CheckTemplateParameterRAII CTP(*this, Param);
           TemplateArgumentLoc Arg(
               TemplateArgument(StringLit, /*IsCanonical=*/false), StringLit);
           if (CheckTemplateArgument(
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 3ebbb30..ef789f6 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -921,9 +921,11 @@
           ? diag::ext_template_param_shadow
           : (SupportedForCompatibility ? diag::ext_compat_template_param_shadow
                                        : diag::err_template_param_shadow);
-  const auto *ND = cast<NamedDecl>(PrevDecl);
+  auto *ND = cast<NamedDecl>(PrevDecl);
+  CheckTemplateParameterRAII CTP(*this, ND);
+  // FIXME: Don't put the name in the diagnostic, unless there is no source
+  // location.
   Diag(Loc, DiagId) << ND->getDeclName();
-  NoteTemplateParameterLocation(*ND);
 }
 
 TemplateDecl *Sema::AdjustDeclIfTemplate(Decl *&D) {
@@ -5135,7 +5137,7 @@
 }
 
 bool Sema::CheckTemplateTypeArgument(
-    TemplateTypeParmDecl *Param, TemplateArgumentLoc &AL,
+    TemplateArgumentLoc &AL,
     SmallVectorImpl<TemplateArgument> &SugaredConverted,
     SmallVectorImpl<TemplateArgument> &CanonicalConverted) {
   const TemplateArgument &Arg = AL.getArgument();
@@ -5191,7 +5193,6 @@
                       ? diag::ext_ms_template_type_arg_missing_typename
                       : diag::err_template_arg_must_be_type_suggest)
             << FixItHint::CreateInsertion(Loc, "typename ");
-        NoteTemplateParameterLocation(*Param);
 
         // Recover by synthesizing a type using the location information that we
         // already have.
@@ -5229,7 +5230,6 @@
     // is not a type.
     SourceRange SR = AL.getSourceRange();
     Diag(SR.getBegin(), diag::err_template_arg_must_be_type) << SR;
-    NoteTemplateParameterLocation(*Param);
 
     return true;
   }
@@ -5502,8 +5502,8 @@
                                  CheckTemplateArgumentInfo &CTAI,
                                  CheckTemplateArgumentKind CTAK) {
   // Check template type parameters.
-  if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
-    return CheckTemplateTypeArgument(TTP, ArgLoc, CTAI.SugaredConverted,
+  if (isa<TemplateTypeParmDecl>(Param))
+    return CheckTemplateTypeArgument(ArgLoc, CTAI.SugaredConverted,
                                      CTAI.CanonicalConverted);
 
   const TemplateArgument &Arg = ArgLoc.getArgument();
@@ -5646,8 +5646,6 @@
       // therefore cannot be a non-type template argument.
       Diag(ArgLoc.getLocation(), diag::err_template_arg_must_be_expr)
           << ArgLoc.getSourceRange();
-      NoteTemplateParameterLocation(*Param);
-
       return true;
 
     case TemplateArgument::Type: {
@@ -5667,7 +5665,6 @@
         Diag(SR.getBegin(), diag::err_template_arg_nontype_ambig) << SR << T;
       else
         Diag(SR.getBegin(), diag::err_template_arg_must_be_expr) << SR;
-      NoteTemplateParameterLocation(*Param);
       return true;
     }
 
@@ -5771,11 +5768,11 @@
 }
 
 /// Diagnose a missing template argument.
-template<typename TemplateParmDecl>
+template <typename TemplateParmDecl>
 static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc,
-                                    TemplateDecl *TD,
-                                    const TemplateParmDecl *D,
-                                    TemplateArgumentListInfo &Args) {
+                                    TemplateDecl *TD, const TemplateParmDecl *D,
+                                    TemplateArgumentListInfo &Args,
+                                    bool MatchingTTP) {
   // Dig out the most recent declaration of the template parameter; there may be
   // declarations of the template that are more recent than TD.
   D = cast<TemplateParmDecl>(cast<TemplateDecl>(TD->getMostRecentDecl())
@@ -5793,16 +5790,12 @@
     return true;
   }
 
+  SourceLocation DiagLoc = Args.getRAngleLoc();
   // FIXME: If there's a more recent default argument that *is* visible,
   // diagnose that it was declared too late.
-
-  TemplateParameterList *Params = TD->getTemplateParameters();
-
-  S.Diag(Loc, diag::err_template_arg_list_different_arity)
-    << /*not enough args*/0
-    << (int)S.getTemplateNameKindForDiagnostics(TemplateName(TD))
-    << TD;
-  S.NoteTemplateLocation(*TD, Params->getSourceRange());
+  S.Diag(DiagLoc.isValid() ? DiagLoc : Loc,
+         MatchingTTP ? diag::err_template_template_param_missing_param
+                     : diag::err_template_param_missing_arg);
   return true;
 }
 
@@ -5836,11 +5829,14 @@
   SmallVector<TemplateArgument, 2> CanonicalArgumentPack;
   unsigned ArgIdx = 0, NumArgs = NewArgs.size();
   LocalInstantiationScope InstScope(*this, true);
+  CheckTemplateParameterRAII CTP(*this);
   for (TemplateParameterList::iterator ParamBegin = Params->begin(),
                                        ParamEnd = Params->end(),
                                        Param = ParamBegin;
        Param != ParamEnd;
        /* increment in loop */) {
+    CTP.setParam(*Param);
+
     if (size_t ParamIdx = Param - ParamBegin;
         DefaultArgs && ParamIdx >= DefaultArgs.StartPos) {
       // All written arguments should have been consumed by this point.
@@ -5877,11 +5873,9 @@
         continue;
       } else if (ArgIdx == NumArgs && !PartialTemplateArgs) {
         // Not enough arguments for this parameter pack.
-        Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
-          << /*not enough args*/0
-          << (int)getTemplateNameKindForDiagnostics(TemplateName(Template))
-          << Template;
-        NoteTemplateLocation(*Template, Params->getSourceRange());
+        Diag(RAngleLoc, CTAI.MatchingTTP
+                            ? diag::err_template_template_param_missing_param
+                            : diag::err_template_param_missing_arg);
         return true;
       }
     }
@@ -5919,6 +5913,7 @@
         SmallVector<TemplateArgument, 4> Args(ParamEnd - Param);
         for (TemplateParameterList::iterator First = Param; Param != ParamEnd;
              ++Param) {
+          CTP.setParam(*Param);
           TemplateArgument &Arg = Args[Param - First];
           Arg = ArgLoc.getArgument();
           if (!(*Param)->isTemplateParameterPack() ||
@@ -5959,7 +5954,6 @@
                  diag::err_template_expansion_into_fixed_list)
                 << (isa<ConceptDecl>(Template) ? 1 : 0)
                 << ArgLoc.getSourceRange();
-            NoteTemplateParameterLocation(**Param);
             return true;
           }
         }
@@ -6066,14 +6060,14 @@
       if (!HasDefaultArg) {
         if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param))
           return diagnoseMissingArgument(*this, TemplateLoc, Template, TTP,
-                                         NewArgs);
+                                         NewArgs, CTAI.MatchingTTP);
         if (NonTypeTemplateParmDecl *NTTP =
                 dyn_cast<NonTypeTemplateParmDecl>(*Param))
           return diagnoseMissingArgument(*this, TemplateLoc, Template, NTTP,
-                                         NewArgs);
+                                         NewArgs, CTAI.MatchingTTP);
         return diagnoseMissingArgument(*this, TemplateLoc, Template,
                                        cast<TemplateTemplateParmDecl>(*Param),
-                                       NewArgs);
+                                       NewArgs, CTAI.MatchingTTP);
       }
       return true;
     }
@@ -6109,6 +6103,7 @@
     ++Param;
     ++ArgIdx;
   }
+  CTP.Clear();
 
   // If we're performing a partial argument substitution, allow any trailing
   // pack expansions; they might be empty. This can happen even if
@@ -6129,8 +6124,7 @@
   // If we have any leftover arguments, then there were too many arguments.
   // Complain and fail.
   if (ArgIdx < NumArgs) {
-    Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
-        << /*too many args*/1
+    Diag(TemplateLoc, diag::err_template_too_many_args)
         << (int)getTemplateNameKindForDiagnostics(TemplateName(Template))
         << Template
         << SourceRange(NewArgs[ArgIdx].getLocation(), NewArgs.getRAngleLoc());
@@ -6558,8 +6552,6 @@
       << Arg->getType() << Arg->getSourceRange();
     for (unsigned I = 0, N = Notes.size(); I != N; ++I)
       S.Diag(Notes[I].first, Notes[I].second);
-
-    S.NoteTemplateParameterLocation(*Param);
     return NPV_Error;
   }
 
@@ -6584,8 +6576,7 @@
     // The types didn't match, but we know we got a null pointer; complain,
     // then recover as if the types were correct.
     S.Diag(Arg->getExprLoc(), diag::err_template_arg_wrongtype_null_constant)
-      << Arg->getType() << ParamType << Arg->getSourceRange();
-    S.NoteTemplateParameterLocation(*Param);
+        << Arg->getType() << ParamType << Arg->getSourceRange();
     return NPV_NullPointer;
   }
 
@@ -6594,8 +6585,7 @@
     // We could just return NPV_NotNullPointer, but we can print a better
     // message with the information we have here.
     S.Diag(Arg->getExprLoc(), diag::err_template_arg_invalid)
-      << EvalResult.Val.getAsString(S.Context, ParamType);
-    S.NoteTemplateParameterLocation(*Param);
+        << EvalResult.Val.getAsString(S.Context, ParamType);
     return NPV_Error;
   }
 
@@ -6607,7 +6597,6 @@
         << ParamType << FixItHint::CreateInsertion(Arg->getBeginLoc(), Code)
         << FixItHint::CreateInsertion(S.getLocForEndOfToken(Arg->getEndLoc()),
                                       ")");
-    S.NoteTemplateParameterLocation(*Param);
     return NPV_NullPointer;
   }
 
@@ -6649,7 +6638,6 @@
           S.Diag(Arg->getBeginLoc(),
                  diag::err_template_arg_ref_bind_ignores_quals)
               << ParamType << Arg->getType() << Arg->getSourceRange();
-          S.NoteTemplateParameterLocation(*Param);
           return true;
         }
       }
@@ -6667,7 +6655,6 @@
       else
         S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_convertible)
             << ArgIn->getType() << ParamType << Arg->getSourceRange();
-      S.NoteTemplateParameterLocation(*Param);
       return true;
     }
   }
@@ -6807,7 +6794,6 @@
   if (!Entity) {
     S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref)
         << Arg->getSourceRange();
-    S.NoteTemplateParameterLocation(*Param);
     return true;
   }
 
@@ -6815,7 +6801,6 @@
   if (isa<FieldDecl>(Entity) || isa<IndirectFieldDecl>(Entity)) {
     S.Diag(Arg->getBeginLoc(), diag::err_template_arg_field)
         << Entity << Arg->getSourceRange();
-    S.NoteTemplateParameterLocation(*Param);
     return true;
   }
 
@@ -6824,7 +6809,6 @@
     if (!Method->isStatic()) {
       S.Diag(Arg->getBeginLoc(), diag::err_template_arg_method)
           << Method << Arg->getSourceRange();
-      S.NoteTemplateParameterLocation(*Param);
       return true;
     }
   }
@@ -6864,7 +6848,6 @@
     if (Var->getType()->isReferenceType()) {
       S.Diag(Arg->getBeginLoc(), diag::err_template_arg_reference_var)
           << Var->getType() << Arg->getSourceRange();
-      S.NoteTemplateParameterLocation(*Param);
       return true;
     }
 
@@ -6884,15 +6867,12 @@
     if (!S.Context.hasSameUnqualifiedType(Entity->getType(),
                                           ParamType.getNonReferenceType())) {
       S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer)
-        << ParamType;
-      S.NoteTemplateParameterLocation(*Param);
+          << ParamType;
       return true;
     }
 
     S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer)
-      << ParamType
-      << FixItHint::CreateRemoval(AddrOpLoc);
-    S.NoteTemplateParameterLocation(*Param);
+        << ParamType << FixItHint::CreateRemoval(AddrOpLoc);
 
     ArgType = Entity->getType();
   }
@@ -6913,15 +6893,12 @@
       ArgType = S.Context.getPointerType(Entity->getType());
       if (!S.Context.hasSameUnqualifiedType(ArgType, ParamType)) {
         S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_address_of)
-          << ParamType;
-        S.NoteTemplateParameterLocation(*Param);
+            << ParamType;
         return true;
       }
 
       S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_address_of)
-        << ParamType << FixItHint::CreateInsertion(Arg->getBeginLoc(), "&");
-
-      S.NoteTemplateParameterLocation(*Param);
+          << ParamType << FixItHint::CreateInsertion(Arg->getBeginLoc(), "&");
     }
   }
 
@@ -7032,7 +7009,6 @@
     // We can't perform this conversion.
     S.Diag(ResultArg->getBeginLoc(), diag::err_template_arg_not_convertible)
         << ResultArg->getType() << ParamType << ResultArg->getSourceRange();
-    S.NoteTemplateParameterLocation(*Param);
     return true;
   }
 
@@ -7142,7 +7118,6 @@
                  diag::err_non_type_template_parm_type_deduction_failure)
                 << Param->getDeclName() << NTTP->getType() << Arg->getType()
                 << Arg->getSourceRange();
-          NoteTemplateParameterLocation(*Param);
           return ExprError();
         }
         ParamType = SubstAutoTypeDependent(ParamType);
@@ -7154,10 +7129,8 @@
     // declaration, but here we'll pass the argument location because that's
     // where the parameter type is deduced.
     ParamType = CheckNonTypeTemplateParameterType(ParamType, Arg->getExprLoc());
-    if (ParamType.isNull()) {
-      NoteTemplateParameterLocation(*Param);
+    if (ParamType.isNull())
       return ExprError();
-    }
   }
 
   // We should have already dropped all cv-qualifiers by now.
@@ -7197,7 +7170,6 @@
     // template parameter type.
     Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch)
         << Arg->getType() << ParamType.getUnqualifiedType();
-    NoteTemplateParameterLocation(*Param);
     return ExprError();
   }
 
@@ -7280,10 +7252,8 @@
           DeductionArg, ParamType,
           StrictCheck ? CCEKind::TempArgStrict : CCEKind::TemplateArg, Param);
       assert(!ArgResult.isUnset());
-      if (ArgResult.isInvalid()) {
-        NoteTemplateParameterLocation(*Param);
+      if (ArgResult.isInvalid())
         return ExprError();
-      }
     } else {
       ArgResult = DeductionArg;
     }
@@ -7449,7 +7419,6 @@
     if (!ArgType->isIntegralOrEnumerationType()) {
       Diag(Arg->getBeginLoc(), diag::err_template_arg_not_integral_or_enumeral)
           << ArgType << Arg->getSourceRange();
-      NoteTemplateParameterLocation(*Param);
       return ExprError();
     }
     if (!Arg->isValueDependent()) {
@@ -7488,7 +7457,6 @@
       // We can't perform this conversion.
       Diag(StartLoc, diag::err_template_arg_not_convertible)
           << Arg->getType() << ParamType << Arg->getSourceRange();
-      NoteTemplateParameterLocation(*Param);
       return ExprError();
     }
 
@@ -7534,7 +7502,6 @@
         Diag(Arg->getBeginLoc(), diag::warn_template_arg_negative)
             << toString(OldValue, 10) << toString(Value, 10) << ParamType
             << Arg->getSourceRange();
-        NoteTemplateParameterLocation(*Param);
       }
 
       // Complain if we overflowed the template parameter's type.
@@ -7545,12 +7512,10 @@
         RequiredBits = OldValue.getActiveBits() + 1;
       else
         RequiredBits = OldValue.getSignificantBits();
-      if (RequiredBits > AllowedBits) {
+      if (RequiredBits > AllowedBits)
         Diag(Arg->getBeginLoc(), diag::warn_template_arg_too_large)
             << toString(OldValue, 10) << toString(Value, 10) << ParamType
             << Arg->getSourceRange();
-        NoteTemplateParameterLocation(*Param);
-      }
     }
 
     QualType T = ParamType->isEnumeralType() ? ParamType : IntegerType;
@@ -7676,7 +7641,6 @@
     case NPV_NotNullPointer:
       Diag(Arg->getExprLoc(), diag::err_template_arg_not_convertible)
           << Arg->getType() << ParamType;
-      NoteTemplateParameterLocation(*Param);
       return ExprError();
 
     case NPV_Error:
@@ -7704,7 +7668,7 @@
 
 static void DiagnoseTemplateParameterListArityMismatch(
     Sema &S, TemplateParameterList *New, TemplateParameterList *Old,
-    Sema::TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc);
+    Sema::TemplateParameterListEqualKind Kind);
 
 bool Sema::CheckDeclCompatibleWithTemplateTemplate(
     TemplateDecl *Template, TemplateTemplateParmDecl *Param,
@@ -7832,7 +7796,6 @@
     Diag(Arg.getLocation(),
          diag::err_template_template_parameter_not_at_least_as_constrained)
         << Template << Param << Arg.getSourceRange();
-    Diag(Param->getLocation(), diag::note_entity_declared_at) << Param;
     Diag(Template->getLocation(), diag::note_entity_declared_at) << Template;
     MaybeEmitAmbiguousAtomicConstraintsDiagnostic(Param, ParamsAC, Template,
                                                   TemplateAC);
@@ -7841,25 +7804,24 @@
   return false;
 }
 
-static Sema::SemaDiagnosticBuilder noteLocation(Sema &S, const NamedDecl &Decl,
-                                                unsigned HereDiagID,
-                                                unsigned ExternalDiagID) {
-  if (Decl.getLocation().isValid())
-    return S.Diag(Decl.getLocation(), HereDiagID);
-
+SmallString<128> Sema::toTerseString(const NamedDecl &D) const {
   SmallString<128> Str;
   llvm::raw_svector_ostream Out(Str);
-  PrintingPolicy PP = S.getPrintingPolicy();
+  PrintingPolicy PP = getPrintingPolicy();
   PP.TerseOutput = 1;
-  Decl.print(Out, PP);
-  return S.Diag(Decl.getLocation(), ExternalDiagID) << Out.str();
+  D.print(Out, PP);
+  return Str;
 }
 
+// FIXME: Transform this into a context note.
 void Sema::NoteTemplateLocation(const NamedDecl &Decl,
                                 std::optional<SourceRange> ParamRange) {
+  bool HasLoc = Decl.getLocation().isValid();
   SemaDiagnosticBuilder DB =
-      noteLocation(*this, Decl, diag::note_template_decl_here,
-                   diag::note_template_decl_external);
+      Diag(Decl.getLocation(), HasLoc ? diag::note_template_decl_here
+                                      : diag::note_template_decl_external);
+  if (!HasLoc)
+    DB << toTerseString(Decl).str();
   if (ParamRange && ParamRange->isValid()) {
     assert(Decl.getLocation().isValid() &&
            "Parameter range has location when Decl does not");
@@ -7867,11 +7829,6 @@
   }
 }
 
-void Sema::NoteTemplateParameterLocation(const NamedDecl &Decl) {
-  noteLocation(*this, Decl, diag::note_template_param_here,
-               diag::note_template_param_external);
-}
-
 /// Given a non-type template argument that refers to a
 /// declaration and the type of its corresponding non-type template
 /// parameter, produce an expression that properly refers to that
@@ -8149,21 +8106,17 @@
 }
 
 /// Match two template parameters within template parameter lists.
-static bool MatchTemplateParameterKind(
-    Sema &S, NamedDecl *New,
-    const Sema::TemplateCompareNewDeclInfo &NewInstFrom, NamedDecl *Old,
-    const NamedDecl *OldInstFrom, bool Complain,
-    Sema::TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc) {
+static bool
+MatchTemplateParameterKind(Sema &S, NamedDecl *New,
+                           const Sema::TemplateCompareNewDeclInfo &NewInstFrom,
+                           NamedDecl *Old, const NamedDecl *OldInstFrom,
+                           bool Complain,
+                           Sema::TemplateParameterListEqualKind Kind) {
   // Check the actual kind (type, non-type, template).
   if (Old->getKind() != New->getKind()) {
     if (Complain) {
-      unsigned NextDiag = diag::err_template_param_different_kind;
-      if (TemplateArgLoc.isValid()) {
-        S.Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch);
-        NextDiag = diag::note_template_param_different_kind;
-      }
-      S.Diag(New->getLocation(), NextDiag)
-        << (Kind != Sema::TPL_TemplateMatch);
+      S.Diag(New->getLocation(), diag::err_template_param_different_kind)
+          << (Kind != Sema::TPL_TemplateMatch);
       S.Diag(Old->getLocation(), diag::note_template_prev_declaration)
         << (Kind != Sema::TPL_TemplateMatch);
     }
@@ -8177,18 +8130,11 @@
   // a parameter pack where the template template argument does not.
   if (Old->isTemplateParameterPack() != New->isTemplateParameterPack()) {
     if (Complain) {
-      unsigned NextDiag = diag::err_template_parameter_pack_non_pack;
-      if (TemplateArgLoc.isValid()) {
-        S.Diag(TemplateArgLoc,
-             diag::err_template_arg_template_params_mismatch);
-        NextDiag = diag::note_template_parameter_pack_non_pack;
-      }
-
       unsigned ParamKind = isa<TemplateTypeParmDecl>(New)? 0
                       : isa<NonTypeTemplateParmDecl>(New)? 1
                       : 2;
-      S.Diag(New->getLocation(), NextDiag)
-        << ParamKind << New->isParameterPack();
+      S.Diag(New->getLocation(), diag::err_template_parameter_pack_non_pack)
+          << ParamKind << New->isParameterPack();
       S.Diag(Old->getLocation(), diag::note_template_parameter_pack_here)
         << ParamKind << Old->isParameterPack();
     }
@@ -8215,13 +8161,8 @@
       QualType NewType = S.Context.getUnconstrainedType(NewNTTP->getType());
       if (!S.Context.hasSameType(OldType, NewType)) {
         if (Complain) {
-          unsigned NextDiag = diag::err_template_nontype_parm_different_type;
-          if (TemplateArgLoc.isValid()) {
-            S.Diag(TemplateArgLoc,
-                   diag::err_template_arg_template_params_mismatch);
-            NextDiag = diag::note_template_nontype_parm_different_type;
-          }
-          S.Diag(NewNTTP->getLocation(), NextDiag)
+          S.Diag(NewNTTP->getLocation(),
+                 diag::err_template_nontype_parm_different_type)
               << NewNTTP->getType() << (Kind != Sema::TPL_TemplateMatch);
           S.Diag(OldNTTP->getLocation(),
                  diag::note_template_nontype_parm_prev_declaration)
@@ -8244,8 +8185,7 @@
             OldTTP->getTemplateParameters(), Complain,
             (Kind == Sema::TPL_TemplateMatch
                  ? Sema::TPL_TemplateTemplateParmMatch
-                 : Kind),
-            TemplateArgLoc))
+                 : Kind)))
       return false;
   }
 
@@ -8297,21 +8237,12 @@
 
 /// Diagnose a known arity mismatch when comparing template argument
 /// lists.
-static
-void DiagnoseTemplateParameterListArityMismatch(Sema &S,
-                                                TemplateParameterList *New,
-                                                TemplateParameterList *Old,
-                                      Sema::TemplateParameterListEqualKind Kind,
-                                                SourceLocation TemplateArgLoc) {
-  unsigned NextDiag = diag::err_template_param_list_different_arity;
-  if (TemplateArgLoc.isValid()) {
-    S.Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch);
-    NextDiag = diag::note_template_param_list_different_arity;
-  }
-  S.Diag(New->getTemplateLoc(), NextDiag)
-    << (New->size() > Old->size())
-    << (Kind != Sema::TPL_TemplateMatch)
-    << SourceRange(New->getTemplateLoc(), New->getRAngleLoc());
+static void DiagnoseTemplateParameterListArityMismatch(
+    Sema &S, TemplateParameterList *New, TemplateParameterList *Old,
+    Sema::TemplateParameterListEqualKind Kind) {
+  S.Diag(New->getTemplateLoc(), diag::err_template_param_list_different_arity)
+      << (New->size() > Old->size()) << (Kind != Sema::TPL_TemplateMatch)
+      << SourceRange(New->getTemplateLoc(), New->getRAngleLoc());
   S.Diag(Old->getTemplateLoc(), diag::note_template_prev_declaration)
     << (Kind != Sema::TPL_TemplateMatch)
     << SourceRange(Old->getTemplateLoc(), Old->getRAngleLoc());
@@ -8320,11 +8251,10 @@
 bool Sema::TemplateParameterListsAreEqual(
     const TemplateCompareNewDeclInfo &NewInstFrom, TemplateParameterList *New,
     const NamedDecl *OldInstFrom, TemplateParameterList *Old, bool Complain,
-    TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc) {
+    TemplateParameterListEqualKind Kind) {
   if (Old->size() != New->size()) {
     if (Complain)
-      DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind,
-                                                 TemplateArgLoc);
+      DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind);
 
     return false;
   }
@@ -8342,21 +8272,18 @@
        OldParm != OldParmEnd; ++OldParm, ++NewParm) {
     if (NewParm == NewParmEnd) {
       if (Complain)
-        DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind,
-                                                   TemplateArgLoc);
+        DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind);
       return false;
     }
     if (!MatchTemplateParameterKind(*this, *NewParm, NewInstFrom, *OldParm,
-                                    OldInstFrom, Complain, Kind,
-                                    TemplateArgLoc))
+                                    OldInstFrom, Complain, Kind))
       return false;
   }
 
   // Make sure we exhausted all of the arguments.
   if (NewParm != NewParmEnd) {
     if (Complain)
-      DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind,
-                                                 TemplateArgLoc);
+      DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind);
 
     return false;
   }
@@ -8664,7 +8591,6 @@
       S.Diag(IsDefaultArgument ? TemplateNameLoc : ArgExpr->getBeginLoc(),
              diag::err_dependent_typed_non_type_arg_in_partial_spec)
           << Param->getType();
-      S.NoteTemplateParameterLocation(*Param);
       return true;
     }
   }
@@ -8682,12 +8608,14 @@
 
   TemplateParameterList *TemplateParams =
       PrimaryTemplate->getTemplateParameters();
+  CheckTemplateParameterRAII CTP(*this);
   for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
     NonTypeTemplateParmDecl *Param
       = dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(I));
     if (!Param)
       continue;
 
+    CTP.setParam(Param);
     if (CheckNonTypeTemplatePartialSpecializationArgs(*this, TemplateNameLoc,
                                                       Param, &TemplateArgs[I],
                                                       1, I >= NumExplicit))
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index f6ee745..cbc64a7 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -2980,7 +2980,7 @@
         // arguments).
         S.Diag(Param->getLocation(),
                diag::err_template_arg_deduced_incomplete_pack)
-          << Arg << Param;
+            << Arg << Param;
         return true;
       }
       if (ConvertArg(InnerArg, SugaredPackedArgsBuilder.size()))
@@ -3039,9 +3039,10 @@
     TemplateDeductionInfo &Info, Sema::CheckTemplateArgumentInfo &CTAI,
     LocalInstantiationScope *CurrentInstantiationScope,
     unsigned NumAlreadyConverted, bool *IsIncomplete) {
+  Sema::CheckTemplateParameterRAII CTP(S);
   for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
     NamedDecl *Param = TemplateParams->getParam(I);
-
+    CTP.setParam(Param);
     // C++0x [temp.arg.explicit]p3:
     //    A trailing template parameter pack (14.5.3) not otherwise deduced will
     //    be deduced to an empty sequence of template arguments.
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 1ff94d7..0c8dec5 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -592,6 +592,7 @@
   case BuildingDeductionGuides:
   case TypeAliasTemplateInstantiation:
   case PartialOrderingTTP:
+  case CheckTemplateParameter:
     return false;
 
   // This function should never be called when Kind's value is Memoization.
@@ -616,29 +617,30 @@
     Invalid = true;
     return;
   }
-  Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
+
+  CodeSynthesisContext Inst;
+  Inst.Kind = Kind;
+  Inst.PointOfInstantiation = PointOfInstantiation;
+  Inst.Entity = Entity;
+  Inst.Template = Template;
+  Inst.TemplateArgs = TemplateArgs.data();
+  Inst.NumTemplateArgs = TemplateArgs.size();
+  Inst.DeductionInfo = DeductionInfo;
+  Inst.InstantiationRange = InstantiationRange;
+  Inst.InConstraintSubstitution =
+      Inst.Kind == CodeSynthesisContext::ConstraintSubstitution;
+  if (!SemaRef.CodeSynthesisContexts.empty())
+    Inst.InConstraintSubstitution |=
+        SemaRef.CodeSynthesisContexts.back().InConstraintSubstitution;
+
+  Invalid = SemaRef.pushCodeSynthesisContext(Inst);
   if (!Invalid) {
-    CodeSynthesisContext Inst;
-    Inst.Kind = Kind;
-    Inst.PointOfInstantiation = PointOfInstantiation;
-    Inst.Entity = Entity;
-    Inst.Template = Template;
-    Inst.TemplateArgs = TemplateArgs.data();
-    Inst.NumTemplateArgs = TemplateArgs.size();
-    Inst.DeductionInfo = DeductionInfo;
-    Inst.InstantiationRange = InstantiationRange;
-    Inst.InConstraintSubstitution =
-        Inst.Kind == CodeSynthesisContext::ConstraintSubstitution;
-    if (!SemaRef.CodeSynthesisContexts.empty())
-      Inst.InConstraintSubstitution |=
-          SemaRef.CodeSynthesisContexts.back().InConstraintSubstitution;
-
-    SemaRef.pushCodeSynthesisContext(Inst);
-
-    AlreadyInstantiating = !Inst.Entity ? false :
-        !SemaRef.InstantiatingSpecializations
-             .insert({Inst.Entity->getCanonicalDecl(), Inst.Kind})
-             .second;
+    AlreadyInstantiating =
+        !Inst.Entity
+            ? false
+            : !SemaRef.InstantiatingSpecializations
+                   .insert({Inst.Entity->getCanonicalDecl(), Inst.Kind})
+                   .second;
     atTemplateBegin(SemaRef.TemplateInstCallbacks, SemaRef, Inst);
   }
 }
@@ -832,20 +834,43 @@
     Sema &SemaRef, SourceLocation ArgLoc, PartialOrderingTTP,
     TemplateDecl *PArg, SourceRange InstantiationRange)
     : InstantiatingTemplate(SemaRef, CodeSynthesisContext::PartialOrderingTTP,
-                            ArgLoc, InstantiationRange, PArg) {}
+                            ArgLoc, SourceRange(), PArg) {}
 
-void Sema::pushCodeSynthesisContext(CodeSynthesisContext Ctx) {
+Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
+                                                   CheckTemplateParameter)
+    : InstantiatingTemplate(
+          SemaRef, CodeSynthesisContext::CheckTemplateParameter,
+          /*PointOfInstantiation*/ SourceLocation(),
+          /*InstantiationRange=*/SourceRange(), /*Entity=*/nullptr) {}
+
+bool Sema::pushCodeSynthesisContext(CodeSynthesisContext Ctx) {
   Ctx.SavedInNonInstantiationSFINAEContext = InNonInstantiationSFINAEContext;
   InNonInstantiationSFINAEContext = false;
 
-  CodeSynthesisContexts.push_back(Ctx);
-
-  if (!Ctx.isInstantiationRecord())
+  if (!Ctx.isInstantiationRecord()) {
     ++NonInstantiationEntries;
+  } else {
+    assert(SemaRef.NonInstantiationEntries <=
+           SemaRef.CodeSynthesisContexts.size());
+    if ((SemaRef.CodeSynthesisContexts.size() -
+         SemaRef.NonInstantiationEntries) >
+        SemaRef.getLangOpts().InstantiationDepth) {
+      SemaRef.Diag(Ctx.PointOfInstantiation,
+                   diag::err_template_recursion_depth_exceeded)
+          << SemaRef.getLangOpts().InstantiationDepth << Ctx.InstantiationRange;
+      SemaRef.Diag(Ctx.PointOfInstantiation,
+                   diag::note_template_recursion_depth)
+          << SemaRef.getLangOpts().InstantiationDepth;
+      return true;
+    }
+  }
+
+  CodeSynthesisContexts.push_back(Ctx);
 
   // Check to see if we're low on stack space. We can't do anything about this
   // from here, but we can at least warn the user.
   StackHandler.warnOnStackNearlyExhausted(Ctx.PointOfInstantiation);
+  return false;
 }
 
 void Sema::popCodeSynthesisContext() {
@@ -907,25 +932,6 @@
   return Result;
 }
 
-bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
-                                        SourceLocation PointOfInstantiation,
-                                           SourceRange InstantiationRange) {
-  assert(SemaRef.NonInstantiationEntries <=
-         SemaRef.CodeSynthesisContexts.size());
-  if ((SemaRef.CodeSynthesisContexts.size() -
-          SemaRef.NonInstantiationEntries)
-        <= SemaRef.getLangOpts().InstantiationDepth)
-    return false;
-
-  SemaRef.Diag(PointOfInstantiation,
-               diag::err_template_recursion_depth_exceeded)
-    << SemaRef.getLangOpts().InstantiationDepth
-    << InstantiationRange;
-  SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth)
-    << SemaRef.getLangOpts().InstantiationDepth;
-  return true;
-}
-
 void Sema::PrintInstantiationStack(InstantiationContextDiagFuncRef DiagFunc) {
   // Determine which template instantiations to skip, if any.
   unsigned SkipStart = CodeSynthesisContexts.size(), SkipEnd = SkipStart;
@@ -1276,12 +1282,20 @@
     case CodeSynthesisContext::PartialOrderingTTP:
       DiagFunc(Active->PointOfInstantiation,
                PDiag(diag::note_template_arg_template_params_mismatch));
-      if (SourceLocation ParamLoc = Active->Entity->getLocation();
-          ParamLoc.isValid())
-        DiagFunc(ParamLoc, PDiag(diag::note_template_prev_declaration)
-                               << /*isTemplateTemplateParam=*/true
-                               << Active->InstantiationRange);
       break;
+    case CodeSynthesisContext::CheckTemplateParameter: {
+      if (!Active->Entity)
+        break;
+      const auto &ND = *cast<NamedDecl>(Active->Entity);
+      if (SourceLocation Loc = ND.getLocation(); Loc.isValid()) {
+        DiagFunc(Loc, PDiag(diag::note_template_param_here)
+                          << ND.getSourceRange());
+        break;
+      }
+      DiagFunc(SourceLocation(), PDiag(diag::note_template_param_external)
+                                     << toTerseString(ND).str());
+      break;
+    }
     }
   }
 }
@@ -1325,6 +1339,7 @@
     case CodeSynthesisContext::DefaultTemplateArgumentChecking:
     case CodeSynthesisContext::RewritingOperatorAsSpaceship:
     case CodeSynthesisContext::PartialOrderingTTP:
+    case CodeSynthesisContext::CheckTemplateParameter:
       // A default template argument instantiation and substitution into
       // template parameters with arguments for prior parameters may or may
       // not be a SFINAE context; look further up the stack.
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 0214078..995465ba 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -16307,6 +16307,8 @@
 template <typename Derived>
 ExprResult TreeTransform<Derived>::TransformSubstNonTypeTemplateParmExpr(
     SubstNonTypeTemplateParmExpr *E) {
+  Sema::CheckTemplateParameterRAII CTP(SemaRef, E->getParameter());
+
   Expr *OrigReplacement = E->getReplacement()->IgnoreImplicitAsWritten();
   ExprResult Replacement = getDerived().TransformExpr(OrigReplacement);
   if (Replacement.isInvalid())
diff --git a/clang/test/AST/ByteCode/cxx1z.cpp b/clang/test/AST/ByteCode/cxx1z.cpp
index 57f9923..ca5f10f 100644
--- a/clang/test/AST/ByteCode/cxx1z.cpp
+++ b/clang/test/AST/ByteCode/cxx1z.cpp
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++17 -verify=expected,both %s
 // RUN: %clang_cc1 -std=c++17 -verify=ref,both %s
 
-template<typename T, T val> struct A {};
+template<typename T, T val> struct A {}; // both-note 6{{template parameter is declared here}}
 namespace Temp {
   struct S { int n; };
   constexpr S &addr(S &&s) { return s; }
diff --git a/clang/test/AST/ByteCode/cxx20.cpp b/clang/test/AST/ByteCode/cxx20.cpp
index 67bf9a7..ad40de3 100644
--- a/clang/test/AST/ByteCode/cxx20.cpp
+++ b/clang/test/AST/ByteCode/cxx20.cpp
@@ -905,7 +905,7 @@
 }
 
 namespace TemporaryInNTTP {
-  template<auto n> struct B { /* ... */ };
+  template<auto n> struct B { /* ... */ }; // both-note {{template parameter is declared here}}
   struct J1 {
     J1 *self=this;
   };
diff --git a/clang/test/AST/ByteCode/cxx2a.cpp b/clang/test/AST/ByteCode/cxx2a.cpp
index 533173d..a13e675 100644
--- a/clang/test/AST/ByteCode/cxx2a.cpp
+++ b/clang/test/AST/ByteCode/cxx2a.cpp
@@ -242,7 +242,8 @@
 
 namespace DependentRequiresExpr {
   template <class T,
-            bool = []() -> bool { // both-error {{not a constant expression}}
+            bool = // both-note {{template parameter is declared here}}
+              []() -> bool { // both-error {{not a constant expression}}
               if (requires { T::type; })
                 return true;
               return false;
diff --git a/clang/test/AST/ByteCode/cxx98.cpp b/clang/test/AST/ByteCode/cxx98.cpp
index 1150a4e..c0587e1 100644
--- a/clang/test/AST/ByteCode/cxx98.cpp
+++ b/clang/test/AST/ByteCode/cxx98.cpp
@@ -6,7 +6,7 @@
 namespace IntOrEnum {
   const int k = 0;
   const int &p = k; // both-note {{declared here}}
-  template<int n> struct S {};
+  template<int n> struct S {}; // both-note {{template parameter is declared here}}
   S<p> s; // both-error {{not an integral constant expression}} \
           // both-note {{read of variable 'p' of non-integral, non-enumeration type 'const int &'}}
 }
diff --git a/clang/test/AST/ByteCode/records.cpp b/clang/test/AST/ByteCode/records.cpp
index 48cf811..fa8f850 100644
--- a/clang/test/AST/ByteCode/records.cpp
+++ b/clang/test/AST/ByteCode/records.cpp
@@ -1738,7 +1738,7 @@
                                                // both-error {{must be initialized by a constant expression}}
 
 #if __cplusplus >= 202002L
-  template <typename T, auto Q>
+  template <typename T, auto Q>// both-note {{template parameter is declared here}}
   concept ReferenceOf = Q;
   /// This calls a valid and constexpr copy constructor of InvalidCtor,
   /// but should still be rejected.
diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p7.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p7.cpp
index 9632fda..fc4e359 100644
--- a/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p7.cpp
+++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p7.cpp
@@ -33,5 +33,6 @@
 // specifiers.
 namespace test2 {
   template <class T> struct bar {};
+  // expected-note@-1 {{template parameter is declared here}}
   template <class T> struct foo : bar<foo> {}; // expected-error {{use of class template 'foo' requires template arguments}} expected-note {{template is declared here}}
 }
diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp
index 5bb4708f..2a2b338 100644
--- a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp
+++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp
@@ -253,5 +253,5 @@
   Agg<bool> tc = {c}; // expected-error {{cannot be narrowed}} expected-note {{}}
   Agg<bool> td = {d}; // expected-error {{cannot be narrowed}} expected-note {{}}
 }
-template<bool> struct BoolParam {};
+template<bool> struct BoolParam {}; // expected-note {{template parameter is declared here}}
 BoolParam<&P1957R2> bp; // expected-error {{not allowed in a converted constant expression}}
diff --git a/clang/test/CXX/drs/cwg0xx.cpp b/clang/test/CXX/drs/cwg0xx.cpp
index 805be67..c94bc02 100644
--- a/clang/test/CXX/drs/cwg0xx.cpp
+++ b/clang/test/CXX/drs/cwg0xx.cpp
@@ -806,6 +806,7 @@
   // since-cxx17-error@#cwg49-c {{non-type template argument is not a constant expression}}
   //   since-cxx17-note@#cwg49-c {{read of non-constexpr variable 'q' is not allowed in a constant expression}}
   //   since-cxx17-note@#cwg49-q {{declared here}}
+  //   since-cxx17-note@#cwg49-A {{template parameter is declared here}}
 } // namespace cwg49
 
 namespace cwg50 { // cwg50: 2.7
@@ -1018,9 +1019,9 @@
   struct A {
     struct { int n; } b;
   };
-  template<typename T> struct X {};
-  template<typename T> T get() { return get<T>(); }
-  template<typename T> int take(T) { return 0; }
+  template<typename T> struct X {}; // #cwg62-X
+  template<typename T> T get() { return get<T>(); } // #cwg62-get
+  template<typename T> int take(T) { return 0; } // #cwg62-take
 
   X<A> x1;
   A a = get<A>();
@@ -1034,22 +1035,27 @@
 
   X<NoNameForLinkagePtr> x2;
   // cxx98-error@-1 {{template argument uses unnamed type}}
+  //   cxx98-note@#cwg62-X {{template parameter is declared here}}
   //   cxx98-note@#cwg62-unnamed {{unnamed type used in template argument was declared here}}
   X<const NoNameForLinkagePtr> x3;
   // cxx98-error@-1 {{template argument uses unnamed type}}
+  //   cxx98-note@#cwg62-X {{template parameter is declared here}}
   //   cxx98-note@#cwg62-unnamed {{unnamed type used in template argument was declared here}}
   NoNameForLinkagePtr p1 = get<NoNameForLinkagePtr>();
   // cxx98-error@-1 {{template argument uses unnamed type}}
+  //   cxx98-note@#cwg62-get {{template parameter is declared here}}
   //   cxx98-note@#cwg62-unnamed {{unnamed type used in template argument was declared here}}
-  //   cxx98-note@-3 {{while substituting explicitly-specified template arguments}}
+  //   cxx98-note@-4 {{while substituting explicitly-specified template arguments}}
   NoNameForLinkagePtr p2 = get<const NoNameForLinkagePtr>();
   // cxx98-error@-1 {{template argument uses unnamed type}}
+  //   cxx98-note@#cwg62-get {{template parameter is declared here}}
   //   cxx98-note@#cwg62-unnamed {{unnamed type used in template argument was declared here}}
-  //   cxx98-note@-3 {{while substituting explicitly-specified template arguments}}
+  //   cxx98-note@-4 {{while substituting explicitly-specified template arguments}}
   int n1 = take(noNameForLinkagePtr);
   // cxx98-error@-1 {{template argument uses unnamed type}}
+  //   cxx98-note@#cwg62-take {{template parameter is declared here}}
   //   cxx98-note@#cwg62-unnamed {{unnamed type used in template argument was declared here}}
-  //   cxx98-note@-3 {{while substituting deduced template arguments}}
+  //   cxx98-note@-4 {{while substituting deduced template arguments}}
 
   X<Danger> x4;
 
@@ -1057,18 +1063,24 @@
     struct NoLinkage {};
     X<NoLinkage> a;
     // cxx98-error@-1 {{template argument uses local type }}
+    //   cxx98-note@#cwg62-X {{template parameter is declared here}}
     X<const NoLinkage> b;
     // cxx98-error@-1 {{template argument uses local type }}
+    //   cxx98-note@#cwg62-X {{template parameter is declared here}}
     get<NoLinkage>();
     // cxx98-error@-1 {{template argument uses local type }}
-    //   cxx98-note@-2 {{while substituting explicitly-specified template arguments}}
+    //   cxx98-note@#cwg62-get {{template parameter is declared here}}
+    //   cxx98-note@-3 {{while substituting explicitly-specified template arguments}}
     get<const NoLinkage>();
     // cxx98-error@-1 {{template argument uses local type }}
-    //   cxx98-note@-2 {{while substituting explicitly-specified template arguments}}
+    //   cxx98-note@#cwg62-get {{template parameter is declared here}}
+    //   cxx98-note@-3 {{while substituting explicitly-specified template arguments}}
     X<void (*)(NoLinkage A::*)> c;
     // cxx98-error@-1 {{template argument uses local type }}
+    //   cxx98-note@#cwg62-X {{template parameter is declared here}}
     X<int NoLinkage::*> d;
     // cxx98-error@-1 {{template argument uses local type }}
+    //   cxx98-note@#cwg62-X {{template parameter is declared here}}
   }
 } // namespace cwg62
 
@@ -1135,10 +1147,11 @@
   extern template void f<char>();
   // cxx98-error@-1 {{extern templates are a C++11 extension}}
   // expected-error@-2 {{explicit instantiation declaration of 'f' with internal linkage}}
-  template<void(*)()> struct Q {};
+  template<void(*)()> struct Q {}; // #cwg69-Q
   Q<&f<int> > q;
   // cxx98-error@-1 {{non-type template argument referring to function 'f<int>' with internal linkage is a C++11 extension}}
   //   cxx98-note@#cwg69-f {{non-type template argument refers to function here}}
+  //   cxx98-note@#cwg69-Q {{template parameter is declared here}}
 } // namespace cwg69
 
 namespace cwg70 { // cwg70: 2.7
diff --git a/clang/test/CXX/drs/cwg10xx.cpp b/clang/test/CXX/drs/cwg10xx.cpp
index c5b96c4..10ee505 100644
--- a/clang/test/CXX/drs/cwg10xx.cpp
+++ b/clang/test/CXX/drs/cwg10xx.cpp
@@ -43,6 +43,7 @@
   template<class T, template<class> class U = T::template A> struct Third { };
   // expected-error@-1 {{is a constructor name}}
   //   expected-note@#cwg1004-t {{in instantiation of default argument}}
+  //   expected-note@-3 {{template parameter is declared here}}
   Third<A<int> > t; // #cwg1004-t
 } // namespace cwg1004
 
diff --git a/clang/test/CXX/drs/cwg13xx.cpp b/clang/test/CXX/drs/cwg13xx.cpp
index ad6ee01..0fae345 100644
--- a/clang/test/CXX/drs/cwg13xx.cpp
+++ b/clang/test/CXX/drs/cwg13xx.cpp
@@ -180,6 +180,7 @@
   // dependent type of T::value is not the same as 'int'.
   // A core issue will be opened to decide what is supposed to happen here.
   template <typename T, int I> struct C;
+  // expected-note@-1 {{template parameter is declared here}}
   template <typename T> struct C<T, T::value>;
   // expected-error@-1 {{type of specialized non-type template argument depends on a template parameter of the partial specialization}}
 } // namespace cwg1315
diff --git a/clang/test/CXX/drs/cwg18xx.cpp b/clang/test/CXX/drs/cwg18xx.cpp
index 9948075..0d46eab 100644
--- a/clang/test/CXX/drs/cwg18xx.cpp
+++ b/clang/test/CXX/drs/cwg18xx.cpp
@@ -26,6 +26,7 @@
 // cxx98-14-error@-1 {{non-type template argument does not refer to any declaration}}
 //   cxx98-14-note@#cwg1801-S {{template parameter is declared here}}
 // cxx17-error@#cwg1801-S-i {{non-type template argument refers to subobject '.i'}}
+//   cxx17-note@#cwg1801-S {{template parameter is declared here}}
 } // namespace cwg1801
 
 namespace cwg1802 { // cwg1802: 3.1
diff --git a/clang/test/CXX/drs/cwg1xx.cpp b/clang/test/CXX/drs/cwg1xx.cpp
index c9dce77..e15a225 100644
--- a/clang/test/CXX/drs/cwg1xx.cpp
+++ b/clang/test/CXX/drs/cwg1xx.cpp
@@ -26,18 +26,22 @@
   // cxx98-14-error@#cwg100-a {{non-type template argument does not refer to any declaration}}
   //   cxx98-14-note@#cwg100-A {{template parameter is declared here}}
   // since-cxx17-error@#cwg100-a {{pointer to string literal is not allowed in a template argument}}
+  //   since-cxx17-note@#cwg100-A {{template parameter is declared here}}
   B<"bar"> b; // #cwg100-b
   // cxx98-14-error@#cwg100-b {{non-type template argument does not refer to any declaration}}
   //   cxx98-14-note@#cwg100-B {{template parameter is declared here}}
   // since-cxx17-error@#cwg100-b {{reference to string literal is not allowed in a template argument}}
+  //   since-cxx17-note@#cwg100-B {{template parameter is declared here}}
   C<"baz"> c; // #cwg100-c
   // cxx98-14-error@#cwg100-c {{non-type template argument does not refer to any declaration}}
   //   cxx98-14-note@#cwg100-C {{template parameter is declared here}}
   // since-cxx17-error@#cwg100-c {{pointer to subobject of string literal is not allowed in a template argument}}
+  //   since-cxx17-note@#cwg100-C {{template parameter is declared here}}
   D<*"quux"> d; // #cwg100-d
   // cxx98-14-error@#cwg100-d {{non-type template argument does not refer to any declaration}}
   //   cxx98-14-note@#cwg100-D {{template parameter is declared here}}
   // since-cxx17-error@#cwg100-d {{reference to subobject of string literal is not allowed in a template argument}}
+  //   since-cxx17-note@#cwg100-D {{template parameter is declared here}}
 } // namespace cwg100
 
 namespace cwg101 { // cwg101: 3.5
@@ -152,15 +156,17 @@
   volatile T a2[1] = {};
   const Arr a3 = {}; // #cwg112-a3
   volatile Arr a4 = {};
-  template<const volatile T*> struct X {};
+  template<const volatile T*> struct X {}; // #cwg112-X
   // FIXME: Test this somehow in C++11 and on.
   X<a1> x1;
   // cxx98-error@-1 {{non-type template argument referring to object 'a1' with internal linkage is a C++11 extension}}
   //   cxx98-note@#cwg112-a1 {{non-type template argument refers to object here}}
+  //   cxx98-note@#cwg112-X {{template parameter is declared here}}
   X<a2> x2;
   X<a3> x3;
   // cxx98-error@-1 {{non-type template argument referring to object 'a3' with internal linkage is a C++11 extension}}
   //   cxx98-note@#cwg112-a3 {{non-type template argument refers to object here}}
+  //   cxx98-note@#cwg112-X {{template parameter is declared here}}
   X<a4> x4;
 } // namespace cwg112
 
@@ -634,7 +640,7 @@
 struct Base {
 private:
   static const int i = 10; // #cwg138-ex3-Base-i
-  
+
 public:
   struct Data;
   // Elaborated type specifier is not the sole constituent of declaration,
@@ -648,7 +654,7 @@
   };
 };
 struct Data {
-  void f() {  
+  void f() {
     int i2 = Base::i;
     // expected-error@-1 {{'i' is a private member of 'cwg138::example3::Base'}}
     //   expected-note@#cwg138-ex3-Base-i {{declared private here}}
@@ -1308,8 +1314,8 @@
 
   template<template<typename TT> class T> void A<T>::f() { // #cwg184-T
     T<> t;
-    // expected-error@-1 {{too few template arguments for template template parameter 'T'}}
-    //   expected-note@#cwg184-T {{template is declared here}}
+    // expected-error@-1 {{missing template argument for template parameter}}
+    //   expected-note@#cwg184-T {{template parameter is declared here}}
   }
 
   template<template<typename TT = char> class T> void A<T>::g() {
diff --git a/clang/test/CXX/drs/cwg20xx.cpp b/clang/test/CXX/drs/cwg20xx.cpp
index 141a101..fd31a51 100644
--- a/clang/test/CXX/drs/cwg20xx.cpp
+++ b/clang/test/CXX/drs/cwg20xx.cpp
@@ -27,7 +27,7 @@
 // cwg2009: na
 
 namespace cwg2026 { // cwg2026: 11
-  template<int> struct X {};
+  template<int> struct X {}; // #cwg2026-X
 
   const int a = a + 1; // #cwg2026-a
   // expected-warning@-1 {{variable 'a' is uninitialized when used within its own initialization}}
@@ -35,9 +35,11 @@
   // cxx98-error@-1 {{non-type template argument of type 'int' is not an integral constant expression}}
   //   cxx98-note@-2 {{initializer of 'a' is not a constant expression}}
   //   cxx98-note@#cwg2026-a {{declared here}}
+  //   cxx98-note@#cwg2026-X {{template parameter is declared here}}
   // since-cxx11-error@#cwg2026-xa {{non-type template argument is not a constant expression}}
   //   since-cxx11-note@#cwg2026-xa {{initializer of 'a' is not a constant expression}}
   //   since-cxx11-note@#cwg2026-a {{declared here}}
+  //   since-cxx11-note@#cwg2026-X {{template parameter is declared here}}
 
 #if __cplusplus >= 201103L
   constexpr int b = b;
@@ -65,9 +67,11 @@
     // cxx98-error@-1 {{non-type template argument of type 'int' is not an integral constant expression}}
     //   cxx98-note@-2 {{initializer of 'e' is not a constant expression}}
     //   cxx98-note@#cwg2026-e {{declared here}}
+    //   cxx98-note@#cwg2026-X {{template parameter is declared here}}
     // since-cxx11-error@#cwg2026-xe {{non-type template argument is not a constant expression}}
     //   since-cxx11-note@#cwg2026-xe {{initializer of 'e' is not a constant expression}}
     //   since-cxx11-note@#cwg2026-e {{declared here}}
+    //   since-cxx11-note@#cwg2026-X {{template parameter is declared here}}
 
 #if __cplusplus >= 201103L
     static constexpr int f = f;
@@ -149,7 +153,7 @@
     operator string_view() const;
   };
 
-  void foo(const string &); // #cwg2076-foo 
+  void foo(const string &); // #cwg2076-foo
   void bar(string_view); // #cwg2076-bar
 
   void func(const string &arg) {
@@ -429,7 +433,7 @@
   return 0;
 }
 } // namespace GH42233
-} // namespace cwg2091 
+} // namespace cwg2091
 
 namespace cwg2094 { // cwg2094: 5
   struct A { int n; };
diff --git a/clang/test/CXX/drs/cwg21xx.cpp b/clang/test/CXX/drs/cwg21xx.cpp
index 42a7c4d..97bf320 100644
--- a/clang/test/CXX/drs/cwg21xx.cpp
+++ b/clang/test/CXX/drs/cwg21xx.cpp
@@ -24,7 +24,7 @@
 }
 
 namespace cwg2100 { // cwg2100: 12
-  template<const int *P, bool = true> struct X {};
+  template<const int *P, bool = true> struct X {}; // #cwg2100-X
   template<typename T> struct A {
     static const int n = 1;
     int f() {
@@ -35,6 +35,7 @@
       return X<&n>::n; // ok, value-dependent
       // cxx98-14-error@-1 {{non-type template argument refers to object 'n' that does not have linkage}}
       //   cxx98-14-note@#cwg2100-n {{non-type template argument refers to object here}}
+      //   cxx98-14-note@#cwg2100-X {{template parameter is declared here}}
     }
   };
   template<const int *P> struct X<P> {
diff --git a/clang/test/CXX/drs/cwg3xx.cpp b/clang/test/CXX/drs/cwg3xx.cpp
index bbd87c0..423322a 100644
--- a/clang/test/CXX/drs/cwg3xx.cpp
+++ b/clang/test/CXX/drs/cwg3xx.cpp
@@ -317,18 +317,20 @@
   typedef int (*pa)[n1];
   pa parr; // ok, type has linkage despite using 'n1'
 
-  template<typename> struct X {};
+  template<typename> struct X {}; // #cwg319-X
 
   void f() {
     struct A { int n; };
     extern A a; // FIXME: ill-formed
     X<A> xa;
     // cxx98-error@-1 {{template argument uses local type 'A'}}
+    //   cxx98-note@#cwg319-X {{template parameter is declared here}}
 
     typedef A B;
     extern B b; // FIXME: ill-formed
     X<B> xb;
     // cxx98-error@-1 {{template argument uses local type 'A'}}
+    //   cxx98-note@#cwg319-X {{template parameter is declared here}}
 
     const int n = 1;
     typedef int (*C)[n];
@@ -997,6 +999,7 @@
   //   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}}
+  //   cxx98-note@#cwg354-ptr_mem {{template parameter is declared here}}
   ptr_mem<(float S::*)0> m2; // #cwg354-m2
   // cxx98-error@#cwg354-m2 {{non-type template argument of type 'float S::*' cannot be converted to a value of type 'int S::*'}}
   //   cxx98-note@#cwg354-ptr_mem {{template parameter is declared here}}
@@ -1502,7 +1505,7 @@
     typedef struct {} const C; // #cwg389-C
     typedef enum {} const D; // #cwg389-D
   };
-  template<typename> struct T {};
+  template<typename> struct T {}; // #cwg389-T
 
   struct WithLinkage1 {};
   enum WithLinkage2 {};
@@ -1543,18 +1546,23 @@
 
   typedef T<WithoutLinkage1> BadArg1;
   // expected-error@-1 {{template argument uses unnamed type}}
+  //   expected-note@#cwg389-T {{template parameter is declared here}}
   //   expected-note@#cwg389-no-link-1 {{unnamed type used in template argument was declared here}}
   typedef T<WithoutLinkage2> BadArg2;
   // expected-error@-1 {{template argument uses unnamed type}}
+  //   expected-note@#cwg389-T {{template parameter is declared here}}
   //   expected-note@#cwg389-no-link-2 {{unnamed type used in template argument was declared here}}
   typedef T<WithoutLinkage3> BadArg3;
   // expected-error@-1 {{template argument uses unnamed type}}
+  //   expected-note@#cwg389-T {{template parameter is declared here}}
   //   expected-note@#cwg389-C {{unnamed type used in template argument was declared here}}
   typedef T<WithoutLinkage4> BadArg4;
   // expected-error@-1 {{template argument uses unnamed type}}
+  //   expected-note@#cwg389-T {{template parameter is declared here}}
   //   expected-note@#cwg389-D {{unnamed type used in template argument was declared here}}
   typedef T<WithoutLinkage5> BadArg5;
   // expected-error@-1 {{template argument uses unnamed type}}
+  //   expected-note@#cwg389-T {{template parameter is declared here}}
   //   expected-note@#cwg389-C {{unnamed type used in template argument was declared here}}
 #endif
 
diff --git a/clang/test/CXX/drs/cwg4xx.cpp b/clang/test/CXX/drs/cwg4xx.cpp
index 8497f97..e5c9efa 100644
--- a/clang/test/CXX/drs/cwg4xx.cpp
+++ b/clang/test/CXX/drs/cwg4xx.cpp
@@ -52,12 +52,15 @@
   // expected-error@#cwg401-A {{'type' is a private member of 'cwg401::C'}}
   //   expected-note@#cwg402-friend-A-C {{in instantiation of default argument for 'A<C>' required here}}
   //   expected-note@#cwg402-C-type {{implicitly declared private here}}
+  //   expected-note@#cwg401-A {{template parameter is declared here}}
   // expected-error@#cwg401-A {{'type' is a protected member of 'cwg401::B'}}
   //   expected-note@#cwg402-b {{in instantiation of default argument for 'A<B>' required here}}
   //   expected-note@#cwg402-B-type {{declared protected here}}
+  //   expected-note@#cwg401-A {{template parameter is declared here}}
   // expected-error@#cwg401-A {{'type' is a private member of 'cwg401::D'}}
   //   expected-note@#cwg402-d {{in instantiation of default argument for 'A<D>' required here}}
   //   expected-note@#cwg402-D-type {{implicitly declared private here}}
+  //   expected-note@#cwg401-A {{template parameter is declared here}}
   class B {
   protected:
     typedef int type; // #cwg402-B-type
@@ -89,8 +92,9 @@
   // to not treat the default template argument as a SFINAE context in C++98.
   template<class T, class U = typename T::type> void f(T) {} // #cwg402-f
   // cxx98-error@-1 {{default template arguments for a function template are a C++11 extension}}
-  // cxx98-error@-2 {{'type' is a protected member of 'cwg401::B'}}
-  //   cxx98-note@-3 {{in instantiation of default argument for 'f<B>' required here}}
+  //   cxx98-note@-2 {{template parameter is declared here}}
+  // cxx98-error@-3 {{'type' is a protected member of 'cwg401::B'}}
+  //   cxx98-note@-4 {{in instantiation of default argument for 'f<B>' required here}}
   //   cxx98-note@#cwg402-f-b {{while substituting deduced template arguments into function template 'f' [with T = B, U = (no value)]}}
   //   cxx98-note@#cwg402-B-type {{declared protected here}}
   void g(B b) { f(b); } // #cwg402-f-b
@@ -645,15 +649,17 @@
 } // namespace cwg431
 
 namespace cwg432 { // cwg432: 3.0
-  template<typename T> struct A {};
+  template<typename T> struct A {}; // #cwg432-A
   template<typename T> struct B : A<B> {};
   // expected-error@-1 {{use of class template 'B' requires template arguments}}
-  //   expected-note@-2 {{template is declared here}}
+  //   expected-note@#cwg432-A {{template parameter is declared here}}
+  //   expected-note@-3 {{template is declared here}}
   template<typename T> struct C : A<C<T> > {};
 #if __cplusplus >= 201103L
   template<typename T> struct D : decltype(A<D>()) {};
   // since-cxx11-error@-1 {{use of class template 'D' requires template arguments}}
-  //   since-cxx11-note@-2 {{template is declared here}}
+  //   since-cxx11-note@#cwg432-A {{template parameter is declared here}}
+  //   since-cxx11-note@-3 {{template is declared here}}
 #endif
 } // namespace cwg432
 
@@ -1386,6 +1392,7 @@
 
 namespace cwg488 { // cwg488: 2.9 c++11
   template <typename T> void f(T);
+  // cxx98-note@-1 {{template parameter is declared here}}
   void f(int);
   void g() {
     // FIXME: It seems CWG thought this should be a SFINAE failure prior to
diff --git a/clang/test/CXX/drs/cwg6xx.cpp b/clang/test/CXX/drs/cwg6xx.cpp
index 11eb0bf..c17e1e2 100644
--- a/clang/test/CXX/drs/cwg6xx.cpp
+++ b/clang/test/CXX/drs/cwg6xx.cpp
@@ -79,10 +79,11 @@
 } // namespace cwg602
 
 namespace cwg603 { // cwg603: 3.1
-  template<unsigned char> struct S {};
+  template<unsigned char> struct S {}; // #cwg603-S
   typedef S<'\001'> S1;
   typedef S<(1ul << __CHAR_BIT__) + 1> S1;
   // since-cxx11-error@-1 {{non-type template argument evaluates to 257, which cannot be narrowed to type 'unsigned char'}}
+  //   since-cxx11-note@#cwg603-S {{template parameter is declared here}}
 } // namespace cwg603
 
 // cwg604: na
diff --git a/clang/test/CXX/expr/expr.const/p3-0x.cpp b/clang/test/CXX/expr/expr.const/p3-0x.cpp
index 3eedef3..f40e1af 100644
--- a/clang/test/CXX/expr/expr.const/p3-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p3-0x.cpp
@@ -4,7 +4,7 @@
 // A converted constant expression of type T is a core constant expression,
 int nonconst = 8; // expected-note 3 {{here}}
 enum NonConstE : unsigned char { NCE = nonconst }; // expected-error {{enumerator value is not a constant expression}} expected-note {{read of non-const}}
-template<int = nonconst> struct NonConstT {}; // expected-error {{non-type template argument is not a constant expression}} expected-note {{read of non-const}}
+template<int = nonconst> struct NonConstT {}; // expected-error {{non-type template argument is not a constant expression}} expected-note {{read of non-const}} expected-note {{template parameter is declared here}}
 void NonConstF() {
   switch (nonconst) {
     case nonconst: // expected-error {{case value is not a constant expression}} expected-note {{read of non-const}}
@@ -66,7 +66,7 @@
   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; // cxx17-note 2{{template parameter is declared here}}
+template<unsigned char> using A = int; // expected-note 4{{template parameter is declared here}}
 
 using Int = A<E6>;
 using Int = A<EE::EE32>; // expected-error {{not implicitly convertible}}
@@ -79,7 +79,8 @@
 // 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}}
+// cxx17-note@-1 1{{template parameter is declared here}}
+// expected-note@-2 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/expr/expr.prim/expr.prim.req/type-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp
index 5433cfb..2572e76 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp
@@ -77,7 +77,7 @@
 namespace ns2 {
   template<typename T, typename U> struct identity {};
 
-  template<typename... Ts> requires requires { typename identity<Ts...>; } // expected-note 2{{because 'typename identity<Ts...>' would be invalid: too few template arguments for class template 'identity'}}
+  template<typename... Ts> requires requires { typename identity<Ts...>; } // expected-note 2{{because 'typename identity<Ts...>' would be invalid: missing template argument for template parameter}}
   struct r4 {};
 
   using r4i1 = r4<int>; // expected-error{{constraints not satisfied for class template 'r4' [with Ts = <int>]}}
diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp
index 692958e..332f69b 100644
--- a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp
+++ b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp
@@ -9,7 +9,7 @@
   IP<ip> *ip2;
 };
 
-template<int &ip> struct IR {};
+template<int &ip> struct IR {}; // expected-note {{template parameter is declared here}}
 
 constexpr std::nullptr_t get_nullptr() { return nullptr; }
 
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 73c7c75..b6a0fdd 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
@@ -31,16 +31,16 @@
 //      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 { }; // expected-note 5{{here}}
+  template <int* p> struct X0 { }; // expected-note 5{{here}} cxx17-note 2{{here}}
 #if __cplusplus >= 201103L
   // precxx17-note@-2 2{{template parameter is declared here}}
 #endif
 
-  template <int (*fp)(int)> struct X1 { }; // cxx17-note {{here}}
+  template <int (*fp)(int)> struct X1 { }; // cxx17-note {{here}} precxx17-note{{here}}
 #if __cplusplus <= 199711L
   // precxx17-note@-2 {{here}}
 #endif
-  template <int &p> struct X2 { }; // expected-note 4{{here}}
+  template <int &p> struct X2 { }; // expected-note 5{{here}}
   template <const int &p> struct X2k { }; // expected-note {{here}}
   template <int (&fp)(int)> struct X3 { }; // expected-note 4{{here}}
 
@@ -180,6 +180,7 @@
 
 namespace bad_args {
   template <int* N> struct X0 { }; // precxx17-note 4{{template parameter is declared here}}
+                                   // cxx17-note@-1 3{{template parameter is declared here}}
   int i = 42;
   X0<&i + 2> x0a; // precxx17-error{{non-type template argument does not refer to any declaration}} \
                      cxx17-error {{non-type template argument is not a constant expression}} \
diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp
index 4b93d86..d35a298 100644
--- a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp
+++ b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp
@@ -49,7 +49,7 @@
     operator int() const;
   };
 
-  template<X const *Ptr> struct A2; // expected-note 0-1{{template parameter is declared here}}
+  template<X const *Ptr> struct A2; // expected-note 1-2{{template parameter is declared here}}
 
   X *X_ptr; // expected-note 0-1{{declared here}}
   X an_X;
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 3caed04..2638bef 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
@@ -20,39 +20,39 @@
 template<
   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}}
+  class TT // expected-note 2{{template parameter is declared here}}
 > struct X0 { };
 
 template<int I, int J, int ...Rest> struct X0a;
 template<int ...Rest> struct X0b;
 template<int I, long J> struct X0c;
-template<int I, short J> struct X0d;
-template<int I, void *J> struct X0e; // expected-note{{template parameter is declared here}}
+template<int I, short J> struct X0d; // expected-note {{template parameter is declared here}}
+template<int I, void *J> struct X0e; // expected-note {{template parameter is declared here}}
 
 X0<X0a> inst_x0a;
 X0<X0b> inst_x0b;
 X0<X0c> inst_x0c;
-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}}
+X0<X0d> inst_x0d; // expected-note {{template template argument is incompatible}}
+X0<X0e> inst_x0e; // expected-note {{template template argument is incompatible}}
 
 template<typename T,
          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}}
+         class TT // expected-note 2{{template parameter is declared here}}
 > struct X1 { };
 
 template<int I, int J, int ...Rest> struct X1a;
 template<long I, long ...Rest> struct X1b;
 template<short I, short J> struct X1c;
-template<short I, long J> struct X1d;
-template<short I, void *J> struct X1e; // expected-note{{template parameter is declared here}}
+template<short I, long J> struct X1d;  // expected-note {{template parameter is declared here}}
+template<short I, void *J> struct X1e; // expected-note {{template parameter is declared here}}
 
 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;  // expected-note {{has different template parameters}}
-X1<short, X1e> inst_x1e; // expected-note {{has different template parameters}}
+X1<int, X1d> inst_ix1d;  // expected-note {{template template argument is incompatible}}
+X1<short, X1e> inst_x1e; // expected-note {{template template argument is incompatible}}
 
 template <int> class X2; // expected-note{{template is declared here}} \
                          // expected-note{{template is declared here}}
diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-2a.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-2a.cpp
index 342ffba..5570a7f 100644
--- a/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-2a.cpp
+++ b/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-2a.cpp
@@ -13,12 +13,12 @@
 S1<X> s11;
 S1<Y> s12;
 // expected-error@-1 {{template template argument 'Y' is more constrained than template template parameter 'P'}}
-// expected-note@#S1 {{'P' declared here}}
+// expected-note@#S1 {{template parameter is declared here}}
 // expected-note@#Y {{'Y' declared here}}
 S1<Z> s13;
 S1<W> s14;
 // expected-error@-1 {{template template argument 'W' is more constrained than template template parameter 'P'}}
-// expected-note@#S1 {{'P' declared here}}
+// expected-note@#S1 {{template parameter is declared here}}
 // expected-note@#W {{'W' declared here}}
 // expected-note@#F 1-2{{similar constraint expressions not considered equivalent}}
 // expected-note@#C 1-2{{similar constraint}}
@@ -43,12 +43,12 @@
 S4<X> s41;
 S4<Y> s42;
 // expected-error@-1 {{template template argument 'Y' is more constrained than template template parameter 'P'}}
-// expected-note@#S4 {{'P' declared here}}
+// expected-note@#S4 {{template parameter is declared here}}
 // expected-note@#Y {{'Y' declared here}}
 S4<Z> s43;
 S4<W> s44;
 // expected-error@-1 {{template template argument 'W' is more constrained than template template parameter 'P'}}
-// expected-note@#S4 {{'P' declared here}}
+// expected-note@#S4 {{template parameter is declared here}}
 // expected-note@#W {{'W' declared here}}
 
 template<template<typename T> requires C<T> typename U> struct S5 {
diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.type/p2.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.type/p2.cpp
index 650f858..65f3e17 100644
--- a/clang/test/CXX/temp/temp.arg/temp.arg.type/p2.cpp
+++ b/clang/test/CXX/temp/temp.arg/temp.arg.type/p2.cpp
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -Wvla %s
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98 -std=c++98 %s
 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
 
 template<class T> struct A {
@@ -13,7 +13,8 @@
 };
 B<function> b; // expected-note{{instantiation of}}
 
-template <typename T> int f0(void *, const T&); // expected-note{{candidate template ignored: substitution failure}}
+template <typename T> // #f0-temphead
+int f0(void *, const T&); // expected-note{{candidate template ignored: substitution failure}}
 enum {e};
 // expected-note@-1 {{unnamed type used in template argument was declared here}}
 
@@ -22,6 +23,7 @@
 #if __cplusplus <= 199711L
   // expected-warning@-2 {{template argument uses unnamed type}}
   // expected-note@-3 {{while substituting deduced template arguments}}
+  // expected-note@#f0-temphead {{template parameter is declared here}}
 #endif
 
   int vla[n]; // expected-warning {{variable length arrays in C++ are a Clang extension}}
@@ -33,9 +35,9 @@
 }
 
 namespace N0 {
-  template <typename R, typename A1> void f0(R (*)(A1));
-  template <typename T> int f1(T);
-  template <typename T, typename U> int f1(T, U);
+  template <typename R, typename A1> void f0(R (*)(A1)); // #f0
+  template <typename T> int f1(T);                       // #f1-1
+  template <typename T, typename U> int f1(T, U);        // #f1-2
   enum {e1};
 #if __cplusplus <= 199711L
   // expected-note@-2 2{{unnamed type used in template argument was declared here}}
@@ -51,7 +53,7 @@
  // expected-note@-2 {{unnamed type used in template argument was declared here}}
 #endif
 
-  template<typename T> struct X;
+  template<typename T> struct X; // cxx98-note {{template parameter is declared here}}
   template<typename T> struct X<T*> { };
 
   void f() {
@@ -59,24 +61,28 @@
 #if __cplusplus <= 199711L
     // expected-warning@-2 {{template argument uses unnamed type}}
     // expected-note@-3 {{while substituting deduced template arguments}}
+    // expected-note@#f0 {{template parameter is declared here}}
 #endif
 
        &f1<__typeof__(e1)>);
 #if __cplusplus <= 199711L
  // expected-warning@-2 {{template argument uses unnamed type}}
  // expected-note@-3 {{while substituting explicitly-specified template arguments}}
+ // expected-note@#f1-1 {{template parameter is declared here}}
 #endif
 
     int (*fp1)(int, __typeof__(e2)) = f1;
 #if __cplusplus <= 199711L
     // expected-warning@-2 {{template argument uses unnamed type}}
     // expected-note@-3 {{while substituting deduced template arguments}}
+    // expected-note@#f1-2 {{template parameter is declared here}}
 #endif
 
     f1(e2);
 #if __cplusplus <= 199711L
     // expected-warning@-2 {{template argument uses unnamed type}}
     // expected-note@-3 {{while substituting deduced template arguments}}
+    // expected-note@#f1-1 {{template parameter is declared here}}
 #endif
 
     f1(e2);
diff --git a/clang/test/CXX/temp/temp.decls/temp.class.spec/p8-1y.cpp b/clang/test/CXX/temp/temp.decls/temp.class.spec/p8-1y.cpp
index 388a80e..cf01e40 100644
--- a/clang/test/CXX/temp/temp.decls/temp.class.spec/p8-1y.cpp
+++ b/clang/test/CXX/temp/temp.decls/temp.class.spec/p8-1y.cpp
@@ -25,7 +25,7 @@
   template<typename Inner> static int y<Outer>; // expected-error 3{{cannot be deduced}} expected-note 3{{'Inner'}}
   template<typename Inner> static int y<Inner>; // expected-error {{does not specialize}}
 
-  template<typename, int> static int z;
+  template<typename, int> static int z; // expected-note {{template parameter is declared here}}
   template<Outer N> static int z<int, N>; // expected-error {{not implicitly convertible}}
 };
 template<typename Outer> template<typename Inner> int X<Outer>::y<Outer>; // expected-error {{cannot be deduced}} expected-note {{'Inner'}}
@@ -33,4 +33,4 @@
 template<> template<typename Inner> int X<int>::y<Inner>; // expected-error {{does not specialize}} expected-note {{instantiation of}}
 
 X<int> xi;
-X<int*> xf; // expected-note {{instantiation of}}
+X<int*> xf; // expected-note 2{{instantiation of}}
diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp
index ab4c663d..cab5c96 100644
--- a/clang/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp
+++ b/clang/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp
@@ -14,10 +14,10 @@
 };
 
 namespace ExpandIntoFixed {
-  template<typename T, 
-           typename U, 
-           typename V = pair<T, U>, 
-           typename W = V*> 
+  template<typename T,
+           typename U,
+           typename V = pair<T, U>,
+           typename W = V*>
   class X0 { };
 
   template<typename ...Ts>
@@ -26,24 +26,24 @@
     typedef X0<Ts...> type;
   };
 
-  static_assert(is_same<X1<int, int>::type, 
+  static_assert(is_same<X1<int, int>::type,
                         X0<int, int, pair<int, int>, pair<int, int>*>>::value,
                 "fails with two default arguments");
 
-  static_assert(is_same<X1<int, int, float>::type, 
+  static_assert(is_same<X1<int, int, float>::type,
                         X0<int, int, float, float*>>::value,
                 "fails with one default argument");
 
-  static_assert(is_same<X1<int, int, float, double>::type, 
+  static_assert(is_same<X1<int, int, float, double>::type,
                         X0<int, int, float, double>>::value,
                 "fails with no default arguments");
 }
 
 namespace ExpandIntoFixedShifted {
-  template<typename T, 
-           typename U, 
-           typename V = pair<T, U>, 
-           typename W = V*> 
+  template<typename T,
+           typename U,
+           typename V = pair<T, U>,
+           typename W = V*>
   class X0 { };
 
   template<typename ...Ts>
@@ -52,15 +52,15 @@
     typedef X0<char, Ts...> type;
   };
 
-  static_assert(is_same<X1<int>::type, 
+  static_assert(is_same<X1<int>::type,
                         X0<char, int, pair<char, int>, pair<char, int>*>>::value,
                 "fails with two default arguments");
 
-  static_assert(is_same<X1<int, float>::type, 
+  static_assert(is_same<X1<int, float>::type,
                         X0<char, int, float, float*>>::value,
                 "fails with one default argument");
 
-  static_assert(is_same<X1<int, float, double>::type, 
+  static_assert(is_same<X1<int, float, double>::type,
                         X0<char, int, float, double>>::value,
                 "fails with no default arguments");
 }
@@ -76,11 +76,11 @@
 }
 
 namespace PR9021a {
-  template<typename, typename> 
+  template<typename, typename>
   struct A { };
 
   template<typename ...T>
-  struct B { 
+  struct B {
     A<T...> a1;
   };
 
@@ -93,9 +93,9 @@
   template<class, class>
   struct t2
   {
-    
+
   };
-  
+
   template<template<class...> class M>
   struct m
   {
@@ -107,14 +107,14 @@
 }
 
 namespace PartialSpecialization {
-  template<typename T, typename U, typename V = U>
-  struct X0; // expected-note 2{{template is declared here}}
+  template<typename T, typename U, typename V = U> // expected-note {{template parameter is declared here}}
+  struct X0; // expected-note {{template is declared here}}
 
   template<typename ...Ts>
   struct X0<Ts...> { // expected-error {{class template partial specialization is not more specialized than the primary template}}
   };
 
-  X0<int> x0i; // expected-error{{too few template arguments for class template 'X0'}}
+  X0<int> x0i; // expected-error{{missing template argument for template parameter}}
   X0<int, float> x0if;
   X0<int, float, double> x0ifd;
 }
diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
index 30e7c65..c6e6038 100644
--- a/clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
+++ b/clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
@@ -48,7 +48,7 @@
   int check1[X<short, int>::Inner<tuple<pair<short, unsigned short>,
                                         pair<int, unsigned int>,
                                         pair<long, unsigned long>>
-                                       >::value == 1? 1 : -1]; 
+                                       >::value == 1? 1 : -1];
 
   template<unsigned ...Values> struct unsigned_tuple { };
   template<typename ...Types>
@@ -99,7 +99,7 @@
   int check5[X2<short, int>::Inner<int(pair<short, unsigned short>,
                                        pair<int, unsigned int>,
                                        pair<long, unsigned long>)
-                                     >::value == 1? 1 : -1]; 
+                                     >::value == 1? 1 : -1];
 
   template<typename T, typename U>
   struct some_function_object {
@@ -217,8 +217,8 @@
   template<typename ...Types>
   struct tuple_of_values {
     template<Types ...Values> // expected-error{{a non-type template parameter cannot have type 'float'}} \
-    // expected-note{{template parameter is declared here}}
-    struct apply { // expected-note 2{{template is declared here}}
+    // expected-note 2{{template parameter is declared here}}
+    struct apply { // expected-note {{template is declared here}}
       typedef tuple<value_c<Types, Values>...> type;
     };
   };
@@ -236,7 +236,7 @@
 
   tuple_of_values<int&, float&>::apply<i, i>::type tv2; // expected-error{{non-type template parameter of reference type 'float &' cannot bind to template argument of type 'int'}}
 
-  tuple_of_values<int&, float&>::apply<i>::type tv3; // expected-error{{too few template arguments for class template 'apply'}}
+  tuple_of_values<int&, float&>::apply<i>::type tv3; // expected-error{{missing template argument for template parameter}}
 
   tuple_of_values<int&, float&>::apply<i, f, i>::type tv4; // expected-error{{too many template arguments for class template 'apply'}}
 }
diff --git a/clang/test/CXX/temp/temp.deduct/p9.cpp b/clang/test/CXX/temp/temp.deduct/p9.cpp
index 7b661c2..5f9ea27 100644
--- a/clang/test/CXX/temp/temp.deduct/p9.cpp
+++ b/clang/test/CXX/temp/temp.deduct/p9.cpp
@@ -15,13 +15,14 @@
 }
 
 template <class T, unsigned = sizeof([]() { T::invalid; })>
+// expected-note@-1 {{template parameter is declared here}}
 void g(T);
 void g(...);
 void test_g() {
-  g(0); // expected-error@-4 {{type 'int' cannot be used prior to '::'}}
+  g(0); // expected-error@-5 {{type 'int' cannot be used prior to '::'}}
         // expected-note@-4 {{in instantiation of default argument}}
         // expected-note@-2 {{while substituting deduced template arguments}}
-        // expected-note@-7 {{while substituting into a lambda expression here}}
+        // expected-note@-8 {{while substituting into a lambda expression here}}
 }
 
 template <class T>
diff --git a/clang/test/CXX/temp/temp.param/p1.cpp b/clang/test/CXX/temp/temp.param/p1.cpp
index e9a9789..e2eecdf 100644
--- a/clang/test/CXX/temp/temp.param/p1.cpp
+++ b/clang/test/CXX/temp/temp.param/p1.cpp
@@ -5,8 +5,9 @@
 
 
 struct A {};
-template<class M, 
-         class T = A,  // expected-note{{previous default template argument defined here}}
+template<class M,
+         class T // expected-note {{template parameter is declared here}}
+           = A,  // expected-note{{previous default template argument defined here}}
          class C> // expected-error{{template parameter missing a default argument}}
-class X0 {}; // expected-note{{template is declared here}}
-X0<int> x0; // expected-error{{too few template arguments for class template 'X0'}}
+class X0 {};
+X0<int> x0; // expected-error{{missing template argument for template parameter}}
diff --git a/clang/test/CXX/temp/temp.param/p12.cpp b/clang/test/CXX/temp/temp.param/p12.cpp
index 8317e7f..e3dfb65 100644
--- a/clang/test/CXX/temp/temp.param/p12.cpp
+++ b/clang/test/CXX/temp/temp.param/p12.cpp
@@ -32,9 +32,9 @@
   class B3n;
 
 // Check validity of default arguments
-template<template<class, int> class =// expected-note {{previous template template parameter is here}}
+template<template<class, int> class =// expected-note {{template parameter is declared here}}
            Y1> // expected-error{{too many template arguments for class template 'Y1'}}
-               // expected-note@-1 {{template template argument has different template parameters than its corresponding template template parameter}}
+               // expected-note@-1 {{template template argument is incompatible}}
   class C1 {};
 
 C1<> c1; // expected-note{{while checking a default template argument}}
diff --git a/clang/test/CXX/temp/temp.param/p15-cxx0x.cpp b/clang/test/CXX/temp/temp.param/p15-cxx0x.cpp
index 238490c..ce29766 100644
--- a/clang/test/CXX/temp/temp.param/p15-cxx0x.cpp
+++ b/clang/test/CXX/temp/temp.param/p15-cxx0x.cpp
@@ -77,9 +77,9 @@
 
 template<typename T> struct takedrop_impl;
 template<place...X> struct takedrop_impl<places<X...>> {
-  template<template<decltype(X)> class ...Take,
+  template<template<decltype(X)> class ...Take, // expected-note 2{{template parameter is declared here}}
            template<place      > class ...Drop>
-  struct inner { // expected-note 2{{declared}}
+  struct inner {
     typedef types<typename Take<_>::type...> take;
     typedef types<typename Drop<_>::type...> drop;
   };
@@ -87,11 +87,11 @@
 
 template<unsigned N, typename...Ts> struct take {
   using type = typename takedrop_impl<typename make_places<N>::type>::
-    template inner<wrap<Ts>::template inner...>::take; // expected-error {{too few template arguments}}
+    template inner<wrap<Ts>::template inner...>::take; // expected-error {{missing template argument}}
 };
 template<unsigned N, typename...Ts> struct drop {
   using type = typename takedrop_impl<typename make_places<N>::type>::
-    template inner<wrap<Ts>::template inner...>::drop; // expected-error {{too few template arguments}}
+    template inner<wrap<Ts>::template inner...>::drop; // expected-error {{missing template argument}}
 };
 
 using T1 = take<3, int, char, double, long>::type; // expected-note {{previous}}
@@ -118,7 +118,7 @@
 // implicitly a pack expansion.
 template<typename ...Default> struct DefArg {
   template<template<typename T = Default> class ...Classes> struct Inner { // expected-error {{default argument contains unexpanded parameter pack}} expected-note {{here}}
-    Inner(Classes<>...); // expected-error {{too few}}
+    Inner(Classes<>...); // expected-error {{missing template argument}}
   };
 };
 template<typename T> struct vector {};
diff --git a/clang/test/CXX/temp/temp.param/p8-cxx20.cpp b/clang/test/CXX/temp/temp.param/p8-cxx20.cpp
index a3478c0..aa1666f 100644
--- a/clang/test/CXX/temp/temp.param/p8-cxx20.cpp
+++ b/clang/test/CXX/temp/temp.param/p8-cxx20.cpp
@@ -59,7 +59,7 @@
     f<D{1, true}>();
   }
 
-  template<D d> struct Z {};
+  template<D d> struct Z {}; // expected-note {{template parameter is declared here}}
   Z<D{2, true}> z1;
   Z<D{2, false}> z2; // expected-error {{non-type template argument is not a constant expression}} expected-note-re {{in call to '{{.*}}.~D()'}}
 }
diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2.cpp
index ecb8237..cb048ec 100644
--- a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2.cpp
+++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2.cpp
@@ -2,7 +2,7 @@
 // RUN: %clang_cc1 -std=c++11 -verify=cxx11 %s
 // cxx11-no-diagnostics
 
-template<int n> struct S;
+template<int n> struct S; // cxx98-note {{template parameter is declared here}}
 
 template<int n> struct T {
   T() {
diff --git a/clang/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp b/clang/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp
index 741ebc5..749b455 100644
--- a/clang/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp
+++ b/clang/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp
@@ -3,27 +3,27 @@
 // RUN: not %clang_cc1 --std=c++1y -x c++ -fixit %t -DFIXING
 // RUN: %clang_cc1 --std=c++1y -x c++ %t -DFIXING
 
-template<typename T> 
-T pi = T(3.1415926535897932385); // expected-note {{template is declared here}}
+template<typename T> // expected-note {{template parameter is declared here}}
+T pi = T(3.1415926535897932385);
 
 template int pi<int>;
 
 #ifndef FIXING
-template float pi<>; // expected-error {{too few template arguments for variable template 'pi'}}
+template float pi<>; // expected-error {{missing template argument for template parameter}}
 template double pi_var0; // expected-error {{explicit instantiation of 'pi_var0' does not refer to a function template, variable template, member function, member class, or static data member}}
 #endif
 
 // Should recover as if definition
 template double pi_var = 5; // expected-error {{variable cannot be defined in an explicit instantiation; if this declaration is meant to be a variable definition, remove the 'template' keyword}}
 #ifndef FIXING
-template<typename T> 
+template<typename T>
 T pi0 = T(3.1415926535897932385); // expected-note {{previous definition is here}}
 
 template int pi0 = 10; // expected-error {{variable cannot be defined in an explicit instantiation; if this declaration is meant to be a variable definition, remove the 'template' keyword}} \
                           expected-error{{redefinition of 'pi0' as different kind of symbol}}
 #endif
 
-template<typename T> 
+template<typename T>
 T pi1 = T(3.1415926535897932385); // expected-note 0-2 {{here}}
 
 // Should recover as if specialization
diff --git a/clang/test/CXX/temp/temp.spec/part.spec.cpp b/clang/test/CXX/temp/temp.spec/part.spec.cpp
index 4b0fdb9..3923d16 100644
--- a/clang/test/CXX/temp/temp.spec/part.spec.cpp
+++ b/clang/test/CXX/temp/temp.spec/part.spec.cpp
@@ -250,7 +250,7 @@
 template <typename T1, typename T2> class PCT2 {};
 template <int X> class PCT3 {};
 template <void (TestClass::*)()> class PCT4 {};
-template <void (*)()> class PCT5 {};
+template <void (*)()> class PCT5 {}; // expected-note {{template parameter is declared here}}
 template <typename T> class PCT6 {
   // expected-note@+1 3{{implicitly declared private here}}
   template <typename NT> class NPCT1 {};
@@ -416,7 +416,7 @@
 template <typename T1, typename T2, typename T3> class PCTT2 {};
 template <typename T, int X> class PCTT3 {};
 template <typename T, void (TestClass::*)()> class PCTT4 {};
-template <typename T, void (*)()> class PCTT5 {};
+template <typename T, void (*)()> class PCTT5 {}; // expected-note {{template parameter is declared here}}
 template <typename T1, typename T2> class PCTT6 {
   template <typename NT> class NCT1 {};
   template <typename NT> class NCT2; // forward declaration
diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp
index 0283dba..63fd997 100644
--- a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp
+++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp
@@ -2,13 +2,13 @@
 template<typename T>
 void f(T);
 
-template<typename T>
-struct A { }; // expected-note{{template is declared here}}
+template<typename T> // expected-note {{template parameter is declared here}}
+struct A { };
 
 struct X {
   template<> friend void f<int>(int); // expected-error{{in a friend}}
   template<> friend class A<int>; // expected-error{{cannot be a friend}}
-  
+
   friend void f<float>(float); // okay
   friend class A<float>; // okay
 };
@@ -18,6 +18,6 @@
   template <> friend void f<>(int);
 
   // expected-error@+2{{template specialization declaration cannot be a friend}}
-  // expected-error@+1{{too few template arguments for class template 'A'}}
+  // expected-error@+1{{missing template argument for template parameter}}
   template <> friend class A<>;
 };
diff --git a/clang/test/Misc/integer-literal-printing.cpp b/clang/test/Misc/integer-literal-printing.cpp
index bd231a3..bc52b3f0 100644
--- a/clang/test/Misc/integer-literal-printing.cpp
+++ b/clang/test/Misc/integer-literal-printing.cpp
@@ -14,6 +14,7 @@
 template <boolTy T> struct Type3Helper;
 template <> struct Type3Helper<boolTy::b> { typedef boolTy Ty; };
 template <boolTy T, typename Type3Helper<T>::Ty U> struct Type3 {};
+// expected-note@-1 {{template parameter is declared here}}
 
 // PR14386
 enum class charTy : char {
@@ -23,6 +24,7 @@
 template <charTy T> struct Type4Helper;
 template <> struct Type4Helper<charTy::c> { typedef charTy Ty; };
 template <charTy T, typename Type4Helper<T>::Ty U> struct Type4 {};
+// expected-note@-1 {{template parameter is declared here}}
 
 enum class scharTy : signed char {
   c = 0,
@@ -31,6 +33,7 @@
 template <scharTy T> struct Type5Helper;
 template <> struct Type5Helper<scharTy::c> { typedef scharTy Ty; };
 template <scharTy T, typename Type5Helper<T>::Ty U> struct Type5 {};
+// expected-note@-1 {{template parameter is declared here}}
 
 enum class ucharTy : unsigned char {
   c = 0,
@@ -39,6 +42,7 @@
 template <ucharTy T> struct Type6Helper;
 template <> struct Type6Helper<ucharTy::c> { typedef ucharTy Ty; };
 template <ucharTy T, typename Type6Helper<T>::Ty U> struct Type6 {};
+// expected-note@-1 {{template parameter is declared here}}
 
 enum class wcharTy : wchar_t {
   c = 0,
@@ -47,6 +51,7 @@
 template <wcharTy T> struct Type7Helper;
 template <> struct Type7Helper<wcharTy::c> { typedef wcharTy Ty; };
 template <wcharTy T, typename Type7Helper<T>::Ty U> struct Type7 {};
+// expected-note@-1 {{template parameter is declared here}}
 
 enum class char16Ty : char16_t {
   c = 0,
@@ -55,6 +60,7 @@
 template <char16Ty T> struct Type8Helper;
 template <> struct Type8Helper<char16Ty::c> { typedef char16Ty Ty; };
 template <char16Ty T, typename Type8Helper<T>::Ty U> struct Type8 {};
+// expected-note@-1 {{template parameter is declared here}}
 
 enum class char32Ty : char16_t {
   c = 0,
@@ -63,6 +69,7 @@
 template <char32Ty T> struct Type9Helper;
 template <> struct Type9Helper<char32Ty::c> { typedef char32Ty Ty; };
 template <char32Ty T, typename Type9Helper<T>::Ty U> struct Type9 {};
+// expected-note@-1 {{template parameter is declared here}}
 
 void Function() {
   Function1(Type1<-42>()); // expected-error{{no matching function for call to 'Function1'}}
diff --git a/clang/test/Modules/malformed-constraint-template-non-type-parm-decl.cpp b/clang/test/Modules/malformed-constraint-template-non-type-parm-decl.cpp
index 73dff88..250b54a 100644
--- a/clang/test/Modules/malformed-constraint-template-non-type-parm-decl.cpp
+++ b/clang/test/Modules/malformed-constraint-template-non-type-parm-decl.cpp
@@ -11,7 +11,7 @@
 //--- mod.cppm
 export module mod;
 
-template <typename T, auto Q>
+template <typename T, auto Q> // expected-note 2{{template parameter is declared here}}
 concept ReferenceOf = Q;
 
 // expected-error@+2 {{unknown type name 'AngleIsInvalidNow'}}
diff --git a/clang/test/Modules/missing-body-in-import.cpp b/clang/test/Modules/missing-body-in-import.cpp
index b52ebba..e25f7b5 100644
--- a/clang/test/Modules/missing-body-in-import.cpp
+++ b/clang/test/Modules/missing-body-in-import.cpp
@@ -29,6 +29,7 @@
 import mod1;
 
 struct C: B <A{"a", "b"}> { // expected-error {{non-type template argument is not a constant expression}}
+                            // expected-note@mod1.cppm:11 {{template parameter is declared here}}
   constexpr C(int a) { }
 };
 
diff --git a/clang/test/Modules/template-default-args.cpp b/clang/test/Modules/template-default-args.cpp
index 85b2a18..1d8de70 100644
--- a/clang/test/Modules/template-default-args.cpp
+++ b/clang/test/Modules/template-default-args.cpp
@@ -22,7 +22,7 @@
 template<typename T = int> struct C;
 template<typename T> struct D {};
 template<typename T> struct F {};
-template<typename T> struct G {};
+template<typename T> struct G {}; // #G
 template<typename T> struct J {};
 template<typename T = int> struct J;
 struct K : J<> {};
@@ -39,8 +39,10 @@
 F<> f;
 G<> g; // expected-error {{missing '#include "a.h"'; default argument of 'G' must be defined before it is used}}
 // expected-note@a.h:7 {{default argument declared here is not reachable}}
+// expected-note@#G {{template parameter is declared here}}
 H<> h; // expected-error {{missing '#include "a.h"'; default argument of 'H' must be defined before it is used}}
 // expected-note@a.h:8 {{default argument declared here is not reachable}}
+// expected-note@a.h:8 {{template parameter is declared here}}
 I<> i;
 L<> *l;
 END
diff --git a/clang/test/Parser/MicrosoftExtensions.cpp b/clang/test/Parser/MicrosoftExtensions.cpp
index e32d7fa..9989fb8 100644
--- a/clang/test/Parser/MicrosoftExtensions.cpp
+++ b/clang/test/Parser/MicrosoftExtensions.cpp
@@ -126,7 +126,7 @@
 }
 
 
-template <class T, const GUID* g = &__uuidof(T)> // expected-note {{template parameter is declared here}}
+template <class T, const GUID* g = &__uuidof(T)> // expected-note 2{{template parameter is declared here}}
 class COM_CLASS_TEMPLATE  { };
 
 typedef COM_CLASS_TEMPLATE<struct_with_uuid, &*&__uuidof(struct_with_uuid)> COM_TYPE_1; // expected-warning {{non-type template argument containing a dereference operation is a Microsoft extension}}
diff --git a/clang/test/Parser/cxx-template-argument.cpp b/clang/test/Parser/cxx-template-argument.cpp
index 3c2169f..ffe53e7 100644
--- a/clang/test/Parser/cxx-template-argument.cpp
+++ b/clang/test/Parser/cxx-template-argument.cpp
@@ -57,9 +57,9 @@
 // Don't emit spurious messages
 namespace pr16225add {
 
-  template<class T1, typename T2> struct Known { }; // expected-note 3 {{template is declared here}}
+  template<class T1, typename T2> struct Known { }; // expected-note 3{{template parameter is declared here}}
   template<class T1, typename T2> struct X;
-  template<class T1, typename T2> struct ABC; // expected-note {{template is declared here}}
+  template<class T1, typename T2> struct ABC; // expected-note {{template parameter is declared here}}
   template<int N1, int N2> struct ABC2 {};
 
   template<class T1, typename T2> struct foo :
@@ -68,7 +68,7 @@
 
   template<class T1, typename T2> struct foo2 :
     UnknownBase<T1,T2>, // expected-error {{no template named 'UnknownBase'}}
-    Known<T1>  // expected-error {{too few template arguments for class template 'Known'}}
+    Known<T1>  // expected-error {{missing template argument for template parameter}}
   { };
 
   template<class T1, typename T2> struct foo3 :
@@ -76,8 +76,8 @@
   { };
 
   template<class T1, typename T2> struct foo4 :
-    UnknownBase<T1,ABC<T2> >, // expected-error {{too few template arguments for class template 'ABC'}}
-    Known<T1>  // expected-error {{too few template arguments for class template 'Known'}}
+    UnknownBase<T1,ABC<T2> >, // expected-error {{missing template argument for template parameter}}
+    Known<T1>  // expected-error {{missing template argument for template parameter}}
   { };
 
   template<class T1, typename T2> struct foo5 :
@@ -92,7 +92,7 @@
 #if __cplusplus <= 199711L
     // expected-error@-2 {{use '> >'}}
 #endif
-    Known<T1>  // expected-error {{too few template arguments for class template 'Known'}}
+    Known<T1>  // expected-error {{missing template argument for template parameter}}
   { };
 
   template<class T1, typename T2, int N> struct foo7 :
diff --git a/clang/test/Parser/cxx-template-template-recovery.cpp b/clang/test/Parser/cxx-template-template-recovery.cpp
index 61ef82d..5f9bf17 100644
--- a/clang/test/Parser/cxx-template-template-recovery.cpp
+++ b/clang/test/Parser/cxx-template-template-recovery.cpp
@@ -19,8 +19,10 @@
 concept C3 = true; // #C3
 template <typename T>
 auto V3 = true; // #V3
-template <template <typename T> typename C>
-constexpr bool test = true;
+
+template <template <typename T>
+  typename C> // expected-note 6{{template parameter is declared here}}
+    constexpr bool test = true;
 
 static_assert(test<a::C1>); // expected-error {{template argument does not refer to a class or alias template, or template template parameter}} \
                             // expected-note@#C1 {{here}}
diff --git a/clang/test/Parser/cxx1z-class-template-argument-deduction.cpp b/clang/test/Parser/cxx1z-class-template-argument-deduction.cpp
index 9d27f83..a8a9f33 100644
--- a/clang/test/Parser/cxx1z-class-template-argument-deduction.cpp
+++ b/clang/test/Parser/cxx1z-class-template-argument-deduction.cpp
@@ -11,7 +11,7 @@
 // Make sure we still correctly parse cases where a template can appear without arguments.
 namespace template_template_arg {
   template<template<typename> typename> struct X {};
-  template<typename> struct Y {};
+  template<typename> struct Y {}; // expected-note 2{{template parameter is declared here}}
 
   X<A> xa;
   Y<A> ya; // expected-error {{requires template arguments}}
@@ -36,7 +36,7 @@
 
 namespace template_template_arg_pack {
   template<template<typename> typename...> struct XP {};
-  template<typename...> struct YP {};
+  template<typename...> struct YP {}; // expected-note 2{{template parameter is declared here}}
 
   struct Z { template<typename T> struct Q {}; }; // expected-note 2{{here}}
 
@@ -116,7 +116,7 @@
 }
 
 namespace expr {
-  template<typename T> struct U {};
+  template<typename T> struct U {}; // expected-note {{template parameter is declared here}}
   void j() {
     (void)typeid(A); // expected-error{{requires template arguments; argument deduction not allowed here}}
     (void)sizeof(A); // expected-error{{requires template arguments; argument deduction not allowed here}}
diff --git a/clang/test/Sema/invalid-member.cpp b/clang/test/Sema/invalid-member.cpp
index 0e3fec1..ccce392 100644
--- a/clang/test/Sema/invalid-member.cpp
+++ b/clang/test/Sema/invalid-member.cpp
@@ -22,7 +22,7 @@
 
 constexpr int N = undef; // expected-error {{use of undeclared identifier}} \
                             expected-note {{declared here}}
-template<int a>
+template<int a> // expected-note {{template parameter is declared here}}
 class ABC {};
 class T {
   ABC<N> abc; // expected-error {{non-type template argument is not a constant expression}} \
diff --git a/clang/test/SemaCXX/access-base-class.cpp b/clang/test/SemaCXX/access-base-class.cpp
index 47d0f02..7d5fe38 100644
--- a/clang/test/SemaCXX/access-base-class.cpp
+++ b/clang/test/SemaCXX/access-base-class.cpp
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 namespace T1 {
-  
+
 class A { };
 class B : private A { }; // expected-note {{declared private here}}
 
@@ -10,7 +10,7 @@
 
 }
 
-namespace T2 { 
+namespace T2 {
 
 class A { };
 class B : A { }; // expected-note {{implicitly declared private here}}
@@ -24,7 +24,7 @@
 namespace T3 {
 
 class A { };
-class B : public A { }; 
+class B : public A { };
 
 void f(B* b) {
   A *a = b;
@@ -50,30 +50,30 @@
 
 namespace T5 {
   class A {};
-    
+
   class B : private A {
     void f(B *b) {
       A *a = b;
     }
-  };    
+  };
 }
 
 namespace T6 {
   class C;
-  
+
   class A {}; // expected-note{{member is declared here}}
-  
+
   class B : private A { // expected-note {{declared private here}} expected-note {{constrained by private inheritance here}}
     void f(C* c);
   };
-  
-  class C : public B { 
+
+  class C : public B {
     void f(C *c) {
       A* a = c; // expected-error {{cannot cast 'C' to its private base class 'A'}} \
                 // expected-error {{'A' is a private member of 'T6::A'}}
     }
   };
-  
+
   void B::f(C *c) {
     A *a = c;
   }
@@ -82,7 +82,7 @@
 namespace T7 {
   class A {};
   class B : public A {};
-  class C : private B { 
+  class C : private B {
     void f(C *c) {
       A* a = c; // okay
     }
@@ -98,7 +98,7 @@
 template <class T>
 struct trait : flag<sizeof(T)> {}; // expected-note 2{{here}}
 
-template <class T, bool Inferred = trait<T>::value> // expected-note {{here}}
+template <class T, bool Inferred = trait<T>::value> // expected-note 2{{here}}
 struct a {};
 
 template <class T>
diff --git a/clang/test/SemaCXX/alias-template.cpp b/clang/test/SemaCXX/alias-template.cpp
index b49d36a..90095b3 100644
--- a/clang/test/SemaCXX/alias-template.cpp
+++ b/clang/test/SemaCXX/alias-template.cpp
@@ -167,7 +167,10 @@
     f<E>();
   }
 
-  template<typename T, typename U = EnableIf<is_enum<T>>> struct fail1 {}; // expected-note {{here}}
+  template<typename T,
+    typename U = // expected-note {{template parameter is declared here}}
+      EnableIf<is_enum<T>>> // expected-note {{in instantiation of template type alias 'EnableIf' requested here}}
+  struct fail1 {};
   template<typename T> struct fail2 : DisableIf<is_enum<T>> {}; // expected-note {{here}}
 
   fail1<int> f1; // expected-note {{here}}
diff --git a/clang/test/SemaCXX/anonymous-struct.cpp b/clang/test/SemaCXX/anonymous-struct.cpp
index 5927f4e..a8688af 100644
--- a/clang/test/SemaCXX/anonymous-struct.cpp
+++ b/clang/test/SemaCXX/anonymous-struct.cpp
@@ -27,7 +27,7 @@
   };
 };
 
-template <class T> void foo(T);
+template <class T> void foo(T); // #foo
 typedef struct { // expected-error {{anonymous non-C-compatible type given name for linkage purposes by typedef declaration after its linkage was computed; add a tag name here to establish linkage prior to definition}}
 // expected-note@-1 {{unnamed type used in template argument was declared here}}
 
@@ -36,6 +36,7 @@
 #if __cplusplus <= 199711L
     // expected-warning@-2 {{template argument uses unnamed type}}
     // expected-note@-3 {{while substituting deduced template arguments}}
+    // expected-note@#foo {{template parameter is declared here}}
 #endif
   }
 } A; // expected-note {{type is given name 'A' for linkage purposes by this typedef declaration}}
diff --git a/clang/test/SemaCXX/builtin-structured-binding-size.cpp b/clang/test/SemaCXX/builtin-structured-binding-size.cpp
index bcd13a6..b780752 100644
--- a/clang/test/SemaCXX/builtin-structured-binding-size.cpp
+++ b/clang/test/SemaCXX/builtin-structured-binding-size.cpp
@@ -119,6 +119,7 @@
 // expected-error@#tpl-1 {{non-type template argument is not a constant expression}} \
 // expected-note@-1 {{in instantiation of default argument for 'T<int>' required here}} \
 // expected-note@-1 {{while checking a default template argument used here}} \
+// expected-note@#tpl-1 2{{template parameter is declared here}}
 
 static_assert(T<S3>::value == 3);
 
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index 91c4ff1..4e17121 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -102,7 +102,7 @@
 }
 
 namespace TemplateArgumentConversion {
-  template<int n> struct IntParam {};
+  template<int n> struct IntParam {}; // expected-note {{template parameter is declared here}}
 
   using IntParam0 = IntParam<0>;
   using IntParam0 = IntParam<id(0)>;
@@ -1533,7 +1533,7 @@
   constexpr int mmn2 = mm.n; // expected-error {{constant expression}} expected-note {{read of mutable member 'n' is not allowed in a constant expression}}
 
   // Here's one reason why allowing this would be a disaster...
-  template<int n> struct Id { int k = n; };
+  template<int n> struct Id { int k = n; }; // expected-note {{template parameter is declared here}}
   int f() {
     constexpr MM m = { 0 };
     ++m.n;
diff --git a/clang/test/SemaCXX/constant-expression.cpp b/clang/test/SemaCXX/constant-expression.cpp
index ef48ee5..a710def 100644
--- a/clang/test/SemaCXX/constant-expression.cpp
+++ b/clang/test/SemaCXX/constant-expression.cpp
@@ -99,7 +99,7 @@
 namespace IntOrEnum {
   const int k = 0;
   const int &p = k; // expected-note {{declared here}}
-  template<int n> struct S {};
+  template<int n> struct S {}; // expected-note {{template parameter is declared here}}
   S<p> s; // expected-error {{not an integral constant expression}} expected-note {{read of variable 'p' of non-integral, non-enumeration type 'const int &'}}
 }
 
diff --git a/clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp b/clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp
index c8204c2..6b8495e 100644
--- a/clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp
+++ b/clang/test/SemaCXX/cxx1z-noexcept-function-type.cpp
@@ -74,6 +74,7 @@
   };
   struct InstantiateFromAnotherClass {
     template <class B, class T = decltype(static_cast<bool (B::*)(int)>(&B::foo))> // expected-note {{in instantiation of function template specialization}}
+    // expected-note@-1 {{template parameter is declared here}}
     InstantiateFromAnotherClass(B *) {} // expected-note {{in instantiation of default argument}}
   };
   NoexceptWithThis<int> f{};
diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp
index 1474c48..54390e3f 100644
--- a/clang/test/SemaCXX/cxx2a-consteval.cpp
+++ b/clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -201,7 +201,7 @@
 
 using mem_ptr_type = int (A::*)(int);
 
-template<mem_ptr_type ptr>
+template<mem_ptr_type ptr> // expected-note 2{{template parameter is declared here}}
 struct C {};
 
 C<&A::f> c;
diff --git a/clang/test/SemaCXX/cxx2c-template-template-param.cpp b/clang/test/SemaCXX/cxx2c-template-template-param.cpp
index ed55a059..a0b8d79 100644
--- a/clang/test/SemaCXX/cxx2c-template-template-param.cpp
+++ b/clang/test/SemaCXX/cxx2c-template-template-param.cpp
@@ -3,12 +3,16 @@
 namespace Errors {
 
 template <template<typename T> auto>
+// expected-note@-1 4{{template parameter is declared here}}
 struct S1;
 template <template<auto T> auto>
+// expected-note@-1 4{{template parameter is declared here}}
 struct S2;
 template <template<typename T> concept>
+// expected-note@-1 4{{template parameter is declared here}}
 struct S3;
 template <template<auto T> concept>
+// expected-note@-1 4{{template parameter is declared here}}
 struct S4;
 int a;
 
@@ -36,7 +40,7 @@
 
 }
 
-template <template<typename T> auto V> // expected-note {{previous template template parameter is here}} \
+template <template<typename T> auto V> // expected-note {{template parameter is declared here}} \
                                        // expected-error{{template argument for non-type template parameter must be an expression}}
 struct S1 {
     static_assert(V<int> == 42);
@@ -44,18 +48,18 @@
     static_assert(V<double> == 0);
 };
 template <template<auto T> auto V>  // expected-error {{template argument for template type parameter must be a type}} \
-                                    // expected-note {{previous template template parameter is here}}
+                                    // expected-note {{template parameter is declared here}}
 struct S2 {
     static_assert(V<0> == 1);
     static_assert(V<1> == 0);
 };
 template <template<typename T> concept C > // expected-error {{template argument for non-type template parameter must be an expression}} \
-                                           // expected-note {{previous template template parameter is here}}
+                                           // expected-note {{template parameter is declared here}}
 struct S3 {
     static_assert(C<int>);
 };
 template <template<auto> concept C> // expected-error {{template argument for template type parameter must be a type}} \
-                                    // expected-note {{previous template template parameter is here}}
+                                    // expected-note {{template parameter is declared here}}
 struct S4 {
     static_assert(C<0>);
 };
@@ -80,14 +84,14 @@
 constexpr auto Var2<N> = 1;
 
 void test () {
-    S1<Var2> sE; // expected-note {{template template argument has different template parameters than its corresponding template template parameter}}
-    S2<Var>  sE; // expected-note {{template template argument has different template parameters than its corresponding template template parameter}}
+    S1<Var2> sE; // expected-note {{template template argument is incompatible with its corresponding template template parameter}}
+    S2<Var>  sE; // expected-note {{template template argument is incompatible with its corresponding template template parameter}}
     S1<Var> s1;
     S2<Var2> s2;
     S3<C> s3;
-    S4<C> sE; // expected-note {{template template argument has different template parameters than its corresponding template template parameter}}
+    S4<C> sE; // expected-note {{template template argument is incompatible with its corresponding template template parameter}}
     S4<CI> s4;
-    S3<CI> sE; // expected-note {{template template argument has different template parameters than its corresponding template template parameter}}
+    S3<CI> sE; // expected-note {{template template argument is incompatible with its corresponding template template parameter}}
 }
 
 
@@ -342,10 +346,11 @@
 
 namespace InvalidName {
 template <typename T, template <typename> concept C>
-concept A = C<T>; // expected-note {{here}}
+// expected-note@-1 {{template parameter is declared here}}
+concept A = C<T>;
 
 template <A<concept missing<int>> T> // expected-error {{expected expression}} \
-                                     // expected-error {{too few template arguments for concept 'A'}} \
+                                     // expected-error {{missing template argument for template parameter}} \
                                      // expected-error {{unknown type name 'T'}}  \
                                      // expected-error {{expected unqualified-id}}
 auto f();
diff --git a/clang/test/SemaCXX/cxx98-compat-flags.cpp b/clang/test/SemaCXX/cxx98-compat-flags.cpp
index 6ffb3a5..3986251 100644
--- a/clang/test/SemaCXX/cxx98-compat-flags.cpp
+++ b/clang/test/SemaCXX/cxx98-compat-flags.cpp
@@ -1,7 +1,8 @@
 // RUN: %clang_cc1 -fsyntax-only -std=c++17 -Wc++98-compat-pedantic -verify %s
 // RUN: %clang_cc1 -fsyntax-only -std=c++17 -Wc++98-compat-pedantic -Wno-bind-to-temporary-copy -Wno-unnamed-type-template-args -Wno-local-type-template-args -Wno-binary-literal -Werror %s
 
-template<typename T> int TemplateFn(T) { return 0; }
+template<typename T> // expected-note 2{{template parameter is declared here}}
+int TemplateFn(T) { return 0; }
 void LocalTemplateArg() {
   struct S {};
   TemplateFn(S()); // expected-warning {{local type 'S' as template argument is incompatible with C++98}}
diff --git a/clang/test/SemaCXX/cxx98-compat.cpp b/clang/test/SemaCXX/cxx98-compat.cpp
index 8e7acf7..9a8a8e2 100644
--- a/clang/test/SemaCXX/cxx98-compat.cpp
+++ b/clang/test/SemaCXX/cxx98-compat.cpp
@@ -183,7 +183,8 @@
 
 template<int n = 0> void DefaultFuncTemplateArg(); // expected-warning {{default template arguments for a function template are incompatible with C++98}}
 
-template<typename T> int TemplateFn(T) { return 0; }
+template<typename T> // expected-note 2{{template parameter is declared here}}
+int TemplateFn(T) { return 0; }
 void LocalTemplateArg() {
   struct S {};
   TemplateFn(S()); // expected-warning {{local type 'S' as template argument is incompatible with C++98}}
@@ -198,7 +199,7 @@
 #ifndef CXX17COMPAT
 namespace RedundantParensInAddressTemplateParam {
   int n;
-  template<int*p> struct S {};
+  template<int*p> struct S {}; // expected-note 2{{template parameter is declared here}}
   S<(&n)> s; // expected-warning {{parentheses around address non-type template argument are incompatible with C++98}}
   S<(((&n)))> t; // expected-warning {{parentheses around address non-type template argument are incompatible with C++98}}
 }
@@ -321,7 +322,7 @@
 // template argument evaluation rules.
 #ifndef CXX17COMPAT
 namespace NonTypeTemplateArgs {
-  template<typename T, T v> struct S {};
+  template<typename T, T v> struct S {}; // expected-note 2{{template parameter is declared here}}
   const int k = 5; // expected-note {{here}}
   static void f() {} // expected-note {{here}}
   S<const int&, k> s1; // expected-warning {{non-type template argument referring to object 'k' with internal linkage is incompatible with C++98}}
@@ -330,8 +331,8 @@
 
 namespace NullPointerTemplateArg {
   struct A {};
-  template<int*> struct X {};
-  template<int A::*> struct Y {};
+  template<int*> struct X {}; // expected-note {{template parameter is declared here}}
+  template<int A::*> struct Y {}; // expected-note {{template parameter is declared here}}
   X<(int*)0> x; // expected-warning {{use of null pointer as non-type template argument is incompatible with C++98}}
   Y<(int A::*)0> y; // expected-warning {{use of null pointer as non-type template argument is incompatible with C++98}}
 }
diff --git a/clang/test/SemaCXX/invalid-requirement-requires-expr.cpp b/clang/test/SemaCXX/invalid-requirement-requires-expr.cpp
index 097ada3..436dfb9 100644
--- a/clang/test/SemaCXX/invalid-requirement-requires-expr.cpp
+++ b/clang/test/SemaCXX/invalid-requirement-requires-expr.cpp
@@ -17,8 +17,7 @@
       b.data_member;
       requires A<x-1>::far(); // #Invalid
       // expected-error@#Invalid {{recursive template instantiation exceeded maximum depth}}
-      // expected-note@#Invalid {{in instantiation}}
-      // expected-note@#Invalid 2 {{while}}
+      // expected-note@#Invalid 3 {{while}}
       // expected-note@#Invalid {{contexts in backtrace}}
       // expected-note@#Invalid {{increase recursive template instantiation depth}}
     };
diff --git a/clang/test/SemaCXX/invalid-std-initializer-list.cpp b/clang/test/SemaCXX/invalid-std-initializer-list.cpp
index 93246b5..6f8af52 100644
--- a/clang/test/SemaCXX/invalid-std-initializer-list.cpp
+++ b/clang/test/SemaCXX/invalid-std-initializer-list.cpp
@@ -2,7 +2,9 @@
 
 namespace std {
 
-template<class T, class = T::x> // expected-error 2 {{type 'int' cannot be used prior to '::' because it has no members}}
+template<class T,
+  class = // expected-note 2 {{template parameter is declared here}}
+    T::x> // expected-error 2 {{type 'int' cannot be used prior to '::' because it has no members}}
 class initializer_list;
 
 }
diff --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp
index 8ea8e32..a6803ea 100644
--- a/clang/test/SemaCXX/lambda-expressions.cpp
+++ b/clang/test/SemaCXX/lambda-expressions.cpp
@@ -447,7 +447,7 @@
   // expected-error@-1 {{field has incomplete type 'void'}}
 };
 
-template <typename F>
+template <typename F> // cxx03-note {{template parameter is declared here}}
 void g(F f) {
   auto a = A<decltype(f())>();
   // expected-note@-1 {{in instantiation of template class 'PR20731::A<void>' requested here}}
@@ -504,12 +504,14 @@
 
 namespace PR21857 {
   template<typename Fn> struct fun : Fn {
+    // cxx03-note@-1 {{template parameter is declared here}}
     fun() = default;
     using Fn::operator();
   };
   template<typename Fn> fun<Fn> wrap(Fn fn); // cxx03-warning {{template argument uses unnamed type}}
+                                             // cxx03-note@-1 {{template parameter is declared here}}
   auto x = wrap([](){}); // cxx03-warning {{template argument uses unnamed type}} cxx03-note 2 {{unnamed type used in template argument was declared here}}
-                         // cxx03-note@-1 {{while substituting deduced template arguments into function template}}
+                         // cxx03-note@-1 2{{while substituting deduced template arguments into function template}}
 }
 
 namespace PR13987 {
diff --git a/clang/test/SemaCXX/make_integer_seq.cpp b/clang/test/SemaCXX/make_integer_seq.cpp
index 71b7b82..7fca9ed 100644
--- a/clang/test/SemaCXX/make_integer_seq.cpp
+++ b/clang/test/SemaCXX/make_integer_seq.cpp
@@ -48,5 +48,6 @@
 template <typename T, T N> void f() {}
 __make_integer_seq<f, int, 0> x; // expected-error{{template template parameter must be a class template or type alias template}}
 
-__make_integer_seq<__make_integer_seq, int, 10> PR28494; // expected-note{{different template parameters}}
+__make_integer_seq<__make_integer_seq, int, 10> PR28494; // expected-note{{template template argument is incompatible}}
 // expected-error@make_integer_seq.cpp:* {{template argument for template template parameter must be a class template or type alias template}}
+// expected-note@*:* 3{{template parameter from hidden source: template <class, type-parameter-1-0 ...> class}}
diff --git a/clang/test/SemaCXX/type-trait-common-type.cpp b/clang/test/SemaCXX/type-trait-common-type.cpp
index 8f2b97b..214f946 100644
--- a/clang/test/SemaCXX/type-trait-common-type.cpp
+++ b/clang/test/SemaCXX/type-trait-common-type.cpp
@@ -5,10 +5,12 @@
 #  error
 #endif
 
-// expected-note@*:* {{template declaration from hidden source: template <template <class ...> class, template <class> class, class, class ...>}}
+// expected-note@*:* {{template parameter from hidden source: template <class ...> class}}
+// expected-note@*:* {{template parameter from hidden source: class ...}}
+// expected-note@*:* 2{{template parameter from hidden source: template <class ...> class}}
 
 void test() {
-  __builtin_common_type<> a; // expected-error {{too few template arguments for template '__builtin_common_type'}}
+  __builtin_common_type<> a; // expected-error {{missing template argument for template parameter}}
   __builtin_common_type<1> b; // expected-error {{template argument for template template parameter must be a class template or type alias template}}
   __builtin_common_type<int, 1> c; // expected-error {{template argument for template template parameter must be a class template or type alias template}}
 }
@@ -219,6 +221,7 @@
 
 // expected-note@+1 {{in instantiation of template type alias 'common_type_base' requested here}}
 template<typename A, typename B, typename Res = common_type_base<A, B>>
+// expected-note@-1 {{template parameter is declared here}}
 static Res common_type_sfinae();
 // expected-note@-1 {{in instantiation of default argument for 'common_type_sfinae<int, InvalidConversion>' required here}}
 
diff --git a/clang/test/SemaCXX/undefined-internal.cpp b/clang/test/SemaCXX/undefined-internal.cpp
index 9745f09..7f46623 100644
--- a/clang/test/SemaCXX/undefined-internal.cpp
+++ b/clang/test/SemaCXX/undefined-internal.cpp
@@ -209,9 +209,11 @@
     t<f>(&n, &n); // expected-note {{used here}}
 #if __cplusplus < 201103L
     // expected-warning@-3 {{non-type template argument referring to function 'f' with internal linkage}}
-    // expected-note@-4 {{while substituting explicitly-specified template arguments}}
-    // expected-warning@-4 {{non-type template argument referring to function 'f' with internal linkage}}
+    // expected-note@-7 {{template parameter is declared here}}
     // expected-note@-5 {{while substituting explicitly-specified template arguments}}
+    // expected-warning@-5 {{non-type template argument referring to function 'f' with internal linkage}}
+    // expected-note@-9 {{template parameter is declared here}}
+    // expected-note@-7 {{while substituting explicitly-specified template arguments}}
 #endif
   }
 }
diff --git a/clang/test/SemaCXX/warn-deprecated-specializations-in-system-headers.cpp b/clang/test/SemaCXX/warn-deprecated-specializations-in-system-headers.cpp
index 79c9d33..1fe0916 100644
--- a/clang/test/SemaCXX/warn-deprecated-specializations-in-system-headers.cpp
+++ b/clang/test/SemaCXX/warn-deprecated-specializations-in-system-headers.cpp
@@ -10,6 +10,7 @@
 struct [[deprecated]] traits<int> {}; // expected-note {{'traits<int>' has been explicitly marked deprecated here}}
 
 template<typename T, typename Trait = traits<T>>  // expected-warning {{'traits<int>' is deprecated}}
+                                                  // expected-note@-1 {{template parameter is declared here}}
 struct basic_string {};
 
 // should not warn, defined and used in system headers
diff --git a/clang/test/SemaHLSL/BuiltIns/Buffers.hlsl b/clang/test/SemaHLSL/BuiltIns/Buffers.hlsl
index d7c6876..31fdf65 100644
--- a/clang/test/SemaHLSL/BuiltIns/Buffers.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/Buffers.hlsl
@@ -8,7 +8,7 @@
 // expected-error@+1 {{class template 'Buffer' requires template arguments}}
 Buffer BufferErr1;
 
-// expected-error@+1 {{too few template arguments for class template 'Buffer'}}
+// expected-error@+1 {{missing template argument for template parameter}}
 Buffer<> BufferErr2;
 
 // test implicit Buffer concept
@@ -39,7 +39,7 @@
 
 // structs not allowed
 // expected-error@+4 {{constraints not satisfied for class template 'Buffer'}}
-// expected-note@*:* {{template declaration from hidden source: template <typename element_type> requires __is_typed_resource_element_compatible<element_type> class Buffer}}
+// expected-note@*:* {{template parameter from hidden source: typename element_type}}
 // expected-note@*:* {{because 's' does not satisfy '__is_typed_resource_element_compatible'}}
 // expected-note@*:* {{because '__builtin_hlsl_is_typed_resource_element_compatible(s)' evaluated to false}}
 Buffer<s> r6;
diff --git a/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl b/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl
index 361f430..78a6d5f 100644
--- a/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl
@@ -8,7 +8,7 @@
 // expected-error@+1 {{class template 'RWBuffer' requires template arguments}}
 RWBuffer BufferErr1;
 
-// expected-error@+1 {{too few template arguments for class template 'RWBuffer'}}
+// expected-error@+1 {{missing template argument for template parameter}}
 RWBuffer<> BufferErr2;
 
 // test implicit RWBuffer concept
@@ -39,7 +39,7 @@
 
 // structs not allowed
 // expected-error@+4 {{constraints not satisfied for class template 'RWBuffer'}}
-// expected-note@*:* {{template declaration from hidden source: template <typename element_type> requires __is_typed_resource_element_compatible<element_type> class RWBuffer}}
+// expected-note@*:* {{template parameter from hidden source: typename element_type}}
 // expected-note@*:* {{because 's' does not satisfy '__is_typed_resource_element_compatible'}}
 // expected-note@*:* {{because '__builtin_hlsl_is_typed_resource_element_compatible(s)' evaluated to false}}
 RWBuffer<s> r6;
diff --git a/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl b/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl
index e5b1125..6bb71dd 100644
--- a/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl
@@ -8,8 +8,8 @@
 // expected-note@*:* {{template declaration from hidden source: template <typename element_type> requires __is_structured_resource_element_compatible<element_type> class StructuredBuffer {}}}
 StructuredBuffer BufferErr1;
 
-// expected-error@+2 {{too few template arguments for class template 'StructuredBuffer'}}
-// expected-note@*:* {{template declaration from hidden source: template <typename element_type> requires __is_structured_resource_element_compatible<element_type> class StructuredBuffer {}}}
+// expected-error@+2 {{missing template argument for template parameter}}
+// expected-note@*:* {{template parameter from hidden source: typename element_type}}
 StructuredBuffer<> BufferErr2;
 
 // test elements of 0 size
diff --git a/clang/test/SemaObjCXX/parameterized_classes_subst.mm b/clang/test/SemaObjCXX/parameterized_classes_subst.mm
index 4658c3d..728e9d4 100644
--- a/clang/test/SemaObjCXX/parameterized_classes_subst.mm
+++ b/clang/test/SemaObjCXX/parameterized_classes_subst.mm
@@ -408,7 +408,7 @@
 // --------------------------------------------------------------------------
 // Parameterized classes are not templates
 // --------------------------------------------------------------------------
-template<template<typename T, typename U> class TT>
+template<template<typename T, typename U> class TT> // expected-note {{template parameter is declared here}}
 struct AcceptsTemplateTemplate { };
 
 typedef AcceptsTemplateTemplate<NSMutableDictionary> TemplateTemplateFail1; // expected-error{{template argument for template template parameter must be a class template or type alias template}}
diff --git a/clang/test/SemaTemplate/alias-templates.cpp b/clang/test/SemaTemplate/alias-templates.cpp
index ab5cad7..7ec420a 100644
--- a/clang/test/SemaTemplate/alias-templates.cpp
+++ b/clang/test/SemaTemplate/alias-templates.cpp
@@ -278,12 +278,12 @@
 namespace an_alias_template_is_not_a_class_template {
   template<typename T> using Foo = int; // expected-note 3{{here}}
   Foo x; // expected-error {{use of alias template 'Foo' requires template arguments}}
-  Foo<> y; // expected-error {{too few template arguments for alias template 'Foo'}}
+  Foo<> y; // expected-error {{missing template argument for template parameter}}
   int z = Foo(); // expected-error {{use of alias template 'Foo' requires template arguments}}
 
   template<template<typename> class Bar> void f() { // expected-note 3{{here}}
     Bar x; // expected-error {{use of template template parameter 'Bar' requires template arguments}}
-    Bar<> y; // expected-error {{too few template arguments for template template parameter 'Bar'}}
+    Bar<> y; // expected-error {{missing template argument for template parameter}}
     int z = Bar(); // expected-error {{use of template template parameter 'Bar' requires template arguments}}
   }
 }
@@ -304,7 +304,8 @@
   using TB = int (*)(int (*)[1], int (*)[2], int (*)[3]);
 
   template <typename T, int ...M> struct C {
-    template <T... N> using Fn = T(int(*...A)[N]);
+    template <T... N> // expected-note {{template parameter is declared here}}
+      using Fn = T(int(*...A)[N]);
     Fn<1, M..., 4> *p; // expected-error-re 3{{evaluates to {{[234]}}, which cannot be narrowed to type 'bool'}}
   };
   using TC = decltype(C<int, 2, 3>::p);
diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp
index 209e7dc..505562a 100644
--- a/clang/test/SemaTemplate/concepts.cpp
+++ b/clang/test/SemaTemplate/concepts.cpp
@@ -1262,7 +1262,8 @@
 
 C auto x = 0;
 // expected-error@#T_Type {{type 'int' cannot be used prior to '::'}} \
-// expected-note@-1 {{in instantiation of default argument}}
+// expected-note@-1 {{in instantiation of default argument}} \
+// expected-note@#T_Type {{template parameter is declared here}}
 
 // This will be fixed when we merge https://github.com/llvm/llvm-project/pull/141776
 // Which makes us behave like GCC.
diff --git a/clang/test/SemaTemplate/cwg2398.cpp b/clang/test/SemaTemplate/cwg2398.cpp
index 315fa95..81079df 100644
--- a/clang/test/SemaTemplate/cwg2398.cpp
+++ b/clang/test/SemaTemplate/cwg2398.cpp
@@ -264,7 +264,7 @@
     template<class T, class U> struct A {};
 
     template<template<class> class TT> auto f(TT<int> a) { return a; }
-    // expected-note@-1 2{{substitution failure: too few template arguments}}
+    // expected-note@-1 2{{no template parameter}}
 
     A<int, float> v1;
     A<int, double> v2;
@@ -280,7 +280,7 @@
       static constexpr auto val = E1;
     };
     template <template <class T3> class TT> void f(TT<int> v) {
-      // expected-note@-1 {{substitution failure: too few template arguments}}
+      // expected-note@-1 {{no template parameter}}
       static_assert(v.val == 3);
     };
     void test() {
@@ -313,7 +313,7 @@
     }
 
     template <template <class T2, int V3> class TT2> auto g(TT2<double, 1>) {
-      // expected-note@-1 {{too few template arguments for class template 'A'}}
+      // expected-note@-1 {{no template parameter}}
       return f(TT2<int, 2>());
     }
 
@@ -347,11 +347,11 @@
   namespace t1 {
     template<template<int, int...> class> struct A {};
     // expected-error@-1 {{non-type parameter of template template parameter cannot be narrowed from type 'int' to 'char'}}
-    // expected-note@-2 {{previous template template parameter is here}}
+    // expected-note@-2 {{template parameter is declared here}}
 
-    template<char> struct B;
+    template<char> struct B; // expected-note {{template parameter is declared here}}
     template struct A<B>;
-    // expected-note@-1 {{has different template parameters}}
+    // expected-note@-1 {{template template argument is incompatible}}
   } // namespace t1
   namespace t2 {
     template<template<char, int...> class> struct A {};
@@ -361,11 +361,11 @@
   namespace t3 {
     template<template<int...> class> struct A {};
     // expected-error@-1 {{non-type parameter of template template parameter cannot be narrowed from type 'int' to 'char'}}
-    // expected-note@-2 {{previous template template parameter is here}}
+    // expected-note@-2 {{template parameter is declared here}}
 
-    template<char> struct B;
+    template<char> struct B; // expected-note {{template parameter is declared here}}
     template struct A<B>;
-    // expected-note@-1 {{has different template parameters}}
+    // expected-note@-1 {{template template argument is incompatible}}
   } // namespace t3
   namespace t4 {
     template<template<char...> class> struct A {};
@@ -501,7 +501,7 @@
   // expected-note@-1 {{similar constraint expressions not considered equivalent}}
 
   namespace t1 {
-    template<template<C1, class... T1s> class TT1> // expected-note {{TT1' declared here}}
+    template<template<C1, class... T1s> class TT1> // expected-note {{template parameter is declared here}}
     struct A {};
     template<D1, class T2> struct B {}; // expected-note {{'B' declared here}}
     template struct A<B>;
@@ -513,7 +513,7 @@
     template struct A<B>;
   } // namespace t2
   namespace t3 {
-    template<template<C1, class... T1s> class TT1> // expected-note {{'TT1' declared here}}
+    template<template<C1, class... T1s> class TT1> // expected-note {{template parameter is declared here}}
     struct A {};
     template<C2, class T2> struct B {}; // expected-note {{'B' declared here}}
     template struct A<B>;
@@ -521,7 +521,7 @@
   } // namespace t2
   namespace t4 {
     // FIXME: This should be accepted.
-    template<template<C1... T1s> class TT1> // expected-note {{'TT1' declared here}}
+    template<template<C1... T1s> class TT1> // expected-note {{template parameter is declared here}}
     struct A {};
     template<C1 T2> struct B {}; // expected-note {{'B' declared here}}
     template struct A<B>;
@@ -529,14 +529,14 @@
   } // namespace t4
   namespace t5 {
     // FIXME: This should be accepted
-    template<template<C2... T1s> class TT1> // expected-note {{'TT1' declared here}}
+    template<template<C2... T1s> class TT1> // expected-note {{template parameter is declared here}}
     struct A {};
     template<C1 T2> struct B {}; // expected-note {{'B' declared here}}
     template struct A<B>;
     // expected-error@-1 {{'B' is more constrained than template template parameter 'TT1'}}
   } // namespace t5
   namespace t6 {
-    template<template<C1... T1s> class TT1> // expected-note {{'TT1' declared here}}
+    template<template<C1... T1s> class TT1> // expected-note {{template parameter is declared here}}
     struct A {};
     template<C2 T2> struct B {}; // expected-note {{'B' declared here}}
     template struct A<B>;
@@ -555,14 +555,14 @@
     template struct A<B>;
   } // namespace t8
   namespace t9 {
-    template<template<C1... T1s> class TT1> // expected-note {{'TT1' declared here}}
+    template<template<C1... T1s> class TT1> // expected-note {{template parameter is declared here}}
     struct A {};
     template<D1 T2> struct B {}; // expected-note {{'B' declared here}}
     template struct A<B>;
     // expected-error@-1 {{'B' is more constrained than template template parameter 'TT1'}}
   } // namespace t9
   namespace t10 {
-    template<template<class...> requires C1<int> class TT1> // expected-note {{'TT1' declared here}}
+    template<template<class...> requires C1<int> class TT1> // expected-note {{template parameter is declared here}}
     struct A {};
 
     template<class> requires C2<int> struct B {}; // expected-note {{'B' declared here}}
@@ -678,16 +678,16 @@
     template<class A, A B> struct X {};
     // expected-error@-1 {{conflicting deduction 'C' against 'int' for parameter}}
     template<template<class C, int D> class TT> struct Y {};
-    // expected-note@-1 {{previous template template parameter is here}}
+    // expected-note@-1 {{template parameter is declared here}}
     template struct Y<X>;
-    // expected-note@-1 {{has different template parameters}}
+    // expected-note@-1 {{template template argument is incompatible with its corresponding template template parameter}}
   } // namespace t1
   namespace t2 {
     template<class A, A B = 0> struct X {};
     // expected-error@-1 {{conflicting deduction 'C' against 'int' for parameter}}
     template<template<class C> class TT> struct Y {};
-    // expected-note@-1 {{previous template template parameter is here}}
+    // expected-note@-1 {{template parameter is declared here}}
     template struct Y<X>;
-    // expected-note@-1 {{has different template parameters}}
+    // expected-note@-1 {{template template argument is incompatible with its corresponding template template parameter}}
   } // namespace t2
 } // namespace nttp_inconsistent
diff --git a/clang/test/SemaTemplate/dedup-types-builtin.cpp b/clang/test/SemaTemplate/dedup-types-builtin.cpp
index fe6efd7..8e97894 100644
--- a/clang/test/SemaTemplate/dedup-types-builtin.cpp
+++ b/clang/test/SemaTemplate/dedup-types-builtin.cpp
@@ -134,7 +134,9 @@
 static_assert(dedup_params_into_type_list(static_cast<TypeList<int,short,long>*>(nullptr), 1, short(1), 1, 1l, 1l) != 5); // expected-error {{static assertion failed}} \
                                                                                                                           // expected-note {{expression evaluates}}
 
-template <class T, __builtin_dedup_pack<T, int>...> // expected-error 2{{expansions of '__builtin_dedup_pack' are not supported here}}
+template <class T, __builtin_dedup_pack<T, int>...>
+// expected-error@-1 2{{expansions of '__builtin_dedup_pack' are not supported here}}
+// expected-note@-2 2{{template parameter is declared here}}
 struct InTemplateParams {};
 InTemplateParams<int> itp1;
 InTemplateParams<int, 1, 2, 3, 4, 5> itp2;
diff --git a/clang/test/SemaTemplate/default-arguments.cpp b/clang/test/SemaTemplate/default-arguments.cpp
index 5ea34c0..fdf666b 100644
--- a/clang/test/SemaTemplate/default-arguments.cpp
+++ b/clang/test/SemaTemplate/default-arguments.cpp
@@ -1,12 +1,12 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
-template<typename T, int N = 2> struct X; // expected-note{{template is declared here}}
+template<typename T, int N = 2> struct X; // expected-note {{template parameter is declared here}}
 
 X<int, 1> *x1;
 X<int> *x2;
 
-X<> *x3; // expected-error{{too few template arguments for class template 'X'}}
+X<> *x3; // expected-error{{missing template argument for template parameter}}
 
 template<typename U = float, int M> struct X;
 
@@ -20,6 +20,7 @@
 template<> struct a<int> { static const bool v = true; };
 
 template<class T, bool = a<T>::v> struct p { }; // expected-error {{no member named 'v'}}
+                                                // expected-note@-1 {{template parameter is declared here}}
 
 template struct p<bool>; // expected-note {{in instantiation of default argument for 'p<bool>' required here}}
 template struct p<int>;
@@ -50,12 +51,14 @@
 template<typename T>
 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}}
+                                              // expected-error{{no type named 'type' in 'X1<char>'}} \
+                                              // expected-note {{template parameter is declared here}}
+  struct Inner1 { };
 
   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}}
+                                   // expected-error{{no member named 'value' in 'X1<char>'}} \
+                                   // expected-note {{template parameter is declared here}}
+  struct NonType1 { };
 
   template<T Value>
   struct Inner2 { };
@@ -74,10 +77,10 @@
 X2<int> x2i; // expected-note{{in instantiation of template class 'X2<int>' requested here}}
 X2<int>::Inner1<float> x2iif;
 
-X2<int>::Inner1<> x2bad; // expected-error{{too few template arguments for class template 'Inner1'}}
+X2<int>::Inner1<> x2bad; // expected-error{{missing template argument for template parameter}}
 
 X2<int>::NonType1<'a'> x2_nontype1;
-X2<int>::NonType1<> x2_nontype1_bad; // expected-error{{too few template arguments for class template 'NonType1'}}
+X2<int>::NonType1<> x2_nontype1_bad; // expected-error{{missing template argument for template parameter}}
 
 // Check multi-level substitution into template type arguments
 X2<int>::Inner3<float>::VeryInner<> vi;
@@ -112,12 +115,12 @@
 int array4[is_same<X4<add_pointer>,
                    X4<add_pointer, add_pointer::apply> >::value? 1 : -1];
 
-template<int> struct X5 {};
+template<int> struct X5 {}; // expected-note {{template parameter is declared here}}
 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}}
+                                   // expected-note@-1 {{template template argument is incompatible}}
+                                   // expected-note@-2 {{template parameter is declared here}}
   struct X6 {};
 
 X6<int> x6a;
diff --git a/clang/test/SemaTemplate/instantiate-member-pointers.cpp b/clang/test/SemaTemplate/instantiate-member-pointers.cpp
index 8b6c2ef..e4974b2 100644
--- a/clang/test/SemaTemplate/instantiate-member-pointers.cpp
+++ b/clang/test/SemaTemplate/instantiate-member-pointers.cpp
@@ -18,7 +18,7 @@
 struct X2 {
   T f(Class &obj, T Class::*pm) { // expected-error{{to a reference}} \
                       // expected-error{{member pointer to void}}
-    return obj.*pm; 
+    return obj.*pm;
   }
 };
 
@@ -40,12 +40,12 @@
 template<IntMember Member>
 struct X4 {
   X3<int, Y, Member> member;
-  
+
   int &getMember(Y& y) { return y.*Member; }
 };
 
-int &get_X4(X4<&Y::x> x4, Y& y) { 
-  return x4.getMember(y); 
+int &get_X4(X4<&Y::x> x4, Y& y) {
+  return x4.getMember(y);
 }
 
 template<IntMember Member>
@@ -64,12 +64,12 @@
   template <typename T> void S<T>::instantiate() {
     int a[(int)sizeof(T)-42]; // expected-error{{array with a negative size}}
   }
-  S<int> s; 
+  S<int> s;
 }
 
 namespace PR18192 {
   struct A { struct { int n; }; };
-  template<int A::*> struct X {};
+  template<int A::*> struct X {}; // expected-note {{template parameter is declared here}}
   constexpr int A::*p = &A::n;
   X<p> x; // expected-error{{not a pointer to member constant}}
 }
diff --git a/clang/test/SemaTemplate/instantiate-template-template-parm.cpp b/clang/test/SemaTemplate/instantiate-template-template-parm.cpp
index dce30aa2..601049a 100644
--- a/clang/test/SemaTemplate/instantiate-template-template-parm.cpp
+++ b/clang/test/SemaTemplate/instantiate-template-template-parm.cpp
@@ -20,17 +20,17 @@
 apply<add_reference, float>::type fr = i; // expected-error{{non-const lvalue reference to type 'float' cannot bind to a value of unrelated type 'int'}}
 
 // Template template parameters
-template<int> struct B;
+template<int> struct B; // expected-note {{template parameter is declared here}}
 
 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}}
+                                    // expected-note@-2 2{{template parameter is declared here}}
 struct X0 { };
 
 X0<int, B> x0b1;
 X0<float, B> x0b2; // expected-note{{while substituting}}
-X0<long long, B> x0b3; // expected-note {{has different template parameters}}
+X0<long long, B> x0b3; // expected-note {{template template argument is incompatible}}
 
 template<template<int V> class TT>
 struct X1 { };
diff --git a/clang/test/SemaTemplate/instantiation-default-1.cpp b/clang/test/SemaTemplate/instantiation-default-1.cpp
index 3e70a21..8ef9f12 100644
--- a/clang/test/SemaTemplate/instantiation-default-1.cpp
+++ b/clang/test/SemaTemplate/instantiation-default-1.cpp
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 template<typename T, typename U = const T> struct Def1;
 
-template<> struct Def1<int> { 
+template<> struct Def1<int> {
   void foo();
 };
 
@@ -22,9 +22,10 @@
 
 template<typename T,  // FIXME: bad error message below, needs better location info
          typename T2 = const T*>  // expected-error{{'T2' declared as a pointer to a reference}}
+                                  // expected-note@-1 {{template parameter is declared here}}
   struct Def2;
 
-template<> struct Def2<int> { 
+template<> struct Def2<int> {
   void foo();
 };
 
@@ -40,11 +41,11 @@
 
 template<typename T, typename T2 = T&> struct Def3;
 
-template<> struct Def3<int> { 
+template<> struct Def3<int> {
   void foo();
 };
 
-template<> struct Def3<int&> { 
+template<> struct Def3<int&> {
   void bar();
 };
 
@@ -83,7 +84,7 @@
          typename FuncType = R (*)(Arg1, Arg2)>
   struct Def6;
 
-template<> struct Def6<int, float> { 
+template<> struct Def6<int, float> {
   void foo();
 };
 
@@ -91,7 +92,7 @@
   void bar();
 };
 
-bool test_Def6(Def6<int, float, float> *d6a, 
+bool test_Def6(Def6<int, float, float> *d6a,
                Def6<int, float, float, int (*)(float, float)> *d6b,
                Def6<bool, int[5], float(double, double),
                     bool(*)(int*, float(*)(double, double))> *d6c) {
diff --git a/clang/test/SemaTemplate/instantiation-default-2.cpp b/clang/test/SemaTemplate/instantiation-default-2.cpp
index ffa77cf..e5db310 100644
--- a/clang/test/SemaTemplate/instantiation-default-2.cpp
+++ b/clang/test/SemaTemplate/instantiation-default-2.cpp
@@ -4,8 +4,7 @@
 
 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}}
+// expected-note@-2 2{{template parameter is declared here}}
 
 Constant<int, 5> *c1;
 
diff --git a/clang/test/SemaTemplate/instantiation-dependence.cpp b/clang/test/SemaTemplate/instantiation-dependence.cpp
index 1a97dbf..d98d982 100644
--- a/clang/test/SemaTemplate/instantiation-dependence.cpp
+++ b/clang/test/SemaTemplate/instantiation-dependence.cpp
@@ -17,7 +17,8 @@
   }
 
   template<class T,
-           class = void_t<decltype(declval<T>() + 1)>> // expected-error {{invalid operands to binary expression}}
+           class = // expected-note {{template parameter is declared here}}
+             void_t<decltype(declval<T>() + 1)>> // expected-error {{invalid operands to binary expression}}
   struct bar {};
 
   bar<s> bar; // expected-note {{in instantiation of}}
diff --git a/clang/test/SemaTemplate/instantiation-depth-subst-2.cpp b/clang/test/SemaTemplate/instantiation-depth-subst-2.cpp
index 2b519e9..66fd1af 100644
--- a/clang/test/SemaTemplate/instantiation-depth-subst-2.cpp
+++ b/clang/test/SemaTemplate/instantiation-depth-subst-2.cpp
@@ -2,5 +2,6 @@
 
 template<int N> struct S { };
 template<typename T> S<T() + T()> operator+(T, T); // expected-error {{instantiation exceeded maximum depth}} expected-note 2{{while substituting}}
+// expected-note@-1 {{use -ftemplate-depth=N to increase recursive template instantiation depth}}
 S<0> s;
 int k = s + s; // expected-note {{while substituting}}
diff --git a/clang/test/SemaTemplate/instantiation-depth-subst.cpp b/clang/test/SemaTemplate/instantiation-depth-subst.cpp
index 062a8ed..17944bc 100644
--- a/clang/test/SemaTemplate/instantiation-depth-subst.cpp
+++ b/clang/test/SemaTemplate/instantiation-depth-subst.cpp
@@ -3,7 +3,8 @@
 // PR9793
 template<typename T> auto f(T t) -> decltype(f(t)); // \
 // expected-error {{recursive template instantiation exceeded maximum depth of 2}} \
-// expected-note 2 {{while substituting}}
+// expected-note 2 {{while substituting}} \
+// expected-note {{use -ftemplate-depth=N to increase recursive template instantiation depth}}
 
 struct S {};
 int k = f(S{}); // expected-note {{while substituting}}
diff --git a/clang/test/SemaTemplate/ms-unqualified-base-class.cpp b/clang/test/SemaTemplate/ms-unqualified-base-class.cpp
index 5e926c5..d2b02e5 100644
--- a/clang/test/SemaTemplate/ms-unqualified-base-class.cpp
+++ b/clang/test/SemaTemplate/ms-unqualified-base-class.cpp
@@ -84,7 +84,7 @@
   return I;
 }
 
-template <typename Type, int TSize> class Vec {}; // expected-note {{template is declared here}}
+template <typename Type, int TSize> class Vec {}; // expected-note {{template parameter is declared here}}
 
 template <int TDim> class Index : public Vec<int, TDim> {
   // after-error@+1 {{member initializer 'Vec' does not name a non-static data member or base class}}
@@ -107,7 +107,7 @@
 template class Wrong<double>;
 
 template <typename T> class Wrong2 : public Vec<T, 4> {
-  Wrong2() : Vec<T>() {} // expected-error {{too few template arguments for class template 'Vec'}}
+  Wrong2() : Vec<T>() {} // expected-error {{missing template argument for template parameter}}
 };
 
 template class Wrong2<double>;
diff --git a/clang/test/SemaTemplate/nested-template.cpp b/clang/test/SemaTemplate/nested-template.cpp
index b5da1b1..dbdf605 100644
--- a/clang/test/SemaTemplate/nested-template.cpp
+++ b/clang/test/SemaTemplate/nested-template.cpp
@@ -114,16 +114,16 @@
 struct X2 {
   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}}
+                                              // expected-note@-2 {{template parameter is declared here}}
     struct Inner { };
 };
 
-template<typename T, int Value>
+template<typename T, int Value> // expected-note {{template parameter is declared here}}
   struct X2_arg;
 
 X2<int>::Inner<X2_arg> x2i1;
 X2<float> x2a; // expected-note{{instantiation}}
-X2<long long>::Inner<X2_arg> x2i3; // expected-note {{has different template parameters}}
+X2<long long>::Inner<X2_arg> x2i3; // expected-note {{template template argument is incompatible}}
 
 namespace PR10896 {
   template<typename TN>
diff --git a/clang/test/SemaTemplate/partial-spec-instantiate.cpp b/clang/test/SemaTemplate/partial-spec-instantiate.cpp
index 0b84df6..f171bf4 100644
--- a/clang/test/SemaTemplate/partial-spec-instantiate.cpp
+++ b/clang/test/SemaTemplate/partial-spec-instantiate.cpp
@@ -42,7 +42,7 @@
 }
 
 namespace rdar9169404 {
-  template<typename T, T N> struct X { };
+  template<typename T, T N> struct X { }; // #rdar9169404-X
   template<bool C> struct X<bool, C> {
     typedef int type;
   };
@@ -50,6 +50,7 @@
   X<bool, -1>::type value;
 #if __cplusplus >= 201103L
   // expected-error@-2 {{non-type template argument evaluates to -1, which cannot be narrowed to type 'bool'}}
+  // expected-note@#rdar9169404-X {{template parameter is declared here}}
 #endif
 }
 
diff --git a/clang/test/SemaTemplate/recovery-crash.cpp b/clang/test/SemaTemplate/recovery-crash.cpp
index 9b106f1..0d8c7e6 100644
--- a/clang/test/SemaTemplate/recovery-crash.cpp
+++ b/clang/test/SemaTemplate/recovery-crash.cpp
@@ -26,13 +26,14 @@
 }
 
 namespace PR16225 {
-  template <typename T> void f();
+  template <typename T> void f(); // #PR16225-f
   template <typename C> void g(C*) {
     struct LocalStruct : UnknownBase<Mumble, C> { };  // expected-error {{use of undeclared identifier 'Mumble'}}
     f<LocalStruct>();
 #if __cplusplus <= 199711L
     // expected-warning@-2 {{template argument uses local type 'LocalStruct'}}
     // expected-note@-3 {{while substituting explicitly-specified template arguments}}
+    // expected-note@#PR16225-f {{template parameter is declared here}}
 #endif
     struct LocalStruct2 : UnknownBase<C> { };  // expected-error {{no template named 'UnknownBase'}}
   }
diff --git a/clang/test/SemaTemplate/temp_arg.cpp b/clang/test/SemaTemplate/temp_arg.cpp
index 538056a..9048744 100644
--- a/clang/test/SemaTemplate/temp_arg.cpp
+++ b/clang/test/SemaTemplate/temp_arg.cpp
@@ -1,10 +1,10 @@
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx17 %std_cxx98-14 %s
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx17 %std_cxx17- %s
-template<typename T, 
-         int I, 
-         template<typename> class TT>
-  class A; // precxx17-note 3 {{template is declared here}} \
-              cxx17-note 2 {{template is declared here}} \
+template<typename T,
+         int I,
+         template<typename> class TT> // expected-note {{template parameter is declared here}}
+  class A; // precxx17-note 2 {{template is declared here}} \
+              cxx17-note {{template is declared here}} \
               cxx17-note {{candidate template ignored: couldn't infer template argument 'T'}} \
               cxx17-note {{implicit deduction guide declared as 'template <typename T, int I, template <typename> class TT> A(A<T, I, TT>) -> A<T, I, TT>'}} \
               cxx17-note {{candidate function template not viable: requires 1 argument, but 0 were provided}} \
@@ -15,7 +15,7 @@
 A<int, 0, X> * a1;
 
 A<float, 1, X, double> *a2; // expected-error{{too many template arguments for class template 'A'}}
-A<float, 1> *a3; // expected-error{{too few template arguments for class template 'A'}}
+A<float, 1> *a3; // expected-error{{missing template argument for template parameter}}
 A a4; // precxx17-error{{use of class template 'A' requires template arguments}} \
          cxx17-error{{no viable constructor or deduction guide for deduction of template arguments of 'A'}}
 
diff --git a/clang/test/SemaTemplate/temp_arg_nontype.cpp b/clang/test/SemaTemplate/temp_arg_nontype.cpp
index 7d2a010..e9194fb 100644
--- a/clang/test/SemaTemplate/temp_arg_nontype.cpp
+++ b/clang/test/SemaTemplate/temp_arg_nontype.cpp
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -std=c++98 -Wconversion -verify %s
-template<int N> struct A; // expected-note 5{{template parameter is declared here}}
+template<int N> struct A; // expected-note 6{{template parameter is declared here}}
 
 A<0> *a0;
 
@@ -42,7 +42,7 @@
 int h(int);
 float h2(float);
 
-template<int fp(int)> struct A3; // expected-note 1{{template parameter is declared here}}
+template<int fp(int)> struct A3; // expected-note 2{{template parameter is declared here}}
 A3<h> *a14_1;
 A3<&h> *a14_2;
 A3<f> *a14_3;
@@ -61,7 +61,7 @@
 A4<y> *15_3; //  expected-error{{non-type template parameter of reference type 'const X &' cannot bind to template argument of type 'struct Y'}} \
             // FIXME: expected-error{{expected unqualified-id}}
 
-template<int (&fr)(int)> struct A5; // expected-note{{template parameter is declared here}}
+template<int (&fr)(int)> struct A5; // expected-note 2{{template parameter is declared here}}
 A5<h> *a16_1;
 A5<f> *a16_3;
 A5<h2> *a16_6;  // expected-error{{non-type template parameter of reference type 'int (&)(int)' cannot bind to template argument of type 'float (float)'}}
@@ -86,7 +86,7 @@
 
 
 template<int Z::*pm> struct A7;  // expected-note{{template parameter is declared here}}
-template<int Z::*pm> struct A7c;
+template<int Z::*pm> struct A7c; // expected-note{{template parameter is declared here}}
 A7<&Z::int_member> *a18_1;
 A7c<&Z::int_member> *a18_2;
 A7<&Z::float_member> *a18_3; // expected-error{{non-type template argument of type 'float Z::*' cannot be converted to a value of type 'int Z::*'}}
@@ -444,7 +444,10 @@
   A<Y>::B<int, &n> ay; // expected-error {{undefined}} expected-note {{instantiation of}}
 
   template<template<typename> class X> struct C {
-    template<typename T, int N, int M> struct D; // expected-note {{here}}
+    template<typename T, int N,
+      int M // expected-note {{template parameter is declared here}}
+    > struct D;
+    // expected-note@-1 {{template is declared here}}
     template<typename T, X<T> N> struct D<T*, N, N + 1> {}; // expected-error {{type of specialized non-type template argument depends on}}
   };
   C<X>::D<int*, 0, 1> cx;
@@ -494,7 +497,12 @@
   Incomplete f(int); // expected-note 2{{here}}
   int f(short);
 
-  template<typename T, T Value, int(*)[sizeof(f(Value))]> struct X {}; // expected-error 2{{incomplete}}
+  template<typename T, T Value,
+    int(*)[ // expected-note 2{{template parameter is declared here}}
+      sizeof(f(Value)) // expected-error 2{{incomplete}}
+    ]
+  > struct X {};
+
   int arr[sizeof(int)];
   // When checking this template-id, we must not treat 'Value' as having type
   // 'int'; its type is the dependent type 'T'.
diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
index 5752cba..32bb678 100644
--- a/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
+++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
@@ -30,7 +30,7 @@
 
 namespace check_conversion_early {
   struct X {};
-  template<int> struct A {};
+  template<int> struct A {}; // expected-note {{template parameter is declared here}}
   template<X &x> struct A<x> {}; // expected-error {{not implicitly convertible}}
 
   struct Y { constexpr operator int() const { return 0; } };
diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
index 9c25e26..55d1d56 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 {}; // expected-note 3{{template parameter is declared here}}
+template<typename T, T val> struct A {}; // expected-note 15{{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;
@@ -254,8 +254,8 @@
   }
 
   namespace DecltypeAuto {
-    template<auto v> struct A { };
-    template<decltype(auto) v> struct DA { };
+    template<auto v> struct A { }; // expected-note {{template parameter is declared here}}
+    template<decltype(auto) v> struct DA { }; // expected-note {{template parameter is declared here}}
     template<auto&> struct R { };
 
     auto n = 0; // expected-note + {{declared here}}
@@ -448,7 +448,7 @@
   struct R {};
   struct S { constexpr S() {} constexpr S(R) {} };
   struct T { constexpr operator S() { return {}; } };
-  template <const S &> struct A {}; // expected-note {{template parameter is declared here}}
+  template <const S &> struct A {}; // expected-note 3{{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 8450ff0..2f029db 100644
--- a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
+++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
@@ -16,7 +16,7 @@
 int n; // expected-note 1+{{here}}
 
 // pointers to subobjects
-template<int *> struct IntPtr {};
+template<int *> struct IntPtr {}; // expected-note 2{{template parameter is declared here}}
 using IPn = IntPtr<&n + 1>;
 using IPn = IntPtr<&n + 1>;
 
@@ -30,7 +30,7 @@
 
 using IP5 = IntPtr<&s.n[5]>; // expected-error {{not a constant expression}} expected-note {{cannot refer to element 5 of array of 3 elements}}
 
-template<int &> struct IntRef {};
+template<int &> struct IntRef {}; // expected-note 4{{template parameter is declared here}}
 using IRn = IntRef<*(&n + 1)>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of 'n'}}
 using IRn = IntRef<*(&n + 1)>; // expected-error {{not a constant expression}} expected-note {{dereferenced pointer past the end of 'n'}}
 
@@ -72,20 +72,20 @@
   static_assert(&id<A{1,3}> != &id<a>);
 
   int k = id<1>; // expected-error {{no viable conversion from 'int' to 'A'}}
-                 // expected-note@#ClassNTTP1 {{passing argument to parameter 'a' here}}
+                 // expected-note@#ClassNTTP1 {{template parameter is declared here}}
 
   struct B {
     constexpr B() {}
     constexpr B(int) = delete; // expected-note {{here}}
   };
-  template<B> struct Q {}; // expected-note {{passing argument to parameter here}}
+  template<B> struct Q {}; // expected-note {{template parameter is declared here}}
   Q<1> q; // expected-error {{conversion function from 'int' to 'B' invokes a deleted function}}
 
   struct C {
     constexpr C() {}
     C(const C&) = delete; // expected-note {{here}}
   };
-  template<C> struct R {}; // expected-note {{passing argument to parameter here}}
+  template<C> struct R {}; // expected-note {{template parameter is declared here}}
   constexpr C c;
   R<c> r; // expected-error {{call to deleted constructor}}
 }
@@ -228,7 +228,7 @@
   //
   // FIXME: We shouldn't track a value for unnamed bit-fields, nor number
   // them when computing field indexes.
-  template <A> struct X {};
+  template <A> struct X {}; // expected-note {{template parameter is declared here}}
   constexpr A a;
   using T = X<a>;
   using T = X<A{}>;
@@ -238,7 +238,7 @@
 }
 
 namespace Temporary {
-  template<const int &> struct A {}; // expected-note {{template parameter is declared here}}
+  template<const int &> struct A {}; // expected-note 6{{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}}
@@ -254,18 +254,18 @@
   X &&x = X{};
   A<x.a[3]> a5; // expected-error {{reference to subobject of temporary object}}
 
-  template<const int*> struct B {};
+  template<const int*> struct B {}; // expected-note 3{{template parameter is declared here}}
   B<&(int&)(int&&)0> b0; // expected-error {{pointer to temporary object}}
   B<&r3> b3; // expected-error {{pointer to temporary object}}
   B<&x.a[3]> b5; // expected-error {{pointer to subobject of temporary object}}
 
   struct C { const int *p[2]; };
-  template<C> struct D {};
+  template<C> struct D {}; // expected-note {{template parameter is declared here}}
   D<C{nullptr, &r3}> d; // expected-error {{pointer to temporary object}}
 }
 
 namespace StringLiteral {
-  template<decltype(auto)> struct Y {};
+  template<decltype(auto)> struct Y {}; // expected-note 6{{template parameter is declared here}}
   Y<&"hello"> y1; // expected-error {{pointer to string literal}}
   Y<"hello"> y2; // expected-error {{reference to string literal}}
   Y<+"hello"> y3; // expected-error {{pointer to subobject of string literal}}
@@ -278,7 +278,7 @@
 }
 
 namespace TypeInfo {
-  template<decltype(auto)> struct Y {};
+  template<decltype(auto)> struct Y {}; // expected-note 4{{template parameter is declared here}}
   Y<&typeid(int)> y1; // expected-error {{pointer to type_info object}}
   Y<typeid(int)> y2; // expected-error {{reference to type_info object}}
 
@@ -289,7 +289,7 @@
 }
 
 namespace Predefined {
-  template<decltype(auto)> struct Y {};
+  template<decltype(auto)> struct Y {}; // expected-note 7{{template parameter is declared here}}
 
   struct A { const char *p; };
   struct B { const char &r; };
diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx2c.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx2c.cpp
index c4ac36e..9ecdd19 100644
--- a/clang/test/SemaTemplate/temp_arg_nontype_cxx2c.cpp
+++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx2c.cpp
@@ -5,16 +5,16 @@
     int b = 42;
 };
 
-template <Test t>
+template <Test t> // expected-note {{template parameter is declared here}}
 struct A {
     static constexpr auto a = t.a;
     static constexpr auto b = t.b;
 };
 
-template <auto N>
+template <auto N> // expected-note {{template parameter is declared here}}
 struct Auto {};
 
-template <typename T, T elem>
+template <typename T, T elem> // expected-note {{template parameter is declared here}}
 struct Explicit{};
 
 struct L {};
@@ -57,8 +57,8 @@
     DefaultParam3<> d3;
 }
 
-template<auto n> struct B { /* ... */ };
-template<int i> struct C { /* ... */ };
+template<auto n> struct B { /* ... */ }; // expected-note 2{{template parameter is declared here}}
+template<int i> struct C { /* ... */ }; // expected-note {{template parameter is declared here}}
 C<{ 42 }> c1;  // expected-warning {{braces around scalar initializer}}
 
 struct J1 {
@@ -129,6 +129,7 @@
   // expected-note@-1 {{candidate function has been explicitly deleted}}
   template<class T, decltype(f(T()))> struct X {};
   // expected-error@-1 {{call to deleted function 'f'}}
+  // expected-note@-2 {{template parameter is declared here}}
   template<class T> void g() { X<T, 0> x; }
   // expected-note@-1 {{while substituting prior template arguments into non-type template parameter [with T = int]}}
   template void g<int>();
diff --git a/clang/test/SemaTemplate/temp_arg_template.cpp b/clang/test/SemaTemplate/temp_arg_template.cpp
index 73fa57b..b4b442c 100644
--- a/clang/test/SemaTemplate/temp_arg_template.cpp
+++ b/clang/test/SemaTemplate/temp_arg_template.cpp
@@ -2,13 +2,13 @@
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx17 -std=c++17 %s
 
 template<template<typename T> class X> struct A; // #A
-// expected-note@-1 2{{previous template template parameter is here}}
+// expected-note@-1 3{{template parameter is declared here}}
 
-template<template<typename T, int I> class X> struct B; // expected-note{{previous template template parameter is here}}
+template<template<typename T, int I> class X> struct B; // expected-note{{template parameter is declared here}}
 
 template<template<int I> class X> struct C;
 // 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}}
+// expected-note@-2 {{template parameter is declared here}}
 
 template<class> struct X; // expected-note {{template is declared here}}
 template<int N> struct Y; // expected-note {{template parameter is declared here}}
@@ -18,7 +18,10 @@
 namespace N {
   template<class> struct Z;
 }
-template<class, class> struct TooMany; // expected-note{{template is declared here}}
+template<
+  class,
+  class> // expected-note {{template parameter is declared here}}
+struct TooMany;
 
 
 A<X> *a1;
@@ -26,14 +29,14 @@
 A< ::N::Z> *a3;
 
 A<Y> *a4; // expected-error@#A {{template argument for non-type template parameter must be an expression}}
-          // expected-note@-1 {{different template parameters}}
-A<TooMany> *a5; // expected-error {{too few template arguments for class template 'TooMany'}}
-                // expected-note@-1 {{different template parameters}}
+          // expected-note@-1 {{template template argument is incompatible}}
+A<TooMany> *a5; // expected-error@#A {{no template parameter in this template template parameter}}
+                // expected-note@-1 {{template template argument is incompatible}}
 B<X> *a6; // expected-error {{too many template arguments for class template 'X'}}
-          // expected-note@-1 {{different template parameters}}
+          // expected-note@-1 {{template template argument is incompatible}}
 C<Y> *a7;
 C<Ylong> *a8;
-C<Yref> *a9; // expected-note {{different template parameters}}
+C<Yref> *a9; // expected-note {{template template argument is incompatible}}
 
 template<typename T> void f(int);
 
@@ -109,7 +112,7 @@
 
 namespace CheckDependentNonTypeParamTypes {
   template<template<typename T, typename U, T v> class X> struct A {
-    // expected-note@-1 {{previous template template parameter is here}}
+    // expected-note@-1 2{{template parameter is declared here}}
     void f() {
       X<int, void*, 3> x;
     }
@@ -128,7 +131,7 @@
   };
 
   // FIXME: This should probably be rejected, but the rules are at best unclear.
-  A<B> ab; // expected-note {{different template parameters}}
+  A<B> ab; // expected-note {{template template argument is incompatible}}
 
   void use() {
     ab.f();
@@ -138,6 +141,7 @@
 
   template<class> struct C {
     template<class T, T V> struct D {};
+    // expected-note@-1 {{template parameter is declared here}}
     using T = D<char, 1234>;
     // expected-error@-1 {{evaluates to 1234, which cannot be narrowed to type 'char'}}
   };
diff --git a/clang/test/SemaTemplate/temp_arg_template_p0522.cpp b/clang/test/SemaTemplate/temp_arg_template_p0522.cpp
index 60d98a6..2b18a9f 100644
--- a/clang/test/SemaTemplate/temp_arg_template_p0522.cpp
+++ b/clang/test/SemaTemplate/temp_arg_template_p0522.cpp
@@ -1,8 +1,6 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s
 
-// expected-note@temp_arg_template_p0522.cpp:* 1+{{template is declared here}}
 // expected-note@temp_arg_template_p0522.cpp:* 1+{{template parameter is declared here}}
-// expected-note@temp_arg_template_p0522.cpp:* 1+{{previous template template parameter is here}}
 
 template<template<int> typename> struct Ti; // #Ti
 template<template<int...> typename> struct TPi; // #TPi
@@ -34,14 +32,14 @@
         Ti<iDi>,
         Ti<Pi>,
         Ti<iDt>>;
-  using err1 = Ti<ii>; // expected-error {{too few template arguments for class template 'ii'}}
-                       // expected-note@-1 {{different template parameters}}
-  using err2 = Ti<iiPi>; // expected-error {{too few template arguments for class template 'iiPi'}}
-                         // expected-note@-1 {{different template parameters}}
+  using err1 = Ti<ii>; // expected-error@#Ti {{no template parameter in this template template parameter}}
+                       // expected-note@-1 {{template template argument is incompatible}}
+  using err2 = Ti<iiPi>; // expected-error@#Ti {{no template parameter in this template template parameter}}
+                         // expected-note@-1 {{template template argument is incompatible}}
   using err3 = Ti<t0>; // expected-error@#Ti {{template argument for template type parameter must be a type}}
-                       // expected-note@-1 {{different template parameters}}
-  using err4 = Ti<it>; // expected-error {{too few template arguments for class template 'it'}}
-                       // expected-note@-1 {{different template parameters}}
+                       // expected-note@-1 {{template template argument is incompatible}}
+  using err4 = Ti<it>; // expected-error@#Ti {{no template parameter in this template template parameter}}
+                       // expected-note@-1 {{template template argument is incompatible}}
 }
 
 // These are accepted by the backwards-compatibility "parameter pack in
@@ -50,11 +48,11 @@
   using ok = TPi<Pi>;
   using ok_compat = Pt<TPi<i>, TPi<iDi>, TPi<ii>, TPi<iiPi>>;
   using err1 = TPi<t0>; // expected-error@#TPi {{template argument for template type parameter must be a type}}
-                        // expected-note@-1 {{different template parameters}}
+                        // expected-note@-1 {{template template argument is incompatible}}
   using err2 = TPi<iDt>; // expected-error@#TPi {{template argument for template type parameter must be a type}}
-                         // expected-note@-1 {{different template parameters}}
+                         // expected-note@-1 {{template template argument is incompatible}}
   using err3 = TPi<it>; // expected-error@#TPi {{template argument for template type parameter must be a type}}
-                        // expected-note@-1 {{different template parameters}}
+                        // expected-note@-1 {{template template argument is incompatible}}
 }
 
 namespace IntAndPackParam {
@@ -65,19 +63,19 @@
 
 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 err1 = tT0<int, ii>; // expected-error@#tT0 {{no template parameter in this template template parameter}}
+                             // expected-note@-1 {{template template argument is incompatible}}
   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}}
+                                   // expected-note@-1 {{template template argument is incompatible}}
   using err2b = tT0<void*, i>; // expected-error@#tT0 {{value of type 'void *' is not implicitly convertible to 'int'}}
-                               // expected-note@-1 {{different template parameters}}
+                               // expected-note@-1 {{template template argument is incompatible}}
   using err3 = tT0<short, t0>; // expected-error@#tT0 {{template argument for template type parameter must be a type}}
-                               // expected-note@-1 {{different template parameters}}
+                               // expected-note@-1 {{template template argument is incompatible}}
 
   using ok2 = Tt0<t0>;
   using err4 = Tt0<it>; // expected-error@#Tt0 {{template argument for non-type template parameter must be an expression}}
-                        // expected-note@-1 {{different template parameters}}
+                        // expected-note@-1 {{template template argument is incompatible}}
 }
 
 namespace Auto {
@@ -94,22 +92,22 @@
 
   TInt<Auto> ia;
   TInt<AutoPtr> iap; // expected-error@#TInt {{non-type template parameter '' with type 'auto *' has incompatible initializer of type 'int'}}
-                     // expected-note@-1 {{different template parameters}}
+                     // expected-note@-1 {{template template argument is incompatible}}
   TInt<DecltypeAuto> ida;
   TInt<Int> ii;
   TInt<IntPtr> iip; // expected-error@#TInt {{conversion from 'int' to 'int *' is not allowed in a converted constant expression}}
-                    // expected-note@-1 {{different template parameters}}
+                    // expected-note@-1 {{template template argument is incompatible}}
 
   TIntPtr<Auto> ipa;
   TIntPtr<AutoPtr> ipap;
   TIntPtr<DecltypeAuto> ipda;
   TIntPtr<Int> ipi; // expected-error@#TIntPtr {{value of type 'int *' is not implicitly convertible to 'int'}}
-                    // expected-note@-1 {{different template parameters}}
+                    // expected-note@-1 {{template template argument is incompatible}}
   TIntPtr<IntPtr> ipip;
 
   TAuto<Auto> aa;
   TAuto<AutoPtr> aap; // expected-error@#TAuto {{non-type template parameter '' with type 'auto *' has incompatible initializer of type 'auto'}}
-                      // expected-note@-1 {{different template parameters}}
+                      // expected-note@-1 {{template template argument is incompatible}}
   TAuto<Int> ai; // FIXME: ill-formed (?)
   TAuto<IntPtr> aip; // FIXME: ill-formed (?)
 
@@ -131,7 +129,7 @@
   // parameters.
   TDecltypeAuto<Auto> daa;
   TDecltypeAuto<AutoPtr> daap; // expected-error@#TDecltypeAuto {{non-type template parameter '' with type 'auto *' has incompatible initializer of type 'decltype(auto)'}}
-                               // expected-note@-1 {{different template parameters}}
+                               // expected-note@-1 {{template template argument is incompatible}}
 
   int n;
   template<auto A, decltype(A) B = &n> struct SubstFailure;
@@ -160,11 +158,10 @@
   } // namespace t1
   namespace t2 {
     template<template<Y> class> struct A {}; // #A
-    template<X> struct B; // #B
+    template<X> struct B;
     template struct A<B>;
     // expected-error@#A {{no viable conversion from 'const Y' to 'X'}}
-    // expected-note@-2  {{different template parameters}}
+    // expected-note@-2  {{template template argument is incompatible}}
     // expected-note@#X 2{{not viable}}
-    // expected-note@#B  {{passing argument to parameter here}}
   } // namespace t2
 } // namespace GH101394
diff --git a/clang/test/SemaTemplate/temp_arg_type.cpp b/clang/test/SemaTemplate/temp_arg_type.cpp
index 392d257..a0d2bc3 100644
--- a/clang/test/SemaTemplate/temp_arg_type.cpp
+++ b/clang/test/SemaTemplate/temp_arg_type.cpp
@@ -1,9 +1,12 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98 -std=c++98 %s
 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s
 
-template<typename T> class A; // expected-note 2 {{template parameter is declared here}} expected-note{{template is declared here}}
+template<typename T> class A;
+// expected-note@-1 4{{template parameter is declared here}}
+// cxx98-note@-2    2{{template parameter is declared here}}
+// expected-note@-3  {{template is declared here}}
 
 // [temp.arg.type]p1
 A<0> *a1; // expected-error{{template argument for template type parameter must be a type}}