]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Don't treat lambda typedef as lambda declaration [PR106221]
authorNathaniel Shead <nathanieloshead@gmail.com>
Sat, 21 Dec 2024 14:18:16 +0000 (01:18 +1100)
committerNathaniel Shead <nathanieloshead@gmail.com>
Sun, 29 Dec 2024 00:15:43 +0000 (11:15 +1100)
I noticed that in a couple of places we sometimes treat any TYPE_DECL of
lambda type as defining a lambda, which isn't always true since C++20:
in `using T = decltype([]{})`, T is not a lambda-declaration.

PR c++/106221
PR c++/110680

gcc/cp/ChangeLog:

* pt.cc (check_default_tmpl_args): Check this is actually a
lambda declaration and not just a typedef.
(push_template_decl): Likewise.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/lambda-uneval19.C: New test.

Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
gcc/cp/pt.cc
gcc/testsuite/g++.dg/cpp2a/lambda-uneval19.C [new file with mode: 0644]

index 7fa286698ef26fd9a429af99a172ca23b96f1d40..0ffa0b53e26a87df3ed2c7202446c68d2800db64 100644 (file)
@@ -5637,8 +5637,7 @@ check_default_tmpl_args (tree decl, tree parms, bool is_primary,
        local scope.  */
     return true;
 
-  if ((TREE_CODE (decl) == TYPE_DECL
-       && TREE_TYPE (decl)
+  if ((DECL_IMPLICIT_TYPEDEF_P (decl)
        && LAMBDA_TYPE_P (TREE_TYPE (decl)))
       || (TREE_CODE (decl) == FUNCTION_DECL
          && LAMBDA_FUNCTION_P (decl)))
@@ -5924,7 +5923,7 @@ push_template_decl (tree decl, bool is_friend)
          template <typename T> friend void A<T>::f();
        is not primary.  */
     ;
-  else if (TREE_CODE (decl) == TYPE_DECL && LAMBDA_TYPE_P (TREE_TYPE (decl)))
+  else if (DECL_IMPLICIT_TYPEDEF_P (decl) && LAMBDA_TYPE_P (TREE_TYPE (decl)))
     /* Lambdas are not primary.  */
     ;
   else
@@ -6077,7 +6076,8 @@ push_template_decl (tree decl, bool is_friend)
   else if (!ctx
           || TREE_CODE (ctx) == FUNCTION_DECL
           || (CLASS_TYPE_P (ctx) && TYPE_BEING_DEFINED (ctx))
-          || (TREE_CODE (decl) == TYPE_DECL && LAMBDA_TYPE_P (TREE_TYPE (decl)))
+          || (DECL_IMPLICIT_TYPEDEF_P (decl)
+              && LAMBDA_TYPE_P (TREE_TYPE (decl)))
           || (is_friend && !(DECL_LANG_SPECIFIC (decl)
                              && DECL_TEMPLATE_INFO (decl))))
     {
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-uneval19.C b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval19.C
new file mode 100644 (file)
index 0000000..a9682cc
--- /dev/null
@@ -0,0 +1,20 @@
+// { dg-do compile { target c++20 } }
+
+// PR c++/106221
+using T = decltype([](){});
+
+template<typename Opts>
+using foo = T;
+
+using bar = foo<int>;
+
+// PR c++/110680
+template <auto X = []{}>
+struct S {
+  auto f() { return X; }
+};
+
+template <class T>
+using C = decltype(S().f());
+
+using D = C<int>;