[clang] [Clang][Sema] Differentiate between partial/explicit specializations when diagnosing unexpanded packs (PR #72015)

2023-11-10 Thread Krystian Stasiowski via cfe-commits

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

None

>From 394e2e0eed84f0102d194174a7c60048556c56dc Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Fri, 10 Nov 2023 20:51:12 -0500
Subject: [PATCH] [Clang] Differentiate between partial/explicit
 specializations when diagnosing unexpanded packs

---
 .../clang/Basic/DiagnosticSemaKinds.td|  6 ++--
 clang/include/clang/Sema/Sema.h   |  3 ++
 clang/lib/Sema/SemaTemplate.cpp   |  8 +++--
 .../CXX/temp/temp.decls/temp.variadic/p5.cpp  | 35 +--
 4 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 4614324babb1c91..0c8f07b095b1eaa 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5655,9 +5655,9 @@ def err_unexpanded_parameter_pack : Error<
   "%select{expression|base type|declaration type|data member type|bit-field "
   "size|static assertion|fixed underlying type|enumerator value|"
   "using declaration|friend declaration|qualifier|initializer|default 
argument|"
-  "non-type template parameter type|exception type|partial specialization|"
-  "__if_exists name|__if_not_exists name|lambda|block|type constraint|"
-  "requirement|requires clause}0 "
+  "non-type template parameter type|exception type|explicit specialization|"
+  "partial specialization|__if_exists name|__if_not_exists name|lambda|block|"
+  "type constraint|requirement|requires clause}0 "
   "contains%plural{0: an|:}1 unexpanded parameter pack"
   "%plural{0:|1: %2|2:s %2 and %3|:s %2, %3, ...}1">;
 
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index f69f366c1750918..e59827b8c281ea1 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -8839,6 +8839,9 @@ class Sema final {
 /// The type of an exception.
 UPPC_ExceptionType,
 
+/// Explicit specialization.
+UPPC_ExplicitSpecialization,
+
 /// Partial specialization.
 UPPC_PartialSpecialization,
 
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 6865e04b94b2050..766ebd90fded0c4 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4559,7 +4559,9 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
   // Check for unexpanded parameter packs in any of the template arguments.
   for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
 if (DiagnoseUnexpandedParameterPack(TemplateArgs[I],
-UPPC_PartialSpecialization))
+IsPartialSpecialization
+? UPPC_PartialSpecialization
+: UPPC_ExplicitSpecialization))
   return true;
 
   // Check that the template argument list is well-formed for this
@@ -8744,7 +8746,9 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
   // Check for unexpanded parameter packs in any of the template arguments.
   for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
 if (DiagnoseUnexpandedParameterPack(TemplateArgs[I],
-UPPC_PartialSpecialization))
+isPartialSpecialization
+? UPPC_PartialSpecialization
+: UPPC_ExplicitSpecialization))
   return true;
 
   // Check that the template argument list is well-formed for this
diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp 
b/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
index 7536339c14a2e08..d00630b0258a734 100644
--- a/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
+++ b/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
@@ -369,9 +369,38 @@ void test_unexpanded_exprs(Types ...values) {
   void f(int arg = values); // expected-error{{default argument contains 
unexpanded parameter pack 'values'}}
 }
 
-// Test unexpanded parameter packs in partial specializations.
-template
-struct TestUnexpandedDecls; // expected-error{{partial 
specialization contains unexpanded parameter pack 'Types'}}
+// Test unexpanded parameter packs in partial/explicit specializations.
+namespace Specializations {
+  template
+  struct PrimaryClass;
+
+  template
+  constexpr int PrimaryVar = 0;
+
+  template
+  struct PrimaryClass; // expected-error{{partial specialization contains 
unexpanded parameter pack 'Ts'}}
+
+  template
+  constexpr int PrimaryVar = 0; // expected-error{{partial specialization 
contains unexpanded parameter pack 'Ts'}}
+
+  template
+  struct OuterClass {
+template
+struct InnerClass;
+template
+constexpr static int InnerVar = 0;
+
+template<>
+struct InnerClass; // expected-error{{explicit specialization contains 
unexpanded parameter pack 

[clang] [Clang][Sema] Differentiate between partial/explicit specializations when diagnosing unexpanded packs (PR #72015)

2023-11-13 Thread Krystian Stasiowski via cfe-commits

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

>From 3667d7646db255890d7e29209581e5b12909bd90 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Fri, 10 Nov 2023 20:51:12 -0500
Subject: [PATCH] [Clang] Differentiate between partial/explicit
 specializations when diagnosing unexpanded packs

---
 .../clang/Basic/DiagnosticSemaKinds.td|  6 ++--
 clang/include/clang/Sema/Sema.h   |  3 ++
 clang/lib/Sema/SemaTemplate.cpp   |  8 +++--
 .../CXX/temp/temp.decls/temp.variadic/p5.cpp  | 36 +--
 4 files changed, 45 insertions(+), 8 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 4614324babb1c91..0c8f07b095b1eaa 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5655,9 +5655,9 @@ def err_unexpanded_parameter_pack : Error<
   "%select{expression|base type|declaration type|data member type|bit-field "
   "size|static assertion|fixed underlying type|enumerator value|"
   "using declaration|friend declaration|qualifier|initializer|default 
argument|"
-  "non-type template parameter type|exception type|partial specialization|"
-  "__if_exists name|__if_not_exists name|lambda|block|type constraint|"
-  "requirement|requires clause}0 "
+  "non-type template parameter type|exception type|explicit specialization|"
+  "partial specialization|__if_exists name|__if_not_exists name|lambda|block|"
+  "type constraint|requirement|requires clause}0 "
   "contains%plural{0: an|:}1 unexpanded parameter pack"
   "%plural{0:|1: %2|2:s %2 and %3|:s %2, %3, ...}1">;
 
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index f69f366c1750918..e59827b8c281ea1 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -8839,6 +8839,9 @@ class Sema final {
 /// The type of an exception.
 UPPC_ExceptionType,
 
+/// Explicit specialization.
+UPPC_ExplicitSpecialization,
+
 /// Partial specialization.
 UPPC_PartialSpecialization,
 
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 6865e04b94b2050..766ebd90fded0c4 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4559,7 +4559,9 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
   // Check for unexpanded parameter packs in any of the template arguments.
   for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
 if (DiagnoseUnexpandedParameterPack(TemplateArgs[I],
-UPPC_PartialSpecialization))
+IsPartialSpecialization
+? UPPC_PartialSpecialization
+: UPPC_ExplicitSpecialization))
   return true;
 
   // Check that the template argument list is well-formed for this
@@ -8744,7 +8746,9 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
   // Check for unexpanded parameter packs in any of the template arguments.
   for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
 if (DiagnoseUnexpandedParameterPack(TemplateArgs[I],
-UPPC_PartialSpecialization))
+isPartialSpecialization
+? UPPC_PartialSpecialization
+: UPPC_ExplicitSpecialization))
   return true;
 
   // Check that the template argument list is well-formed for this
diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp 
b/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
index 7536339c14a2e08..30ce6b40e1fb5f0 100644
--- a/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
+++ b/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
@@ -369,9 +369,39 @@ void test_unexpanded_exprs(Types ...values) {
   void f(int arg = values); // expected-error{{default argument contains 
unexpanded parameter pack 'values'}}
 }
 
-// Test unexpanded parameter packs in partial specializations.
-template
-struct TestUnexpandedDecls; // expected-error{{partial 
specialization contains unexpanded parameter pack 'Types'}}
+// Test unexpanded parameter packs in partial/explicit specializations.
+namespace Specializations {
+  template
+  struct PrimaryClass;
+  template
+  struct PrimaryClass; // expected-error{{partial specialization contains 
unexpanded parameter pack 'Ts'}}
+
+#if __cplusplus >= 201402L
+  template
+  constexpr int PrimaryVar = 0;
+  template
+  constexpr int PrimaryVar = 0; // expected-error{{partial specialization 
contains unexpanded parameter pack 'Ts'}}
+#endif
+
+  template
+  struct OuterClass {
+template
+struct InnerClass;
+template<>
+struct InnerClass; // expected-error{{explicit specialization contains 
unexpanded parameter pack 'Ts'}}
+template
+stru

[clang] [Clang][Sema] Differentiate between partial/explicit specializations when diagnosing unexpanded packs (PR #72015)

2023-11-13 Thread Krystian Stasiowski via cfe-commits

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


[clang] [Clang][Sema] Differentiate between partial/explicit specializations when diagnosing unexpanded packs (PR #72015)

2023-11-13 Thread Krystian Stasiowski via cfe-commits

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


[clang] [Clang][Sema] Differentiate between partial/explicit specializations when diagnosing unexpanded packs (PR #72015)

2023-11-13 Thread Krystian Stasiowski via cfe-commits

sdkrystian wrote:

Ping @erichkeane 

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


[clang] [Clang][Sema] Differentiate between partial/explicit specializations when diagnosing unexpanded packs (PR #72015)

2023-11-13 Thread Krystian Stasiowski via cfe-commits


@@ -369,9 +369,39 @@ void test_unexpanded_exprs(Types ...values) {
   void f(int arg = values); // expected-error{{default argument contains 
unexpanded parameter pack 'values'}}
 }
 
-// Test unexpanded parameter packs in partial specializations.
-template
-struct TestUnexpandedDecls; // expected-error{{partial 
specialization contains unexpanded parameter pack 'Types'}}
+// Test unexpanded parameter packs in partial/explicit specializations.
+namespace Specializations {

sdkrystian wrote:

@erichkeane The existing behavior is to call explicit specializations "partial 
specializations" in the diagnostic for unexpanded parameter packs. This patch 
fixes that, so a distinction is made between partial/explicit specializations. 
For example, the test on line 391 displays different behavior:
```cpp
struct InnerClass; // expected-error{{explicit specialization contains 
unexpanded parameter pack 'Ts'}}
```
Note "explicit specialization" in the diagnostic. 

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


[clang] [Clang][Sema] Differentiate between partial/explicit specializations when diagnosing unexpanded packs (PR #72015)

2023-11-13 Thread Krystian Stasiowski via cfe-commits

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


[clang] [Clang][Sema] Diagnose friend function specialization definitions (PR #72863)

2023-12-11 Thread Krystian Stasiowski via cfe-commits

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

>From 7b26c6ea5f3c75f1146df21f51c1f40967aaae98 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Mon, 20 Nov 2023 07:11:41 -0500
Subject: [PATCH] [Clang][Sema] Diagnose friend function specialization
 definitions

---
 clang/docs/ReleaseNotes.rst   |  1 +
 .../clang/Basic/DiagnosticSemaKinds.td|  2 +
 clang/lib/AST/Decl.cpp|  1 +
 clang/lib/Sema/SemaDeclCXX.cpp| 71 +--
 .../test/CXX/class.access/class.friend/p6.cpp | 13 
 .../CXX/temp/temp.decls/temp.friend/p1.cpp|  6 +-
 clang/test/SemaCXX/friend.cpp |  2 +-
 7 files changed, 55 insertions(+), 41 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b4b5352a306c1c..bc3acf165f0759 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -513,6 +513,7 @@ Improvements to Clang's diagnostics
48 | static_assert(1 << 4 == 15);
   |   ~~~^
 
+- Clang now diagnoses definitions of friend function specializations, e.g. 
``friend void f<>(int) {}``.
 
 Improvements to Clang's time-trace
 --
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 28d95ca9b13893..0b53c6dce810f8 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1669,6 +1669,8 @@ def err_qualified_friend_def : Error<
   "friend function definition cannot be qualified with '%0'">;
 def err_friend_def_in_local_class : Error<
   "friend function cannot be defined in a local class">;
+def err_friend_specialization_def : Error<
+  "friend function specialization cannot be defined">;
 def err_friend_not_first_in_declaration : Error<
   "'friend' must appear first in a non-function declaration">;
 def err_using_decl_friend : Error<
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index c5c2edf1bfe3ab..527ea6042daa03 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -4150,6 +4150,7 @@ 
FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C,
   assert(TSK != TSK_Undeclared &&
  "Must specify the type of function template specialization");
   assert((TemplateOrSpecialization.isNull() ||
+  getFriendObjectKind() != FOK_None ||
   TSK == TSK_ExplicitSpecialization) &&
  "Member specialization must be an explicit specialization");
   FunctionTemplateSpecializationInfo *Info =
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index c6218a491aecec..36e53c684ac4dc 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -17879,6 +17879,8 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, 
Declarator &D,
   LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
 ForExternalRedeclaration);
 
+  bool isTemplateId = D.getName().getKind() == 
UnqualifiedIdKind::IK_TemplateId;
+
   // There are five cases here.
   //   - There's no scope specifier and we're in a local class. Only look
   // for functions declared in the immediately-enclosing block scope.
@@ -17916,14 +17918,6 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, 
Declarator &D,
 }
 adjustContextForLocalExternDecl(DC);
 
-// C++ [class.friend]p6:
-//   A function can be defined in a friend declaration of a class if and
-//   only if the class is a non-local class (9.8), the function name is
-//   unqualified, and the function has namespace scope.
-if (D.isFunctionDefinition()) {
-  Diag(NameInfo.getBeginLoc(), diag::err_friend_def_in_local_class);
-}
-
   //   - There's no scope specifier, in which case we just go to the
   // appropriate scope and look for a function or function template
   // there as appropriate.
@@ -17934,8 +17928,6 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, 
Declarator &D,
 //   elaborated-type-specifier, the lookup to determine whether
 //   the entity has been previously declared shall not consider
 //   any scopes outside the innermost enclosing namespace.
-bool isTemplateId =
-D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId;
 
 // Find the appropriate context according to the above.
 DC = CurContext;
@@ -17988,39 +17980,12 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, 
Declarator &D,
  diag::warn_cxx98_compat_friend_is_member :
  diag::err_friend_is_member);
 
