https://github.com/jcsxky created 
https://github.com/llvm/llvm-project/pull/93411

Consider the following testcase:
```cpp
namespace PR12884_original {
  template <typename T> struct A {
    struct B { ##1
      template <typename U> struct X {};
      typedef int arg;
    };
    struct C {
      typedef B::X<typename B::arg> x; 
    };
  };

  template <> struct A<int>::B { ##2
    template <int N> struct X {};
    static const int arg = 0;
  };

  A<int>::C::x a;
}
```
It will crash when compiling with `clang(assertions trunk)`. The reason is that 
we lookup `X`(`B::X`) in `##1` when instantiating `typedef B::X<typename 
B::arg> x; ` during instantiating `A<int>::C::x`. This is incorrect because we 
should lookup `X` in `##2` when we see the declaration `A<int>::C::x a;`. Since 
clang parse `A<T>::B<T>` to an `ElaboratedType`(`typename` is not required 
while compiling with `-std=c++20`)  while `typename A<T>::B<T>` turns to be a 
`DependentTemplateSpecializationType`, we should rebuild the `TemplateName` 
with transformed `Qualifier`(whose type is `NestedNameSpecifier`) to make sure 
the lookup context is correct.
This patch also attempts to fix #91677 which crashes with the same reason.

>From ee56373184dff3fd721709ca07a1770957eace29 Mon Sep 17 00:00:00 2001
From: Qizhi Hu <836744...@qq.com>
Date: Sat, 25 May 2024 16:30:27 +0800
Subject: [PATCH 1/2] [Clang][Sema] Use correct TemplateName when transforming
 TemplateSpecializationType

---
 clang/lib/Sema/TreeTransform.h | 43 +++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index dee335b526991..7e8b080a347e8 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -29,8 +29,10 @@
 #include "clang/AST/StmtObjC.h"
 #include "clang/AST/StmtOpenACC.h"
 #include "clang/AST/StmtOpenMP.h"
+#include "clang/AST/TypeLoc.h"
 #include "clang/Basic/DiagnosticParse.h"
 #include "clang/Basic/OpenMPKinds.h"
+#include "clang/Sema/DeclSpec.h"
 #include "clang/Sema/Designator.h"
 #include "clang/Sema/EnterExpressionEvaluationContext.h"
 #include "clang/Sema/Lookup.h"
@@ -7216,7 +7218,46 @@ 
TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB,
       return QualType();
   }
 
-  QualType NamedT = getDerived().TransformType(TLB, TL.getNamedTypeLoc());
+  QualType NamedT;
+  if (0 && SemaRef.getLangOpts().CPlusPlus20 && QualifierLoc && 
isa<TemplateSpecializationType>(TL.getNamedTypeLoc().getType())) {
+    const TemplateSpecializationType *TST = 
TL.getNamedTypeLoc().getType()->getAs<TemplateSpecializationType>();
+    TemplateSpecializationTypeLoc SpecTL =
+        TL.getNamedTypeLoc().castAs<TemplateSpecializationTypeLoc>();
+    // TemplateArgumentListInfo NewTemplateArgs;
+    // NewTemplateArgs.setLAngleLoc(SpecTL.getLAngleLoc());
+    // NewTemplateArgs.setRAngleLoc(SpecTL.getRAngleLoc());
+
+    // typedef TemplateArgumentLocContainerIterator<
+    // TemplateSpecializationTypeLoc> ArgIterator;
+    // if (getDerived().TransformTemplateArguments(ArgIterator(SpecTL, 0),
+    //                                             ArgIterator(SpecTL, 
SpecTL.getNumArgs()),
+    //                                             NewTemplateArgs))
+    //   return QualType();
+
+    CXXScopeSpec SS;
+    SS.Adopt(QualifierLoc);
+    TemplateName InstName = getDerived().RebuildTemplateName(
+        SS, TL.getTemplateKeywordLoc(), 
*TST->getTemplateName().getAsTemplateDecl()->getIdentifier(), 
TL.getNamedTypeLoc().getBeginLoc(), QualType(), nullptr,
+        false);
+
+    if (InstName.isNull())
+      return QualType();
+
+    // If it's still dependent, make a dependent specialization.
+    // if (InstName.getAsDependentTemplateName())
+    //   return SemaRef.Context.getDependentTemplateSpecializationType(
+    //       Keyword, QualifierLoc.getNestedNameSpecifier(), Name,
+    //       Args.arguments());
+
+    // Otherwise, make an elaborated type wrapping a non-dependent
+    // specialization.
+    // NamedT = getDerived().RebuildTemplateSpecializationType(InstName, 
TL.getNamedTypeLoc().getBeginLoc(), NewTemplateArgs);
+    NamedT = TransformTemplateSpecializationType(TLB, SpecTL, InstName);
+  } else {
+    NamedT = getDerived().TransformType(TLB, TL.getNamedTypeLoc());
+    
+  }
+
   if (NamedT.isNull())
     return QualType();
 

