https://github.com/mizvekov created 
https://github.com/llvm/llvm-project/pull/155342

This makes sure NestedNameSpecifierLocs don't apply to the replacement 
TemplateName of SubstTemplate* nodes.

Also removes improper name qualification over these Subst Nodes, causing some 
canonical TemplateNames to not be fully qualified when printed.

Since this is a regression introduced in #147835, which was never released, 
there are no release notes.

Fixes #155281

>From 3b3e1b30d55f4f4ff67b631652982ed2d9cd8887 Mon Sep 17 00:00:00 2001
From: Matheus Izvekov <mizve...@gmail.com>
Date: Mon, 25 Aug 2025 22:18:31 -0300
Subject: [PATCH] [clang] fix TemplateName Subst* nodes transform

This makes sure NestedNameSpecifierLocs don't apply to the replacement
TemplateName of SubstTemplate* nodes.

Also removes improper name qualification over these Subst Nodes, causing
some canonical TemplateNames to not be fully qualified when printed.

Since this is a regression introduced in #147835, which was never released,
there are no release notes.

Fixes #155281
---
 clang/include/clang/AST/TemplateName.h        | 14 ++--
 clang/include/clang/AST/TypeLoc.h             | 21 +++---
 clang/lib/AST/ASTContext.cpp                  |  6 ++
 clang/lib/AST/TemplateName.cpp                | 38 +++++-----
 clang/lib/AST/Type.cpp                        | 10 ++-
 clang/lib/AST/TypeLoc.cpp                     | 12 ++--
 clang/lib/Sema/SemaLookup.cpp                 |  2 +-
 clang/lib/Sema/SemaTemplateInstantiate.cpp    | 15 ++--
 clang/lib/Sema/TreeTransform.h                | 71 +++++++++----------
 clang/test/SemaCXX/cxx20-ctad-type-alias.cpp  | 38 +++++-----
 clang/test/SemaTemplate/deduction-guide.cpp   | 42 +++++------
 .../nested-name-spec-template.cpp             | 24 +++++++
 12 files changed, 152 insertions(+), 141 deletions(-)

diff --git a/clang/include/clang/AST/TemplateName.h 
b/clang/include/clang/AST/TemplateName.h
index 37ea401a0045a..abb0669bff378 100644
--- a/clang/include/clang/AST/TemplateName.h
+++ b/clang/include/clang/AST/TemplateName.h
@@ -335,17 +335,17 @@ class TemplateName {
   /// structure, if any.
   QualifiedTemplateName *getAsQualifiedTemplateName() const;
 
-  /// Retrieve the underlying qualified template name,
-  /// looking through underlying nodes.
-  QualifiedTemplateName *getAsAdjustedQualifiedTemplateName() const;
-
   /// Retrieve the underlying dependent template name
   /// structure, if any.
   DependentTemplateName *getAsDependentTemplateName() const;
 
-  // Retrieve the qualifier stored in either a underlying DependentTemplateName
-  // or QualifiedTemplateName.
-  NestedNameSpecifier getQualifier() const;
+  // Retrieve the qualifier and template keyword stored in either a underlying
+  // DependentTemplateName or QualifiedTemplateName.
+  std::tuple<NestedNameSpecifier, bool> getQualifierAndTemplateKeyword() const;
+
+  NestedNameSpecifier getQualifier() const {
+    return std::get<0>(getQualifierAndTemplateKeyword());
+  }
 
   /// Retrieve the using shadow declaration through which the underlying
   /// template declaration is introduced, if any.
diff --git a/clang/include/clang/AST/TypeLoc.h 
b/clang/include/clang/AST/TypeLoc.h
index 00835f1490eda..9df7844e4b90b 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -1872,11 +1872,10 @@ class TemplateSpecializationTypeLoc :
     if (!getLocalData()->QualifierData)
       return NestedNameSpecifierLoc();
 
-    auto *QTN =
-        getTypePtr()->getTemplateName().getAsAdjustedQualifiedTemplateName();
-    assert(QTN && "missing qualification");
-    return NestedNameSpecifierLoc(QTN->getQualifier(),
-                                  getLocalData()->QualifierData);
+    NestedNameSpecifier Qualifier =
+        getTypePtr()->getTemplateName().getQualifier();
+    assert(Qualifier && "missing qualification");
+    return NestedNameSpecifierLoc(Qualifier, getLocalData()->QualifierData);
   }
 
   SourceLocation getTemplateKeywordLoc() const {
@@ -2503,10 +2502,9 @@ class DeducedTemplateSpecializationTypeLoc
     void *Data = getLocalData()->QualifierData;
     if (!Data)
       return NestedNameSpecifierLoc();
-    NestedNameSpecifier Qualifier = getTypePtr()
-                                        ->getTemplateName()
-                                        .getAsAdjustedQualifiedTemplateName()
-                                        ->getQualifier();
+    NestedNameSpecifier Qualifier =
+        getTypePtr()->getTemplateName().getQualifier();
+    assert(Qualifier && "missing qualification");
     return NestedNameSpecifierLoc(Qualifier, Data);
   }
 
