Author: Younan Zhang
Date: 2026-10-12T18:29:53+08:00
New Revision: d8749d7026d05d9e111ceeae0b599d478dc4473a

URL: 
https://github.com/llvm/llvm-project/commit/d8749d7026d05d9e111ceeae0b599d478dc4473a
DIFF: 
https://github.com/llvm/llvm-project/commit/d8749d7026d05d9e111ceeae0b599d478dc4473a.diff

LOG: [Clang] Suggest missing typename to dependent packs (#230766)

We were not correctly handling packs in the error-recovery path

Fixes https://github.com/llvm/llvm-project/issues/75248

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.md
    clang/lib/Sema/SemaTemplate.cpp
    clang/test/SemaTemplate/typename-specifier.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 2bea8614a2963..11f9e6e7a13b6 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -604,6 +604,8 @@ features cannot lower the translation-unit ABI level;
   `operator delete`, since such a delete expression never invokes the
   destructor. (#GH65524)
 
+- Suggest missing `typename` prefixes to dependent packs within template 
arguments. (#GH75248)
+
 - Fixed a false-positive `-Wshadow` warning when a variable in an
   inline-defined friend function shares the name of a non-static class
   member variable. (#GH221190)
@@ -622,7 +624,7 @@ features cannot lower the translation-unit ABI level;
   keyword, such as when deferring the last statement of a block; when
   used as the body of a conditional; or when it immediately precedes
   a `break`/`continue` statement or a `return` with no argument.
- 
+
 - Clang now diagnoses arrays whose size is deduced from an initializer list 
when they exceed the maximum object size
 
 - Added `-Wunsafe-buffer-usage-main-argv` as a diagnostic group under

diff  --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 4406e81d189b6..499563dd3c155 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -5245,13 +5245,17 @@ bool Sema::CheckTemplateTypeArgument(
     // expression; see if maybe it is missing the "typename" keyword.
     CXXScopeSpec SS;
     DeclarationNameInfo NameInfo;
+    TemplateArgument Pattern = Arg;
+    if (Pattern.isPackExpansion())
+      Pattern = Pattern.getPackExpansionPattern();
+    Expr *E = Pattern.getAsExpr();
 
-   if (DependentScopeDeclRefExpr *ArgExpr =
-               dyn_cast<DependentScopeDeclRefExpr>(Arg.getAsExpr())) {
+    if (DependentScopeDeclRefExpr *ArgExpr =
+            dyn_cast<DependentScopeDeclRefExpr>(E)) {
       SS.Adopt(ArgExpr->getQualifierLoc());
       NameInfo = ArgExpr->getNameInfo();
     } else if (CXXDependentScopeMemberExpr *ArgExpr =
-               dyn_cast<CXXDependentScopeMemberExpr>(Arg.getAsExpr())) {
+                   dyn_cast<CXXDependentScopeMemberExpr>(E)) {
       if (ArgExpr->isImplicitAccess()) {
         SS.Adopt(ArgExpr->getQualifierLoc());
         NameInfo = ArgExpr->getMemberNameInfo();
@@ -5282,6 +5286,12 @@ bool Sema::CheckTemplateTypeArgument(
         TL.setElaboratedKeywordLoc(SourceLocation(/*synthesized*/));
         TL.setQualifierLoc(SS.getWithLocInContext(Context));
         TL.setNameLoc(NameInfo.getLoc());
+        if (Arg.isPackExpansion()) {
+          ArgType = Context.getPackExpansionType(ArgType, std::nullopt);
+          PackExpansionTypeLoc TL = TLB.push<PackExpansionTypeLoc>(ArgType);
+          TL.setEllipsisLoc(
+              cast<PackExpansionExpr>(Arg.getAsExpr())->getEllipsisLoc());
+        }
         TSI = TLB.getTypeSourceInfo(Context, ArgType);
 
         // Overwrite our input TemplateArgumentLoc so that we can recover

diff  --git a/clang/test/SemaTemplate/typename-specifier.cpp 
b/clang/test/SemaTemplate/typename-specifier.cpp
index 27175c5b0b568..3c88d0806ffd8 100644
--- a/clang/test/SemaTemplate/typename-specifier.cpp
+++ b/clang/test/SemaTemplate/typename-specifier.cpp
@@ -192,6 +192,24 @@ class ExampleClass1 {
   pair<ExampleItemMap::iterator, int> entry;
   pair<bar, int> foobar; // expected-error {{template argument for template 
type parameter must be a type}}
 };
+
+#if __cplusplus >= 201103L
+namespace GH75248 {
+
+template <typename... Ts> struct S;
+
+template <typename... Ts>
+using U2 = S<Ts::Type...>;
+#ifdef MSVC
+// expected-warning@-2 {{must be a type; omitted 'typename' is a Microsoft 
extension}}
+#else
+// expected-error@-4 {{must be a type; did you forget 'typename'?}}
+#endif
+// expected-note@-9 {{declared here}}
+
+}
+#endif
+
 } // namespace missing_typename
 
 namespace missing_typename_and_base {


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to