>From cb29d45c174f4fd267c273c4386a2010941a63ac Mon Sep 17 00:00:00 2001
From: Qizhi Hu <836744...@qq.com>
Date: Sun, 26 May 2024 19:35:17 +0800
Subject: [PATCH 2/2] [Clang][Sema] Use correct TemplateName when transforming
 TemplateSpecializationType

---
 clang/lib/Sema/TreeTransform.h                | 54 ++++++-------------
 clang/test/SemaCXX/PR91677.cpp                | 31 +++++++++++
 .../SemaTemplate/typename-specifier-3.cpp     |  7 +--
 3 files changed, 52 insertions(+), 40 deletions(-)
 create mode 100644 clang/test/SemaCXX/PR91677.cpp

diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 7e8b080a347e8..6ef2eec09ec02 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -29,10 +29,8 @@
 #include "clang/AST/StmtObjC.h"
 #include "clang/AST/StmtOpenACC.h"
 #include "clang/AST/StmtOpenMP.h"
-#include "clang/AST/TypeLoc.h"
 #include "clang/Basic/DiagnosticParse.h"
 #include "clang/Basic/OpenMPKinds.h"
-#include "clang/Sema/DeclSpec.h"
 #include "clang/Sema/Designator.h"
 #include "clang/Sema/EnterExpressionEvaluationContext.h"
 #include "clang/Sema/Lookup.h"
@@ -7219,48 +7217,30 @@ 
TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB,
   }
 
   QualType NamedT;
-  if (0 && SemaRef.getLangOpts().CPlusPlus20 && QualifierLoc && 
isa<TemplateSpecializationType>(TL.getNamedTypeLoc().getType())) {
-    const TemplateSpecializationType *TST = 
TL.getNamedTypeLoc().getType()->getAs<TemplateSpecializationType>();
+  if (SemaRef.getLangOpts().CPlusPlus20 && QualifierLoc &&
+      isa<TemplateSpecializationType>(TL.getNamedTypeLoc().getType())) {
     TemplateSpecializationTypeLoc SpecTL =
         TL.getNamedTypeLoc().castAs<TemplateSpecializationTypeLoc>();
-    // TemplateArgumentListInfo NewTemplateArgs;
-    // NewTemplateArgs.setLAngleLoc(SpecTL.getLAngleLoc());
-    // NewTemplateArgs.setRAngleLoc(SpecTL.getRAngleLoc());
-
-    // typedef TemplateArgumentLocContainerIterator<
-    // TemplateSpecializationTypeLoc> ArgIterator;
-    // if (getDerived().TransformTemplateArguments(ArgIterator(SpecTL, 0),
-    //                                             ArgIterator(SpecTL, 
SpecTL.getNumArgs()),
-    //                                             NewTemplateArgs))
-    //   return QualType();
-
+    const TemplateSpecializationType *TST =
+        SpecTL.getType()->castAs<TemplateSpecializationType>();
     CXXScopeSpec SS;
     SS.Adopt(QualifierLoc);
-    TemplateName InstName = getDerived().RebuildTemplateName(
-        SS, TL.getTemplateKeywordLoc(), 
*TST->getTemplateName().getAsTemplateDecl()->getIdentifier(), 
TL.getNamedTypeLoc().getBeginLoc(), QualType(), nullptr,
-        false);
-
-    if (InstName.isNull())
-      return QualType();
-
-    // If it's still dependent, make a dependent specialization.
-    // if (InstName.getAsDependentTemplateName())
-    //   return SemaRef.Context.getDependentTemplateSpecializationType(
-    //       Keyword, QualifierLoc.getNestedNameSpecifier(), Name,
-    //       Args.arguments());
-
-    // Otherwise, make an elaborated type wrapping a non-dependent
-    // specialization.
-    // NamedT = getDerived().RebuildTemplateSpecializationType(InstName, 
TL.getNamedTypeLoc().getBeginLoc(), NewTemplateArgs);
-    NamedT = TransformTemplateSpecializationType(TLB, SpecTL, InstName);
-  } else {
+    if (TemplateDecl *TD = TST->getTemplateName().getAsTemplateDecl()) {
+      TemplateName InstName = getDerived().RebuildTemplateName(
+          SS, TL.getTemplateKeywordLoc(), *TD->getIdentifier(),
+          TL.getNamedTypeLoc().getBeginLoc(), /*ObjectType=*/QualType(),
+          /*FirstQualifierInScope=*/nullptr, /*AllowInjectedClassName=*/false);
+      if (InstName.isNull())
+        return QualType();
+      NamedT = TransformTemplateSpecializationType(TLB, SpecTL, InstName);
+    }
+  }
+  if (NamedT.isNull()) {
     NamedT = getDerived().TransformType(TLB, TL.getNamedTypeLoc());
-    
+    if (NamedT.isNull())
+      return QualType();
   }
 