@@ -2521,10 +2519,7 @@ class DeducedTemplateSpecializationTypeLoc
     }
 
     assert(QualifierLoc.getNestedNameSpecifier() ==
-               getTypePtr()
-                   ->getTemplateName()
-                   .getAsAdjustedQualifiedTemplateName()
-                   ->getQualifier() &&
+               getTypePtr()->getTemplateName().getQualifier() &&
            "Inconsistent nested-name-specifier pointer");
     getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
   }
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 036df53063568..621973bd19aad 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -10447,6 +10447,12 @@ TemplateName 
ASTContext::getQualifiedTemplateName(NestedNameSpecifier Qualifier,
   assert(Template.getKind() == TemplateName::Template ||
          Template.getKind() == TemplateName::UsingTemplate);
 
+  if (Template.getAsTemplateDecl()->getKind() == Decl::TemplateTemplateParm) {
+    assert(!Qualifier && "unexpected qualified template template parameter");
+    assert(TemplateKeyword == false);
+    return Template;
+  }
+
   // FIXME: Canonicalization?
   llvm::FoldingSetNodeID ID;
   QualifiedTemplateName::Profile(ID, Qualifier, TemplateKeyword, Template);
diff --git a/clang/lib/AST/TemplateName.cpp b/clang/lib/AST/TemplateName.cpp
index c171516c38c10..f2cb15dbc43dd 100644
--- a/clang/lib/AST/TemplateName.cpp
+++ b/clang/lib/AST/TemplateName.cpp
@@ -289,28 +289,23 @@ QualifiedTemplateName 
*TemplateName::getAsQualifiedTemplateName() const {
   return dyn_cast_if_present<QualifiedTemplateName *>(Storage);
 }
 
-QualifiedTemplateName *
-TemplateName::getAsAdjustedQualifiedTemplateName() const {
-  for (std::optional<TemplateName> Cur = *this; Cur;
-       Cur = Cur->desugar(/*IgnoreDeduced=*/true))
-    if (QualifiedTemplateName *N = Cur->getAsQualifiedTemplateName())
-      return N;
-  return nullptr;
-}
-
 DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
   return Storage.dyn_cast<DependentTemplateName *>();
 }
 