-if (D.isFunctionDefinition()) {
-  // C++ [class.friend]p6:
-  //   A function can be defined in a friend declaration of a class if and
-  //   only if the class is a non-local class (9.8), the function name is
-  //   unqualified, and the function has namespace scope.
-  //
-  // FIXME: We should only do this if t

[clang] [Clang][Sema] Diagnose friend function specialization definitions (PR #72863)

2023-12-11 Thread Krystian Stasiowski via cfe-commits

sdkrystian wrote:

@erichkeane Rebased and squashed. Will need you (or someone else with write 
access) to merge.

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


[clang] [Clang][Sema] Differentiate between partial/explicit specializations when diagnosing unexpanded packs (PR #72015)

2023-11-16 Thread Krystian Stasiowski via cfe-commits

sdkrystian wrote:

@erichkeane Unless you would like someone else to review this, could you please 
merge this when you have time? I don't have write access 🙂

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


[clang] [Clang][Sema] Diagnose friend function specialization definitions (PR #72863)

2023-11-20 Thread Krystian Stasiowski via cfe-commits

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

Per [[class.friend]p6](http://eel.is/c++draft/class.friend#6) a friend function 
shall not be defined if its name isn't unqualified. A _template-id_ is not a 
name, meaning that a friend function specialization does not meet this criteria 
and cannot be defined. 

GCC, MSVC, and EDG all consider friend function specialization definitions to 
be invalid de facto explicit specializations and diagnose them as such. 

Instantiating a dependent friend function specialization definition [currently 
trips an assert](https://godbolt.org/z/sonhbKWKT) in 
`FunctionDecl::setFunctionTemplateSpecialization`. This happens because we do 
not set the `TemplateSpecializationKind` of the `FunctionDecl` created by 
template argument deduction to `TSK_ExplicitSpecialization` for friend 
functions 
[here](https://github.com/llvm/llvm-project/blob/main/clang/lib/Sema/SemaTemplate.cpp#L9600).
 I changed the assert condition because I believe this is the correct behavior. 


>From 3e191f245325742338eba223a3f98b6bb5ad414b Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Mon, 20 Nov 2023 07:11:41 -0500
Subject: [PATCH] [Clang][Sema] Diagnose friend function specialization
 definitions

---
 clang/include/clang/Basic/DiagnosticSemaKinds.td   |  2 ++
 clang/lib/AST/Decl.cpp |  1 +
 clang/lib/Sema/SemaDeclCXX.cpp | 14 ++
 clang/test/CXX/class.access/class.friend/p6.cpp| 13 +
 clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp  |  8 +---
 .../CXX/temp/temp.spec/temp.expl.spec/p20-2.cpp|  3 ++-
 6 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 3f6ca64baf23ae6..35acbb40a4b4f38 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1669,6 +1669,8 @@ def err_qualified_friend_def : Error<
   "friend function definition cannot be qualified with '%0'">;
 def err_friend_def_in_local_class : Error<
   "friend function cannot be defined in a local class">;
+def err_friend_specialization_def : Error<
+  "friend function specialization cannot be defined">;
 def err_friend_not_first_in_declaration : Error<
   "'friend' must appear first in a non-function declaration">;
 def err_using_decl_friend : Error<
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index c5c2edf1bfe3aba..527ea6042daa034 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -4150,6 +4150,7 @@ 
FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C,
   assert(TSK != TSK_Undeclared &&
  "Must specify the type of function template specialization");
   assert((TemplateOrSpecialization.isNull() ||
+  getFriendObjectKind() != FOK_None ||
   TSK == TSK_ExplicitSpecialization) &&
  "Member specialization must be an explicit specialization");
   FunctionTemplateSpecializationInfo *Info =
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 3688192e6cbe5c5..2bfb02da08bde54 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -17960,6 +17960,20 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, 
Declarator &D,
 
 DCScope = getScopeForDeclContext(S, DC);
 
+// C++ [class.friend]p6:
+//   A function may be defined in a friend declaration of a class if and
+//   only if the class is a non-local class, and the function name is
+//   unqualified.
+//
+// Per [basic.pre]p4, a template-id is not a name. Therefore, if we have
+// a template-id, the function name is not unqualified because these is no
+// name. While the wording requires some reading in-between the lines, GCC,
+// MSVC, and EDG all consider a friend function specialization definitions
+// to be de facto explicit specialization and diagnose them as such.
+if (D.isFunctionDefinition() && isTemplateId) {
+  Diag(NameInfo.getBeginLoc(), diag::err_friend_specialization_def);
+}
+
   //   - There's a non-dependent scope specifier, in which case we
   // compute it and do a previous lookup there for a function
   // or function template.
diff --git a/clang/test/CXX/class.access/class.friend/p6.cpp 
b/clang/test/CXX/class.access/class.friend/p6.cpp
index 2fe20fe77fc8f21..47104e29dc6b3c7 100644
--- a/clang/test/CXX/class.access/class.friend/p6.cpp
+++ b/clang/test/CXX/class.access/class.friend/p6.cpp
@@ -22,3 +22,16 @@ void local() {
 friend void f() { } // expected-error{{friend function cannot be defined 
in a local class}}
   };
 }
+
+template void f3(T);
+
+namespace N {
+  template void f4(T);
+}
+
+template struct A {
+  friend void f3(T) {}
+  friend void f3(T) {} // expected-error{{friend function specialization 
cannot be defined}}
+  friend void N::f4(T) {} // expected-error{

[clang] [Clang][Sema] Diagnose friend function specialization definitions (PR #72863)

2023-11-20 Thread Krystian Stasiowski via cfe-commits

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


[clang] [Clang][Sema] Diagnose friend function specialization definitions (PR #72863)

2023-11-20 Thread Krystian Stasiowski via cfe-commits

sdkrystian wrote:

Ping @AaronBallman @erichkeane 

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


[clang] [Clang][Sema] Diagnose friend function specialization definitions (PR #72863)

2023-11-27 Thread Krystian Stasiowski via cfe-commits


@@ -4,7 +4,8 @@ void f(T);
 
 template
 struct A {
-  // expected-error@+1{{cannot declare an explicit specialization in a friend}}
+  // expected-error@+2{{cannot declare an explicit specialization in a friend}}
+  // expected-error@+1{{friend function specialization cannot be defined}}

sdkrystian wrote:

@erichkeane I suppose we don't want double-erroring for any of these 
https://godbolt.org/z/Wdo7bqe1v... if that is the case, perhaps we should 
postpone diagnosing friend function definitions until after we call 
`ActOnFunctionDecl`?

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


[clang] [Clang][Sema] Diagnose friend function specialization definitions (PR #72863)

2023-11-27 Thread Krystian Stasiowski via cfe-commits


@@ -373,6 +373,7 @@ template  void foo() {} // 
expected-note{{candidate ignored: not a memb
 }
 using ns::foo;
 template  struct A {
+  // expected-error@+1{{friend function specialization cannot be defined}}

sdkrystian wrote:

Per my other comment, I think the right thing to do here is to diagnose friend 
function definitions after calling `ActOnFunctionDecl`... in this case we would 
emit the "no candidate function template was found for dependent friend 
function template specialization" diagnostic, but not "friend function 
specialization cannot be defined".

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


[clang] [Clang][Sema] Diagnose friend function specialization definitions (PR #72863)

2023-11-27 Thread Krystian Stasiowski via cfe-commits

sdkrystian wrote:

@erichkeane the most recent commit results in the following:
```cpp
template void f(T);
void g() { }

template
struct A {
  // error: cannot declare an explicit specialization in a friend
  template<> friend void f<>(T) { }
  // error: friend function specialization cannot be defined
  friend void f<>(T) { }
  // error: cannot declare an explicit specialization in a friend
  template<> friend void ::g() { }
  // error: friend function definition cannot be qualified with '::'
  friend void ::g() { }
};

void h() {
  void i();
  struct B {
// error: templates can only be declared in namespace or class scope
// error: cannot declare an explicit specialization in a friend
template<> friend void i() { }
// error: friend function cannot be defined in a local class
friend void i() { }
  };
}
```
Unrelated, but it also seems that `template<> friend void f<>(T) { }` causes 
[this 
assert](https://github.com/llvm/llvm-project/blob/main/clang/lib/Sema/SemaDecl.cpp#L10477)
 to fire. This happens because we clear `HasExplicitTemplateArgs` for invalid 
declarations 
[here](https://github.com/llvm/llvm-project/blob/main/clang/lib/Sema/SemaDecl.cpp#L10427).
 I could include a fix, but it might fall outside the scope of this PR.

I also added a release note as requested.

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


[clang] [Clang][Sema] Diagnose friend function specialization definitions (PR #72863)

2023-11-27 Thread Krystian Stasiowski via cfe-commits

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

>From 3e191f245325742338eba223a3f98b6bb5ad414b Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Mon, 20 Nov 2023 07:11:41 -0500
Subject: [PATCH 1/2] [Clang][Sema] Diagnose friend function specialization
 definitions

---
 clang/include/clang/Basic/DiagnosticSemaKinds.td   |  2 ++
 clang/lib/AST/Decl.cpp |  1 +
 clang/lib/Sema/SemaDeclCXX.cpp | 14 ++
 clang/test/CXX/class.access/class.friend/p6.cpp| 13 +
 clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp  |  8 +---
 .../CXX/temp/temp.spec/temp.expl.spec/p20-2.cpp|  3 ++-
 6 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 3f6ca64baf23ae6..35acbb40a4b4f38 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1669,6 +1669,8 @@ def err_qualified_friend_def : Error<
   "friend function definition cannot be qualified with '%0'">;
 def err_friend_def_in_local_class : Error<
   "friend function cannot be defined in a local class">;
+def err_friend_specialization_def : Error<
+  "friend function specialization cannot be defined">;
 def err_friend_not_first_in_declaration : Error<
   "'friend' must appear first in a non-function declaration">;
 def err_using_decl_friend : Error<
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index c5c2edf1bfe3aba..527ea6042daa034 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -4150,6 +4150,7 @@ 
FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C,
   assert(TSK != TSK_Undeclared &&
  "Must specify the type of function template specialization");
   assert((TemplateOrSpecialization.isNull() ||
+  getFriendObjectKind() != FOK_None ||
   TSK == TSK_ExplicitSpecialization) &&
  "Member specialization must be an explicit specialization");
   FunctionTemplateSpecializationInfo *Info =
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 3688192e6cbe5c5..2bfb02da08bde54 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -17960,6 +17960,20 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, 
Declarator &D,
 
 DCScope = getScopeForDeclContext(S, DC);
 
+// C++ [class.friend]p6:
+//   A function may be defined in a friend declaration of a class if and
+//   only if the class is a non-local class, and the function name is
+//   unqualified.
+//
+// Per [basic.pre]p4, a template-id is not a name. Therefore, if we have
+// a template-id, the function name is not unqualified because these is no
+// name. While the wording requires some reading in-between the lines, GCC,
+// MSVC, and EDG all consider a friend function specialization definitions
+// to be de facto explicit specialization and diagnose them as such.
+if (D.isFunctionDefinition() && isTemplateId) {
+  Diag(NameInfo.getBeginLoc(), diag::err_friend_specialization_def);
+}
+
   //   - There's a non-dependent scope specifier, in which case we
   // compute it and do a previous lookup there for a function
   // or function template.
diff --git a/clang/test/CXX/class.access/class.friend/p6.cpp 
b/clang/test/CXX/class.access/class.friend/p6.cpp
index 2fe20fe77fc8f21..47104e29dc6b3c7 100644
--- a/clang/test/CXX/class.access/class.friend/p6.cpp
+++ b/clang/test/CXX/class.access/class.friend/p6.cpp
@@ -22,3 +22,16 @@ void local() {
 friend void f() { } // expected-error{{friend function cannot be defined 
in a local class}}
   };
 }
+
+template void f3(T);
+
+namespace N {
+  template void f4(T);
+}
+
+template struct A {
+  friend void f3(T) {}
+  friend void f3(T) {} // expected-error{{friend function specialization 
cannot be defined}}
+  friend void N::f4(T) {} // expected-error{{friend function definition cannot 
be qualified with 'N::'}}
+  friend void N::f4(T) {} // expected-error{{friend function definition 
cannot be qualified with 'N::'}}
+};
diff --git a/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp 
b/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp
index ab1b9f7a73eec89..974b080f2783934 100644
--- a/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp
+++ b/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp
@@ -17,7 +17,7 @@ template  struct Num {
   for (U count = n.count_; count; --count)
 x += a;
   return x;
-} 
+}
   };
 
   friend Num operator+(const Num &a, const Num &b) {
@@ -145,7 +145,7 @@ namespace test5 {
 
 namespace Dependent {
   template class X;
-  template 
+  template
   X operator+(const X&, const T*);
 
   template class X {
@@ -249,7 +249,7 @@ namespace test11 {
   };
 
   template struct Foo::IteratorImpl;
-  template struct Foo::IteratorImpl;  
+  template struct Fo

[clang] [Clang][Sema] Diagnose friend function specialization definitions (PR #72863)

2023-11-27 Thread Krystian Stasiowski via cfe-commits

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

>From 3e191f245325742338eba223a3f98b6bb5ad414b Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Mon, 20 Nov 2023 07:11:41 -0500
Subject: [PATCH 1/2] [Clang][Sema] Diagnose friend function specialization
 definitions

---
 clang/include/clang/Basic/DiagnosticSemaKinds.td   |  2 ++
 clang/lib/AST/Decl.cpp |  1 +
 clang/lib/Sema/SemaDeclCXX.cpp | 14 ++
 clang/test/CXX/class.access/class.friend/p6.cpp| 13 +
 clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp  |  8 +---
 .../CXX/temp/temp.spec/temp.expl.spec/p20-2.cpp|  3 ++-
 6 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 3f6ca64baf23ae6..35acbb40a4b4f38 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1669,6 +1669,8 @@ def err_qualified_friend_def : Error<
   "friend function definition cannot be qualified with '%0'">;
 def err_friend_def_in_local_class : Error<
   "friend function cannot be defined in a local class">;
+def err_friend_specialization_def : Error<
+  "friend function specialization cannot be defined">;
 def err_friend_not_first_in_declaration : Error<
   "'friend' must appear first in a non-function declaration">;
 def err_using_decl_friend : Error<
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index c5c2edf1bfe3aba..527ea6042daa034 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -4150,6 +4150,7 @@ 
FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C,
   assert(TSK != TSK_Undeclared &&
  "Must specify the type of function template specialization");
   assert((TemplateOrSpecialization.isNull() ||
+  getFriendObjectKind() != FOK_None ||
   TSK == TSK_ExplicitSpecialization) &&
  "Member specialization must be an explicit specialization");
   FunctionTemplateSpecializationInfo *Info =
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 3688192e6cbe5c5..2bfb02da08bde54 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -17960,6 +17960,20 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, 
Declarator &D,
 
 DCScope = getScopeForDeclContext(S, DC);
 
+// C++ [class.friend]p6:
+//   A function may be defined in a friend declaration of a class if and
+//   only if the class is a non-local class, and the function name is
+//   unqualified.
+//
+// Per [basic.pre]p4, a template-id is not a name. Therefore, if we have
+// a template-id, the function name is not unqualified because these is no
+// name. While the wording requires some reading in-between the lines, GCC,
+// MSVC, and EDG all consider a friend function specialization definitions
+// to be de facto explicit specialization and diagnose them as such.
+if (D.isFunctionDefinition() && isTemplateId) {
+  Diag(NameInfo.getBeginLoc(), diag::err_friend_specialization_def);
+}
+
   //   - There's a non-dependent scope specifier, in which case we
   // compute it and do a previous lookup there for a function
   // or function template.
diff --git a/clang/test/CXX/class.access/class.friend/p6.cpp 
b/clang/test/CXX/class.access/class.friend/p6.cpp
index 2fe20fe77fc8f21..47104e29dc6b3c7 100644
--- a/clang/test/CXX/class.access/class.friend/p6.cpp
+++ b/clang/test/CXX/class.access/class.friend/p6.cpp
@@ -22,3 +22,16 @@ void local() {
 friend void f() { } // expected-error{{friend function cannot be defined 
in a local class}}
   };
 }
+
+template void f3(T);
+
+namespace N {
+  template void f4(T);
+}
+
+template struct A {
+  friend void f3(T) {}
+  friend void f3(T) {} // expected-error{{friend function specialization 
cannot be defined}}
+  friend void N::f4(T) {} // expected-error{{friend function definition cannot 
be qualified with 'N::'}}
+  friend void N::f4(T) {} // expected-error{{friend function definition 
cannot be qualified with 'N::'}}
+};
diff --git a/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp 
b/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp
index ab1b9f7a73eec89..974b080f2783934 100644
--- a/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp
+++ b/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp
@@ -17,7 +17,7 @@ template  struct Num {
   for (U count = n.count_; count; --count)
 x += a;
   return x;
-} 
+}
   };
 
   friend Num operator+(const Num &a, const Num &b) {
@@ -145,7 +145,7 @@ namespace test5 {
 
 namespace Dependent {
   template class X;
-  template 
+  template
   X operator+(const X&, const T*);
 
   template class X {
@@ -249,7 +249,7 @@ namespace test11 {
   };
 
   template struct Foo::IteratorImpl;
-  template struct Foo::IteratorImpl;  
+  template struct Fo

[clang] [Clang][Sema] Diagnose friend function specialization definitions (PR #72863)

2023-12-04 Thread Krystian Stasiowski via cfe-commits

sdkrystian wrote:

Ping @erichkeane 

https://github.com/llvm/llvm-project/pull/72863
___
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 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 &D, 
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 &D, 
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 &D, 
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 &D, 
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 &ArgLoc : TemplateArgs.arguments()) {
+if (DiagnoseUnexpandedParameterPack(
+ArgLoc, isFriend ? UPPC_FriendDeclaration
+   

[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 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-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 &D, 
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 &D, 
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 &D, 
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 &D, 
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 spec

[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 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-tools-extra] [clang-doc] Fix failing test (PR #76857)

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

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

This fixes a failing test case in clang-doc introduced by 
7fbc1de9896029636dd572a692ee90ba88285943. I presume the test is intended to be 
well-formed, so I have changed it accordingly. 

>From 7b7c9b78bc48a0df6c5fffce202a9ae7b84812d4 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Wed, 3 Jan 2024 14:55:55 -0500
Subject: [PATCH] [clang-doc] Fix failing test

---
 clang-tools-extra/test/clang-doc/templates.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang-tools-extra/test/clang-doc/templates.cpp 
b/clang-tools-extra/test/clang-doc/templates.cpp
index eb7f4599629f48..2e04a77ac9e621 100644
--- a/clang-tools-extra/test/clang-doc/templates.cpp
+++ b/clang-tools-extra/test/clang-doc/templates.cpp
@@ -7,7 +7,7 @@
 // RUN: rm -rf %t
 
 template
-void function(T x) {}
+void function(T x) {}
 
 template<>
 void function(bool x) {}

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


[clang-tools-extra] [clang-doc] Fix failing test (PR #76857)

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

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


[clang-tools-extra] [clang-doc] Fix failing test (PR #76857)

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

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


[clang] [clang-tools-extra] Reapply "[Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations" (#76876) (PR #76915)

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

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

This reapplies f034044ad94d6f7ccec13d89f08acac257ed28bb after it was reverted 
by 687396b5f4ba0713d103ebd172b308e92eb930cc due to a test failure in clang-doc.

The test in question declares a partial specialization of a function template, 
as well as an explicit specialization of the same function template. Both 
declarations are now set as invalid, meaning neither is emitted by clang-doc. 

Since this is the sole test of function template specializations in clang-doc, 
I presume the intent is for the partial specialization to actually be the 
primary template. 

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

---
 .../test/clang-doc/templates.cpp  |  2 +-
 clang/docs/ReleaseNotes.rst   |  1 +
 clang/lib/Sema/SemaDecl.cpp   | 89 +--
 .../CXX/temp/temp.decls/temp.variadic/p5.cpp  | 12 +++
 4 files changed, 57 insertions(+), 47 deletions(-)

diff --git a/clang-tools-extra/test/clang-doc/templates.cpp 
b/clang-tools-extra/test/clang-doc/templates.cpp
index eb7f4599629f48..2e04a77ac9e621 100644
--- a/clang-tools-extra/test/clang-doc/templates.cpp
+++ b/clang-tools-extra/test/clang-doc/templates.cpp
@@ -7,7 +7,7 @@
 // RUN: rm -rf %t
 
 template
-void function(T x) {}
+void function(T x) {}
 
 template<>
 void function(bool x) {}
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 &D, 
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 &D, 
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 &D, 
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 &D, 
DeclContext *DC,
   if (TemplateParamLists.size() > 0)
 // For source fidelity, store all the template param lists.
 NewFD->setTemplateParameterListsInfo(Context, TemplateParamLi

[clang] [clang-tools-extra] Reapply "[Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations" (#76876) (PR #76915)

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

sdkrystian wrote:

Ping @erichkeane 


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


[clang] [clang-tools-extra] Reapply "[Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations" (#76876) (PR #76915)

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

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


[clang-tools-extra] [clang] Reapply "[Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations" (#76876) (PR #76915)

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

sdkrystian wrote:

@cor3ntin @erichkeane if either of you could merge that that would be 
appreciated :)

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


[clang] [Clang][NFC] Fix out-of-bounds access (PR #77193)

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

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

The changes to tablegen made by https://github.com/llvm/llvm-project/pull/76825 
result in `StmtClass::lastStmtConstant` changing from 
`StmtClass::WhileStmtClass` to `StmtClass::GCCAsmStmtClass`. Since 
`CFG::BuildOptions::alwaysAdd` is never called with a `WhileStmt`, this has 
flown under the radar until now. 

>From a06f149e584376aefd7b4f88e0b6db23963b367c Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Sat, 6 Jan 2024 07:26:06 -0500
Subject: [PATCH] [Clang][NFC] Fix out-of-bounds access

---
 clang/include/clang/Analysis/CFG.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/include/clang/Analysis/CFG.h 
b/clang/include/clang/Analysis/CFG.h
index 67383bb316d318..ec10768f600a2a 100644
--- a/clang/include/clang/Analysis/CFG.h
+++ b/clang/include/clang/Analysis/CFG.h
@@ -1215,7 +1215,7 @@ class CFG {
   
//======//
 
   class BuildOptions {
-std::bitset alwaysAddMask;
+std::bitset alwaysAddMask;
 
   public:
 using ForcedBlkExprs = llvm::DenseMap;

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


[clang] [Clang][NFC] Fix out-of-bounds access (PR #77193)

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

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


[clang] [Clang][NFC] Fix out-of-bounds access (PR #77193)

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

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

>From b737ce548ad554bc351820cedd693b9f8737be45 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Sat, 6 Jan 2024 07:26:06 -0500
Subject: [PATCH] [Clang][NFC] Fix out-of-bounds access

---
 clang/include/clang/Analysis/CFG.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/Analysis/CFG.h 
b/clang/include/clang/Analysis/CFG.h
index 67383bb316d318..9f776ca6cc260d 100644
--- a/clang/include/clang/Analysis/CFG.h
+++ b/clang/include/clang/Analysis/CFG.h
@@ -1215,7 +1215,9 @@ class CFG {
   
//======//
 
   class BuildOptions {
-std::bitset alwaysAddMask;
+// Stmt::lastStmtConstant has the same value as the last Stmt kind,
+// so make sure we add one to account for this!
+std::bitset alwaysAddMask;
 
   public:
 using ForcedBlkExprs = llvm::DenseMap;

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


[clang] [Clang][NFC] Fix out-of-bounds access (PR #77193)

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


@@ -1215,7 +1215,7 @@ class CFG {
   
//======//
 
   class BuildOptions {
-std::bitset alwaysAddMask;

sdkrystian wrote:

@ymand Fair enough, I added one.

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


[clang] [Clang][NFC] Fix out-of-bounds access (PR #77193)

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

sdkrystian wrote:

@qedawkins Ah, I should have clarified... I will need someone with write access 
to merge this :)

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


[clang] [clang][Sema] Track trivial-relocatability as a type trait (PR #84621)

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


@@ -826,6 +842,14 @@ void CXXRecordDecl::addedMember(Decl *D) {
   ? !Constructor->isImplicit()
   : (Constructor->isUserProvided() || Constructor->isExplicit()))
 data().Aggregate = false;
+
+  // A trivially relocatable class is a class:
+  // -- where no eligible copy constructor, move constructor, copy
+  // assignment operator, move assignment operator, or destructor is
+  // user-provided,
+  if (Constructor->isUserProvided() && (Constructor->isCopyConstructor() ||

sdkrystian wrote:

This does not appear to do what the comment says -- 
`IsNaturallyTriviallyRelocatable` is cleared even when the constructor is 
ineligible. Maybe this should be moved to `addedEligibleSpecialMemberFunction`?

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


[clang] [clang][Sema] Track trivial-relocatability as a type trait (PR #84621)

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

https://github.com/sdkrystian commented:

Minor nit, but otherwise looks good.

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


[clang] [Clang][Sema] Diagnose class member access expressions naming non-existent members of the current instantiation prior to instantiation in the absence of dependent base classes (PR #84050)

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

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

>From 67d9b107a1e5dde52769f6e7d9dc41b1d777cb60 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Fri, 1 Mar 2024 08:08:52 -0500
Subject: [PATCH 01/14] [Clang][Sema] Earlier resolution of class member access
 expressions naming member of the current instantiation

---
 clang/lib/AST/Expr.cpp  |   2 +-
 clang/lib/Sema/SemaExpr.cpp |   4 +-
 clang/lib/Sema/SemaExprMember.cpp   | 121 ++--
 clang/lib/Sema/SemaOverload.cpp |   3 +
 clang/test/SemaTemplate/dependent-names.cpp |   4 +-
 5 files changed, 93 insertions(+), 41 deletions(-)

diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 131dace77f9c25..e60360435c32a5 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -103,7 +103,7 @@ const Expr *Expr::skipRValueSubobjectAdjustments(
   }
 } else if (const auto *ME = dyn_cast(E)) {
   if (!ME->isArrow()) {
-assert(ME->getBase()->getType()->isRecordType());
+assert(ME->getBase()->getType()->getAsRecordDecl());
 if (const auto *Field = dyn_cast(ME->getMemberDecl())) {
   if (!Field->isBitField() && !Field->getType()->isReferenceType()) {
 E = ME->getBase();
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 8725b09f8546cf..31d902b3572413 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -666,7 +666,9 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
   // expressions of certain types in C++.
   if (getLangOpts().CPlusPlus &&
   (E->getType() == Context.OverloadTy ||
-   T->isDependentType() ||
+  // FIXME: This is a hack! We want the lvalue-to-rvalue conversion applied
+  // to pointer types even if the pointee type is dependent.
+  (T->isDependentType() && !T->isPointerType()) ||
T->isRecordType()))
 return E;
 
diff --git a/clang/lib/Sema/SemaExprMember.cpp 
b/clang/lib/Sema/SemaExprMember.cpp
index 32998ae60eafe2..fd55e6f46a1066 100644
--- a/clang/lib/Sema/SemaExprMember.cpp
+++ b/clang/lib/Sema/SemaExprMember.cpp
@@ -624,8 +624,8 @@ namespace {
 // classes, one of its base classes.
 class RecordMemberExprValidatorCCC final : public CorrectionCandidateCallback {
 public:
-  explicit RecordMemberExprValidatorCCC(const RecordType *RTy)
-  : Record(RTy->getDecl()) {
+  explicit RecordMemberExprValidatorCCC(QualType RTy)
+  : Record(RTy->getAsRecordDecl()) {
 // Don't add bare keywords to the consumer since they will always fail
 // validation by virtue of not being associated with any decls.
 WantTypeSpecifiers = false;
@@ -671,33 +671,55 @@ class RecordMemberExprValidatorCCC final : public 
CorrectionCandidateCallback {
 
 static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
  Expr *BaseExpr,
- const RecordType *RTy,
+ QualType RTy,
  SourceLocation OpLoc, bool IsArrow,
  CXXScopeSpec &SS, bool HasTemplateArgs,
  SourceLocation TemplateKWLoc,
  TypoExpr *&TE) {
+  RecordDecl *RDecl = RTy->getAsRecordDecl();
+  DeclContext *DC = SemaRef.computeDeclContext(RTy);
+  // If the object expression is dependent and isn't the current instantiation,
+  // lookup will not find anything and we must defer until instantiation.
+  if (!DC) {
+R.setNotFoundInCurrentInstantiation();
+return false;
+  }
+
+  // FIXME: Should this use Name.isDependentName()?
+  if (DeclarationName Name = R.getLookupName();
+  Name.getNameKind() == DeclarationName::CXXConversionFunctionName &&
+  Name.getCXXNameType()->isDependentType()) {
+R.setNotFoundInCurrentInstantiation();
+return false;
+  }
+
   SourceRange BaseRange = BaseExpr ? BaseExpr->getSourceRange() : 
SourceRange();
-  RecordDecl *RDecl = RTy->getDecl();
-  if (!SemaRef.isThisOutsideMemberFunctionBody(QualType(RTy, 0)) &&
-  SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0),
+  if (!RTy->isDependentType() &&
+  !SemaRef.isThisOutsideMemberFunctionBody(RTy) &&
+  SemaRef.RequireCompleteType(OpLoc, RTy,
   diag::err_typecheck_incomplete_tag,
   BaseRange))
 return true;
 
   if (HasTemplateArgs || TemplateKWLoc.isValid()) {
 // LookupTemplateName doesn't expect these both to exist simultaneously.
-QualType ObjectType = SS.isSet() ? QualType() : QualType(RTy, 0);
+QualType ObjectType = SS.isSet() ? QualType() : RTy;
 
 bool MOUS;
 return SemaRef.LookupTemplateName(R, nullptr, SS, ObjectType, false, MOUS,
   TemplateKWLoc);
   }
 
-  DeclContext *DC = RDecl;
   if (SS.isSet()) {
 // If the member name 

[clang] [Clang][Sema] Diagnose class member access expressions naming non-existent members of the current instantiation prior to instantiation in the absence of dependent base classes (PR #84050)

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

sdkrystian wrote:

@erichkeane This PR is in a more "ready" state now, if you'd like to take 
another look. The added overload of `LookupTemplateName` which has no 
`MemberOfUnknownSpecialization` parameter it more of an experimental change... 
it can be ignored. 

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


[clang] [Clang][AST][NFC] MemberExpr stores NestedNameSpecifierLoc and DeclAccessPair separately (PR #86678)

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

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

Currently, `MemberExpr` allocates a trailing `MemberExprNameQualifier` object 
if it either has a `NestedNameSpecifierLoc`, or if it names a member found via 
using declaration. Since the presence of a _nested-name-specifier_ does not 
necessarily imply the named member was found via using declaration, this patch 
removes `MemberExprNameQualifier` and allocates the members separately. 

>From d3c3d22a07189433e54483c2b472e99691c926f2 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 26 Mar 2024 10:04:44 -0400
Subject: [PATCH] [Clang][AST][NFC] MemberExpr stores NestedNameSpecifierLoc
 and DeclAccessPair separately

---
 clang/include/clang/AST/Expr.h| 37 
 clang/include/clang/AST/Stmt.h| 11 +++---
 clang/lib/AST/Expr.cpp| 42 +++
 clang/lib/Serialization/ASTReaderStmt.cpp | 26 +-
 clang/lib/Serialization/ASTWriterStmt.cpp | 11 +++---
 5 files changed, 55 insertions(+), 72 deletions(-)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 6e153ebe024b42..e43098e144c88f 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3163,23 +3163,12 @@ class CallExpr : public Expr {
   }
 };
 
-/// Extra data stored in some MemberExpr objects.
-struct MemberExprNameQualifier {
-  /// The nested-name-specifier that qualifies the name, including
-  /// source-location information.
-  NestedNameSpecifierLoc QualifierLoc;
-
-  /// The DeclAccessPair through which the MemberDecl was found due to
-  /// name qualifiers.
-  DeclAccessPair FoundDecl;
-};
-
 /// MemberExpr - [C99 6.5.2.3] Structure and Union Members.  X->F and X.F.
 ///
 class MemberExpr final
 : public Expr,
-  private llvm::TrailingObjects {
   friend class ASTReader;
   friend class ASTStmtReader;
@@ -3201,17 +3190,19 @@ class MemberExpr final
   /// MemberLoc - This is the location of the member name.
   SourceLocation MemberLoc;
 
-  size_t numTrailingObjects(OverloadToken) const {
-return hasQualifierOrFoundDecl();
+  size_t numTrailingObjects(OverloadToken) const {
+return hasQualifier();
+  }
+
+  size_t numTrailingObjects(OverloadToken) const {
+return hasFoundDecl();
   }
 
   size_t numTrailingObjects(OverloadToken) const {
 return hasTemplateKWAndArgsInfo();
   }
 
-  bool hasQualifierOrFoundDecl() const {
-return MemberExprBits.HasQualifierOrFoundDecl;
-  }
+  bool hasFoundDecl() const { return MemberExprBits.HasFoundDecl; }
 
   bool hasTemplateKWAndArgsInfo() const {
 return MemberExprBits.HasTemplateKWAndArgsInfo;
@@ -3264,24 +3255,24 @@ class MemberExpr final
 
   /// Retrieves the declaration found by lookup.
   DeclAccessPair getFoundDecl() const {
-if (!hasQualifierOrFoundDecl())
+if (!hasFoundDecl())
   return DeclAccessPair::make(getMemberDecl(),
   getMemberDecl()->getAccess());
-return getTrailingObjects()->FoundDecl;
+return *getTrailingObjects();
   }
 
   /// Determines whether this member expression actually had
   /// a C++ nested-name-specifier prior to the name of the member, e.g.,
   /// x->Base::foo.
-  bool hasQualifier() const { return getQualifier() != nullptr; }
+  bool hasQualifier() const { return MemberExprBits.HasQualifier; }
 
   /// If the member name was qualified, retrieves the
   /// nested-name-specifier that precedes the member name, with source-location
   /// information.
   NestedNameSpecifierLoc getQualifierLoc() const {
-if (!hasQualifierOrFoundDecl())
+if (!hasQualifier())
   return NestedNameSpecifierLoc();
-return getTrailingObjects()->QualifierLoc;
+return *getTrailingObjects();
   }
 
   /// If the member name was qualified, retrieves the
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 55eca4007d17ea..425814912136f5 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -583,11 +583,14 @@ class alignas(void *) Stmt {
 unsigned IsArrow : 1;
 
 /// True if this member expression used a nested-name-specifier to
-/// refer to the member, e.g., "x->Base::f", or found its member via
-/// a using declaration.  When true, a MemberExprNameQualifier
-/// structure is allocated immediately after the MemberExpr.
+/// refer to the member, e.g., "x->Base::f".
 LLVM_PREFERRED_TYPE(bool)
-unsigned HasQualifierOrFoundDecl : 1;
+unsigned HasQualifier : 1;
+
+// True if this member expression found its member via
+/// a using declaration.
+LLVM_PREFERRED_TYPE(bool)
+unsigned HasFoundDecl : 1;
 
 /// True if this member expression specified a template keyword
 /// and/or a template argument list explicitly, e.g., x->f,
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 6221ebd5c9b4e9..6835c43197e39f 100644
--- a/clang/lib/AST/Expr.

[clang] [Clang][AST][NFC] Move template argument dependence computations for MemberExpr to computeDependence (PR #86682)

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

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

(This patch depends on #86678)

Pretty straightforward change, addresses the FIXME's in 
`computeDependence(MemberExpr*)` and `MemberExpr::Create` by moving the 
template argument dependence computations to `computeDependence`.

>From d3c3d22a07189433e54483c2b472e99691c926f2 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 26 Mar 2024 10:04:44 -0400
Subject: [PATCH 1/2] [Clang][AST][NFC] MemberExpr stores
 NestedNameSpecifierLoc and DeclAccessPair separately

---
 clang/include/clang/AST/Expr.h| 37 
 clang/include/clang/AST/Stmt.h| 11 +++---
 clang/lib/AST/Expr.cpp| 42 +++
 clang/lib/Serialization/ASTReaderStmt.cpp | 26 +-
 clang/lib/Serialization/ASTWriterStmt.cpp | 11 +++---
 5 files changed, 55 insertions(+), 72 deletions(-)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 6e153ebe024b42..e43098e144c88f 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3163,23 +3163,12 @@ class CallExpr : public Expr {
   }
 };
 
-/// Extra data stored in some MemberExpr objects.
-struct MemberExprNameQualifier {
-  /// The nested-name-specifier that qualifies the name, including
-  /// source-location information.
-  NestedNameSpecifierLoc QualifierLoc;
-
-  /// The DeclAccessPair through which the MemberDecl was found due to
-  /// name qualifiers.
-  DeclAccessPair FoundDecl;
-};
-
 /// MemberExpr - [C99 6.5.2.3] Structure and Union Members.  X->F and X.F.
 ///
 class MemberExpr final
 : public Expr,
-  private llvm::TrailingObjects {
   friend class ASTReader;
   friend class ASTStmtReader;
@@ -3201,17 +3190,19 @@ class MemberExpr final
   /// MemberLoc - This is the location of the member name.
   SourceLocation MemberLoc;
 
-  size_t numTrailingObjects(OverloadToken) const {
-return hasQualifierOrFoundDecl();
+  size_t numTrailingObjects(OverloadToken) const {
+return hasQualifier();
+  }
+
+  size_t numTrailingObjects(OverloadToken) const {
+return hasFoundDecl();
   }
 
   size_t numTrailingObjects(OverloadToken) const {
 return hasTemplateKWAndArgsInfo();
   }
 
-  bool hasQualifierOrFoundDecl() const {
-return MemberExprBits.HasQualifierOrFoundDecl;
-  }
+  bool hasFoundDecl() const { return MemberExprBits.HasFoundDecl; }
 
   bool hasTemplateKWAndArgsInfo() const {
 return MemberExprBits.HasTemplateKWAndArgsInfo;
@@ -3264,24 +3255,24 @@ class MemberExpr final
 
   /// Retrieves the declaration found by lookup.
   DeclAccessPair getFoundDecl() const {
-if (!hasQualifierOrFoundDecl())
+if (!hasFoundDecl())
   return DeclAccessPair::make(getMemberDecl(),
   getMemberDecl()->getAccess());
-return getTrailingObjects()->FoundDecl;
+return *getTrailingObjects();
   }
 
   /// Determines whether this member expression actually had
   /// a C++ nested-name-specifier prior to the name of the member, e.g.,
   /// x->Base::foo.
-  bool hasQualifier() const { return getQualifier() != nullptr; }
+  bool hasQualifier() const { return MemberExprBits.HasQualifier; }
 
   /// If the member name was qualified, retrieves the
   /// nested-name-specifier that precedes the member name, with source-location
   /// information.
   NestedNameSpecifierLoc getQualifierLoc() const {
-if (!hasQualifierOrFoundDecl())
+if (!hasQualifier())
   return NestedNameSpecifierLoc();
-return getTrailingObjects()->QualifierLoc;
+return *getTrailingObjects();
   }
 
   /// If the member name was qualified, retrieves the
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 55eca4007d17ea..425814912136f5 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -583,11 +583,14 @@ class alignas(void *) Stmt {
 unsigned IsArrow : 1;
 
 /// True if this member expression used a nested-name-specifier to
-/// refer to the member, e.g., "x->Base::f", or found its member via
-/// a using declaration.  When true, a MemberExprNameQualifier
-/// structure is allocated immediately after the MemberExpr.
+/// refer to the member, e.g., "x->Base::f".
 LLVM_PREFERRED_TYPE(bool)
-unsigned HasQualifierOrFoundDecl : 1;
+unsigned HasQualifier : 1;
+
+// True if this member expression found its member via
+/// a using declaration.
+LLVM_PREFERRED_TYPE(bool)
+unsigned HasFoundDecl : 1;
 
 /// True if this member expression specified a template keyword
 /// and/or a template argument list explicitly, e.g., x->f,
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 6221ebd5c9b4e9..6835c43197e39f 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1721,7 +1721,8 @@ MemberExpr::MemberExpr(Expr *Base, bool IsArrow, 
SourceLocation OperatorLoc,
   assert(!NameInfo.getN

[clang] [Clang][Comments] Add argument parsing for @throw @throws @exception (PR #84726)

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


@@ -75,6 +75,25 @@ class TextTokenRetokenizer {
 return *Pos.BufferPtr;
   }
 
+  char peekNext(unsigned offset) const {
+assert(!isEnd());
+assert(Pos.BufferPtr != Pos.BufferEnd);
+if (Pos.BufferPtr + offset <= Pos.BufferEnd) {

sdkrystian wrote:

Shouldn't this be `if (Pos.BufferPtr + offset < Pos.BufferEnd)` (unless this 
depends of the buffer being null terminated)? Otherwise this allows for an 
`offset` which results in `Pos.BufferEnd` being read.

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


[clang] [Clang][Comments] Add argument parsing for @throw @throws @exception (PR #84726)

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


@@ -149,6 +276,93 @@ class TextTokenRetokenizer {
 addToken();
   }
 
+  /// Extract a type argument
+  bool lexType(Token &Tok) {
+if (isEnd())
+  return false;
+Position SavedPos = Pos;
+consumeWhitespace();
+SmallString<32> NextToken;
+SmallString<32> WordText;
+const char *WordBegin = Pos.BufferPtr;
+SourceLocation Loc = getSourceLocation();
+StringRef ConstVal = StringRef("const");
+StringRef PointerVal = StringRef("*");
+StringRef ReferenceVal = StringRef("&");
+bool ConstPointer = false;
+
+while (!isEnd()) {
+  const char C = peek();
+  if (!isWhitespace(C)) {
+if (C == '<') {
+  if (!lexTemplate(WordText))
+return false;
+} else {
+  WordText.push_back(C);

sdkrystian wrote:

Does this treat any non-whitespace character (other than `<`) as being part of 
a name?

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


[clang] [Clang][Comments] Add argument parsing for @throw @throws @exception (PR #84726)

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


@@ -149,6 +276,93 @@ class TextTokenRetokenizer {
 addToken();
   }
 
+  /// Extract a type argument
+  bool lexType(Token &Tok) {
+if (isEnd())
+  return false;
+Position SavedPos = Pos;
+consumeWhitespace();
+SmallString<32> NextToken;
+SmallString<32> WordText;
+const char *WordBegin = Pos.BufferPtr;
+SourceLocation Loc = getSourceLocation();
+StringRef ConstVal = StringRef("const");
+StringRef PointerVal = StringRef("*");
+StringRef ReferenceVal = StringRef("&");
+bool ConstPointer = false;
+
+while (!isEnd()) {

sdkrystian wrote:

Some comments wouldn't hurt...

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


[clang] [Clang][Comments] Add argument parsing for @throw @throws @exception (PR #84726)

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


@@ -89,6 +108,114 @@ class TextTokenRetokenizer {
 }
   }
 
+  bool continueInt(SmallString<32> &NextToken) {
+return NextToken.ends_with(StringRef("char")) ||

sdkrystian wrote:

Don't really understand what this is for...

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


[clang] [Clang][Comments] Add argument parsing for @throw @throws @exception (PR #84726)

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


@@ -149,6 +276,93 @@ class TextTokenRetokenizer {
 addToken();
   }
 
+  /// Extract a type argument
+  bool lexType(Token &Tok) {
+if (isEnd())
+  return false;
+Position SavedPos = Pos;
+consumeWhitespace();
+SmallString<32> NextToken;
+SmallString<32> WordText;
+const char *WordBegin = Pos.BufferPtr;
+SourceLocation Loc = getSourceLocation();
+StringRef ConstVal = StringRef("const");
+StringRef PointerVal = StringRef("*");

sdkrystian wrote:

What about pointers to members? Arrays? Function? More complex declarators like 
`void(*)(int, int)`?

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


[clang] [Clang][Sema] Diagnose class member access expressions naming non-existent members of the current instantiation prior to instantiation in the absence of dependent base classes (PR #84050)

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

sdkrystian wrote:

Ping @erichkeane 

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


[clang] [clang-tools-extra] [Clang][Sema] Fix explicit specializations of member function templates with a deduced return type (PR #86817)

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

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

Currently, clang erroneously rejects the following:
```cpp
template
struct A
{
template
auto f();
};

template<>
template
auto A::f(); // error: conflicting types for 'f'
```
This happens because the explicit specialization of `f` has its return type 
replaced with a dependent `AutoType` in `ActOnFunctionDeclarator`, but no such 
replacement occurs for the implicitly instantiated function template 
`A::f`. Since the return types don't match, the explicit specialization is 
diagnosed as an invalid redeclaration. 

This patch moves the replacement of the return type to 
`CheckFunctionDeclaration` so it also happens during instantiation. 
`setObjectOfFriendDecl` will have been called by then, so the `isFriend && 
CurContext->isDependentContext()` condition is made redundant & removed (as it 
already happens in `DeclContext::isDependentContext`). `Sema::IsOverload` only 
checks the _declared_ return type (which isn't changed by the adjustment), so 
adjusting the return type afterwards should be safe.

>From 647052c0545d73fbf5cb4fa4930bf5c38b575985 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Wed, 27 Mar 2024 11:23:19 -0400
Subject: [PATCH] [Clang][Sema] Fix explicit specializations of member function
 templates with a deduced return type

---
 .../clang-tidy/infrastructure/diagnostic.cpp  |  2 -
 clang/lib/Sema/SemaDecl.cpp   | 50 ---
 .../SemaCXX/deduced-return-type-cxx14.cpp | 18 +++
 3 files changed, 51 insertions(+), 19 deletions(-)

diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp 
b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
index d0efc5ca763753..e333c83b895ee7 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
@@ -68,6 +68,4 @@ auto S<>::foo(auto)
 {
 return 1;
 }
-// CHECK8: error: conflicting types for 'foo' [clang-diagnostic-error]
-// CHECK8: note: previous declaration is here
 #endif
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 9a286e0b26a4c6..d7388f6cc6aa2a 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -10119,23 +10119,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, 
DeclContext *DC,
 Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_auto_fn_virtual);
 }
 
-if (getLangOpts().CPlusPlus14 &&
-(NewFD->isDependentContext() ||
- (isFriend && CurContext->isDependentContext())) &&
-NewFD->getReturnType()->isUndeducedType()) {
-  // If the function template is referenced directly (for instance, as a
-  // member of the current instantiation), pretend it has a dependent type.
-  // This is not really justified by the standard, but is the only sane
-  // thing to do.
-  // FIXME: For a friend function, we have not marked the function as being
-  // a friend yet, so 'isDependentContext' on the FD doesn't work.
-  const FunctionProtoType *FPT =
-  NewFD->getType()->castAs();
-  QualType Result = SubstAutoTypeDependent(FPT->getReturnType());
-  NewFD->setType(Context.getFunctionType(Result, FPT->getParamTypes(),
- FPT->getExtProtoInfo()));
-}
-
 // C++ [dcl.fct.spec]p3:
 //  The inline specifier shall not appear on a block scope function
 //  declaration.
@@ -12107,6 +12090,39 @@ bool Sema::CheckFunctionDeclaration(Scope *S, 
FunctionDecl *NewFD,
 
   CheckConstPureAttributesUsage(*this, NewFD);
 
+  // C++23 [dcl.spec.auto.general]p12:
+  //   Return type deduction for a templated function with a placeholder in its
+  //   declared type occurs when the definition is instantiated even if the
+  //   function body contains a return statement with a non-type-dependent
+  //   operand.
+  //
+  // C++23 [temp.dep.expr]p3:
+  //   An id-expression is type-dependent if it is a template-id that is not a
+  //   concept-id and is dependent; or if its terminal name is:
+  //   - [...]
+  //   - associated by name lookup with one or more declarations of member
+  // functions of a class that is the current instantiation declared with a
+  // return type that contains a placeholder type,
+  //   - [...]
+  //
+  // If this is a templated function with a placeholder in its return type,
+  // make the placeholder type dependent since it won't be deduced until the
+  // definition is instantiated. We do this here because it needs to happen
+  // for implicitly instantiated member functions/member function templates.
+  if (getLangOpts().CPlusPlus14 &&
+  (NewFD->isDependentContext() &&
+   NewFD->getReturnType()->isUndeducedType())) {
+// If the function template is referenced directly (for instance, as a
+// member of the current instantiation), pretend it has a dependent type.
+// T

[clang] [clang-tools-extra] [Clang][Sema] Fix explicit specializations of member function templates with a deduced return type (PR #86817)

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

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

>From 468e3d9414a797ea73411a779343dee351e09e42 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Wed, 27 Mar 2024 11:23:19 -0400
Subject: [PATCH] [Clang][Sema] Fix explicit specializations of member function
 templates with a deduced return type

---
 .../clang-tidy/infrastructure/diagnostic.cpp  |  2 -
 clang/lib/Sema/SemaDecl.cpp   | 46 ---
 .../SemaCXX/deduced-return-type-cxx14.cpp | 18 
 3 files changed, 47 insertions(+), 19 deletions(-)

diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp 
b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
index d0efc5ca763753..e333c83b895ee7 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
@@ -68,6 +68,4 @@ auto S<>::foo(auto)
 {
 return 1;
 }
-// CHECK8: error: conflicting types for 'foo' [clang-diagnostic-error]
-// CHECK8: note: previous declaration is here
 #endif
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 9a286e0b26a4c6..be9a05dd2ce570 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -10119,23 +10119,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, 
DeclContext *DC,
 Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_auto_fn_virtual);
 }
 
-if (getLangOpts().CPlusPlus14 &&
-(NewFD->isDependentContext() ||
- (isFriend && CurContext->isDependentContext())) &&
-NewFD->getReturnType()->isUndeducedType()) {
-  // If the function template is referenced directly (for instance, as a
-  // member of the current instantiation), pretend it has a dependent type.
-  // This is not really justified by the standard, but is the only sane
-  // thing to do.
-  // FIXME: For a friend function, we have not marked the function as being
-  // a friend yet, so 'isDependentContext' on the FD doesn't work.
-  const FunctionProtoType *FPT =
-  NewFD->getType()->castAs();
-  QualType Result = SubstAutoTypeDependent(FPT->getReturnType());
-  NewFD->setType(Context.getFunctionType(Result, FPT->getParamTypes(),
- FPT->getExtProtoInfo()));
-}
-
 // C++ [dcl.fct.spec]p3:
 //  The inline specifier shall not appear on a block scope function
 //  declaration.
@@ -12107,6 +12090,35 @@ bool Sema::CheckFunctionDeclaration(Scope *S, 
FunctionDecl *NewFD,
 
   CheckConstPureAttributesUsage(*this, NewFD);
 
+  // C++23 [dcl.spec.auto.general]p12:
+  //   Return type deduction for a templated function with a placeholder in its
+  //   declared type occurs when the definition is instantiated even if the
+  //   function body contains a return statement with a non-type-dependent
+  //   operand.
+  //
+  // C++23 [temp.dep.expr]p3:
+  //   An id-expression is type-dependent if it is a template-id that is not a
+  //   concept-id and is dependent; or if its terminal name is:
+  //   - [...]
+  //   - associated by name lookup with one or more declarations of member
+  // functions of a class that is the current instantiation declared with a
+  // return type that contains a placeholder type,
+  //   - [...]
+  //
+  // If this is a templated function with a placeholder in its return type,
+  // make the placeholder type dependent since it won't be deduced until the
+  // definition is instantiated. We do this here because it needs to happen
+  // for implicitly instantiated member functions/member function templates.
+  if (getLangOpts().CPlusPlus14 &&
+  (NewFD->isDependentContext() &&
+   NewFD->getReturnType()->isUndeducedType())) {
+const FunctionProtoType *FPT =
+NewFD->getType()->castAs();
+QualType NewReturnType = SubstAutoTypeDependent(FPT->getReturnType());
+NewFD->setType(Context.getFunctionType(NewReturnType, FPT->getParamTypes(),
+   FPT->getExtProtoInfo()));
+  }
+
   // C++11 [dcl.constexpr]p8:
   //   A constexpr specifier for a non-static member function that is not
   //   a constructor declares that member function to be const.
diff --git a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp 
b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
index 431d77ca785b8e..c33e07088ba32f 100644
--- a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
+++ b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
@@ -237,6 +237,24 @@ namespace Templates {
 int (S::*(*p)())(double) = f;
 int (S::*(*q)())(double) = f;
   }
+
+  template
+  struct MemberSpecialization {
+auto f();
+template auto f(U);
+template auto *f(U);
+  };
+
+  template<>
+  auto MemberSpecialization::f();
+
+  template<>
+  template
+  auto MemberSpecialization::f(U);
+
+  template<>
+  template
+  auto *MemberSpecialization::f(U);
 }
 
 auto fwd_decl_u

[clang] [clang-tools-extra] [Clang][Sema] Fix explicit specializations of member function templates with a deduced return type (PR #86817)

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

sdkrystian wrote:

Still needs a release note but should otherwise be good to go 

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


[clang] [clang-tools-extra] [Clang][Sema] Fix explicit specializations of member function templates with a deduced return type (PR #86817)

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

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

>From 468e3d9414a797ea73411a779343dee351e09e42 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Wed, 27 Mar 2024 11:23:19 -0400
Subject: [PATCH 1/3] [Clang][Sema] Fix explicit specializations of member
 function templates with a deduced return type

---
 .../clang-tidy/infrastructure/diagnostic.cpp  |  2 -
 clang/lib/Sema/SemaDecl.cpp   | 46 ---
 .../SemaCXX/deduced-return-type-cxx14.cpp | 18 
 3 files changed, 47 insertions(+), 19 deletions(-)

diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp 
b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
index d0efc5ca763753..e333c83b895ee7 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
@@ -68,6 +68,4 @@ auto S<>::foo(auto)
 {
 return 1;
 }
-// CHECK8: error: conflicting types for 'foo' [clang-diagnostic-error]
-// CHECK8: note: previous declaration is here
 #endif
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 9a286e0b26a4c6..be9a05dd2ce570 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -10119,23 +10119,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, 
DeclContext *DC,
 Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_auto_fn_virtual);
 }
 
-if (getLangOpts().CPlusPlus14 &&
-(NewFD->isDependentContext() ||
- (isFriend && CurContext->isDependentContext())) &&
-NewFD->getReturnType()->isUndeducedType()) {
-  // If the function template is referenced directly (for instance, as a
-  // member of the current instantiation), pretend it has a dependent type.
-  // This is not really justified by the standard, but is the only sane
-  // thing to do.
-  // FIXME: For a friend function, we have not marked the function as being
-  // a friend yet, so 'isDependentContext' on the FD doesn't work.
-  const FunctionProtoType *FPT =
-  NewFD->getType()->castAs();
-  QualType Result = SubstAutoTypeDependent(FPT->getReturnType());
-  NewFD->setType(Context.getFunctionType(Result, FPT->getParamTypes(),
- FPT->getExtProtoInfo()));
-}
-
 // C++ [dcl.fct.spec]p3:
 //  The inline specifier shall not appear on a block scope function
 //  declaration.
@@ -12107,6 +12090,35 @@ bool Sema::CheckFunctionDeclaration(Scope *S, 
FunctionDecl *NewFD,
 
   CheckConstPureAttributesUsage(*this, NewFD);
 
+  // C++23 [dcl.spec.auto.general]p12:
+  //   Return type deduction for a templated function with a placeholder in its
+  //   declared type occurs when the definition is instantiated even if the
+  //   function body contains a return statement with a non-type-dependent
+  //   operand.
+  //
+  // C++23 [temp.dep.expr]p3:
+  //   An id-expression is type-dependent if it is a template-id that is not a
+  //   concept-id and is dependent; or if its terminal name is:
+  //   - [...]
+  //   - associated by name lookup with one or more declarations of member
+  // functions of a class that is the current instantiation declared with a
+  // return type that contains a placeholder type,
+  //   - [...]
+  //
+  // If this is a templated function with a placeholder in its return type,
+  // make the placeholder type dependent since it won't be deduced until the
+  // definition is instantiated. We do this here because it needs to happen
+  // for implicitly instantiated member functions/member function templates.
+  if (getLangOpts().CPlusPlus14 &&
+  (NewFD->isDependentContext() &&
+   NewFD->getReturnType()->isUndeducedType())) {
+const FunctionProtoType *FPT =
+NewFD->getType()->castAs();
+QualType NewReturnType = SubstAutoTypeDependent(FPT->getReturnType());
+NewFD->setType(Context.getFunctionType(NewReturnType, FPT->getParamTypes(),
+   FPT->getExtProtoInfo()));
+  }
+
   // C++11 [dcl.constexpr]p8:
   //   A constexpr specifier for a non-static member function that is not
   //   a constructor declares that member function to be const.
diff --git a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp 
b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
index 431d77ca785b8e..c33e07088ba32f 100644
--- a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
+++ b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
@@ -237,6 +237,24 @@ namespace Templates {
 int (S::*(*p)())(double) = f;
 int (S::*(*q)())(double) = f;
   }
+
+  template
+  struct MemberSpecialization {
+auto f();
+template auto f(U);
+template auto *f(U);
+  };
+
+  template<>
+  auto MemberSpecialization::f();
+
+  template<>
+  template
+  auto MemberSpecialization::f(U);
+
+  template<>
+  template
+  auto *MemberSpecialization::f(U);
 }
 
 auto fwd_de

[clang] [clang-tools-extra] [Clang][Sema] Fix explicit specializations of member function templates with a deduced return type (PR #86817)

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


@@ -12107,6 +12090,35 @@ bool Sema::CheckFunctionDeclaration(Scope *S, 
FunctionDecl *NewFD,
 
   CheckConstPureAttributesUsage(*this, NewFD);
 
+  // C++23 [dcl.spec.auto.general]p12:
+  //   Return type deduction for a templated function with a placeholder in its
+  //   declared type occurs when the definition is instantiated even if the
+  //   function body contains a return statement with a non-type-dependent
+  //   operand.

sdkrystian wrote:

I changed both quotes to "C++"

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


[clang] [clang-tools-extra] [Clang][Sema] Fix explicit specializations of member function templates with a deduced return type (PR #86817)

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


@@ -345,6 +345,10 @@ Bug Fixes in This Version
 - Fixes an assertion failure on invalid code when trying to define member
   functions in lambdas.
 
+- Clang now allows for member function templates of class templates declared 
with a deduced return type
+  to be explicitly specialized for a given implicit instantiation of the class 
template.

sdkrystian wrote:

How about:
> Fixed a bug that prevented member function templates of class templates 
> declared with a deduced return type from being explicitly specialized for a 
> given implicit instantiation of the class template.

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


[clang] [clang-tools-extra] [Clang][Sema] Fix explicit specializations of member function templates with a deduced return type (PR #86817)

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

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

>From 468e3d9414a797ea73411a779343dee351e09e42 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Wed, 27 Mar 2024 11:23:19 -0400
Subject: [PATCH 1/4] [Clang][Sema] Fix explicit specializations of member
 function templates with a deduced return type

---
 .../clang-tidy/infrastructure/diagnostic.cpp  |  2 -
 clang/lib/Sema/SemaDecl.cpp   | 46 ---
 .../SemaCXX/deduced-return-type-cxx14.cpp | 18 
 3 files changed, 47 insertions(+), 19 deletions(-)

diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp 
b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
index d0efc5ca763753..e333c83b895ee7 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
@@ -68,6 +68,4 @@ auto S<>::foo(auto)
 {
 return 1;
 }
-// CHECK8: error: conflicting types for 'foo' [clang-diagnostic-error]
-// CHECK8: note: previous declaration is here
 #endif
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 9a286e0b26a4c6..be9a05dd2ce570 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -10119,23 +10119,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, 
DeclContext *DC,
 Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_auto_fn_virtual);
 }
 
-if (getLangOpts().CPlusPlus14 &&
-(NewFD->isDependentContext() ||
- (isFriend && CurContext->isDependentContext())) &&
-NewFD->getReturnType()->isUndeducedType()) {
-  // If the function template is referenced directly (for instance, as a
-  // member of the current instantiation), pretend it has a dependent type.
-  // This is not really justified by the standard, but is the only sane
-  // thing to do.
-  // FIXME: For a friend function, we have not marked the function as being
-  // a friend yet, so 'isDependentContext' on the FD doesn't work.
-  const FunctionProtoType *FPT =
-  NewFD->getType()->castAs();
-  QualType Result = SubstAutoTypeDependent(FPT->getReturnType());
-  NewFD->setType(Context.getFunctionType(Result, FPT->getParamTypes(),
- FPT->getExtProtoInfo()));
-}
-
 // C++ [dcl.fct.spec]p3:
 //  The inline specifier shall not appear on a block scope function
 //  declaration.
@@ -12107,6 +12090,35 @@ bool Sema::CheckFunctionDeclaration(Scope *S, 
FunctionDecl *NewFD,
 
   CheckConstPureAttributesUsage(*this, NewFD);
 
+  // C++23 [dcl.spec.auto.general]p12:
+  //   Return type deduction for a templated function with a placeholder in its
+  //   declared type occurs when the definition is instantiated even if the
+  //   function body contains a return statement with a non-type-dependent
+  //   operand.
+  //
+  // C++23 [temp.dep.expr]p3:
+  //   An id-expression is type-dependent if it is a template-id that is not a
+  //   concept-id and is dependent; or if its terminal name is:
+  //   - [...]
+  //   - associated by name lookup with one or more declarations of member
+  // functions of a class that is the current instantiation declared with a
+  // return type that contains a placeholder type,
+  //   - [...]
+  //
+  // If this is a templated function with a placeholder in its return type,
+  // make the placeholder type dependent since it won't be deduced until the
+  // definition is instantiated. We do this here because it needs to happen
+  // for implicitly instantiated member functions/member function templates.
+  if (getLangOpts().CPlusPlus14 &&
+  (NewFD->isDependentContext() &&
+   NewFD->getReturnType()->isUndeducedType())) {
+const FunctionProtoType *FPT =
+NewFD->getType()->castAs();
+QualType NewReturnType = SubstAutoTypeDependent(FPT->getReturnType());
+NewFD->setType(Context.getFunctionType(NewReturnType, FPT->getParamTypes(),
+   FPT->getExtProtoInfo()));
+  }
+
   // C++11 [dcl.constexpr]p8:
   //   A constexpr specifier for a non-static member function that is not
   //   a constructor declares that member function to be const.
diff --git a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp 
b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
index 431d77ca785b8e..c33e07088ba32f 100644
--- a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
+++ b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
@@ -237,6 +237,24 @@ namespace Templates {
 int (S::*(*p)())(double) = f;
 int (S::*(*q)())(double) = f;
   }
+
+  template
+  struct MemberSpecialization {
+auto f();
+template auto f(U);
+template auto *f(U);
+  };
+
+  template<>
+  auto MemberSpecialization::f();
+
+  template<>
+  template
+  auto MemberSpecialization::f(U);
+
+  template<>
+  template
+  auto *MemberSpecialization::f(U);
 }
 
 auto fwd_de

[clang] [Clang][AST][NFC] Move template argument dependence computations for MemberExpr to computeDependence (PR #86682)

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

sdkrystian wrote:

Ping @erichkeane 

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


[clang] [Clang][AST][NFC] Move template argument dependence computations for MemberExpr to computeDependence (PR #86682)

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


@@ -1735,48 +1757,21 @@ MemberExpr *MemberExpr::Create(
 ValueDecl *MemberDecl, DeclAccessPair FoundDecl,
 DeclarationNameInfo NameInfo, const TemplateArgumentListInfo *TemplateArgs,
 QualType T, ExprValueKind VK, ExprObjectKind OK, NonOdrUseReason NOUR) {
-  bool HasQualOrFound = QualifierLoc || FoundDecl.getDecl() != MemberDecl ||
-FoundDecl.getAccess() != MemberDecl->getAccess();
+  bool HasQualifier = QualifierLoc.hasQualifier();
+  bool HasFoundDecl = FoundDecl.getDecl() != MemberDecl ||
+  FoundDecl.getAccess() != MemberDecl->getAccess();
   bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid();
   std::size_t Size =
-  totalSizeToAlloc(
-  HasQualOrFound ? 1 : 0, HasTemplateKWAndArgsInfo ? 1 : 0,
+  totalSizeToAlloc(
+  HasQualifier ? 1 : 0, HasFoundDecl ? 1 : 0,

sdkrystian wrote:

Sounds good to me, I prefer writing it that way anyways :) (was just following 
the style of the existing code)

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


[clang] [Clang] Unify interface for accessing template arguments as written for class/variable template specializations (PR #81642)

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

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

>From b45a42322682f3b872e6753965c4e4a7edb68333 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Fri, 9 Feb 2024 14:00:49 -0500
Subject: [PATCH 1/4] [Clang] Unify interface for accessing template arguments
 as written for class/variable template specializations

---
 clang/include/clang/AST/DeclTemplate.h| 186 --
 clang/include/clang/AST/RecursiveASTVisitor.h |  27 +--
 clang/include/clang/ASTMatchers/ASTMatchers.h |   7 +-
 .../clang/ASTMatchers/ASTMatchersInternal.h   |   4 -
 clang/lib/AST/ASTImporter.cpp |  55 +++---
 clang/lib/AST/DeclPrinter.cpp |  15 +-
 clang/lib/AST/DeclTemplate.cpp| 145 --
 clang/lib/AST/TypePrinter.cpp |  24 +--
 clang/lib/Index/IndexDecl.cpp |   9 +-
 clang/lib/Sema/Sema.cpp   |   2 +-
 clang/lib/Sema/SemaTemplate.cpp   |  47 ++---
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  | 155 ++-
 clang/lib/Serialization/ASTReaderDecl.cpp |  20 +-
 clang/lib/Serialization/ASTWriterDecl.cpp |  16 +-
 clang/test/AST/ast-dump-template-decls.cpp|  18 +-
 clang/test/Index/Core/index-source.cpp|  11 --
 clang/test/Index/index-refs.cpp   |   1 -
 clang/tools/libclang/CIndex.cpp   |  29 ++-
 .../ASTMatchers/ASTMatchersNodeTest.cpp   |  12 --
 .../ASTMatchers/ASTMatchersTraversalTest.cpp  |  18 +-
 20 files changed, 360 insertions(+), 441 deletions(-)

diff --git a/clang/include/clang/AST/DeclTemplate.h 
b/clang/include/clang/AST/DeclTemplate.h
index e3b6a7efb1127af..b5c2d4597151205 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -1792,10 +1792,9 @@ class ClassTemplateSpecializationDecl
   llvm::PointerUnion
 SpecializedTemplate;
 
-  /// Further info for explicit template specialization/instantiation.
-  struct ExplicitSpecializationInfo {
-/// The type-as-written.
-TypeSourceInfo *TypeAsWritten = nullptr;
+  struct ExplicitInstantiationInfo {
+/// The template arguments as written..
+const ASTTemplateArgumentListInfo *TemplateArgsAsWritten = nullptr;
 
 /// The location of the extern keyword.
 SourceLocation ExternLoc;
@@ -1803,12 +1802,14 @@ class ClassTemplateSpecializationDecl
 /// The location of the template keyword.
 SourceLocation TemplateKeywordLoc;
 
-ExplicitSpecializationInfo() = default;
+ExplicitInstantiationInfo() = default;
   };
 
   /// Further info for explicit template specialization/instantiation.
   /// Does not apply to implicit specializations.
-  ExplicitSpecializationInfo *ExplicitInfo = nullptr;
+  llvm::PointerUnion
+  ExplicitInfo = nullptr;
 
   /// The template arguments used to describe this specialization.
   const TemplateArgumentList *TemplateArgs;
@@ -1985,44 +1986,45 @@ class ClassTemplateSpecializationDecl
 SpecializedTemplate = TemplDecl;
   }
 
-  /// Sets the type of this specialization as it was written by
-  /// the user. This will be a class template specialization type.
-  void setTypeAsWritten(TypeSourceInfo *T) {
-if (!ExplicitInfo)
-  ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
-ExplicitInfo->TypeAsWritten = T;
-  }
-
-  /// Gets the type of this specialization as it was written by
-  /// the user, if it was so written.
-  TypeSourceInfo *getTypeAsWritten() const {
-return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr;
+  const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
+if (auto *Info = ExplicitInfo.dyn_cast())
+  return Info->TemplateArgsAsWritten;
+return ExplicitInfo.get();
   }
 
   /// Gets the location of the extern keyword, if present.
   SourceLocation getExternLoc() const {
-return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation();
+if (auto *Info = ExplicitInfo.dyn_cast())
+  return Info->ExternLoc;
+return SourceLocation();
   }
 
-  /// Sets the location of the extern keyword.
-  void setExternLoc(SourceLocation Loc) {
-if (!ExplicitInfo)
-  ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
-ExplicitInfo->ExternLoc = Loc;
+  /// Gets the location of the template keyword, if present.
+  SourceLocation getTemplateKeywordLoc() const {
+if (auto *Info = ExplicitInfo.dyn_cast())
+  return Info->TemplateKeywordLoc;
+return SourceLocation();
   }
 
-  /// Sets the location of the template keyword.
-  void setTemplateKeywordLoc(SourceLocation Loc) {
-if (!ExplicitInfo)
-  ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
-ExplicitInfo->TemplateKeywordLoc = Loc;
+  void
+  setTemplateArgsAsWritten(const ASTTemplateArgumentListInfo *ArgsWritten) {
+if (auto *Info = ExplicitInfo.dyn_cast())
+  Info->TemplateArgsAsWritten = ArgsWritten;
+else
+  ExplicitInfo = ArgsW

[clang] [Clang] Unify interface for accessing template arguments as written for class/variable template specializations (PR #81642)

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

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

>From b45a42322682f3b872e6753965c4e4a7edb68333 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Fri, 9 Feb 2024 14:00:49 -0500
Subject: [PATCH 1/5] [Clang] Unify interface for accessing template arguments
 as written for class/variable template specializations

---
 clang/include/clang/AST/DeclTemplate.h| 186 --
 clang/include/clang/AST/RecursiveASTVisitor.h |  27 +--
 clang/include/clang/ASTMatchers/ASTMatchers.h |   7 +-
 .../clang/ASTMatchers/ASTMatchersInternal.h   |   4 -
 clang/lib/AST/ASTImporter.cpp |  55 +++---
 clang/lib/AST/DeclPrinter.cpp |  15 +-
 clang/lib/AST/DeclTemplate.cpp| 145 --
 clang/lib/AST/TypePrinter.cpp |  24 +--
 clang/lib/Index/IndexDecl.cpp |   9 +-
 clang/lib/Sema/Sema.cpp   |   2 +-
 clang/lib/Sema/SemaTemplate.cpp   |  47 ++---
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  | 155 ++-
 clang/lib/Serialization/ASTReaderDecl.cpp |  20 +-
 clang/lib/Serialization/ASTWriterDecl.cpp |  16 +-
 clang/test/AST/ast-dump-template-decls.cpp|  18 +-
 clang/test/Index/Core/index-source.cpp|  11 --
 clang/test/Index/index-refs.cpp   |   1 -
 clang/tools/libclang/CIndex.cpp   |  29 ++-
 .../ASTMatchers/ASTMatchersNodeTest.cpp   |  12 --
 .../ASTMatchers/ASTMatchersTraversalTest.cpp  |  18 +-
 20 files changed, 360 insertions(+), 441 deletions(-)

diff --git a/clang/include/clang/AST/DeclTemplate.h 
b/clang/include/clang/AST/DeclTemplate.h
index e3b6a7efb1127af..b5c2d4597151205 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -1792,10 +1792,9 @@ class ClassTemplateSpecializationDecl
   llvm::PointerUnion
 SpecializedTemplate;
 
-  /// Further info for explicit template specialization/instantiation.
-  struct ExplicitSpecializationInfo {
-/// The type-as-written.
-TypeSourceInfo *TypeAsWritten = nullptr;
+  struct ExplicitInstantiationInfo {
+/// The template arguments as written..
+const ASTTemplateArgumentListInfo *TemplateArgsAsWritten = nullptr;
 
 /// The location of the extern keyword.
 SourceLocation ExternLoc;
@@ -1803,12 +1802,14 @@ class ClassTemplateSpecializationDecl
 /// The location of the template keyword.
 SourceLocation TemplateKeywordLoc;
 
-ExplicitSpecializationInfo() = default;
+ExplicitInstantiationInfo() = default;
   };
 
   /// Further info for explicit template specialization/instantiation.
   /// Does not apply to implicit specializations.
-  ExplicitSpecializationInfo *ExplicitInfo = nullptr;
+  llvm::PointerUnion
+  ExplicitInfo = nullptr;
 
   /// The template arguments used to describe this specialization.
   const TemplateArgumentList *TemplateArgs;
@@ -1985,44 +1986,45 @@ class ClassTemplateSpecializationDecl
 SpecializedTemplate = TemplDecl;
   }
 
-  /// Sets the type of this specialization as it was written by
-  /// the user. This will be a class template specialization type.
-  void setTypeAsWritten(TypeSourceInfo *T) {
-if (!ExplicitInfo)
-  ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
-ExplicitInfo->TypeAsWritten = T;
-  }
-
-  /// Gets the type of this specialization as it was written by
-  /// the user, if it was so written.
-  TypeSourceInfo *getTypeAsWritten() const {
-return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr;
+  const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
+if (auto *Info = ExplicitInfo.dyn_cast())
+  return Info->TemplateArgsAsWritten;
+return ExplicitInfo.get();
   }
 
   /// Gets the location of the extern keyword, if present.
   SourceLocation getExternLoc() const {
-return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation();
+if (auto *Info = ExplicitInfo.dyn_cast())
+  return Info->ExternLoc;
+return SourceLocation();
   }
 
-  /// Sets the location of the extern keyword.
-  void setExternLoc(SourceLocation Loc) {
-if (!ExplicitInfo)
-  ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
-ExplicitInfo->ExternLoc = Loc;
+  /// Gets the location of the template keyword, if present.
+  SourceLocation getTemplateKeywordLoc() const {
+if (auto *Info = ExplicitInfo.dyn_cast())
+  return Info->TemplateKeywordLoc;
+return SourceLocation();
   }
 
-  /// Sets the location of the template keyword.
-  void setTemplateKeywordLoc(SourceLocation Loc) {
-if (!ExplicitInfo)
-  ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
-ExplicitInfo->TemplateKeywordLoc = Loc;
+  void
+  setTemplateArgsAsWritten(const ASTTemplateArgumentListInfo *ArgsWritten) {
+if (auto *Info = ExplicitInfo.dyn_cast())
+  Info->TemplateArgsAsWritten = ArgsWritten;
+else
+  ExplicitInfo = ArgsW

[clang] [Clang] Unify interface for accessing template arguments as written for class/variable template specializations (PR #81642)

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

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

>From b45a42322682f3b872e6753965c4e4a7edb68333 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Fri, 9 Feb 2024 14:00:49 -0500
Subject: [PATCH 1/6] [Clang] Unify interface for accessing template arguments
 as written for class/variable template specializations

---
 clang/include/clang/AST/DeclTemplate.h| 186 --
 clang/include/clang/AST/RecursiveASTVisitor.h |  27 +--
 clang/include/clang/ASTMatchers/ASTMatchers.h |   7 +-
 .../clang/ASTMatchers/ASTMatchersInternal.h   |   4 -
 clang/lib/AST/ASTImporter.cpp |  55 +++---
 clang/lib/AST/DeclPrinter.cpp |  15 +-
 clang/lib/AST/DeclTemplate.cpp| 145 --
 clang/lib/AST/TypePrinter.cpp |  24 +--
 clang/lib/Index/IndexDecl.cpp |   9 +-
 clang/lib/Sema/Sema.cpp   |   2 +-
 clang/lib/Sema/SemaTemplate.cpp   |  47 ++---
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  | 155 ++-
 clang/lib/Serialization/ASTReaderDecl.cpp |  20 +-
 clang/lib/Serialization/ASTWriterDecl.cpp |  16 +-
 clang/test/AST/ast-dump-template-decls.cpp|  18 +-
 clang/test/Index/Core/index-source.cpp|  11 --
 clang/test/Index/index-refs.cpp   |   1 -
 clang/tools/libclang/CIndex.cpp   |  29 ++-
 .../ASTMatchers/ASTMatchersNodeTest.cpp   |  12 --
 .../ASTMatchers/ASTMatchersTraversalTest.cpp  |  18 +-
 20 files changed, 360 insertions(+), 441 deletions(-)

diff --git a/clang/include/clang/AST/DeclTemplate.h 
b/clang/include/clang/AST/DeclTemplate.h
index e3b6a7efb1127a..b5c2d459715120 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -1792,10 +1792,9 @@ class ClassTemplateSpecializationDecl
   llvm::PointerUnion
 SpecializedTemplate;
 
-  /// Further info for explicit template specialization/instantiation.
-  struct ExplicitSpecializationInfo {
-/// The type-as-written.
-TypeSourceInfo *TypeAsWritten = nullptr;
+  struct ExplicitInstantiationInfo {
+/// The template arguments as written..
+const ASTTemplateArgumentListInfo *TemplateArgsAsWritten = nullptr;
 
 /// The location of the extern keyword.
 SourceLocation ExternLoc;
@@ -1803,12 +1802,14 @@ class ClassTemplateSpecializationDecl
 /// The location of the template keyword.
 SourceLocation TemplateKeywordLoc;
 
-ExplicitSpecializationInfo() = default;
+ExplicitInstantiationInfo() = default;
   };
 
   /// Further info for explicit template specialization/instantiation.
   /// Does not apply to implicit specializations.
-  ExplicitSpecializationInfo *ExplicitInfo = nullptr;
+  llvm::PointerUnion
+  ExplicitInfo = nullptr;
 
   /// The template arguments used to describe this specialization.
   const TemplateArgumentList *TemplateArgs;
@@ -1985,44 +1986,45 @@ class ClassTemplateSpecializationDecl
 SpecializedTemplate = TemplDecl;
   }
 
-  /// Sets the type of this specialization as it was written by
-  /// the user. This will be a class template specialization type.
-  void setTypeAsWritten(TypeSourceInfo *T) {
-if (!ExplicitInfo)
-  ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
-ExplicitInfo->TypeAsWritten = T;
-  }
-
-  /// Gets the type of this specialization as it was written by
-  /// the user, if it was so written.
-  TypeSourceInfo *getTypeAsWritten() const {
-return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr;
+  const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
+if (auto *Info = ExplicitInfo.dyn_cast())
+  return Info->TemplateArgsAsWritten;
+return ExplicitInfo.get();
   }
 
   /// Gets the location of the extern keyword, if present.
   SourceLocation getExternLoc() const {
-return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation();
+if (auto *Info = ExplicitInfo.dyn_cast())
+  return Info->ExternLoc;
+return SourceLocation();
   }
 
-  /// Sets the location of the extern keyword.
-  void setExternLoc(SourceLocation Loc) {
-if (!ExplicitInfo)
-  ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
-ExplicitInfo->ExternLoc = Loc;
+  /// Gets the location of the template keyword, if present.
+  SourceLocation getTemplateKeywordLoc() const {
+if (auto *Info = ExplicitInfo.dyn_cast())
+  return Info->TemplateKeywordLoc;
+return SourceLocation();
   }
 
-  /// Sets the location of the template keyword.
-  void setTemplateKeywordLoc(SourceLocation Loc) {
-if (!ExplicitInfo)
-  ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
-ExplicitInfo->TemplateKeywordLoc = Loc;
+  void
+  setTemplateArgsAsWritten(const ASTTemplateArgumentListInfo *ArgsWritten) {
+if (auto *Info = ExplicitInfo.dyn_cast())
+  Info->TemplateArgsAsWritten = ArgsWritten;
+else
+  ExplicitInfo = ArgsWri

[clang] [Clang] Unify interface for accessing template arguments as written for class/variable template specializations (PR #81642)

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

sdkrystian wrote:

@erichkeane Regarding "Still waiting on this?", I pushed a commit that 
addresses the fixme. I'll be addressing the rest of your review comments in a 
subsequent commit..

Also, if we are renaming `ExplicitInstantiationInfo::ExternLoc` to 
`ExternKeywordLoc`, should we rename the getters and setters to 
`getExternKeywordLoc`/`setExternKeywordLoc` as well?

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


[clang] [Clang][Sema] Diagnose class member access expressions naming non-existent members of the current instantiation prior to instantiation in the absence of dependent base classes (PR #84050)

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


@@ -1287,7 +1287,10 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult 
&R,
 return ExprError();
 
   QualType BaseType = BaseExpr.get()->getType();
+
+#if 0

sdkrystian wrote:

This assertion should be deleted since the lookup context could be the current 
instantiation (ergo dependent). 

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


[clang] [Clang][Sema] Diagnose class member access expressions naming non-existent members of the current instantiation prior to instantiation in the absence of dependent base classes (PR #84050)

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


@@ -990,6 +970,18 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType 
BaseExprType,
const Scope *S,
bool SuppressQualifierCheck,
ActOnMemberAccessExtraArgs *ExtraArgs) {
+  assert(!SS.isInvalid() && "nested-name-specifier cannot be invalid");
+  if (R.wasNotFoundInCurrentInstantiation() ||
+#if 0

sdkrystian wrote:

The inactive branch of the `#if` directive is left over from when 
`LookupMemberExprInRecord` would call `LookupQualified` directly. Since it now 
calls `LookupParsedName`, `R.wasNotFoundInCurrentInstantiation()` will be 
`true` when the _nested-name-specifier_ in the _id-expression_ of the class 
member access expression is dependent, so this check is no longer necessary. 
I'll remove it.

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


[clang] [clang-tools-extra] [Clang][Sema] Fix explicit specializations of member function templates with a deduced return type (PR #86817)

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

sdkrystian wrote:

Ping @erichkeane 

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


[clang] [clang-tools-extra] [Clang][Sema] Fix explicit specializations of member function templates with a deduced return type (PR #86817)

2024-04-02 Thread Krystian Stasiowski via cfe-commits

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

>From e84e4b6fedb5a643082cd38d0e10d910b299f73f Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Wed, 27 Mar 2024 11:23:19 -0400
Subject: [PATCH] [Clang][Sema] Fix explicit specializations of member function
 templates with a deduced return type

---
 .../clang-tidy/infrastructure/diagnostic.cpp  |  4 +-
 clang/docs/ReleaseNotes.rst   |  2 +
 clang/lib/Sema/SemaDecl.cpp   | 46 ---
 .../SemaCXX/deduced-return-type-cxx14.cpp | 18 
 4 files changed, 50 insertions(+), 20 deletions(-)

diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp 
b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
index d0efc5ca763753..57d930b26e64c0 100644
--- a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp
@@ -25,7 +25,7 @@
 // RUN: not clang-tidy -checks='-*,modernize-use-override' 
%T/diagnostics/input.cpp -- -DCOMPILATION_ERROR 2>&1 | FileCheck 
-check-prefix=CHECK6 -implicit-check-not='{{warning:|error:}}' %s
 // RUN: clang-tidy 
-checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %s -- 
-DMACRO_FROM_COMMAND_LINE -std=c++20 | FileCheck -check-prefix=CHECK4 
-implicit-check-not='{{warning:|error:}}' %s
 // RUN: clang-tidy 
-checks='-*,modernize-use-override,clang-diagnostic-macro-redefined,clang-diagnostic-literal-conversion'
 %s -- -DMACRO_FROM_COMMAND_LINE -std=c++20 -Wno-macro-redefined | FileCheck 
--check-prefix=CHECK7 -implicit-check-not='{{warning:|error:}}' %s
-// RUN: not clang-tidy -checks='-*,modernize-use-override' %s -- -std=c++20 
-DPR64602 | FileCheck -check-prefix=CHECK8 
-implicit-check-not='{{warning:|error:}}' %s
+// RUN: clang-tidy -checks='-*,modernize-use-override' %s -- -std=c++20 
-DPR64602
 
 // CHECK1: error: no input files [clang-diagnostic-error]
 // CHECK1: error: no such file or directory: '{{.*}}nonexistent.cpp' 
[clang-diagnostic-error]
@@ -68,6 +68,4 @@ auto S<>::foo(auto)
 {
 return 1;
 }
-// CHECK8: error: conflicting types for 'foo' [clang-diagnostic-error]
-// CHECK8: note: previous declaration is here
 #endif
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b2faab1f1525b2..3a84ff16a1e4d4 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -483,6 +483,8 @@ Bug Fixes to C++ Support
   following the first `::` were ignored).
 - Fix an out-of-bounds crash when checking the validity of template partial 
specializations. (part of #GH86757).
 - Fix an issue caused by not handling invalid cases when substituting into the 
parameter mapping of a constraint. Fixes (#GH86757).
+- Fixed a bug that prevented member function templates of class templates 
declared with a deduced return type
+  from being explicitly specialized for a given implicit instantiation of the 
class template.
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 6ff85c0c5c29da..5c1152896559b5 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -10124,23 +10124,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, 
DeclContext *DC,
 Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_auto_fn_virtual);
 }
 
-if (getLangOpts().CPlusPlus14 &&
-(NewFD->isDependentContext() ||
- (isFriend && CurContext->isDependentContext())) &&
-NewFD->getReturnType()->isUndeducedType()) {
-  // If the function template is referenced directly (for instance, as a
-  // member of the current instantiation), pretend it has a dependent type.
-  // This is not really justified by the standard, but is the only sane
-  // thing to do.
-  // FIXME: For a friend function, we have not marked the function as being
-  // a friend yet, so 'isDependentContext' on the FD doesn't work.
-  const FunctionProtoType *FPT =
-  NewFD->getType()->castAs();
-  QualType Result = SubstAutoTypeDependent(FPT->getReturnType());
-  NewFD->setType(Context.getFunctionType(Result, FPT->getParamTypes(),
- FPT->getExtProtoInfo()));
-}
-
 // C++ [dcl.fct.spec]p3:
 //  The inline specifier shall not appear on a block scope function
 //  declaration.
@@ -12112,6 +12095,35 @@ bool Sema::CheckFunctionDeclaration(Scope *S, 
FunctionDecl *NewFD,
 
   CheckConstPureAttributesUsage(*this, NewFD);
 
+  // C++ [dcl.spec.auto.general]p12:
+  //   Return type deduction for a templated function with a placeholder in its
+  //   declared type occurs when the definition is instantiated even if the
+  //   function body contains a return statement with a non-type-dependent
+  //   operand.
+  //
+  // C++ [temp.dep.expr]p3:
+  //   An id-expression is type-dependent if it is a template-id that is not a
+

[clang] [clang-tools-extra] [Clang][Sema] Fix explicit specializations of member function templates with a deduced return type (PR #86817)

2024-04-02 Thread Krystian Stasiowski via cfe-commits

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


[clang] [Clang][AST][NFC] MemberExpr stores NestedNameSpecifierLoc and DeclAccessPair separately (PR #86678)

2024-04-02 Thread Krystian Stasiowski via cfe-commits

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

>From d257fa46da4f84dfcedfa8d25267f3326996d72e Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 26 Mar 2024 10:04:44 -0400
Subject: [PATCH] [Clang][AST][NFC] MemberExpr stores NestedNameSpecifierLoc
 and DeclAccessPair separately

---
 clang/include/clang/AST/Expr.h| 37 
 clang/include/clang/AST/Stmt.h| 10 +++---
 clang/lib/AST/Expr.cpp| 41 +++
 clang/lib/Serialization/ASTReaderStmt.cpp | 26 +-
 clang/lib/Serialization/ASTWriterStmt.cpp | 11 +++---
 5 files changed, 53 insertions(+), 72 deletions(-)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 6e153ebe024b42..e43098e144c88f 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3163,23 +3163,12 @@ class CallExpr : public Expr {
   }
 };
 
-/// Extra data stored in some MemberExpr objects.
-struct MemberExprNameQualifier {
-  /// The nested-name-specifier that qualifies the name, including
-  /// source-location information.
-  NestedNameSpecifierLoc QualifierLoc;
-
-  /// The DeclAccessPair through which the MemberDecl was found due to
-  /// name qualifiers.
-  DeclAccessPair FoundDecl;
-};
-
 /// MemberExpr - [C99 6.5.2.3] Structure and Union Members.  X->F and X.F.
 ///
 class MemberExpr final
 : public Expr,
-  private llvm::TrailingObjects {
   friend class ASTReader;
   friend class ASTStmtReader;
@@ -3201,17 +3190,19 @@ class MemberExpr final
   /// MemberLoc - This is the location of the member name.
   SourceLocation MemberLoc;
 
-  size_t numTrailingObjects(OverloadToken) const {
-return hasQualifierOrFoundDecl();
+  size_t numTrailingObjects(OverloadToken) const {
+return hasQualifier();
+  }
+
+  size_t numTrailingObjects(OverloadToken) const {
+return hasFoundDecl();
   }
 
   size_t numTrailingObjects(OverloadToken) const {
 return hasTemplateKWAndArgsInfo();
   }
 
-  bool hasQualifierOrFoundDecl() const {
-return MemberExprBits.HasQualifierOrFoundDecl;
-  }
+  bool hasFoundDecl() const { return MemberExprBits.HasFoundDecl; }
 
   bool hasTemplateKWAndArgsInfo() const {
 return MemberExprBits.HasTemplateKWAndArgsInfo;
@@ -3264,24 +3255,24 @@ class MemberExpr final
 
   /// Retrieves the declaration found by lookup.
   DeclAccessPair getFoundDecl() const {
-if (!hasQualifierOrFoundDecl())
+if (!hasFoundDecl())
   return DeclAccessPair::make(getMemberDecl(),
   getMemberDecl()->getAccess());
-return getTrailingObjects()->FoundDecl;
+return *getTrailingObjects();
   }
 
   /// Determines whether this member expression actually had
   /// a C++ nested-name-specifier prior to the name of the member, e.g.,
   /// x->Base::foo.
-  bool hasQualifier() const { return getQualifier() != nullptr; }
+  bool hasQualifier() const { return MemberExprBits.HasQualifier; }
 
   /// If the member name was qualified, retrieves the
   /// nested-name-specifier that precedes the member name, with source-location
   /// information.
   NestedNameSpecifierLoc getQualifierLoc() const {
-if (!hasQualifierOrFoundDecl())
+if (!hasQualifier())
   return NestedNameSpecifierLoc();
-return getTrailingObjects()->QualifierLoc;
+return *getTrailingObjects();
   }
 
   /// If the member name was qualified, retrieves the
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 55eca4007d17ea..8892518d58e853 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -583,11 +583,13 @@ class alignas(void *) Stmt {
 unsigned IsArrow : 1;
 
 /// True if this member expression used a nested-name-specifier to
-/// refer to the member, e.g., "x->Base::f", or found its member via
-/// a using declaration.  When true, a MemberExprNameQualifier
-/// structure is allocated immediately after the MemberExpr.
+/// refer to the member, e.g., "x->Base::f".
 LLVM_PREFERRED_TYPE(bool)
-unsigned HasQualifierOrFoundDecl : 1;
+unsigned HasQualifier : 1;
+
+// True if this member expression found its member via a using declaration.
+LLVM_PREFERRED_TYPE(bool)
+unsigned HasFoundDecl : 1;
 
 /// True if this member expression specified a template keyword
 /// and/or a template argument list explicitly, e.g., x->f,
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 6221ebd5c9b4e9..997af9ddd4f306 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1721,7 +1721,8 @@ MemberExpr::MemberExpr(Expr *Base, bool IsArrow, 
SourceLocation OperatorLoc,
   assert(!NameInfo.getName() ||
  MemberDecl->getDeclName() == NameInfo.getName());
   MemberExprBits.IsArrow = IsArrow;
-  MemberExprBits.HasQualifierOrFoundDecl = false;
+  MemberExprBits.HasQualifier = false;
+  MemberExprBits.HasFoundDecl = false;
   Me

[clang] [Clang][AST][NFC] Move template argument dependence computations for MemberExpr to computeDependence (PR #86682)

2024-04-02 Thread Krystian Stasiowski via cfe-commits

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

>From d257fa46da4f84dfcedfa8d25267f3326996d72e Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 26 Mar 2024 10:04:44 -0400
Subject: [PATCH 1/2] [Clang][AST][NFC] MemberExpr stores
 NestedNameSpecifierLoc and DeclAccessPair separately

---
 clang/include/clang/AST/Expr.h| 37 
 clang/include/clang/AST/Stmt.h| 10 +++---
 clang/lib/AST/Expr.cpp| 41 +++
 clang/lib/Serialization/ASTReaderStmt.cpp | 26 +-
 clang/lib/Serialization/ASTWriterStmt.cpp | 11 +++---
 5 files changed, 53 insertions(+), 72 deletions(-)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 6e153ebe024b42..e43098e144c88f 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3163,23 +3163,12 @@ class CallExpr : public Expr {
   }
 };
 
-/// Extra data stored in some MemberExpr objects.
-struct MemberExprNameQualifier {
-  /// The nested-name-specifier that qualifies the name, including
-  /// source-location information.
-  NestedNameSpecifierLoc QualifierLoc;
-
-  /// The DeclAccessPair through which the MemberDecl was found due to
-  /// name qualifiers.
-  DeclAccessPair FoundDecl;
-};
-
 /// MemberExpr - [C99 6.5.2.3] Structure and Union Members.  X->F and X.F.
 ///
 class MemberExpr final
 : public Expr,
-  private llvm::TrailingObjects {
   friend class ASTReader;
   friend class ASTStmtReader;
@@ -3201,17 +3190,19 @@ class MemberExpr final
   /// MemberLoc - This is the location of the member name.
   SourceLocation MemberLoc;
 
-  size_t numTrailingObjects(OverloadToken) const {
-return hasQualifierOrFoundDecl();
+  size_t numTrailingObjects(OverloadToken) const {
+return hasQualifier();
+  }
+
+  size_t numTrailingObjects(OverloadToken) const {
+return hasFoundDecl();
   }
 
   size_t numTrailingObjects(OverloadToken) const {
 return hasTemplateKWAndArgsInfo();
   }
 
-  bool hasQualifierOrFoundDecl() const {
-return MemberExprBits.HasQualifierOrFoundDecl;
-  }
+  bool hasFoundDecl() const { return MemberExprBits.HasFoundDecl; }
 
   bool hasTemplateKWAndArgsInfo() const {
 return MemberExprBits.HasTemplateKWAndArgsInfo;
@@ -3264,24 +3255,24 @@ class MemberExpr final
 
   /// Retrieves the declaration found by lookup.
   DeclAccessPair getFoundDecl() const {
-if (!hasQualifierOrFoundDecl())
+if (!hasFoundDecl())
   return DeclAccessPair::make(getMemberDecl(),
   getMemberDecl()->getAccess());
-return getTrailingObjects()->FoundDecl;
+return *getTrailingObjects();
   }
 
   /// Determines whether this member expression actually had
   /// a C++ nested-name-specifier prior to the name of the member, e.g.,
   /// x->Base::foo.
-  bool hasQualifier() const { return getQualifier() != nullptr; }
+  bool hasQualifier() const { return MemberExprBits.HasQualifier; }
 
   /// If the member name was qualified, retrieves the
   /// nested-name-specifier that precedes the member name, with source-location
   /// information.
   NestedNameSpecifierLoc getQualifierLoc() const {
-if (!hasQualifierOrFoundDecl())
+if (!hasQualifier())
   return NestedNameSpecifierLoc();
-return getTrailingObjects()->QualifierLoc;
+return *getTrailingObjects();
   }
 
   /// If the member name was qualified, retrieves the
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 55eca4007d17ea..8892518d58e853 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -583,11 +583,13 @@ class alignas(void *) Stmt {
 unsigned IsArrow : 1;
 
 /// True if this member expression used a nested-name-specifier to
-/// refer to the member, e.g., "x->Base::f", or found its member via
-/// a using declaration.  When true, a MemberExprNameQualifier
-/// structure is allocated immediately after the MemberExpr.
+/// refer to the member, e.g., "x->Base::f".
 LLVM_PREFERRED_TYPE(bool)
-unsigned HasQualifierOrFoundDecl : 1;
+unsigned HasQualifier : 1;
+
+// True if this member expression found its member via a using declaration.
+LLVM_PREFERRED_TYPE(bool)
+unsigned HasFoundDecl : 1;
 
 /// True if this member expression specified a template keyword
 /// and/or a template argument list explicitly, e.g., x->f,
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 6221ebd5c9b4e9..997af9ddd4f306 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1721,7 +1721,8 @@ MemberExpr::MemberExpr(Expr *Base, bool IsArrow, 
SourceLocation OperatorLoc,
   assert(!NameInfo.getName() ||
  MemberDecl->getDeclName() == NameInfo.getName());
   MemberExprBits.IsArrow = IsArrow;
-  MemberExprBits.HasQualifierOrFoundDecl = false;
+  MemberExprBits.HasQualifier = false;
+  MemberExprBits.HasFoundDecl = false;
 

[clang] [Clang][AST][NFC] Move template argument dependence computations for MemberExpr to computeDependence (PR #86682)

2024-04-02 Thread Krystian Stasiowski via cfe-commits


@@ -583,11 +583,14 @@ class alignas(void *) Stmt {
 unsigned IsArrow : 1;
 
 /// True if this member expression used a nested-name-specifier to
-/// refer to the member, e.g., "x->Base::f", or found its member via
-/// a using declaration.  When true, a MemberExprNameQualifier
-/// structure is allocated immediately after the MemberExpr.
+/// refer to the member, e.g., "x->Base::f".
 LLVM_PREFERRED_TYPE(bool)
-unsigned HasQualifierOrFoundDecl : 1;
+unsigned HasQualifier : 1;
+
+// True if this member expression found its member via

sdkrystian wrote:

Could have been me? I made the comment a single line and clang-format seems 
happy.

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


[clang] [Clang][AST][NFC] Move template argument dependence computations for MemberExpr to computeDependence (PR #86682)

2024-04-02 Thread Krystian Stasiowski via cfe-commits

sdkrystian wrote:

@erichkeane Requested changes applied... should I wait for other reviews on the 
other PR (#86678), or do you think I should go ahead and merge #86678 and then 
this one?

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


[clang] [Clang][AST][NFC] Move template argument dependence computations for MemberExpr to computeDependence (PR #86682)

2024-04-02 Thread Krystian Stasiowski via cfe-commits

sdkrystian wrote:

@erichkeane Just merging this PR will result in the commits being squashed into 
a single commit... is that alright?

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


[clang] [Clang][AST][NFC] Move template argument dependence computations for MemberExpr to computeDependence (PR #86682)

2024-04-02 Thread Krystian Stasiowski via cfe-commits

sdkrystian wrote:

Thanks! I'll add a comment on the other PR saying the commit was reviewed here 
& then I'll merge

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


[clang] [Clang][AST][NFC] MemberExpr stores NestedNameSpecifierLoc and DeclAccessPair separately (PR #86678)

2024-04-02 Thread Krystian Stasiowski via cfe-commits

sdkrystian wrote:

Changes were reviewed in the review of #86682

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


[clang] [Clang][AST][NFC] MemberExpr stores NestedNameSpecifierLoc and DeclAccessPair separately (PR #86678)

2024-04-02 Thread Krystian Stasiowski via cfe-commits

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


[clang] [Clang][AST][NFC] Move template argument dependence computations for MemberExpr to computeDependence (PR #86682)

2024-04-02 Thread Krystian Stasiowski via cfe-commits

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

>From 125b91778874e9f61e178ea4dd2efaf592ea84bb Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 26 Mar 2024 11:27:28 -0400
Subject: [PATCH] [Clang][AST][NFC] Move template argument dependence
 computations for MemberExpr to computeDependence

---
 clang/include/clang/AST/Expr.h  |  8 ++--
 clang/lib/AST/ComputeDependence.cpp |  4 +-
 clang/lib/AST/Expr.cpp  | 64 +
 3 files changed, 37 insertions(+), 39 deletions(-)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index e43098e144c88f..2bfefeabc348be 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3209,9 +3209,11 @@ class MemberExpr final
   }
 
   MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc,
- ValueDecl *MemberDecl, const DeclarationNameInfo &NameInfo,
- QualType T, ExprValueKind VK, ExprObjectKind OK,
- NonOdrUseReason NOUR);
+ NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
+ ValueDecl *MemberDecl, DeclAccessPair FoundDecl,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs, QualType T,
+ ExprValueKind VK, ExprObjectKind OK, NonOdrUseReason NOUR);
   MemberExpr(EmptyShell Empty)
   : Expr(MemberExprClass, Empty), Base(), MemberDecl() {}
 
diff --git a/clang/lib/AST/ComputeDependence.cpp 
b/clang/lib/AST/ComputeDependence.cpp
index 9d3856b8f7e08a..86b77b49a0fbc4 100644
--- a/clang/lib/AST/ComputeDependence.cpp
+++ b/clang/lib/AST/ComputeDependence.cpp
@@ -654,6 +654,9 @@ ExprDependence clang::computeDependence(MemberExpr *E) {
 D |= toExprDependence(NNS->getDependence() &
   ~NestedNameSpecifierDependence::Dependent);
 
+  for (const auto &A : E->template_arguments())
+D |= toExprDependence(A.getArgument().getDependence());
+
   auto *MemberDecl = E->getMemberDecl();
   if (FieldDecl *FD = dyn_cast(MemberDecl)) {
 DeclContext *DC = MemberDecl->getDeclContext();
@@ -670,7 +673,6 @@ ExprDependence clang::computeDependence(MemberExpr *E) {
   D |= ExprDependence::Type;
 }
   }
-  // FIXME: move remaining dependence computation from MemberExpr::Create()
   return D;
 }
 
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index a85755efeb8b8e..07c9f287dd0767 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1712,8 +1712,11 @@ UnaryExprOrTypeTraitExpr::UnaryExprOrTypeTraitExpr(
 }
 
 MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc,
-   ValueDecl *MemberDecl,
-   const DeclarationNameInfo &NameInfo, QualType T,
+   NestedNameSpecifierLoc QualifierLoc,
+   SourceLocation TemplateKWLoc, ValueDecl *MemberDecl,
+   DeclAccessPair FoundDecl,
+   const DeclarationNameInfo &NameInfo,
+   const TemplateArgumentListInfo *TemplateArgs, QualType 
T,
ExprValueKind VK, ExprObjectKind OK,
NonOdrUseReason NOUR)
 : Expr(MemberExprClass, T, VK, OK), Base(Base), MemberDecl(MemberDecl),
@@ -1721,12 +1724,30 @@ MemberExpr::MemberExpr(Expr *Base, bool IsArrow, 
SourceLocation OperatorLoc,
   assert(!NameInfo.getName() ||
  MemberDecl->getDeclName() == NameInfo.getName());
   MemberExprBits.IsArrow = IsArrow;
-  MemberExprBits.HasQualifier = false;
-  MemberExprBits.HasFoundDecl = false;
-  MemberExprBits.HasTemplateKWAndArgsInfo = false;
+  MemberExprBits.HasQualifier = QualifierLoc.hasQualifier();
+  MemberExprBits.HasFoundDecl =
+  FoundDecl.getDecl() != MemberDecl ||
+  FoundDecl.getAccess() != MemberDecl->getAccess();
+  MemberExprBits.HasTemplateKWAndArgsInfo =
+  TemplateArgs || TemplateKWLoc.isValid();
   MemberExprBits.HadMultipleCandidates = false;
   MemberExprBits.NonOdrUseReason = NOUR;
   MemberExprBits.OperatorLoc = OperatorLoc;
+
+  if (hasQualifier())
+new (getTrailingObjects())
+NestedNameSpecifierLoc(QualifierLoc);
+  if (hasFoundDecl())
+*getTrailingObjects() = FoundDecl;
+  if (TemplateArgs) {
+auto Deps = TemplateArgumentDependence::None;
+getTrailingObjects()->initializeFrom(
+TemplateKWLoc, *TemplateArgs, 
getTrailingObjects(),
+Deps);
+  } else if (TemplateKWLoc.isValid()) {
+getTrailingObjects()->initializeFrom(
+TemplateKWLoc);
+  }
   setDependence(computeDependence(this));
 }
 
@@ -1747,36 +1768,9 @@ MemberExpr *MemberExpr::Create(
   TemplateArgs ? TemplateArgs->size() : 0);
 
   void *Mem = C.Allocate(Size, alignof(MemberExpr));
-  MemberExpr *E = new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, MemberDecl,
-   NameInfo, T, VK, OK, NOUR);
-
-  E->MemberExprBits.HasQualifie

[clang] [Clang][AST][NFC] Move template argument dependence computations for MemberExpr to computeDependence (PR #86682)

2024-04-02 Thread Krystian Stasiowski via cfe-commits

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


[clang] [Clang][Sema] Diagnose declarative nested-name-specifiers naming alias templates (PR #80842)

2024-02-06 Thread Krystian Stasiowski via cfe-commits

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

According to [[expr.prim.id.qual] 
p3](http://eel.is/c++draft/expr.prim.id.qual#3):
> The _nested-name-specifier_ `​:`:​ nominates the global namespace. A 
> _nested-name-specifier_ with a _computed-type-specifier_ nominates the type 
> denoted by the _computed-type-specifier_, which shall be a class or 
> enumeration type. **If a _nested-name-specifier_ `N` is declarative and has a 
> _simple-template-id_ with a template argument list `A` that involves a 
> template parameter, let `T` be the template nominated by `N` without `A`. `T` 
> shall be a class template.**

Meaning, the out-of-line definition of `A::f` in the following example is 
ill-formed:
```cpp
template
struct A 
{ 
void f(); 
};

template
using B = A;

template
void B::f() { } // error: a declarative nested name specifier cannot name a 
type alias template
```

This patch diagnoses such cases as an extension (in group 
`alias-template-in-declaration-name`).


>From 6f701b092a99d49a56d661255e76fa1b1d3a4601 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 6 Feb 2024 09:14:42 -0500
Subject: [PATCH] [Clang][Sema] Diagnose declarative nested-name-specifiers
 naming alias templates

---
 .../clang/Basic/DiagnosticSemaKinds.td|  3 ++
 clang/lib/Sema/SemaDecl.cpp   | 36 +--
 .../expr.prim.id/expr.prim.id.qual/p3.cpp | 29 +++
 .../temp.res/temp.dep/temp.dep.type/p1.cpp|  2 +-
 4 files changed, 59 insertions(+), 11 deletions(-)
 create mode 100644 
clang/test/CXX/expr/expr.prim/expr.prim.id/expr.prim.id.qual/p3.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f76e7a3392183e..d02fddd0693413 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8250,6 +8250,9 @@ def err_not_tag_in_scope : Error<
 def ext_template_after_declarative_nns : ExtWarn<
 "'template' cannot be used after a declarative nested name specifier">,
 InGroup>;
+def ext_alias_template_in_declarative_nns : ExtWarn<
+  "a declarative nested name specifier cannot name an alias template">,
+  InGroup>;
 
 def err_no_typeid_with_fno_rtti : Error<
   "use of typeid requires -frtti">;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 481d952d2389bb..464f3738b0ba56 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -6207,6 +6207,8 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, 
DeclContext *DC,
 SourceLocation Loc,
 TemplateIdAnnotation *TemplateId,
 bool IsMemberSpecialization) {
+  assert(SS.isValid() && "diagnoseQualifiedDeclaration called for declaration "
+ "without nested-name-specifier");
   DeclContext *Cur = CurContext;
   while (isa(Cur) || isa(Cur))
 Cur = Cur->getParent();
@@ -6295,22 +6297,36 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec 
&SS, DeclContext *DC,
 << FixItHint::CreateRemoval(TemplateId->TemplateKWLoc);
 
   NestedNameSpecifierLoc SpecLoc(SS.getScopeRep(), SS.location_data());
-  while (SpecLoc.getPrefix()) {
+  do {
 if (SpecLoc.getNestedNameSpecifier()->getKind() ==
 NestedNameSpecifier::TypeSpecWithTemplate)
   Diag(Loc, diag::ext_template_after_declarative_nns)
   << FixItHint::CreateRemoval(
  SpecLoc.getTypeLoc().getTemplateKeywordLoc());
 
-SpecLoc = SpecLoc.getPrefix();
-  }
-  // C++11 [dcl.meaning]p1:
-  //   [...] "The nested-name-specifier of the qualified declarator-id shall
-  //   not begin with a decltype-specifer"
-  if (isa_and_nonnull(
-  SpecLoc.getNestedNameSpecifier()->getAsType()))
-Diag(Loc, diag::err_decltype_in_declarator)
-  << SpecLoc.getTypeLoc().getSourceRange();
+if (const Type *T = SpecLoc.getNestedNameSpecifier()->getAsType()) {
+  if (const auto *TST = T->getAsAdjusted()) {
+// C++23 [expr.prim.id.qual]p3:
+//   [...] If a nested-name-specifier N is declarative and has a
+//   simple-template-id with a template argument list A that involves a
+//   template parameter, let T be the template nominated by N without 
A.
+//   T shall be a class template.
+if (TST->isDependentType() && TST->isTypeAlias())
+  Diag(Loc, diag::ext_alias_template_in_declarative_nns)
+  << SpecLoc.getLocalSourceRange();
+  } else if (T->isDecltypeType()) {
+// C++23 [expr.prim.id.qual]p2:
+//   [...] A declarative nested-name-specifier shall not have a
+//   decltype-specifier.
+//
+// FIXME: This wording appears to be defective, as it does not
+// forbid declarative nested-name-specifiers that begin with a
+// pack-index-speci

[clang] [Clang][Sema] Diagnose declarative nested-name-specifiers naming alias templates (PR #80842)

2024-02-06 Thread Krystian Stasiowski via cfe-commits

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


[clang] [Clang][Sema] Diagnose declarative nested-name-specifiers naming alias templates (PR #80842)

2024-02-06 Thread Krystian Stasiowski via cfe-commits


@@ -6295,22 +6297,36 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec 
&SS, DeclContext *DC,
 << FixItHint::CreateRemoval(TemplateId->TemplateKWLoc);
 
   NestedNameSpecifierLoc SpecLoc(SS.getScopeRep(), SS.location_data());
-  while (SpecLoc.getPrefix()) {
+  do {
 if (SpecLoc.getNestedNameSpecifier()->getKind() ==
 NestedNameSpecifier::TypeSpecWithTemplate)
   Diag(Loc, diag::ext_template_after_declarative_nns)
   << FixItHint::CreateRemoval(
  SpecLoc.getTypeLoc().getTemplateKeywordLoc());
 
-SpecLoc = SpecLoc.getPrefix();
-  }
-  // C++11 [dcl.meaning]p1:
-  //   [...] "The nested-name-specifier of the qualified declarator-id shall
-  //   not begin with a decltype-specifer"
-  if (isa_and_nonnull(
-  SpecLoc.getNestedNameSpecifier()->getAsType()))
-Diag(Loc, diag::err_decltype_in_declarator)
-  << SpecLoc.getTypeLoc().getSourceRange();
+if (const Type *T = SpecLoc.getNestedNameSpecifier()->getAsType()) {
+  if (const auto *TST = T->getAsAdjusted()) {
+// C++23 [expr.prim.id.qual]p3:
+//   [...] If a nested-name-specifier N is declarative and has a
+//   simple-template-id with a template argument list A that involves a
+//   template parameter, let T be the template nominated by N without 
A.
+//   T shall be a class template.
+if (TST->isDependentType() && TST->isTypeAlias())
+  Diag(Loc, diag::ext_alias_template_in_declarative_nns)
+  << SpecLoc.getLocalSourceRange();
+  } else if (T->isDecltypeType()) {
+// C++23 [expr.prim.id.qual]p2:
+//   [...] A declarative nested-name-specifier shall not have a
+//   decltype-specifier.
+//
+// FIXME: This wording appears to be defective, as it does not

sdkrystian wrote:

@erichkeane Yup, I am drafting wording for this as we speak (as well some other 
issues relating to declarative nested-name-specifiers)

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


[clang] [Clang][Sema] Diagnose declarative nested-name-specifiers naming alias templates (PR #80842)

2024-02-06 Thread Krystian Stasiowski via cfe-commits

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

>From 75734c9cf5c9467130fdc08efa64eb624e659879 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 6 Feb 2024 09:14:42 -0500
Subject: [PATCH] [Clang][Sema] Diagnose declarative nested-name-specifiers
 naming alias templates

---
 .../clang/Basic/DiagnosticSemaKinds.td|  3 ++
 clang/lib/Sema/SemaDecl.cpp   | 36 +--
 .../expr.prim.id/expr.prim.id.qual/p3.cpp | 29 +++
 .../temp.res/temp.dep/temp.dep.type/p1.cpp|  2 +-
 4 files changed, 59 insertions(+), 11 deletions(-)
 create mode 100644 
clang/test/CXX/expr/expr.prim/expr.prim.id/expr.prim.id.qual/p3.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f76e7a3392183e..d02fddd0693413 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8250,6 +8250,9 @@ def err_not_tag_in_scope : Error<
 def ext_template_after_declarative_nns : ExtWarn<
 "'template' cannot be used after a declarative nested name specifier">,
 InGroup>;
+def ext_alias_template_in_declarative_nns : ExtWarn<
+  "a declarative nested name specifier cannot name an alias template">,
+  InGroup>;
 
 def err_no_typeid_with_fno_rtti : Error<
   "use of typeid requires -frtti">;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 481d952d2389bb..f11fc814d73a85 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -6207,6 +6207,8 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, 
DeclContext *DC,
 SourceLocation Loc,
 TemplateIdAnnotation *TemplateId,
 bool IsMemberSpecialization) {
+  assert(SS.isValid() && "diagnoseQualifiedDeclaration called for declaration "
+ "without nested-name-specifier");
   DeclContext *Cur = CurContext;
   while (isa(Cur) || isa(Cur))
 Cur = Cur->getParent();
@@ -6295,22 +6297,36 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec 
&SS, DeclContext *DC,
 << FixItHint::CreateRemoval(TemplateId->TemplateKWLoc);
 
   NestedNameSpecifierLoc SpecLoc(SS.getScopeRep(), SS.location_data());
-  while (SpecLoc.getPrefix()) {
+  do {
 if (SpecLoc.getNestedNameSpecifier()->getKind() ==
 NestedNameSpecifier::TypeSpecWithTemplate)
   Diag(Loc, diag::ext_template_after_declarative_nns)
   << FixItHint::CreateRemoval(
  SpecLoc.getTypeLoc().getTemplateKeywordLoc());
 
-SpecLoc = SpecLoc.getPrefix();
-  }
-  // C++11 [dcl.meaning]p1:
-  //   [...] "The nested-name-specifier of the qualified declarator-id shall
-  //   not begin with a decltype-specifer"
-  if (isa_and_nonnull(
-  SpecLoc.getNestedNameSpecifier()->getAsType()))
-Diag(Loc, diag::err_decltype_in_declarator)
-  << SpecLoc.getTypeLoc().getSourceRange();
+if (const Type *T = SpecLoc.getNestedNameSpecifier()->getAsType()) {
+  if (const auto *TST = T->getAsAdjusted()) {
+// C++23 [expr.prim.id.qual]p3:
+//   [...] If a nested-name-specifier N is declarative and has a
+//   simple-template-id with a template argument list A that involves a
+//   template parameter, let T be the template nominated by N without 
A.
+//   T shall be a class template.
+if (TST->isDependentType() && TST->isTypeAlias())
+  Diag(Loc, diag::ext_alias_template_in_declarative_nns)
+  << SpecLoc.getLocalSourceRange();
+  } else if (T->isDecltypeType()) {
+// C++23 [expr.prim.id.qual]p2:
+//   [...] A declarative nested-name-specifier shall not have a
+//   decltype-specifier.
+//
+// FIXME: This wording appears to be defective as it does not
+// forbid declarative nested-name-specifiers that begin with a
+// pack-index-specifier.
+Diag(Loc, diag::err_decltype_in_declarator)
+<< SpecLoc.getTypeLoc().getSourceRange();
+  }
+}
+  } while ((SpecLoc = SpecLoc.getPrefix()));
 
   return false;
 }
diff --git 
a/clang/test/CXX/expr/expr.prim/expr.prim.id/expr.prim.id.qual/p3.cpp 
b/clang/test/CXX/expr/expr.prim/expr.prim.id/expr.prim.id.qual/p3.cpp
new file mode 100644
index 00..c73ffa55a26a31
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.id/expr.prim.id.qual/p3.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -verify %s
+
+template
+struct A {
+  void f();
+};
+
+template
+using B = A;
+
+template
+void B::f() { } // expected-warning {{a declarative nested name specifier 
cannot name an alias template}}
+
+template<>
+void B::f() { } // ok, template argument list of simple-template-id 
doesn't involve template parameters
+
+namespace N {
+
+  template
+  struct D {
+void f();
+  };
+
+  template
+  using E =

[clang] [Clang][Sema] Diagnose declarative nested-name-specifiers naming alias templates (PR #80842)

2024-02-06 Thread Krystian Stasiowski via cfe-commits


@@ -6295,22 +6297,36 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec 
&SS, DeclContext *DC,
 << FixItHint::CreateRemoval(TemplateId->TemplateKWLoc);
 
   NestedNameSpecifierLoc SpecLoc(SS.getScopeRep(), SS.location_data());
-  while (SpecLoc.getPrefix()) {
+  do {
 if (SpecLoc.getNestedNameSpecifier()->getKind() ==
 NestedNameSpecifier::TypeSpecWithTemplate)
   Diag(Loc, diag::ext_template_after_declarative_nns)
   << FixItHint::CreateRemoval(
  SpecLoc.getTypeLoc().getTemplateKeywordLoc());
 
-SpecLoc = SpecLoc.getPrefix();
-  }
-  // C++11 [dcl.meaning]p1:
-  //   [...] "The nested-name-specifier of the qualified declarator-id shall
-  //   not begin with a decltype-specifer"
-  if (isa_and_nonnull(
-  SpecLoc.getNestedNameSpecifier()->getAsType()))
-Diag(Loc, diag::err_decltype_in_declarator)
-  << SpecLoc.getTypeLoc().getSourceRange();
+if (const Type *T = SpecLoc.getNestedNameSpecifier()->getAsType()) {
+  if (const auto *TST = T->getAsAdjusted()) {
+// C++23 [expr.prim.id.qual]p3:
+//   [...] If a nested-name-specifier N is declarative and has a
+//   simple-template-id with a template argument list A that involves a
+//   template parameter, let T be the template nominated by N without 
A.
+//   T shall be a class template.
+if (TST->isDependentType() && TST->isTypeAlias())
+  Diag(Loc, diag::ext_alias_template_in_declarative_nns)
+  << SpecLoc.getLocalSourceRange();
+  } else if (T->isDecltypeType()) {
+// C++23 [expr.prim.id.qual]p2:
+//   [...] A declarative nested-name-specifier shall not have a
+//   decltype-specifier.
+//
+// FIXME: This wording appears to be defective, as it does not

sdkrystian wrote:

https://github.com/cplusplus/CWG/issues/499


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


[clang] [Clang][Sema] Diagnose declarative nested-name-specifiers naming alias templates (PR #80842)

2024-02-06 Thread Krystian Stasiowski via cfe-commits

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

>From 13abf4ca1003f4cc04926881ce74c5f4818a761c Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 6 Feb 2024 09:14:42 -0500
Subject: [PATCH] [Clang][Sema] Diagnose declarative nested-name-specifiers
 naming alias templates

---
 .../clang/Basic/DiagnosticSemaKinds.td|  3 ++
 clang/lib/Sema/SemaDecl.cpp   | 36 +--
 .../expr.prim.id/expr.prim.id.qual/p3.cpp | 29 +++
 .../temp.res/temp.dep/temp.dep.type/p1.cpp|  2 +-
 4 files changed, 59 insertions(+), 11 deletions(-)
 create mode 100644 
clang/test/CXX/expr/expr.prim/expr.prim.id/expr.prim.id.qual/p3.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f76e7a3392183e..d02fddd0693413 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8250,6 +8250,9 @@ def err_not_tag_in_scope : Error<
 def ext_template_after_declarative_nns : ExtWarn<
 "'template' cannot be used after a declarative nested name specifier">,
 InGroup>;
+def ext_alias_template_in_declarative_nns : ExtWarn<
+  "a declarative nested name specifier cannot name an alias template">,
+  InGroup>;
 
 def err_no_typeid_with_fno_rtti : Error<
   "use of typeid requires -frtti">;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 481d952d2389bb..9d4f757caf9ca3 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -6207,6 +6207,8 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, 
DeclContext *DC,
 SourceLocation Loc,
 TemplateIdAnnotation *TemplateId,
 bool IsMemberSpecialization) {
+  assert(SS.isValid() && "diagnoseQualifiedDeclaration called for declaration "
+ "without nested-name-specifier");
   DeclContext *Cur = CurContext;
   while (isa(Cur) || isa(Cur))
 Cur = Cur->getParent();
@@ -6295,22 +6297,36 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec 
&SS, DeclContext *DC,
 << FixItHint::CreateRemoval(TemplateId->TemplateKWLoc);
 
   NestedNameSpecifierLoc SpecLoc(SS.getScopeRep(), SS.location_data());
-  while (SpecLoc.getPrefix()) {
+  do {
 if (SpecLoc.getNestedNameSpecifier()->getKind() ==
 NestedNameSpecifier::TypeSpecWithTemplate)
   Diag(Loc, diag::ext_template_after_declarative_nns)
   << FixItHint::CreateRemoval(
  SpecLoc.getTypeLoc().getTemplateKeywordLoc());
 
-SpecLoc = SpecLoc.getPrefix();
-  }
-  // C++11 [dcl.meaning]p1:
-  //   [...] "The nested-name-specifier of the qualified declarator-id shall
-  //   not begin with a decltype-specifer"
-  if (isa_and_nonnull(
-  SpecLoc.getNestedNameSpecifier()->getAsType()))
-Diag(Loc, diag::err_decltype_in_declarator)
-  << SpecLoc.getTypeLoc().getSourceRange();
+if (const Type *T = SpecLoc.getNestedNameSpecifier()->getAsType()) {
+  if (const auto *TST = T->getAsAdjusted()) {
+// C++23 [expr.prim.id.qual]p3:
+//   [...] If a nested-name-specifier N is declarative and has a
+//   simple-template-id with a template argument list A that involves a
+//   template parameter, let T be the template nominated by N without 
A.
+//   T shall be a class template.
+if (TST->isDependentType() && TST->isTypeAlias())
+  Diag(Loc, diag::ext_alias_template_in_declarative_nns)
+  << SpecLoc.getLocalSourceRange();
+  } else if (T->isDecltypeType()) {
+// C++23 [expr.prim.id.qual]p2:
+//   [...] A declarative nested-name-specifier shall not have a
+//   decltype-specifier.
+//
+// FIXME: This wording appears to be defective as it does not forbid
+// declarative nested-name-specifiers with pack-index-specifiers.
+// See https://github.com/cplusplus/CWG/issues/499.
+Diag(Loc, diag::err_decltype_in_declarator)
+<< SpecLoc.getTypeLoc().getSourceRange();
+  }
+}
+  } while ((SpecLoc = SpecLoc.getPrefix()));
 
   return false;
 }
diff --git 
a/clang/test/CXX/expr/expr.prim/expr.prim.id/expr.prim.id.qual/p3.cpp 
b/clang/test/CXX/expr/expr.prim/expr.prim.id/expr.prim.id.qual/p3.cpp
new file mode 100644
index 00..c73ffa55a26a31
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.id/expr.prim.id.qual/p3.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -verify %s
+
+template
+struct A {
+  void f();
+};
+
+template
+using B = A;
+
+template
+void B::f() { } // expected-warning {{a declarative nested name specifier 
cannot name an alias template}}
+
+template<>
+void B::f() { } // ok, template argument list of simple-template-id 
doesn't involve template parameters
+
+namespace N {
+
+  template
+  struct D {
+void 

[clang] [Clang][Sema] Abbreviated function templates do not append invented parameters to empty template parameter lists (PR #80864)

2024-02-06 Thread Krystian Stasiowski via cfe-commits

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

According to [[dcl.fct] p23](http://eel.is/c++draft/dcl.fct#23):
> An abbreviated function template can have a _template-head_. The invented 
> _template-parameters_ are appended to the _template-parameter-list_ after the 
> explicitly declared _template-parameters_.

`template<>` is not a _template-head_ -- a _template-head_ must have at least 
one _template-parameter_. This patch corrects our current behavior of appending 
the invented template parameters to the innermost template parameter list, 
regardless of whether it is empty. Example:
```cpp
template
struct A 
{ 
void f(auto); 
};

template<>
void A::f(auto); // ok

template<>
template<> // warning: extraneous template parameter list in template 
specialization
void A::f(auto);
```


>From 570e25f19b428fb7d2936091726727f9633eec35 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 6 Feb 2024 11:08:04 -0500
Subject: [PATCH] [Clang][Sema] Abbreviated function templates do not append
 invented parameters to empty template parameter lists

---
 clang/docs/ReleaseNotes.rst   |  2 ++
 clang/lib/Sema/SemaDecl.cpp   |  2 +-
 clang/lib/Sema/SemaDeclCXX.cpp| 11 -
 .../CXX/dcl.decl/dcl.meaning/dcl.fct/p23.cpp  | 24 +++
 4 files changed, 37 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p23.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 4d57ea4fd55b8..d0ba986601e92 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -204,6 +204,8 @@ Bug Fixes to C++ Support
   parameter where we did an incorrect specialization of the initialization of
   the default parameter.
   Fixes (`#68490 `_)
+- Fixed a bug where abbreviated function templates would append their invented 
template parameters to
+  an empty template parameter lists.
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 481d952d2389b..d9704e5bfd67c 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9759,7 +9759,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, 
DeclContext *DC,
   SmallVector TemplateParamLists;
   llvm::append_range(TemplateParamLists, TemplateParamListsRef);
   if (TemplateParameterList *Invented = D.getInventedTemplateParameterList()) {
-if (!TemplateParamLists.empty() &&
+if (!TemplateParamLists.empty() && TemplateParamLists.back()->size() &&
 Invented->getDepth() == TemplateParamLists.back()->getDepth())
   TemplateParamLists.back() = Invented;
 else
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index ab8a967b06a45..f34893d88a3b3 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -19294,7 +19294,16 @@ void Sema::ActOnStartFunctionDeclarationDeclarator(
 ExplicitLists, /*IsFriend=*/false, IsMemberSpecialization, IsInvalid,
 /*SuppressDiagnostic=*/true);
   }
-  if (ExplicitParams) {
+  // C++23 [dcl.fct]p23:
+  //   An abbreviated function template can have a template-head. The invented
+  //   template-parameters are appended to the template-parameter-list after
+  //   the explicitly declared template-parameters.
+  //
+  // A template-head must have one or more template-parameters (read:
+  // 'template<>' is *not* a template-head). Only append the invented
+  // template parameters if we matched the nested-name-specifier to a non-empty
+  // TemplateParameterList.
+  if (ExplicitParams && ExplicitParams->size()) {
 Info.AutoTemplateParameterDepth = ExplicitParams->getDepth();
 llvm::append_range(Info.TemplateParams, *ExplicitParams);
 Info.NumExplicitTemplateParams = ExplicitParams->size();
diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p23.cpp 
b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p23.cpp
new file mode 100644
index 0..469c4e091953c
--- /dev/null
+++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p23.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -std=c++20 -pedantic-errors -verify %s
+
+// FIXME: This should be an error with -pedantic-errors.
+template<> // expected-warning {{extraneous template parameter list in 
template specialization}}
+void f(auto);
+
+template
+void f(auto);
+
+template
+struct A {
+  void g(auto);
+};
+
+template
+void A::g(auto) { }
+
+template<>
+void A::g(auto) { }
+
+// FIXME: This should be an error with -pedantic-errors.
+template<>
+template<> // expected-warning {{extraneous template parameter list in 
template specialization}}
+void A::g(auto) { }

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


[clang] [Clang][Sema] Diagnose declarative nested-name-specifiers naming alias templates (PR #80842)

2024-02-06 Thread Krystian Stasiowski via cfe-commits

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

>From c7457d759a93a04c3243c036e1c31296c8e81ec4 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 6 Feb 2024 09:14:42 -0500
Subject: [PATCH] [Clang][Sema] Diagnose declarative nested-name-specifiers
 naming alias templates

---
 clang/docs/ReleaseNotes.rst   |  1 +
 .../clang/Basic/DiagnosticSemaKinds.td|  3 ++
 clang/lib/Sema/SemaDecl.cpp   | 36 +--
 .../expr.prim.id/expr.prim.id.qual/p3.cpp | 29 +++
 .../temp.res/temp.dep/temp.dep.type/p1.cpp|  2 +-
 5 files changed, 60 insertions(+), 11 deletions(-)
 create mode 100644 
clang/test/CXX/expr/expr.prim/expr.prim.id/expr.prim.id.qual/p3.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 4d57ea4fd55b8..866bc0048ef5f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -150,6 +150,7 @@ Improvements to Clang's diagnostics
 
 - Clang now diagnoses member template declarations with multiple declarators.
 - Clang now diagnoses use of the ``template`` keyword after declarative nested 
name specifiers.
+- Clang now diagnoses declarative nested name specifiers that name alias 
templates.
 
 Improvements to Clang's time-trace
 --
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f76e7a3392183..d02fddd069341 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8250,6 +8250,9 @@ def err_not_tag_in_scope : Error<
 def ext_template_after_declarative_nns : ExtWarn<
 "'template' cannot be used after a declarative nested name specifier">,
 InGroup>;
+def ext_alias_template_in_declarative_nns : ExtWarn<
+  "a declarative nested name specifier cannot name an alias template">,
+  InGroup>;
 
 def err_no_typeid_with_fno_rtti : Error<
   "use of typeid requires -frtti">;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 481d952d2389b..9d4f757caf9ca 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -6207,6 +6207,8 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, 
DeclContext *DC,
 SourceLocation Loc,
 TemplateIdAnnotation *TemplateId,
 bool IsMemberSpecialization) {
+  assert(SS.isValid() && "diagnoseQualifiedDeclaration called for declaration "
+ "without nested-name-specifier");
   DeclContext *Cur = CurContext;
   while (isa(Cur) || isa(Cur))
 Cur = Cur->getParent();
@@ -6295,22 +6297,36 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec 
&SS, DeclContext *DC,
 << FixItHint::CreateRemoval(TemplateId->TemplateKWLoc);
 
   NestedNameSpecifierLoc SpecLoc(SS.getScopeRep(), SS.location_data());
-  while (SpecLoc.getPrefix()) {
+  do {
 if (SpecLoc.getNestedNameSpecifier()->getKind() ==
 NestedNameSpecifier::TypeSpecWithTemplate)
   Diag(Loc, diag::ext_template_after_declarative_nns)
   << FixItHint::CreateRemoval(
  SpecLoc.getTypeLoc().getTemplateKeywordLoc());
 
-SpecLoc = SpecLoc.getPrefix();
-  }
-  // C++11 [dcl.meaning]p1:
-  //   [...] "The nested-name-specifier of the qualified declarator-id shall
-  //   not begin with a decltype-specifer"
-  if (isa_and_nonnull(
-  SpecLoc.getNestedNameSpecifier()->getAsType()))
-Diag(Loc, diag::err_decltype_in_declarator)
-  << SpecLoc.getTypeLoc().getSourceRange();
+if (const Type *T = SpecLoc.getNestedNameSpecifier()->getAsType()) {
+  if (const auto *TST = T->getAsAdjusted()) {
+// C++23 [expr.prim.id.qual]p3:
+//   [...] If a nested-name-specifier N is declarative and has a
+//   simple-template-id with a template argument list A that involves a
+//   template parameter, let T be the template nominated by N without 
A.
+//   T shall be a class template.
+if (TST->isDependentType() && TST->isTypeAlias())
+  Diag(Loc, diag::ext_alias_template_in_declarative_nns)
+  << SpecLoc.getLocalSourceRange();
+  } else if (T->isDecltypeType()) {
+// C++23 [expr.prim.id.qual]p2:
+//   [...] A declarative nested-name-specifier shall not have a
+//   decltype-specifier.
+//
+// FIXME: This wording appears to be defective as it does not forbid
+// declarative nested-name-specifiers with pack-index-specifiers.
+// See https://github.com/cplusplus/CWG/issues/499.
+Diag(Loc, diag::err_decltype_in_declarator)
+<< SpecLoc.getTypeLoc().getSourceRange();
+  }
+}
+  } while ((SpecLoc = SpecLoc.getPrefix()));
 
   return false;
 }
diff --git 
a/clang/test/CXX/expr/expr.prim/expr.prim.id/expr.prim.id.qual/p3.cpp 

[clang] [Clang][Sema] Abbreviated function templates do not append invented parameters to empty template parameter lists (PR #80864)

2024-02-06 Thread Krystian Stasiowski via cfe-commits


@@ -9759,7 +9759,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, 
DeclContext *DC,
   SmallVector TemplateParamLists;
   llvm::append_range(TemplateParamLists, TemplateParamListsRef);
   if (TemplateParameterList *Invented = D.getInventedTemplateParameterList()) {
-if (!TemplateParamLists.empty() &&
+if (!TemplateParamLists.empty() && TemplateParamLists.back()->size() &&

sdkrystian wrote:

Unfortunately, `TemplateParameterList` doesn't have an `empty` member function. 
I can add one though, since we perform this check fairly often.

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


[clang] [Clang][Sema] Abbreviated function templates do not append invented parameters to empty template parameter lists (PR #80864)

2024-02-06 Thread Krystian Stasiowski via cfe-commits

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

>From 570e25f19b428fb7d2936091726727f9633eec35 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 6 Feb 2024 11:08:04 -0500
Subject: [PATCH 1/2] [Clang][Sema] Abbreviated function templates do not
 append invented parameters to empty template parameter lists

---
 clang/docs/ReleaseNotes.rst   |  2 ++
 clang/lib/Sema/SemaDecl.cpp   |  2 +-
 clang/lib/Sema/SemaDeclCXX.cpp| 11 -
 .../CXX/dcl.decl/dcl.meaning/dcl.fct/p23.cpp  | 24 +++
 4 files changed, 37 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p23.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 4d57ea4fd55b8c..d0ba986601e92f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -204,6 +204,8 @@ Bug Fixes to C++ Support
   parameter where we did an incorrect specialization of the initialization of
   the default parameter.
   Fixes (`#68490 `_)
+- Fixed a bug where abbreviated function templates would append their invented 
template parameters to
+  an empty template parameter lists.
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 481d952d2389bb..d9704e5bfd67c8 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9759,7 +9759,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, 
DeclContext *DC,
   SmallVector TemplateParamLists;
   llvm::append_range(TemplateParamLists, TemplateParamListsRef);
   if (TemplateParameterList *Invented = D.getInventedTemplateParameterList()) {
-if (!TemplateParamLists.empty() &&
+if (!TemplateParamLists.empty() && TemplateParamLists.back()->size() &&
 Invented->getDepth() == TemplateParamLists.back()->getDepth())
   TemplateParamLists.back() = Invented;
 else
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index ab8a967b06a456..f34893d88a3b3f 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -19294,7 +19294,16 @@ void Sema::ActOnStartFunctionDeclarationDeclarator(
 ExplicitLists, /*IsFriend=*/false, IsMemberSpecialization, IsInvalid,
 /*SuppressDiagnostic=*/true);
   }
-  if (ExplicitParams) {
+  // C++23 [dcl.fct]p23:
+  //   An abbreviated function template can have a template-head. The invented
+  //   template-parameters are appended to the template-parameter-list after
+  //   the explicitly declared template-parameters.
+  //
+  // A template-head must have one or more template-parameters (read:
+  // 'template<>' is *not* a template-head). Only append the invented
+  // template parameters if we matched the nested-name-specifier to a non-empty
+  // TemplateParameterList.
+  if (ExplicitParams && ExplicitParams->size()) {
 Info.AutoTemplateParameterDepth = ExplicitParams->getDepth();
 llvm::append_range(Info.TemplateParams, *ExplicitParams);
 Info.NumExplicitTemplateParams = ExplicitParams->size();
diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p23.cpp 
b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p23.cpp
new file mode 100644
index 00..469c4e091953c3
--- /dev/null
+++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p23.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -std=c++20 -pedantic-errors -verify %s
+
+// FIXME: This should be an error with -pedantic-errors.
+template<> // expected-warning {{extraneous template parameter list in 
template specialization}}
+void f(auto);
+
+template
+void f(auto);
+
+template
+struct A {
+  void g(auto);
+};
+
+template
+void A::g(auto) { }
+
+template<>
+void A::g(auto) { }
+
+// FIXME: This should be an error with -pedantic-errors.
+template<>
+template<> // expected-warning {{extraneous template parameter list in 
template specialization}}
+void A::g(auto) { }

>From 0037ab6bc32106d1eecccb1ad662bf4ca217555c Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 6 Feb 2024 11:32:41 -0500
Subject: [PATCH 2/2] [FOLD]

---
 clang/include/clang/AST/DeclTemplate.h | 1 +
 clang/lib/Sema/SemaDecl.cpp| 2 +-
 clang/lib/Sema/SemaDeclCXX.cpp | 2 +-
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/AST/DeclTemplate.h 
b/clang/include/clang/AST/DeclTemplate.h
index baf71145d99dc6..e3b6a7efb1127a 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -134,6 +134,7 @@ class TemplateParameterList final
   const_iterator end() const { return begin() + NumParams; }
 
   unsigned size() const { return NumParams; }
+  bool empty() const { return NumParams == 0; }
 
   ArrayRef asArray() { return llvm::ArrayRef(begin(), end()); }
   ArrayRef asArray() const {
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.c

[clang] [Clang][Sema] Abbreviated function templates do not append invented parameters to empty template parameter lists (PR #80864)

2024-02-06 Thread Krystian Stasiowski via cfe-commits


@@ -9759,7 +9759,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, 
DeclContext *DC,
   SmallVector TemplateParamLists;
   llvm::append_range(TemplateParamLists, TemplateParamListsRef);
   if (TemplateParameterList *Invented = D.getInventedTemplateParameterList()) {
-if (!TemplateParamLists.empty() &&
+if (!TemplateParamLists.empty() && TemplateParamLists.back()->size() &&

sdkrystian wrote:

Added. I'll open a separate PR that converts other uses of `size()` to use 
`empty()` where appropriate 

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


[clang] [Clang][Sema] Diagnose friend declarations with enum elaborated-type-specifier in all language modes (PR #80171)

2024-02-06 Thread Krystian Stasiowski via cfe-commits

sdkrystian wrote:

Ping @Endilll @erichkeane 

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


[clang] [Clang][Sema] Diagnose friend declarations with enum elaborated-type-specifier in all language modes (PR #80171)

2024-02-06 Thread Krystian Stasiowski via cfe-commits


@@ -145,6 +145,7 @@ Improvements to Clang's diagnostics
   prints.
 
 - Clang now diagnoses member template declarations with multiple declarators.
+- Clang now diagnoses friend declarations with an ``enum`` 
elaborated-type-specifier outside of C++98.

sdkrystian wrote:

Yes :)

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


[clang] [Clang][Sema] Diagnose friend declarations with enum elaborated-type-specifier in all language modes (PR #80171)

2024-02-06 Thread Krystian Stasiowski via cfe-commits


@@ -380,7 +375,8 @@ class DeclSpec {
   unsigned FS_noreturn_specified : 1;
 
   // friend-specifier
-  unsigned Friend_specified : 1;
+  unsigned FriendSpecified : 1;

sdkrystian wrote:

`LLVM_PREFERRED_TYPE` I believe

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


[clang] [Clang][Sema] Diagnose friend declarations with enum elaborated-type-specifier in all language modes (PR #80171)

2024-02-06 Thread Krystian Stasiowski via cfe-commits


@@ -145,6 +145,7 @@ Improvements to Clang's diagnostics
   prints.
 
 - Clang now diagnoses member template declarations with multiple declarators.
+- Clang now diagnoses friend declarations with an ``enum`` 
elaborated-type-specifier outside of C++98.

sdkrystian wrote:

Yup, will do

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


[clang] [Clang][Sema] Diagnose friend declarations with enum elaborated-type-specifier in all language modes (PR #80171)

2024-02-06 Thread Krystian Stasiowski via cfe-commits


@@ -1637,10 +1637,8 @@ def err_inline_namespace_std : Error<
 def err_unexpected_friend : Error<
   "friends can only be classes or functions">;
 def ext_enum_friend : ExtWarn<
-  "befriending enumeration type %0 is a C++11 extension">, InGroup;
-def warn_cxx98_compat_enum_friend : Warning<
-  "befriending enumeration type %0 is incompatible with C++98">,
-  InGroup, DefaultIgnore;
+  "elaborated enumeration type cannot be a friend">,

sdkrystian wrote:

@Endilll I tried to follow the existing "naming convention" used in other 
diagnostics to strike a balance between being correct & comprehensible for 
users. Removing "elaborated" isn't quite correct because an enumeration type 
_can_ be a friend (e.g. `enum class E; struct A { friend E; };`; such a 
declaration is ignored) -- you just can't declare a friend using an 
elaborated-type-specifier starting with `enum` (i.e. `friend enum E`). 

Here is an alternative if you think changing this is necessary:
> A friend declaration cannot use an elaborated type specifier starting with 
> `enum`



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


[clang] [Clang][Sema] Implement proposed resolution for CWG2847 (PR #80899)

2024-02-06 Thread Krystian Stasiowski via cfe-commits

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

Per the approved resolution for 
[CWG2847](https://cplusplus.github.io/CWG/issues/2847.html), [temp.expl.spec] 
p8 will state:
> An explicit specialization shall not have a trailing _requires-clause_ unless 
> it declares a function template.

We already implement this _partially_ insofar that a diagnostic is issued upon 
instantiation of `A` in the following example:
```cpp
template
struct A
{
template
void f();

template<>
void f() requires true; // error: non-templated function cannot have a 
requires clause
};
template struct A;  // note: in instantiation of template class 'A' 
requested here
```

This patch adds a bespoke diagnostic for such declarations, and moves the point 
of diagnosis for non-templated functions with trailing requires-clauses from 
`CheckFunctionDeclaration` to `ActOnFunctionDeclarator` (there is no point in 
diagnosing this during instantiation since we already have all the necessary 
information when parsing the declaration).

>From f9079ac4098b2debf3df4ebee3e5f4f0c2b1e6a2 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 6 Feb 2024 14:22:37 -0500
Subject: [PATCH] [Clang][Sema] Implement proposed resolution for CWG2847

---
 .../clang/Basic/DiagnosticSemaKinds.td|   3 +
 clang/lib/Sema/SemaDecl.cpp   | 103 +-
 clang/test/CXX/drs/dr28xx.cpp |  41 +++
 3 files changed, 98 insertions(+), 49 deletions(-)
 create mode 100644 clang/test/CXX/drs/dr28xx.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f76e7a3392183..b4dc4feee8e63 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2982,6 +2982,9 @@ def err_trailing_requires_clause_on_deduction_guide : 
Error<
   "deduction guide cannot have a requires clause">;
 def err_constrained_non_templated_function
 : Error<"non-templated function cannot have a requires clause">;
+def err_non_temp_spec_requires_clause : Error<
+  "%select{explicit|friend}0 specialization cannot have a trailing requires 
clause "
+  "unless it declares a function template">;
 def err_reference_to_function_with_unsatisfied_constraints : Error<
   "invalid reference to function %0: constraints not satisfied">;
 def err_requires_expr_local_parameter_default_argument : Error<
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 481d952d2389b..18a5d93ab8e8c 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -10440,6 +10440,60 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, 
DeclContext *DC,
diag::ext_operator_new_delete_declared_inline)
 << NewFD->getDeclName();
 
+if (Expr *TRC = NewFD->getTrailingRequiresClause()) {
+  // C++20 [dcl.decl.general]p4:
+  //   The optional requires-clause in an init-declarator or
+  //   member-declarator shall be present only if the declarator declares a
+  //   templated function.
+  //
+  // C++20 [temp.pre]p8:
+  //   An entity is templated if it is
+  // - a template,
+  // - an entity defined or created in a templated entity,
+  // - a member of a templated entity,
+  // - an enumerator for an enumeration that is a templated entity, or
+  // - the closure type of a lambda-expression appearing in the
+  //   declaration of a templated entity.
+  //
+  //   [Note 6: A local class, a local or block variable, or a friend
+  //   function defined in a templated entity is a templated entity.
+  //   — end note]
+  //
+  //   A templated function is a function template or a function that is
+  //   templated. A templated class is a class template or a class that is
+  //   templated. A templated variable is a variable template or a variable
+  //   that is templated.
+  if (!FunctionTemplate) {
+if (isFunctionTemplateSpecialization || isMemberSpecialization) {
+  // C++ [temp.expl.spec]p8 (proposed resolution for CWG2847):
+  //   An explicit specialization shall not have a trailing
+  //   requires-clause unless it declares a function template.
+  //
+  // Since a friend function template specialization cannot be
+  // definition, and since a non-template friend declaration with a
+  // trailing requires-clause must be a definition, we diagnose
+  // friend function template specializations with trailing
+  // requires-clauses on the same path as explicit specializations
+  // even though they aren't necessarily prohibited by the same
+  // language rule.
+  Diag(TRC->getBeginLoc(), diag::err_non_temp_spec_requires_clause)
+  << isFriend;
+} else if (isFriend && NewFD->isTemplated() &&
+   

[clang] [Clang][Sema] Diagnose friend declarations with enum elaborated-type-specifier in all language modes (PR #80171)

2024-02-06 Thread Krystian Stasiowski via cfe-commits


@@ -1637,10 +1637,8 @@ def err_inline_namespace_std : Error<
 def err_unexpected_friend : Error<
   "friends can only be classes or functions">;
 def ext_enum_friend : ExtWarn<
-  "befriending enumeration type %0 is a C++11 extension">, InGroup;
-def warn_cxx98_compat_enum_friend : Warning<
-  "befriending enumeration type %0 is incompatible with C++98">,
-  InGroup, DefaultIgnore;
+  "elaborated enumeration type cannot be a friend">,

sdkrystian wrote:


> What if we skip complicated standardese altogether?
> 
> > 'enum' keyword is not allowed after 'friend' keyword

This isn't quite correct either because `enum` _can_ follow the `friend` 
keyword 😛, e.g. 
```cpp
enum class E;
struct A
{
friend enum E f(); // ok
};
```

> Possibly followed by
> 
> > Omit 'enum' keyword if you intend to befriend an enumeration

I don't think a note would be particularly helpful since the friend declaration 
would be ignored anyways...

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


[clang] [Clang][Sema] Diagnose friend declarations with enum elaborated-type-specifier in all language modes (PR #80171)

2024-02-06 Thread Krystian Stasiowski via cfe-commits

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


[clang] [Clang][Sema] Diagnose friend declarations with enum elaborated-type-specifier in all language modes (PR #80171)

2024-02-06 Thread Krystian Stasiowski via cfe-commits


@@ -252,4 +252,14 @@ namespace dr2397 { // dr2397: 17
 auto (*c)[5] = &a;
   }
 } // namespace dr2397
+
+// CWG2363 was closed as NAD, but its resolution does affirm that
+// a friend declaration cannot have an opaque-enumm-specifier.
+namespace dr2363 { // dr2363: yes
+struct A {
+  friend enum class E; // since-cxx11-error {{reference to enumeration must 
use 'enum' not 'enum class'}}

sdkrystian wrote:

@Endilll like so?
```cpp
struct A {
  friend enum class E;
  // since-cxx11-error@-1 {{reference to enumeration must use 'enum' not 'enum 
class'}}
  // expected-error@-2 {{elaborated enumeration type cannot be a friend}}
};
```

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


[clang] [Clang][Sema] Diagnose friend declarations with enum elaborated-type-specifier in all language modes (PR #80171)

2024-02-06 Thread Krystian Stasiowski via cfe-commits

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

>From a39aab07696acfea3e3b78d6ad92c8b771eaf0d2 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Wed, 31 Jan 2024 11:09:11 -0500
Subject: [PATCH 1/3] [Clang][Sema] Diagnose friend declarations with enum
 elaborated-type-specifier in all language modes

---
 clang/docs/ReleaseNotes.rst   |   1 +
 .../clang/Basic/DiagnosticSemaKinds.td|   6 +-
 clang/include/clang/Parse/Parser.h|   8 +-
 clang/include/clang/Sema/DeclSpec.h   |  20 +--
 clang/include/clang/Sema/Sema.h   |   3 -
 clang/lib/Parse/ParseDecl.cpp |   2 +-
 clang/lib/Parse/ParseTentative.cpp|   2 +-
 clang/lib/Sema/DeclSpec.cpp   |  10 +-
 clang/lib/Sema/SemaDecl.cpp   |  16 ++
 clang/lib/Sema/SemaDeclCXX.cpp| 137 +-
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  |   7 +-
 .../dcl.spec/dcl.type/dcl.type.elab/p3.cpp|   6 +-
 .../dcl.spec/dcl.type/dcl.type.elab/p4.cpp|  33 +
 clang/test/CXX/drs/dr16xx.cpp |   1 +
 .../temp.class/temp.mem.enum/p1.cpp   |   5 +-
 clang/test/FixIt/fixit-c++11.cpp  |   1 +
 clang/test/Parser/cxx-decl.cpp|   3 -
 clang/test/Parser/cxx0x-decl.cpp  |   2 +-
 clang/test/SemaCXX/cxx98-compat.cpp   |   2 +-
 clang/test/SemaCXX/enum-scoped.cpp|   5 +
 20 files changed, 123 insertions(+), 147 deletions(-)
 create mode 100644 
clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p4.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index efd925e990f43..1624ba30dd326 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -145,6 +145,7 @@ Improvements to Clang's diagnostics
   prints.
 
 - Clang now diagnoses member template declarations with multiple declarators.
+- Clang now diagnoses friend declarations with an ``enum`` 
elaborated-type-specifier outside of C++98.
 
 Improvements to Clang's time-trace
 --
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 7638a7e84c3c0..ca0c4509a9eb5 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1637,10 +1637,8 @@ def err_inline_namespace_std : Error<
 def err_unexpected_friend : Error<
   "friends can only be classes or functions">;
 def ext_enum_friend : ExtWarn<
-  "befriending enumeration type %0 is a C++11 extension">, InGroup;
-def warn_cxx98_compat_enum_friend : Warning<
-  "befriending enumeration type %0 is incompatible with C++98">,
-  InGroup, DefaultIgnore;
+  "elaborated enumeration type cannot be a friend">,
+  InGroup>;
 def ext_nonclass_type_friend : ExtWarn<
   "non-class friend type %0 is a C++11 extension">, InGroup;
 def warn_cxx98_compat_nonclass_type_friend : Warning<
diff --git a/clang/include/clang/Parse/Parser.h 
b/clang/include/clang/Parse/Parser.h
index da18cf88edcc9..ab92d4e7e9a2f 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2552,10 +2552,10 @@ class Parser : public CodeCompletionHandler {
   /// Starting with a scope specifier, identifier, or
   /// template-id that refers to the current class, determine whether
   /// this is a constructor declarator.
-  bool isConstructorDeclarator(
-  bool Unqualified, bool DeductionGuide = false,
-  DeclSpec::FriendSpecified IsFriend = DeclSpec::FriendSpecified::No,
-  const ParsedTemplateInfo *TemplateInfo = nullptr);
+  bool
+  isConstructorDeclarator(bool Unqualified, bool DeductionGuide = false,
+  bool IsFriend = false,
+  const ParsedTemplateInfo *TemplateInfo = nullptr);
 
   /// Specifies the context in which type-id/expression
   /// disambiguation will occur.
diff --git a/clang/include/clang/Sema/DeclSpec.h 
b/clang/include/clang/Sema/DeclSpec.h
index 77638def60063..c7266b66c014d 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -346,11 +346,6 @@ class DeclSpec {
 // FIXME: Attributes should be included here.
   };
 
-  enum FriendSpecified : bool {
-No,
-Yes,
-  };
-
 private:
   // storage-class-specifier
   /*SCS*/unsigned StorageClassSpec : 3;
@@ -380,7 +375,8 @@ class DeclSpec {
   unsigned FS_noreturn_specified : 1;
 
   // friend-specifier
-  unsigned Friend_specified : 1;
+  unsigned FriendSpecified : 1;
+  unsigned FriendSpecifiedFirst : 1;
 
   // constexpr-specifier
   unsigned ConstexprSpecifier : 2;
@@ -470,9 +466,9 @@ class DeclSpec {
 TypeSpecPipe(false), TypeSpecSat(false), ConstrainedAuto(false),
 TypeQualifiers(TQ_unspecified), FS_inline_specified(false),
 FS_forceinline_specified(false), FS_virtual_specified(false),
-FS_noreturn_specified(false), Friend

[clang] [Clang][Sema] Implement proposed resolution for CWG2847 (PR #80899)

2024-02-06 Thread Krystian Stasiowski via cfe-commits

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

>From f9079ac4098b2debf3df4ebee3e5f4f0c2b1e6a2 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski 
Date: Tue, 6 Feb 2024 14:22:37 -0500
Subject: [PATCH 1/2] [Clang][Sema] Implement proposed resolution for CWG2847

---
 .../clang/Basic/DiagnosticSemaKinds.td|   3 +
 clang/lib/Sema/SemaDecl.cpp   | 103 +-
 clang/test/CXX/drs/dr28xx.cpp |  41 +++
 3 files changed, 98 insertions(+), 49 deletions(-)
 create mode 100644 clang/test/CXX/drs/dr28xx.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f76e7a3392183..b4dc4feee8e63 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2982,6 +2982,9 @@ def err_trailing_requires_clause_on_deduction_guide : 
Error<
   "deduction guide cannot have a requires clause">;
 def err_constrained_non_templated_function
 : Error<"non-templated function cannot have a requires clause">;
+def err_non_temp_spec_requires_clause : Error<
+  "%select{explicit|friend}0 specialization cannot have a trailing requires 
clause "
+  "unless it declares a function template">;
 def err_reference_to_function_with_unsatisfied_constraints : Error<
   "invalid reference to function %0: constraints not satisfied">;
 def err_requires_expr_local_parameter_default_argument : Error<
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 481d952d2389b..18a5d93ab8e8c 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -10440,6 +10440,60 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, 
DeclContext *DC,
diag::ext_operator_new_delete_declared_inline)
 << NewFD->getDeclName();
 
+if (Expr *TRC = NewFD->getTrailingRequiresClause()) {
+  // C++20 [dcl.decl.general]p4:
+  //   The optional requires-clause in an init-declarator or
+  //   member-declarator shall be present only if the declarator declares a
+  //   templated function.
+  //
+  // C++20 [temp.pre]p8:
+  //   An entity is templated if it is
+  // - a template,
+  // - an entity defined or created in a templated entity,
+  // - a member of a templated entity,
+  // - an enumerator for an enumeration that is a templated entity, or
+  // - the closure type of a lambda-expression appearing in the
+  //   declaration of a templated entity.
+  //
+  //   [Note 6: A local class, a local or block variable, or a friend
+  //   function defined in a templated entity is a templated entity.
+  //   — end note]
+  //
+  //   A templated function is a function template or a function that is
+  //   templated. A templated class is a class template or a class that is
+  //   templated. A templated variable is a variable template or a variable
+  //   that is templated.
+  if (!FunctionTemplate) {
+if (isFunctionTemplateSpecialization || isMemberSpecialization) {
+  // C++ [temp.expl.spec]p8 (proposed resolution for CWG2847):
+  //   An explicit specialization shall not have a trailing
+  //   requires-clause unless it declares a function template.
+  //
+  // Since a friend function template specialization cannot be
+  // definition, and since a non-template friend declaration with a
+  // trailing requires-clause must be a definition, we diagnose
+  // friend function template specializations with trailing
+  // requires-clauses on the same path as explicit specializations
+  // even though they aren't necessarily prohibited by the same
+  // language rule.
+  Diag(TRC->getBeginLoc(), diag::err_non_temp_spec_requires_clause)
+  << isFriend;
+} else if (isFriend && NewFD->isTemplated() &&
+   !D.isFunctionDefinition()) {
+  // C++ [temp.friend]p9:
+  //   A non-template friend declaration with a requires-clause shall 
be
+  //   a definition.
+  Diag(NewFD->getBeginLoc(),
+   
diag::err_non_temp_friend_decl_with_requires_clause_must_be_def);
+  NewFD->setInvalidDecl();
+} else if (!NewFD->isTemplated() ||
+   !(isa(NewFD) || D.isFunctionDefinition())) {
+  Diag(TRC->getBeginLoc(),
+   diag::err_constrained_non_templated_function);
+}
+  }
+}
+
 // We do not add HD attributes to specializations here because
 // they may have different constexpr-ness compared to their
 // templates and, after maybeAddCUDAHostDeviceAttrs() is applied,
@@ -12063,55 +12117,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, 
FunctionDecl *NewFD,
 checkThisInStaticMemberFunctionType(Method);
 }
 
-if (Expr *TRC = NewFD->getTrailingRe

[clang] [Clang][Sema] Implement proposed resolution for CWG2847 (PR #80899)

2024-02-06 Thread Krystian Stasiowski via cfe-commits

sdkrystian wrote:

@Endilll I applied your suggested changes... how does it look?

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


  1   2   3   4   5   6   7   8   9   10   >