[clang] d8749d7 - [Clang] Suggest missing typename to dependent packs (#230766)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 12 03:29:58 PDT 2026
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 at -2 {{must be a type; omitted 'typename' is a Microsoft extension}}
+#else
+// expected-error at -4 {{must be a type; did you forget 'typename'?}}
+#endif
+// expected-note at -9 {{declared here}}
+
+}
+#endif
+
} // namespace missing_typename
namespace missing_typename_and_base {
More information about the cfe-commits
mailing list