-NestedNameSpecifier TemplateName::getQualifier() const {
+std::tuple<NestedNameSpecifier, bool>
+TemplateName::getQualifierAndTemplateKeyword() const {
   for (std::optional<TemplateName> Cur = *this; Cur;
        Cur = Cur->desugar(/*IgnoreDeduced=*/true)) {
     if (DependentTemplateName *N = Cur->getAsDependentTemplateName())
-      return N->getQualifier();
+      return {N->getQualifier(), N->hasTemplateKeyword()};
     if (QualifiedTemplateName *N = Cur->getAsQualifiedTemplateName())
-      return N->getQualifier();
+      return {N->getQualifier(), N->hasTemplateKeyword()};
+    if (Cur->getAsSubstTemplateTemplateParm() ||
+        Cur->getAsSubstTemplateTemplateParmPack())
+      break;
   }
-  return std::nullopt;
+  return {std::nullopt, false};
 }
 
 UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const {
@@ -448,8 +443,14 @@ void TemplateName::print(raw_ostream &OS, const 
PrintingPolicy &Policy,
       Template = cast<TemplateDecl>(Template->getCanonicalDecl());
     if (handleAnonymousTTP(Template, OS))
       return;
-    if (Qual == Qualified::None || Policy.SuppressScope) {
-      OS << *Template;
+    if (Qual == Qualified::None || isa<TemplateTemplateParmDecl>(Template) ||
+        Policy.SuppressScope) {
+      if (IdentifierInfo *II = Template->getIdentifier();
+          Policy.CleanUglifiedParameters && II &&
+          isa<TemplateTemplateParmDecl>(Template))
+        OS << II->deuglifiedName();
+      else
+        OS << *Template;
     } else {
       PrintingPolicy NestedNamePolicy = Policy;
       NestedNamePolicy.SuppressUnwrittenScope = true;
@@ -474,12 +475,7 @@ void TemplateName::print(raw_ostream &OS, const 
PrintingPolicy &Policy,
     if (handleAnonymousTTP(UTD, OS))
       return;
 
-    if (IdentifierInfo *II = UTD->getIdentifier();
-        Policy.CleanUglifiedParameters && II &&
-        isa<TemplateTemplateParmDecl>(UTD))
-      OS << II->deuglifiedName();
-    else
-      OS << *UTD;
+    OS << *UTD;
   } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
     DTN->print(OS, Policy);
   } else if (SubstTemplateTemplateParmStorage *subst =
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 9df01b8b361c1..63d808f631591 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -1961,12 +1961,10 @@ NestedNameSpecifier Type::getPrefix() const {
   switch (getTypeClass()) {
   case Type::DependentName:
     return cast<DependentNameType>(this)->getQualifier();
-  case Type::TemplateSpecialization: {
-    QualifiedTemplateName *S = cast<TemplateSpecializationType>(this)
-                                   ->getTemplateName()
-                                   .getAsAdjustedQualifiedTemplateName();
-    return S ? S->getQualifier() : std::nullopt;
-  }
+  case Type::TemplateSpecialization:
+    return cast<TemplateSpecializationType>(this)
+        ->getTemplateName()
+        .getQualifier();
   case Type::DependentTemplateSpecialization:
     return cast<DependentTemplateSpecializationType>(this)
         ->getDependentTemplateName()
diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp
index fbe8772924465..3e9597fc4d471 100644
--- a/clang/lib/AST/TypeLoc.cpp
+++ b/clang/lib/AST/TypeLoc.cpp
@@ -750,8 +750,9 @@ void TemplateSpecializationTypeLoc::set(SourceLocation 
ElaboratedKeywordLoc,
 
 void TemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
                                                     SourceLocation Loc) {
-  QualifiedTemplateName *Name =
-      getTypePtr()->getTemplateName().getAsAdjustedQualifiedTemplateName();
+
+  auto [Qualifier, HasTemplateKeyword] =
+      getTypePtr()->getTemplateName().getQualifierAndTemplateKeyword();
 
   SourceLocation ElaboratedKeywordLoc =
       getTypePtr()->getKeyword() != ElaboratedTypeKeyword::None
@@ -759,8 +760,7 @@ void 
TemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
           : SourceLocation();
 
   NestedNameSpecifierLoc QualifierLoc;
-  if (NestedNameSpecifier Qualifier =
-          Name ? Name->getQualifier() : std::nullopt) {
+  if (Qualifier) {
     NestedNameSpecifierLocBuilder Builder;
     Builder.MakeTrivial(Context, Qualifier, Loc);
     QualifierLoc = Builder.getWithLocInContext(Context);
@@ -768,9 +768,7 @@ void 
TemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
 
   TemplateArgumentListInfo TAL(Loc, Loc);
   set(ElaboratedKeywordLoc, QualifierLoc,
-      /*TemplateKeywordLoc=*/Name && Name->hasTemplateKeyword()
-          ? Loc
-          : SourceLocation(),
+      /*TemplateKeywordLoc=*/HasTemplateKeyword ? Loc : SourceLocation(),
       /*NameLoc=*/Loc, /*LAngleLoc=*/Loc, /*RAngleLoc=*/Loc);
   initializeArgLocs(Context, getTypePtr()->template_arguments(), getArgInfos(),
                     Loc);
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 68f7af139af46..42519a52b57ac 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -4578,7 +4578,7 @@ static void getNestedNameSpecifierIdentifiers(
         TemplateName Name =
             cast<TemplateSpecializationType>(T)->getTemplateName();
         if (const QualifiedTemplateName *QTN =
-                Name.getAsAdjustedQualifiedTemplateName()) {
+                Name.getAsQualifiedTemplateName()) {
           getNestedNameSpecifierIdentifiers(QTN->getQualifier(), Identifiers);
           Name = QTN->getUnderlyingTemplate();
         }
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp 
b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index fe1c5faba9e40..a72c95d6d77cf 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2124,9 +2124,11 @@ TemplateName TemplateInstantiator::TransformTemplateName(
     NestedNameSpecifierLoc &QualifierLoc, SourceLocation TemplateKWLoc,
     TemplateName Name, SourceLocation NameLoc, QualType ObjectType,
     NamedDecl *FirstQualifierInScope, bool AllowInjectedClassName) {
-  if (TemplateTemplateParmDecl *TTP
-       = dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl())) 
{
-    if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
+  if (Name.getKind() == TemplateName::Template) {
+    assert(!QualifierLoc && "Unexpected qualifier");
+    if (auto *TTP =
+            dyn_cast<TemplateTemplateParmDecl>(Name.getAsTemplateDecl());
+        TTP && TTP->getDepth() < TemplateArgs.getNumLevels()) {
       // If the corresponding template argument is NULL or non-existent, it's
       // because we are performing instantiation from explicitly-specified
       // template arguments in a function template, but there were some
@@ -2169,13 +2171,6 @@ TemplateName TemplateInstantiator::TransformTemplateName(
 
       TemplateName Template = Arg.getAsTemplate();
       assert(!Template.isNull() && "Null template template argument");
-
-      if (NestedNameSpecifier Qualifier = Template.getQualifier()) {
-        NestedNameSpecifierLocBuilder Builder;
-        Builder.MakeTrivial(SemaRef.Context, Qualifier, NameLoc);
-        QualifierLoc = Builder.getWithLocInContext(SemaRef.Context);
-      }
-
       return getSema().Context.getSubstTemplateTemplateParm(
           Template, AssociatedDecl, TTP->getIndex(), PackIndex, Final);
     }
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index b9404c60f3bd1..79aca11839802 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -744,11 +744,6 @@ class TreeTransform {
 
   StmtResult TransformSEHHandler(Stmt *Handler);
 
-  QualType TransformTemplateSpecializationType(TypeLocBuilder &TLB,
-                                               TemplateSpecializationTypeLoc 
TL,
-                                               TemplateName Template,
-                                               CXXScopeSpec &SS);
-
   QualType TransformDependentTemplateSpecializationType(
       TypeLocBuilder &TLB, DependentTemplateSpecializationTypeLoc TL,
       QualType ObjectType, NamedDecl *UnqualLookup,
@@ -1315,9 +1310,8 @@ class TreeTransform {
   ///
   /// By default, builds the new template name directly. Subclasses may 
override
   /// this routine to provide different behavior.
-  TemplateName RebuildTemplateName(CXXScopeSpec &SS,
-                                   bool TemplateKW,
-                                   TemplateDecl *Template);
+  TemplateName RebuildTemplateName(CXXScopeSpec &SS, bool TemplateKW,
+                                   TemplateName Name);
 
   /// Build a new template name given a nested name specifier and the
   /// name that is referred to as a template.
@@ -4822,9 +4816,7 @@ TemplateName 
TreeTransform<Derived>::TransformTemplateName(
     TemplateName Name, SourceLocation NameLoc, QualType ObjectType,
     NamedDecl *FirstQualifierInScope, bool AllowInjectedClassName) {
   if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) {
-    // FIXME: Preserve UsingTemplateName.
-    TemplateDecl *Template = QTN->getUnderlyingTemplate().getAsTemplateDecl();
-    assert(Template && "qualified template name must refer to a template");
+    TemplateName UnderlyingName = QTN->getUnderlyingTemplate();
 
     if (QualifierLoc) {
       QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(
@@ -4833,20 +4825,22 @@ TemplateName 
TreeTransform<Derived>::TransformTemplateName(
         return TemplateName();
     }
 
-    TemplateDecl *TransTemplate
-      = cast_or_null<TemplateDecl>(getDerived().TransformDecl(NameLoc,
-                                                              Template));
-    if (!TransTemplate)
+    NestedNameSpecifierLoc UnderlyingQualifier;
+    TemplateName NewUnderlyingName = getDerived().TransformTemplateName(
+        UnderlyingQualifier, TemplateKWLoc, UnderlyingName, NameLoc, 
ObjectType,
+        FirstQualifierInScope, AllowInjectedClassName);
+    if (NewUnderlyingName.isNull())
       return TemplateName();
+    assert(!UnderlyingQualifier && "unexpected qualifier");
 
     if (!getDerived().AlwaysRebuild() &&
         QualifierLoc.getNestedNameSpecifier() == QTN->getQualifier() &&
-        TransTemplate == Template)
+        NewUnderlyingName == UnderlyingName)
       return Name;
     CXXScopeSpec SS;
     SS.Adopt(QualifierLoc);
     return getDerived().RebuildTemplateName(SS, QTN->hasTemplateKeyword(),
-                                            TransTemplate);
+                                            NewUnderlyingName);
   }
 
   if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) {
@@ -4874,9 +4868,19 @@ TemplateName 
TreeTransform<Derived>::TransformTemplateName(
 
   if (SubstTemplateTemplateParmStorage *S =
           Name.getAsSubstTemplateTemplateParm()) {
+    assert(!QualifierLoc && "Unexpected qualified SubstTemplateTemplateParm");
+
+    NestedNameSpecifierLoc ReplacementQualifierLoc;
+    TemplateName ReplacementName = S->getReplacement();
+    if (NestedNameSpecifier Qualifier = ReplacementName.getQualifier()) {
+      NestedNameSpecifierLocBuilder Builder;
+      Builder.MakeTrivial(SemaRef.Context, Qualifier, NameLoc);
+      ReplacementQualifierLoc = Builder.getWithLocInContext(SemaRef.Context);
+    }
+
     TemplateName NewName = getDerived().TransformTemplateName(
-        QualifierLoc, TemplateKWLoc, S->getReplacement(), NameLoc, ObjectType,
-        FirstQualifierInScope, AllowInjectedClassName);
+        ReplacementQualifierLoc, TemplateKWLoc, ReplacementName, NameLoc,
+        ObjectType, FirstQualifierInScope, AllowInjectedClassName);
     if (NewName.isNull())
       return TemplateName();
     Decl *AssociatedDecl =
@@ -4892,21 +4896,17 @@ TemplateName 
TreeTransform<Derived>::TransformTemplateName(
   assert(!Name.getAsDeducedTemplateName() &&
          "DeducedTemplateName should not escape partial ordering");
 
-  if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
-    assert(!QualifierLoc && "missed a Qualified Template");
-    TemplateDecl *TransTemplate
-      = cast_or_null<TemplateDecl>(getDerived().TransformDecl(NameLoc,
-                                                              Template));
-    if (!TransTemplate)
-      return TemplateName();
-
-    CXXScopeSpec SS;
-    return getDerived().RebuildTemplateName(SS, /*TemplateKeyword=*/false,
-                                            TransTemplate);
+  // FIXME: Preserve UsingTemplateName.
+  if (auto *Template = Name.getAsTemplateDecl()) {
+    assert(!QualifierLoc && "Unexpected qualifier");
+    return TemplateName(cast_or_null<TemplateDecl>(
+        getDerived().TransformDecl(NameLoc, Template)));
   }
 
   if (SubstTemplateTemplateParmPackStorage *SubstPack
       = Name.getAsSubstTemplateTemplateParmPack()) {
+    assert(!QualifierLoc &&
+           "Unexpected qualified SubstTemplateTemplateParmPack");
     return getDerived().RebuildTemplateName(
         SubstPack->getArgumentPack(), SubstPack->getAssociatedDecl(),
         SubstPack->getIndex(), SubstPack->getFinal());
@@ -17497,13 +17497,12 @@ QualType 
TreeTransform<Derived>::RebuildDependentBitIntType(
   return SemaRef.BuildBitIntType(IsUnsigned, NumBitsExpr, Loc);
 }
 
-template<typename Derived>
-TemplateName
-TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
-                                            bool TemplateKW,
-                                            TemplateDecl *Template) {
+template <typename Derived>
+TemplateName TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
+                                                         bool TemplateKW,
+                                                         TemplateName Name) {
   return SemaRef.Context.getQualifiedTemplateName(SS.getScopeRep(), TemplateKW,
-                                                  TemplateName(Template));
+                                                  Name);
 }
 
 template <typename Derived>
diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp 
b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
index ae70cd9eeac43..1f4d44218ad1f 100644
--- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
+++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
@@ -110,10 +110,10 @@ struct Foo {
 
 template <typename X, int Y>
 using Bar = Foo<X, sizeof(X)>; // expected-note {{candidate template ignored: 
couldn't infer template argument 'X'}} \
-                               // expected-note {{implicit deduction guide 
declared as 'template <typename X> requires __is_deducible(test9::Bar, Foo<X, 
sizeof(X)>) Bar(Foo<X, sizeof(X)>) -> Foo<X, sizeof(X)>'}} \
-                               // expected-note {{implicit deduction guide 
declared as 'template <typename X> requires __is_deducible(test9::Bar, Foo<X, 
sizeof(X)>) Bar(const X (&)[sizeof(X)]) -> Foo<X, sizeof(X)>'}} \
+                               // expected-note {{implicit deduction guide 
declared as 'template <typename X> requires __is_deducible(test9::Bar, 
test9::Foo<X, sizeof(X)>) Bar(test9::Foo<X, sizeof(X)>) -> test9::Foo<X, 
sizeof(X)>'}} \
+                               // expected-note {{implicit deduction guide 
declared as 'template <typename X> requires __is_deducible(test9::Bar, 
test9::Foo<X, sizeof(X)>) Bar(const X (&)[sizeof(X)]) -> test9::Foo<X, 
sizeof(X)>'}} \
                                // expected-note {{candidate template ignored: 
constraints not satisfied [with X = int]}} \
-                               // expected-note {{cannot deduce template 
arguments for 'Bar' from 'Foo<int, 4UL>'}}
+                               // expected-note {{cannot deduce template 
arguments for 'test9::Bar' from 'test9::Foo<int, 4UL>'}}
 
 
 Bar s = {{1}}; // expected-error {{no viable constructor or deduction guide }}
@@ -138,13 +138,13 @@ namespace test11 {
 struct A {};
 template<class T> struct Foo { T c; };
 template<class X, class Y=A>
-using AFoo = Foo<Y>; // expected-note {{candidate template ignored: could not 
match 'Foo<Y>' against 'int'}} \
-                    // expected-note {{implicit deduction guide declared as 
'template <class Y = A> requires __is_deducible(test11::AFoo, Foo<Y>) 
AFoo(Foo<Y>) -> Foo<Y>'}} \
+using AFoo = Foo<Y>; // expected-note {{candidate template ignored: could not 
match 'test11::Foo<Y>' against 'int'}} \
+                    // expected-note {{implicit deduction guide declared as 
'template <class Y = A> requires __is_deducible(test11::AFoo, test11::Foo<Y>) 
AFoo(test11::Foo<Y>) -> test11::Foo<Y>'}} \
                     // expected-note {{candidate template ignored: constraints 
not satisfied [with Y = int]}} \
-                    // expected-note {{cannot deduce template arguments for 
'AFoo' from 'Foo<int>'}} \
-                    // expected-note {{implicit deduction guide declared as 
'template <class Y = A> requires __is_deducible(test11::AFoo, Foo<Y>) AFoo(Y) 
-> Foo<Y>'}} \
+                    // expected-note {{cannot deduce template arguments for 
'test11::AFoo' from 'test11::Foo<int>'}} \
+                    // expected-note {{implicit deduction guide declared as 
'template <class Y = A> requires __is_deducible(test11::AFoo, test11::Foo<Y>) 
AFoo(Y) -> test11::Foo<Y>'}} \
                     // expected-note {{candidate function template not viable: 
