[clang] [Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations (PR #76677)

2024-01-03 Thread Erich Keane via cfe-commits

erichkeane wrote:

Reverted here: https://github.com/llvm/llvm-project/pull/76876

@sdkrystian : please take a look at the regression that nico pointed out and 
re-submit with considerations for that.

https://github.com/llvm/llvm-project/pull/76677
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations (PR #76677)

2024-01-03 Thread Nico Weber via cfe-commits

nico wrote:

This broke check-clang-tools: http://45.33.8.238/linux/127018/step_8.txt

Please take a look and revert for now if it takes a while to fix.

https://github.com/llvm/llvm-project/pull/76677
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations (PR #76677)

2024-01-03 Thread Erich Keane via cfe-commits

https://github.com/erichkeane closed 
https://github.com/llvm/llvm-project/pull/76677
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations (PR #76677)

2024-01-03 Thread Krystian Stasiowski via cfe-commits

sdkrystian wrote:

Added release note & rebased. I'll need someone to merge this for me :)

https://github.com/llvm/llvm-project/pull/76677
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations (PR #76677)

2024-01-03 Thread Krystian Stasiowski via cfe-commits


@@ -518,6 +518,7 @@ Improvements to Clang's diagnostics
 - Clang now diagnoses definitions of friend function specializations, e.g. 
``friend void f<>(int) {}``.
 - Clang now diagnoses narrowing conversions involving const references.
   (`#63151: `_).
+- Clang now diagnoses unexpanded packs within the template argument lists of 
function template specializations.

sdkrystian wrote:

@erichkeane I just looked -- I don't see an open issue.

https://github.com/llvm/llvm-project/pull/76677
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations (PR #76677)

2024-01-03 Thread Erich Keane via cfe-commits

https://github.com/erichkeane approved this pull request.


https://github.com/llvm/llvm-project/pull/76677
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations (PR #76677)

2024-01-03 Thread Erich Keane via cfe-commits


@@ -518,6 +518,7 @@ Improvements to Clang's diagnostics
 - Clang now diagnoses definitions of friend function specializations, e.g. 
``friend void f<>(int) {}``.
 - Clang now diagnoses narrowing conversions involving const references.
   (`#63151: `_).
+- Clang now diagnoses unexpanded packs within the template argument lists of 
function template specializations.

erichkeane wrote:

Do you have a github issue that this fixes, or is this just something that 
never had an issue?  If it has one, please include here, else, this is fine.

https://github.com/llvm/llvm-project/pull/76677
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations (PR #76677)

2024-01-03 Thread Erich Keane via cfe-commits

https://github.com/erichkeane edited 
https://github.com/llvm/llvm-project/pull/76677
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations (PR #76677)

2024-01-03 Thread Krystian Stasiowski via cfe-commits

https://github.com/sdkrystian updated 
https://github.com/llvm/llvm-project/pull/76677

>From f034044ad94d6f7ccec13d89f08acac257ed28bb Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Mon, 1 Jan 2024 07:35:09 -0500
Subject: [PATCH] [Clang][Sema] Diagnose unexpanded packs in the template
 argument lists of function template specializations

---
 clang/docs/ReleaseNotes.rst   |  1 +
 clang/lib/Sema/SemaDecl.cpp   | 89 +--
 .../CXX/temp/temp.decls/temp.variadic/p5.cpp  | 12 +++
 3 files changed, 56 insertions(+), 46 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a3107c4a695321..778ce0e0e52d06 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -518,6 +518,7 @@ Improvements to Clang's diagnostics
 - Clang now diagnoses definitions of friend function specializations, e.g. 
``friend void f<>(int) {}``.
 - Clang now diagnoses narrowing conversions involving const references.
   (`#63151: `_).
+- Clang now diagnoses unexpanded packs within the template argument lists of 
function template specializations.
 
 
 Improvements to Clang's time-trace
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 2de631941325fa..8e46c4984d93dc 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9900,15 +9900,15 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator , 
DeclContext *DC,
 // Match up the template parameter lists with the scope specifier, then
 // determine whether we have a template or a template specialization.
 bool Invalid = false;
+TemplateIdAnnotation *TemplateId =
+D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
+? D.getName().TemplateId
+: nullptr;
 TemplateParameterList *TemplateParams =
 MatchTemplateParametersToScopeSpecifier(
 D.getDeclSpec().getBeginLoc(), D.getIdentifierLoc(),
-D.getCXXScopeSpec(),
-D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
-? D.getName().TemplateId
-: nullptr,
-TemplateParamLists, isFriend, isMemberSpecialization,
-Invalid);
+D.getCXXScopeSpec(), TemplateId, TemplateParamLists, isFriend,
+isMemberSpecialization, Invalid);
 if (TemplateParams) {
   // Check that we can declare a template here.
   if (CheckTemplateDeclScope(S, TemplateParams))
@@ -9921,6 +9921,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator , 
DeclContext *DC,
 if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
   Diag(NewFD->getLocation(), diag::err_destructor_template);
   NewFD->setInvalidDecl();
+  // Function template with explicit template arguments.
+} else if (TemplateId) {
+  Diag(D.getIdentifierLoc(), diag::err_function_template_partial_spec)
+  << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc);
+  NewFD->setInvalidDecl();
 }
 
 // If we're adding a template to a dependent context, we may need to
@@ -9973,6 +9978,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator , 
DeclContext *DC,
 << FixItHint::CreateRemoval(RemoveRange)
 << FixItHint::CreateInsertion(InsertLoc, "<>");
   Invalid = true;
+
+  // Recover by faking up an empty template argument list.
+  HasExplicitTemplateArgs = true;
+  TemplateArgs.setLAngleLoc(InsertLoc);
+  TemplateArgs.setRAngleLoc(InsertLoc);
 }
   }
 } else {
@@ -9986,6 +9996,33 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator , 
DeclContext *DC,
   if (TemplateParamLists.size() > 0)
 // For source fidelity, store all the template param lists.
 NewFD->setTemplateParameterListsInfo(Context, TemplateParamLists);
+
+  // "friend void foo<>(int);" is an implicit specialization decl.
+  if (isFriend && TemplateId)
+isFunctionTemplateSpecialization = true;
+}
+
+// If this is a function template specialization and the unqualified-id of
+// the declarator-id is a template-id, convert the template argument list
+// into our AST format and check for unexpanded packs.
+if (isFunctionTemplateSpecialization && TemplateId) {
+  HasExplicitTemplateArgs = true;
+
+  TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
+  TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
+  ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
+ TemplateId->NumArgs);
+  translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
+
+  // FIXME: Should we check for unexpanded packs if this was an (invalid)
+  // declaration of a function template partial specialization? Should we
+  // consider the unexpanded pack context to be a partial 

[clang] [Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations (PR #76677)

2024-01-03 Thread Erich Keane via cfe-commits

https://github.com/erichkeane commented:

As Corentin said, needs a release note, else LGTM.

https://github.com/llvm/llvm-project/pull/76677
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations (PR #76677)

2024-01-03 Thread via cfe-commits

cor3ntin wrote:

Can you add a release note?
Otherwise, I think the changes are reasonable. I'd like a second pair of eyes 
though @erichkeane 

https://github.com/llvm/llvm-project/pull/76677
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations (PR #76677)

2024-01-01 Thread Krystian Stasiowski via cfe-commits

https://github.com/sdkrystian edited 
https://github.com/llvm/llvm-project/pull/76677
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations (PR #76677)

2024-01-01 Thread Krystian Stasiowski via cfe-commits

sdkrystian wrote:

Ping @erichkeane 

https://github.com/llvm/llvm-project/pull/76677
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations (PR #76677)

2024-01-01 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Krystian Stasiowski (sdkrystian)


Changes

This diagnoses unexpanded packs in the _unqualified-id_ of a function template 
specialization's _declarator-id_, e.g.:
```cpp
templatetypename... Ts
struct A
{
templatetypename U
void f();

template
void fTs(); // error: explicit specialization contains unexpanded 
parameter pack 'Ts'
};
```

I moved the handling of template-id's so it happens right after we determine 
whether we are declaring a function template/function template specialization 
so diagnostics are issued in lexical order. 

---
Full diff: https://github.com/llvm/llvm-project/pull/76677.diff


2 Files Affected:

- (modified) clang/lib/Sema/SemaDecl.cpp (+43-46) 
- (modified) clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp (+12) 


``diff
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index ffbe317d559995..e94637b4f053e0 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9900,15 +9900,15 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator , 
DeclContext *DC,
 // Match up the template parameter lists with the scope specifier, then
 // determine whether we have a template or a template specialization.
 bool Invalid = false;
+TemplateIdAnnotation *TemplateId =
+D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
+? D.getName().TemplateId
+: nullptr;
 TemplateParameterList *TemplateParams =
 MatchTemplateParametersToScopeSpecifier(
 D.getDeclSpec().getBeginLoc(), D.getIdentifierLoc(),
-D.getCXXScopeSpec(),
-D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
-? D.getName().TemplateId
-: nullptr,
-TemplateParamLists, isFriend, isMemberSpecialization,
-Invalid);
+D.getCXXScopeSpec(), TemplateId, TemplateParamLists, isFriend,
+isMemberSpecialization, Invalid);
 if (TemplateParams) {
   // Check that we can declare a template here.
   if (CheckTemplateDeclScope(S, TemplateParams))
@@ -9921,6 +9921,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator , 
DeclContext *DC,
 if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
   Diag(NewFD->getLocation(), diag::err_destructor_template);
   NewFD->setInvalidDecl();
+  // Function template with explicit template arguments.
+} else if (TemplateId) {
+  Diag(D.getIdentifierLoc(), diag::err_function_template_partial_spec)
+  << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc);
+  NewFD->setInvalidDecl();
 }
 
 // If we're adding a template to a dependent context, we may need to
@@ -9973,6 +9978,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator , 
DeclContext *DC,
 << FixItHint::CreateRemoval(RemoveRange)
 << FixItHint::CreateInsertion(InsertLoc, "<>");
   Invalid = true;
+
+  // Recover by faking up an empty template argument list.
+  HasExplicitTemplateArgs = true;
+  TemplateArgs.setLAngleLoc(InsertLoc);
+  TemplateArgs.setRAngleLoc(InsertLoc);
 }
   }
 } else {
@@ -9986,6 +9996,33 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator , 
DeclContext *DC,
   if (TemplateParamLists.size() > 0)
 // For source fidelity, store all the template param lists.
 NewFD->setTemplateParameterListsInfo(Context, TemplateParamLists);
+
+  // "friend void foo<>(int);" is an implicit specialization decl.
+  if (isFriend && TemplateId)
+isFunctionTemplateSpecialization = true;
+}
+
+// If this is a function template specialization and the unqualified-id of
+// the declarator-id is a template-id, convert the template argument list
+// into our AST format and check for unexpanded packs.
+if (isFunctionTemplateSpecialization && TemplateId) {
+  HasExplicitTemplateArgs = true;
+
+  TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
+  TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
+  ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
+ TemplateId->NumArgs);
+  translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
+
+  // FIXME: Should we check for unexpanded packs if this was an (invalid)
+  // declaration of a function template partial specialization? Should we
+  // consider the unexpanded pack context to be a partial specialization?
+  for (const TemplateArgumentLoc  : TemplateArgs.arguments()) {
+if (DiagnoseUnexpandedParameterPack(
+ArgLoc, isFriend ? UPPC_FriendDeclaration
+ : UPPC_ExplicitSpecialization))
+  NewFD->setInvalidDecl();
+  }
 }
 
 if (Invalid) {
@@ -10438,46 +10475,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, 

[clang] [Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations (PR #76677)

2024-01-01 Thread Krystian Stasiowski via cfe-commits

https://github.com/sdkrystian created 
https://github.com/llvm/llvm-project/pull/76677

This diagnoses unexpanded packs in the _unqualified-id_ of a function template 
specialization's _declarator-id_, e.g.:
```cpp
template
struct A
{
template
void f();

template<>
void f(); // error: explicit specialization contains unexpanded 
parameter pack 'Ts'
};
```

I moved the handling of template-id's so it happens right after we determine 
whether we are declaring a function template/function template specialization 
so diagnostics are issued in lexical order. 

>From 7c53e9cd31601f59367879384ad3b1c6b0ae3a98 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Mon, 1 Jan 2024 07:35:09 -0500
Subject: [PATCH] [Clang][Sema] Diagnose unexpanded packs in the template
 argument lists of function template specializations

---
 clang/lib/Sema/SemaDecl.cpp   | 89 +--
 .../CXX/temp/temp.decls/temp.variadic/p5.cpp  | 12 +++
 2 files changed, 55 insertions(+), 46 deletions(-)

diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index ffbe317d559995..e94637b4f053e0 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9900,15 +9900,15 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator , 
DeclContext *DC,
 // Match up the template parameter lists with the scope specifier, then
 // determine whether we have a template or a template specialization.
 bool Invalid = false;
+TemplateIdAnnotation *TemplateId =
+D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
+? D.getName().TemplateId
+: nullptr;
 TemplateParameterList *TemplateParams =
 MatchTemplateParametersToScopeSpecifier(
 D.getDeclSpec().getBeginLoc(), D.getIdentifierLoc(),
-D.getCXXScopeSpec(),
-D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
-? D.getName().TemplateId
-: nullptr,
-TemplateParamLists, isFriend, isMemberSpecialization,
-Invalid);
+D.getCXXScopeSpec(), TemplateId, TemplateParamLists, isFriend,
+isMemberSpecialization, Invalid);
 if (TemplateParams) {
   // Check that we can declare a template here.
   if (CheckTemplateDeclScope(S, TemplateParams))
@@ -9921,6 +9921,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator , 
DeclContext *DC,
 if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
   Diag(NewFD->getLocation(), diag::err_destructor_template);
   NewFD->setInvalidDecl();
+  // Function template with explicit template arguments.
+} else if (TemplateId) {
+  Diag(D.getIdentifierLoc(), diag::err_function_template_partial_spec)
+  << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc);
+  NewFD->setInvalidDecl();
 }
 
 // If we're adding a template to a dependent context, we may need to
@@ -9973,6 +9978,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator , 
DeclContext *DC,
 << FixItHint::CreateRemoval(RemoveRange)
 << FixItHint::CreateInsertion(InsertLoc, "<>");
   Invalid = true;
+
+  // Recover by faking up an empty template argument list.
+  HasExplicitTemplateArgs = true;
+  TemplateArgs.setLAngleLoc(InsertLoc);
+  TemplateArgs.setRAngleLoc(InsertLoc);
 }
   }
 } else {
@@ -9986,6 +9996,33 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator , 
DeclContext *DC,
   if (TemplateParamLists.size() > 0)
 // For source fidelity, store all the template param lists.
 NewFD->setTemplateParameterListsInfo(Context, TemplateParamLists);
+
+  // "friend void foo<>(int);" is an implicit specialization decl.
+  if (isFriend && TemplateId)
+isFunctionTemplateSpecialization = true;
+}
+
+// If this is a function template specialization and the unqualified-id of
+// the declarator-id is a template-id, convert the template argument list
+// into our AST format and check for unexpanded packs.
+if (isFunctionTemplateSpecialization && TemplateId) {
+  HasExplicitTemplateArgs = true;
+
+  TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
+  TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
+  ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
+ TemplateId->NumArgs);
+  translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
+
+  // FIXME: Should we check for unexpanded packs if this was an (invalid)
+  // declaration of a function template partial specialization? Should we
+  // consider the unexpanded pack context to be a partial specialization?
+  for (const TemplateArgumentLoc  : TemplateArgs.arguments()) {
+if (DiagnoseUnexpandedParameterPack(
+ArgLoc, isFriend ? UPPC_FriendDeclaration
+