-  if (NamedT.isNull())
-    return QualType();
-
   // C++0x [dcl.type.elab]p2:
   //   If the identifier resolves to a typedef-name or the simple-template-id
   //   resolves to an alias template specialization, the
diff --git a/clang/test/SemaCXX/PR91677.cpp b/clang/test/SemaCXX/PR91677.cpp
new file mode 100644
index 0000000000000..ef2999f959506
--- /dev/null
+++ b/clang/test/SemaCXX/PR91677.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s
+// expected-no-diagnostics
+
+template <typename> struct t1 {
+  template <typename>
+  struct t2 {};
+};
+
+template <typename T>
+t1<T>::template t2<T> f1();
+
+void f2() {
+  f1<bool>();
+}
+
+namespace N {
+  template <typename T> struct A {
+    struct B {
+      template <typename U> struct X {};
+      typedef int arg;
+    };
+    struct C {
+      typedef B::template X<B::arg> x;
+    };
+  };
+
+  template <> struct A<int>::B {
+    template <int N> struct X {};
+    static const int arg = 0;
+  };
+}
diff --git a/clang/test/SemaTemplate/typename-specifier-3.cpp 
b/clang/test/SemaTemplate/typename-specifier-3.cpp
index 714830f0032d2..a62a1fc5ab39c 100644
--- a/clang/test/SemaTemplate/typename-specifier-3.cpp
+++ b/clang/test/SemaTemplate/typename-specifier-3.cpp
@@ -28,16 +28,17 @@ namespace PR12884_original {
       typedef int arg;
     };
     struct C {
-      typedef B::X<typename B::arg> x; // precxx17-warning{{missing 'typename' 
prior to dependent type name B::X; implicit 'typename' is a C++20 extension}}
+      typedef B::X<typename B::arg> x; // precxx17-warning{{missing 'typename' 
prior to dependent type name B::X; implicit 'typename' is a C++20 extension}} \
+                                       cxx17-error{{typename specifier refers 
to non-type member 'arg' in 'PR12884_original::A<int>::B'}}
     };
   };
 
   template <> struct A<int>::B {
     template <int N> struct X {};
-    static const int arg = 0;
+    static const int arg = 0; // cxx17-note{{referenced member 'arg' is 
declared here}}
   };
 
-  A<int>::C::x a;
+  A<int>::C::x a; // cxx17-note{{in instantiation of member class 
'PR12884_original::A<int>::C' requested here}}
 }
 namespace PR12884_half_fixed {
   template <typename T> struct A {

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

Reply via email to