requires 0 arguments, but 1 was provided}} \
-                    // expected-note {{implicit deduction guide declared as 
'template <class Y = A> requires __is_deducible(test11::AFoo, Foo<Y>) AFoo() -> 
Foo<Y>'}}
+                    // expected-note {{implicit deduction guide declared as 
'template <class Y = A> requires __is_deducible(test11::AFoo, test11::Foo<Y>) 
AFoo() -> test11::Foo<Y>'}}
 
 AFoo s = {1}; // expected-error {{no viable constructor or deduction guide for 
deduction of template arguments of 'AFoo'}}
 } // namespace test11
@@ -197,8 +197,8 @@ struct Foo {
 template <int K>
 using Bar = Foo<double, K>; // expected-note {{constraints not satisfied for 
class template 'Foo'}}
 // expected-note@-1 {{candidate template ignored: could not match}} 
expected-note@-1 {{candidate template ignored: constraints not satisfied}}
-// expected-note@-2 {{implicit deduction guide declared as 'template <int K> 
requires __is_deducible(test14::Bar, Foo<double, K>) Bar(Foo<double, K>) -> 
Foo<double, K>'}}
-// expected-note@-3 {{implicit deduction guide declared as 'template <int K> 
requires __is_deducible(test14::Bar, Foo<double, K>) Bar(const double (&)[K]) 
-> Foo<double, K>'}}
+// expected-note@-2 {{implicit deduction guide declared as 'template <int K> 
requires __is_deducible(test14::Bar, test14::Foo<double, K>) 
Bar(test14::Foo<double, K>) -> test14::Foo<double, K>'}}
+// expected-note@-3 {{implicit deduction guide declared as 'template <int K> 
requires __is_deducible(test14::Bar, test14::Foo<double, K>) Bar(const double 
(&)[K]) -> test14::Foo<double, K>'}}
 double abc[3];
 Bar s2 = {abc}; // expected-error {{no viable constructor or deduction guide 
