aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2019-03-27 14:39:20 -0400
committerJason Merrill <jason@gcc.gnu.org>2019-03-27 14:39:20 -0400
commit03bed1538f8c71f06dd0afa68713de019595e71e (patch)
treed96fdda8e7b4e3ad5ac5f60f34e802ca241c70c1 /gcc
parentbbf1efe1b46737304cde7b35a95b30d21157e54d (diff)
downloadgcc-03bed1538f8c71f06dd0afa68713de019595e71e.zip
gcc-03bed1538f8c71f06dd0afa68713de019595e71e.tar.gz
gcc-03bed1538f8c71f06dd0afa68713de019595e71e.tar.bz2
PR c++/89241 - ICE with lambda in template parameter list.
We were getting confused by a lambda in template definition context that isn't actually in the scope of any templated entity. Fixed by telling type_dependent_expression_p that such a lambda is type-dependent even if we can't tell that from its closure type. I've also restored the error for defining a non-lambda class in a default template argument, and for a lambda befor C++20. * parser.c (cp_parser_lambda_expression): Also reject a lambda in a template parameter list before C++20. * pt.c (type_dependent_expression_p): True for LAMBDA_EXPR. * semantics.c (begin_class_definition): Restore error about defining non-lambda class in template parm list. From-SVN: r269972
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/parser.c2
-rw-r--r--gcc/cp/pt.c6
-rw-r--r--gcc/cp/semantics.c6
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/lambda-uneval10.C12
-rw-r--r--gcc/testsuite/g++.dg/ext/complit16.C5
6 files changed, 39 insertions, 1 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index bce9b10..4807194 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+2019-03-27 Jason Merrill <jason@redhat.com>
+
+ PR c++/89241 - ICE with lambda in template parameter list.
+ * parser.c (cp_parser_lambda_expression): Also reject a lambda in a
+ template parameter list before C++20.
+ * pt.c (type_dependent_expression_p): True for LAMBDA_EXPR.
+ * semantics.c (begin_class_definition): Restore error about defining
+ non-lambda class in template parm list.
+
2019-03-26 Jason Merrill <jason@redhat.com>
PR c++/86932 - missed SFINAE with empty pack.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 4119d2a..348e4ac 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -10397,7 +10397,7 @@ cp_parser_lambda_expression (cp_parser* parser)
}
ok = false;
}
- else if (parser->in_template_argument_list_p)
+ else if (parser->in_template_argument_list_p || processing_template_parmlist)
{
if (!token->error_reported)
{
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index dc982f3..229b34a 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -25692,6 +25692,12 @@ type_dependent_expression_p (tree expression)
|| TREE_CODE (expression) == WILDCARD_DECL)
return true;
+ /* A lambda-expression in template context is dependent. dependent_type_p is
+ true for a lambda in the scope of a class or function template, but that
+ doesn't cover all template contexts, like a default template argument. */
+ if (TREE_CODE (expression) == LAMBDA_EXPR)
+ return true;
+
/* A fold expression is type-dependent. */
if (TREE_CODE (expression) == UNARY_LEFT_FOLD_EXPR
|| TREE_CODE (expression) == UNARY_RIGHT_FOLD_EXPR
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index d7e97e0..fea2696 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3043,6 +3043,12 @@ begin_class_definition (tree t)
if (error_operand_p (t) || error_operand_p (TYPE_MAIN_DECL (t)))
return error_mark_node;
+ if (processing_template_parmlist && !LAMBDA_TYPE_P (t))
+ {
+ error ("definition of %q#T inside template parameter list", t);
+ return error_mark_node;
+ }
+
/* According to the C++ ABI, decimal classes defined in ISO/IEC TR 24733
are passed the same as decimal scalar types. */
if (TREE_CODE (t) == RECORD_TYPE
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-uneval10.C b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval10.C
new file mode 100644
index 0000000..86065eb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval10.C
@@ -0,0 +1,12 @@
+// PR c++/89421
+
+template <int I = []{return 1;}()> // { dg-message "lambda" "" { target c++17_down } }
+struct B
+{
+ static const int i = I;
+};
+
+#if __cplusplus > 201703L
+B<> b;
+static_assert (b.i == 1);
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/complit16.C b/gcc/testsuite/g++.dg/ext/complit16.C
new file mode 100644
index 0000000..5625ced
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/complit16.C
@@ -0,0 +1,5 @@
+// { dg-options "" }
+
+template <int = (struct A{int i;}){42}.i> struct B{}; // { dg-error "" }
+
+B<0> b;