aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2021-04-08 14:39:28 -0400
committerMarek Polacek <polacek@redhat.com>2021-04-09 10:23:30 -0400
commit625dadaf5df5a2ae0d8c5660fd1eec8ba354479c (patch)
treed2241dd0b717ec3196f7b3f1c239342ffbd64a08
parent2dd7c570e67ce47702db4c5f776f02e0b35d7dd4 (diff)
downloadgcc-625dadaf5df5a2ae0d8c5660fd1eec8ba354479c.zip
gcc-625dadaf5df5a2ae0d8c5660fd1eec8ba354479c.tar.gz
gcc-625dadaf5df5a2ae0d8c5660fd1eec8ba354479c.tar.bz2
c++: Fix two issues with auto function parameter [PR99806]
When we have a member function with auto parameter like this: struct S { void f(auto); }; cp_parser_member_declaration -> grokfield produces a FUNCTION_DECL "void S::foo(auto:1)", and then finish_fully_implicit_template turns that FUNCTION_DECL into a TEMPLATE_DECL. The bug here is that we only call cp_parser_save_default_args for a FUNCTION_DECL. As a consequence, abbrev10.C is rejected because we complain that the default argument has not been defined, and abbrev11.C ICEs, because we don't re-parse the delayed noexcept, so the DEFERRED_PARSE tree leaks into tsubst* where we crash. This patch fixes both issues. gcc/cp/ChangeLog: PR c++/99806 * parser.c (cp_parser_member_declaration): Call cp_parser_save_default_args even for function templates. Use STRIP_TEMPLATE on the declaration we're passing. gcc/testsuite/ChangeLog: PR c++/99806 * g++.dg/concepts/abbrev10.C: New test. * g++.dg/concepts/abbrev11.C: New test.
-rw-r--r--gcc/cp/parser.c4
-rw-r--r--gcc/testsuite/g++.dg/concepts/abbrev10.C18
-rw-r--r--gcc/testsuite/g++.dg/concepts/abbrev11.C10
3 files changed, 30 insertions, 2 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 59adac4..e6e6ed7 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -26433,8 +26433,8 @@ cp_parser_member_declaration (cp_parser* parser)
|| !DECL_DECLARES_FUNCTION_P (decl))
finish_member_declaration (decl);
- if (TREE_CODE (decl) == FUNCTION_DECL)
- cp_parser_save_default_args (parser, decl);
+ if (DECL_DECLARES_FUNCTION_P (decl))
+ cp_parser_save_default_args (parser, STRIP_TEMPLATE (decl));
else if (TREE_CODE (decl) == FIELD_DECL
&& DECL_INITIAL (decl))
/* Add DECL to the queue of NSDMI to be parsed later. */
diff --git a/gcc/testsuite/g++.dg/concepts/abbrev10.C b/gcc/testsuite/g++.dg/concepts/abbrev10.C
new file mode 100644
index 0000000..b611346
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/abbrev10.C
@@ -0,0 +1,18 @@
+// PR c++/99806
+// { dg-do compile { target c++14 } }
+// { dg-additional-options "-fconcepts" }
+
+struct S {
+ void f(auto, auto, int = 3);
+ void f2(auto, auto, int = 3) { }
+ template<typename T> static T g(T, auto, int = 3);
+};
+
+void
+g ()
+{
+ S::g(1, 2);
+ S s;
+ s.f(1, 2);
+ s.f2(1, 2);
+}
diff --git a/gcc/testsuite/g++.dg/concepts/abbrev11.C b/gcc/testsuite/g++.dg/concepts/abbrev11.C
new file mode 100644
index 0000000..ddb4793
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/abbrev11.C
@@ -0,0 +1,10 @@
+// PR c++/99806
+// { dg-do compile { target c++14 } }
+// { dg-additional-options "-fconcepts" }
+
+template <typename T> concept C = requires (T a) { a.f(0); };
+struct S {
+ void f(auto) noexcept(B);
+ static constexpr bool B = true;
+};
+static_assert(C<S>, "");