for deduction }}
 } // namespace test14
@@ -212,9 +212,9 @@ template<False W>
 using BFoo = AFoo<W>; // expected-note {{candidate template ignored: 
constraints not satisfied [with W = int]}} \
                       // expected-note@-1 {{because 'int' does not satisfy 
'False'}} \
                       // expected-note@#test15_False {{because 'false' 
evaluated to false}} \
-                      // expected-note {{implicit deduction guide declared as 
'template <False<> W> requires __is_deducible(AFoo, Foo<W *>) && 
__is_deducible(test15::BFoo, Foo<W *>) BFoo(W *) -> Foo<W *>}} \
-                      // expected-note {{candidate template ignored: could not 
match 'Foo<W *>' against 'int *'}} \
-                      // expected-note {{template <False<> W> requires 
__is_deducible(AFoo, Foo<W *>) && __is_deducible(test15::BFoo, Foo<W *>) 
BFoo(Foo<W *>) -> Foo<W *>}}
+                      // expected-note {{implicit deduction guide declared as 
'template <False<> W> requires __is_deducible(test15::AFoo, test15::Foo<W *>) 
&& __is_deducible(test15::BFoo, test15::Foo<W *>) BFoo(W *) -> test15::Foo<W 
*>}} \
+                      // expected-note {{candidate template ignored: could not 
match 'test15::Foo<W *>' against 'int *'}} \
+                      // expected-note {{template <False<> W> requires 
__is_deducible(test15::AFoo, test15::Foo<W *>) && __is_deducible(test15::BFoo, 
test15::Foo<W *>) BFoo(test15::Foo<W *>) -> test15::Foo<W *>}}
 int i = 0;
 AFoo a1(&i); // OK, deduce Foo<int *>
 
@@ -276,12 +276,12 @@ template<typename T> requires False<T> // expected-note 
{{because 'int' does not
 Foo(T) -> Foo<int>;
 
 template <typename U>
-using Bar = Foo<U>; // expected-note {{could not match 'Foo<U>' against 
'int'}} \
-                    // expected-note {{implicit deduction guide declared as 
'template <typename U> requires __is_deducible(test18::Bar, Foo<U>) Bar(Foo<U>) 
-> Foo<U>'}} \
+using Bar = Foo<U>; // expected-note {{could not match 'test18::Foo<U>' 
against 'int'}} \
+                    // expected-note {{implicit deduction guide declared as 
'template <typename U> requires __is_deducible(test18::Bar, test18::Foo<U>) 
Bar(test18::Foo<U>) -> test18::Foo<U>'}} \
                     // expected-note {{candidate template ignored: constraints 
not satisfied}} \
                     // expected-note {{implicit deduction guide declared as 
'template <typename T> requires False<T> && __is_deducible(test18::Bar, 
Foo<int>) Bar(T) -> Foo<int>'}} \
                     // expected-note {{candidate function template not 
viable}} \
-                    // expected-note {{implicit deduction guide declared as 
'template <typename U> requires __is_deducible(test18::Bar, Foo<U>) Bar() -> 
Foo<U>'}}
+                    // expected-note {{implicit deduction guide declared as 
'template <typename U> requires __is_deducible(test18::Bar, test18::Foo<U>) 
Bar() -> test18::Foo<U>'}}
 
 Bar s = {1}; // expected-error {{no viable constructor or deduction guide for 
deduction of template arguments}}
 } // namespace test18
@@ -309,8 +309,8 @@ class Foo {};
 // Verify that template template type parameter TTP is referenced/used in the
 // template arguments of the RHS.
 template <template<typename> typename TTP>
-using Bar = Foo<K<TTP>>; // expected-note {{candidate template ignored: could 
not match 'Foo<K<TTP>>' against 'int'}} \
-                        // expected-note {{implicit deduction guide declared 
as 'template <template <typename> typename TTP> requires 
__is_deducible(test20::Bar, Foo<K<TTP>>) Bar(Foo<K<TTP>>) -> Foo<K<TTP>>'}}
+using Bar = Foo<K<TTP>>; // expected-note {{candidate template ignored: could 
not match 'test20::Foo<K<TTP>>' against 'int'}} \
+                        // expected-note {{implicit deduction guide declared 
as 'template <template <typename> typename TTP> requires 
__is_deducible(test20::Bar, test20::Foo<K<TTP>>) Bar(test20::Foo<K<TTP>>) -> 
test20::Foo<K<TTP>>'}}
 
 template <class T>
 class Container {};
@@ -463,7 +463,7 @@ static_assert(__is_same(decltype(a), A<int>));
 BB b{0, 1};
 // expected-error@-1 {{no viable}}
 // expected-note@#test25_BB 2{{not viable}}
-// expected-note@#test25_BB {{template <typename ...US, typename V> requires 
__is_same(V, int) && __is_deducible(AA, A<int, US...>) && 
__is_deducible(test25::BB, A<int, US...>) BB(V) -> A<int, US...>}}
+// expected-note@#test25_BB {{template <typename ...US, typename V> requires 
__is_same(V, int) && __is_deducible(test25::AA, test25::A<int, US...>) && 
__is_deducible(test25::BB, test25::A<int, US...>) BB(V) -> test25::A<int, 
US...>}}
 // expected-note@#test25_BB {{implicit deduction guide}}
 
 }
diff --git a/clang/test/SemaTemplate/deduction-guide.cpp 
b/clang/test/SemaTemplate/deduction-guide.cpp
index ef9b91ca0b18e..e41ba7b3eeb2e 100644
--- a/clang/test/SemaTemplate/deduction-guide.cpp
+++ b/clang/test/SemaTemplate/deduction-guide.cpp
@@ -331,7 +331,7 @@ namespace TTP {
 // CHECK-NEXT:  |-InjectedClassNameType {{.+}} 'TTP::B<T>' dependent{{$}}
 // CHECK-NEXT:  | `-CXXRecord {{.+}} 'B'{{$}}
 // CHECK-NEXT:  `-TemplateSpecializationType {{.+}} 'TT<T>' dependent{{$}}
-// CHECK-NEXT:    |-name: 'TT':'template-parameter-0-1' qualified
+// CHECK-NEXT:    |-name: 'TT':'template-parameter-0-1'
 // CHECK-NEXT:    | `-TemplateTemplateParmDecl {{.+}} depth 0 index 1
 // CHECK-NEXT:    `-TemplateArgument type 'T':'type-parameter-0-0'{{$}}
 // CHECK-NEXT:      `-TemplateTypeParmType {{.+}} 'T' dependent depth 0 index 
0{{$}}
@@ -673,8 +673,8 @@ Test test(42);
 // CHECK-NEXT: | |-DeducedTemplateSpecializationType {{.*}} 'GH122134::Test' 
dependent
 // CHECK-NEXT: | | `-name: 'GH122134::Test'
 // CHECK-NEXT: | |   `-TypeAliasTemplateDecl {{.*}} Test
-// CHECK-NEXT: | `-TemplateSpecializationType {{.*}} 'Struct<int, N>' dependent
-// CHECK-NEXT: |   |-name: 'Struct':'GH122134::Struct' qualified
+// CHECK-NEXT: | `-TemplateSpecializationType {{.*}} 'GH122134::Struct<int, 
N>' dependent
+// CHECK-NEXT: |   |-name: 'GH122134::Struct'
 // CHECK-NEXT: |   | `-ClassTemplateDecl {{.*}} Struct
 // CHECK-NEXT: |   |-TemplateArgument type 'int'
 // CHECK-NEXT: |   | `-SubstTemplateTypeParmType {{.*}} 'int' sugar class 
depth 0 index 0 T
@@ -684,7 +684,7 @@ Test test(42);
 // CHECK-NEXT: |     `-SubstNonTypeTemplateParmExpr {{.*}} 'int'
 // CHECK-NEXT: |       |-NonTypeTemplateParmDecl {{.*}} 'int' depth 0 index 1
 // CHECK-NEXT: |       `-DeclRefExpr {{.*}} 'int' NonTypeTemplateParm {{.*}} 
'N' 'int'
-// CHECK-NEXT: |-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for 
Test> 'auto (auto:1) -> Struct<int, N>'
+// CHECK-NEXT: |-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for 
Test> 'auto (auto:1) -> GH122134::Struct<int, N>'
 // CHECK-NEXT: | `-ParmVarDecl {{.*}} 'auto:1'
 
 } // namespace GH122134
@@ -792,16 +792,16 @@ AA a{};
 // CHECK-NEXT:  | |-DeducedTemplateSpecializationType {{.+}} 'GH133132::AA' 
dependent
 // CHECK-NEXT:  | | `-name: 'GH133132::AA'
 // CHECK-NEXT:  | |   `-TypeAliasTemplateDecl {{.+}} AA
-// CHECK-NEXT:  | `-TemplateSpecializationType {{.+}} 'A<U>' dependent
-// CHECK-NEXT:  |   |-name: 'A':'GH133132::A' qualified
+// CHECK-NEXT:  | `-TemplateSpecializationType {{.+}} 'GH133132::A<U>' 
dependent
+// CHECK-NEXT:  |   |-name: 'GH133132::A'
 // CHECK-NEXT:  |   | `-ClassTemplateDecl {{.+}} A
 // CHECK-NEXT:  |   `-TemplateArgument type 'U':'type-parameter-0-1'
 // CHECK-NEXT:  |     `-SubstTemplateTypeParmType {{.+}} 'U' sugar dependent 
class depth 0 index 0 _Ty
 // CHECK-NEXT:  |       |-FunctionTemplate {{.+}} '<deduction guide for A>'
 // CHECK-NEXT:  |       `-TemplateTypeParmType {{.+}} 'U' dependent depth 0 
index 1
 // CHECK-NEXT:  |         `-TemplateTypeParm {{.+}} 'U'
-// CHECK-NEXT:  |-CXXDeductionGuideDecl {{.+}} implicit <deduction guide for 
AA> 'auto () -> A<U>'
-// CHECK-NEXT:  `-CXXDeductionGuideDecl {{.+}} implicit used <deduction guide 
for AA> 'auto () -> A<int>' implicit_instantiation
+// CHECK-NEXT:  |-CXXDeductionGuideDecl {{.+}} implicit <deduction guide for 
AA> 'auto () -> GH133132::A<U>'
+// CHECK-NEXT:  `-CXXDeductionGuideDecl {{.+}} implicit used <deduction guide 
for AA> 'auto () -> GH133132::A<int>' implicit_instantiation
 // CHECK-NEXT:    |-TemplateArgument type 'int'
 // CHECK-NEXT:    | `-BuiltinType {{.+}} 'int'
 // CHECK-NEXT:    `-TemplateArgument type 'int'
@@ -823,22 +823,22 @@ BB b{};
 // CHECK-NEXT:  |   `-ClassTemplateDecl {{.+}} A
 // CHECK-NEXT:  |-TemplateTemplateParmDecl {{.+}} depth 0 index 1 _Y
 // CHECK-NEXT:  | |-TemplateTypeParmDecl {{.+}} class depth 0 index 0
-// CHECK-NEXT:  | `-TemplateArgument {{.+}} template 
'_X':'template-parameter-0-0' qualified
+// CHECK-NEXT:  | `-TemplateArgument {{.+}} template 
'_X':'template-parameter-0-0'
 // CHECK-NEXT:  |   `-TemplateTemplateParmDecl {{.+}} depth 0 index 0 _X
 // CHECK-NEXT:  |-TypeTraitExpr {{.+}} 'bool' __is_deducible
 // CHECK-NEXT:  | |-DeducedTemplateSpecializationType {{.+}} 'GH133132::BB' 
dependent
 // CHECK-NEXT:  | | `-name: 'GH133132::BB'
 // CHECK-NEXT:  | |   `-TypeAliasTemplateDecl {{.+}} BB
-// CHECK-NEXT:  | `-TemplateSpecializationType {{.+}} 'B<_Y>' dependent
-// CHECK-NEXT:  |   |-name: 'B':'GH133132::B' qualified
+// CHECK-NEXT:  | `-TemplateSpecializationType {{.+}} 'GH133132::B<_Y>' 
dependent
+// CHECK-NEXT:  |   |-name: 'GH133132::B'
 // CHECK-NEXT:  |   | `-ClassTemplateDecl {{.+}} B
 // CHECK-NEXT:  |   `-TemplateArgument template '_Y':'template-parameter-0-1' 
subst index 0
 // CHECK-NEXT:  |     |-parameter: TemplateTemplateParmDecl {{.+}} depth 0 
index 0 _X
 // CHECK-NEXT:  |     |-associated FunctionTemplate {{.+}} '<deduction guide 
for B>'
-// CHECK-NEXT:  |     `-replacement: '_Y':'template-parameter-0-1' qualified
+// CHECK-NEXT:  |     `-replacement: '_Y':'template-parameter-0-1'
 // CHECK-NEXT:  |       `-TemplateTemplateParmDecl {{.+}} depth 0 index 1 _Y
-// CHECK-NEXT:  |-CXXDeductionGuideDecl {{.+}} implicit <deduction guide for 
BB> 'auto () -> B<_Y>'
-// CHECK-NEXT:  `-CXXDeductionGuideDecl {{.+}} implicit used <deduction guide 
for BB> 'auto () -> B<GH133132::A>' implicit_instantiation
+// CHECK-NEXT:  |-CXXDeductionGuideDecl {{.+}} implicit <deduction guide for 
BB> 'auto () -> GH133132::B<_Y>'
+// CHECK-NEXT:  `-CXXDeductionGuideDecl {{.+}} implicit used <deduction guide 
for BB> 'auto () -> GH133132::B<GH133132::A>' implicit_instantiation
 // CHECK-NEXT:    |-TemplateArgument template 'GH133132::A'
 // CHECK-NEXT:    | `-ClassTemplateDecl {{.+}} A
 // CHECK-NEXT:    `-TemplateArgument template 'GH133132::A'
@@ -866,16 +866,16 @@ CC c{};
 // CHECK-NEXT:  | |-DeducedTemplateSpecializationType {{.+}} 'GH133132::CC' 
dependent
 // CHECK-NEXT:  | | `-name: 'GH133132::CC'
 // CHECK-NEXT:  | |   `-TypeAliasTemplateDecl {{.+}} CC
-// CHECK-NEXT:  | `-TemplateSpecializationType {{.+}} 'A<U>' dependent
-// CHECK-NEXT:  |   |-name: 'A':'GH133132::A' qualified
+// CHECK-NEXT:  | `-TemplateSpecializationType {{.+}} 'GH133132::A<U>' 
dependent
+// CHECK-NEXT:  |   |-name: 'GH133132::A'
 // CHECK-NEXT:  |   | `-ClassTemplateDecl {{.+}} A
 // CHECK-NEXT:  |   `-TemplateArgument type 'U':'type-parameter-0-1'
 // CHECK-NEXT:  |     `-SubstTemplateTypeParmType {{.+}} 'U' sugar dependent 
class depth 0 index 0 _Ty
 // CHECK-NEXT:  |       |-FunctionTemplate {{.+}} '<deduction guide for A>'
 // CHECK-NEXT:  |       `-TemplateTypeParmType {{.+}} 'U' dependent depth 0 
index 1
 // CHECK-NEXT:  |         `-TemplateTypeParm {{.+}} 'U'
-// CHECK-NEXT:  |-CXXDeductionGuideDecl {{.+}} implicit <deduction guide for 
CC> 'auto () -> A<U>'
-// CHECK-NEXT:  `-CXXDeductionGuideDecl {{.+}} implicit used <deduction guide 
for CC> 'auto () -> A<GH133132::A<int>>' implicit_instantiation
+// CHECK-NEXT:  |-CXXDeductionGuideDecl {{.+}} implicit <deduction guide for 
CC> 'auto () -> GH133132::A<U>'
+// CHECK-NEXT:  `-CXXDeductionGuideDecl {{.+}} implicit used <deduction guide 
for CC> 'auto () -> GH133132::A<GH133132::A<int>>' implicit_instantiation
 // CHECK-NEXT:    |-TemplateArgument integral '42'
 // CHECK-NEXT:    `-TemplateArgument type 'GH133132::A<int>'
 // CHECK-NEXT:      `-RecordType {{.+}} 'GH133132::A<int>'
@@ -949,8 +949,8 @@ Expand<Type, Invocable<>> _{};
 // CHECK-NEXT:   | |-DeducedTemplateSpecializationType {{.+}} 
'GH141425::Alias' dependent
 // CHECK-NEXT:   | | `-name: 'GH141425::Alias'
 // CHECK-NEXT:   | |   `-TypeAliasTemplateDecl {{.+}} Alias
-// CHECK-NEXT:   | `-TemplateSpecializationType {{.+}} 'Container<T...>' 
dependent
-// CHECK-NEXT:   |   |-name: 'Container':'GH141425::Container' qualified
+// CHECK-NEXT:   | `-TemplateSpecializationType {{.+}} 
'GH141425::Container<T...>' dependent
+// CHECK-NEXT:   |   |-name: 'GH141425::Container'
 // CHECK-NEXT:   |   | `-ClassTemplateDecl {{.+}} Container
 // CHECK-NEXT:   |   `-TemplateArgument type 'T...':'type-parameter-0-0...'
 // CHECK-NEXT:   |     `-PackExpansionType {{.+}} 'T...' dependent
@@ -958,7 +958,7 @@ Expand<Type, Invocable<>> _{};
 // CHECK-NEXT:   |         |-FunctionTemplate {{.+}} '<deduction guide for 
Container>'
 // CHECK-NEXT:   |         `-TemplateTypeParmType {{.+}} 'T' dependent 
contains_unexpanded_pack depth 0 index 0 pack
 // CHECK-NEXT:   |           `-TemplateTypeParm {{.+}} 'T'
-// CHECK-NEXT:   |-CXXDeductionGuideDecl {{.+}} implicit <deduction guide for 
Alias> 'auto (T...) -> Container<T...>'
+// CHECK-NEXT:   |-CXXDeductionGuideDecl {{.+}} implicit <deduction guide for 
Alias> 'auto (T...) -> GH141425::Container<T...>'
 // CHECK-NEXT:   | `-ParmVarDecl {{.+}} 'T...' pack
 
 }
diff --git a/clang/test/SemaTemplate/nested-name-spec-template.cpp 
b/clang/test/SemaTemplate/nested-name-spec-template.cpp
index 0f51a14af9e52..f99fa4b464859 100644
--- a/clang/test/SemaTemplate/nested-name-spec-template.cpp
+++ b/clang/test/SemaTemplate/nested-name-spec-template.cpp
@@ -186,3 +186,27 @@ namespace DependentSizedArray {
   template <class, class> struct A;
   template <class T> struct A<T, typename Z<T(0)>::X>;
 } // namespace DependentUnaryTransform
+
+namespace GH155281 {
+  template <bool> struct enable_if;
+  template <class _Tp, _Tp> struct integral_constant;
+  template <typename> struct conjunction;
+  template <typename T> using value_type_t = T;
+  template <class Check> using require_t = typename 
enable_if<Check::value>::type;
+  template <template <class> class, template <class> class,
+            template <class> class, class... Check>
+  using container_type_check_base =
+      integral_constant<bool, conjunction<Check...>::value>;
+  template <typename> struct is_std_vector;
+  template <template <class> class TypeCheck, class... Check>
+  using require_std_vector_vt =
+      require_t<container_type_check_base<is_std_vector, value_type_t, 
TypeCheck,
+                                          Check...> >;
+  template <typename, typename> class vector_seq_view;
+  namespace internal {
+  template <typename> using is_matrix_or_std_vector = int;
+  }
+  template <typename T>
+  class vector_seq_view<
+      T, require_std_vector_vt<internal::is_matrix_or_std_vector, T> >;
+} // namespace GH155281

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

Reply via email to