This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [c++-concepts] Allow function parameters to be referenced in trailing requires clauses


Applied an updated version of this patch.

2014-7-30  Braden Obrzut  <admin@maniacsvault.net>
        * gcc/cp/parser.c (cp_parser_trailing_requirements): Handle requires
        keyword manually so that we can push function parameters back into
        scope.
        * gcc/cp/decl.c (push_function_parms): New. Recovers and reopens
        function parameter scope from declarator.
        * gcc/testsuite/g++.dg/concepts/req*.C: New tests.

2014-07-30  Andrew Sutton  <andrew.n.sutton@gmail.com>
        * gcc/testsuite/g++.dg/concepts/test.C: Removed.

Andrew Sutton


On Tue, Jun 17, 2014 at 5:06 AM, Braden Obrzut <admin@maniacsvault.net> wrote:
> This patch allows function parameters to be referenced by trailing requires
> clauses.  Typically this is used to refer to the type of an implicitly
> generated template.  For example, the following should now be valid (where C
> is some previously defined concept):
>
> auto f1 (auto x) requires C<decltype(x)> ();
>
> Note that the test case trailing-requires-overload.C will fail to compile
> unless the previously submitted patch is applied first.
>
> 2014-06-17  Braden Obrzut  <admin@maniacsvault.net>
>     * gcc/cp/parser.c (cp_parser_trailing_requirements): Handle requires
>     keyword manually so that we can push function parameters back into
>     scope.
>     * gcc/cp/decl.c (push_function_parms): New. Recovers and reopens
>     function parameter scope from declarator.
>     * gcc/testsuite/g++.dg/concepts/trailing-requires.C: New tests.
>     * gcc/testsuite/g++.dg/concepts/trailing-requires-overload.C: New tests.
Index: gcc/testsuite/g++.dg/concepts/traits1.C
===================================================================
--- gcc/testsuite/g++.dg/concepts/traits1.C	(revision 212456)
+++ gcc/testsuite/g++.dg/concepts/traits1.C	(working copy)
@@ -79,21 +79,21 @@ void f18() requires Enum<void>();
 
 
 int main() { 
-  f1(); // { dg-error "cannot" }
-  f2(); // { dg-error "cannot" }
-  f3(); // { dg-error "cannot" }
-  f4(); // { dg-error "cannot" }
-  f5(); // { dg-error "cannot" }
-  f6(); // { dg-error "cannot" }
-  f7(); // { dg-error "cannot" }
-  f8(); // { dg-error "cannot" }
-  f9(); // { dg-error "cannot" }
-  f10(); // { dg-error "cannot" }
-  f11(); // { dg-error "cannot" }
-  f12(); // { dg-error "cannot" }
-  f13(); // { dg-error "cannot" }
-  f14(); // { dg-error "cannot" }
-  f15(); // { dg-error "cannot" }
-  f16(); // { dg-error "cannot" }
-  f17(); // { dg-error "cannot" }
+  f1(); // { dg-error "cannot call" }
+  f2(); // { dg-error "cannot call" }
+  f3(); // { dg-error "cannot call" }
+  f4(); // { dg-error "cannot call" }
+  f5(); // { dg-error "cannot call" }
+  f6(); // { dg-error "cannot call" }
+  f7(); // { dg-error "cannot call" }
+  f8(); // { dg-error "cannot call" }
+  f9(); // { dg-error "cannot call" }
+  f10(); // { dg-error "cannot call" }
+  f11(); // { dg-error "cannot call" }
+  f12(); // { dg-error "cannot call" }
+  f13(); // { dg-error "cannot call" }
+  f14(); // { dg-error "cannot call" }
+  f15(); // { dg-error "cannot call" }
+  f16(); // { dg-error "cannot call" }
+  f17(); // { dg-error "cannot call" }
 }
Index: gcc/testsuite/g++.dg/concepts/req1.C
===================================================================
--- gcc/testsuite/g++.dg/concepts/req1.C	(revision 0)
+++ gcc/testsuite/g++.dg/concepts/req1.C	(revision 0)
@@ -0,0 +1,15 @@
+// { dg-do run }
+// { dg-options "-std=c++1z" }
+
+template<typename T>
+  concept bool Class () { return __is_class(T); }
+
+void f1(auto a) requires Class<decltype(a)>() { }
+void f2(auto a) requires requires (decltype(a) x) { -x; } { }
+
+struct S { } s;
+
+int main() {
+  f1(s);
+  f2(0);
+}
Index: gcc/testsuite/g++.dg/concepts/req2.C
===================================================================
--- gcc/testsuite/g++.dg/concepts/req2.C	(revision 0)
+++ gcc/testsuite/g++.dg/concepts/req2.C	(revision 0)
@@ -0,0 +1,21 @@
+// { dg-options "-std=c++1z" }
+
+#include <cassert>
+
+template<typename T>
+  concept bool Class () { return __is_class(T); }
+
+void f1 (auto a) requires Class<decltype(a)>() { }
+
+  // FIXME: This is generating excess errors related to pretty
+  // printing the trailing requires expression.
+void f2(auto a) 
+  requires requires (decltype(a) x) { -x; } 
+{ } 
+
+struct S { } s;
+
+int main() {
+  f1(0); // { dg-error "matching" }
+  f2((void*)0); // { dg-error "matching" }
+}
Index: gcc/testsuite/g++.dg/concepts/req3.C
===================================================================
--- gcc/testsuite/g++.dg/concepts/req3.C	(revision 0)
+++ gcc/testsuite/g++.dg/concepts/req3.C	(revision 0)
@@ -0,0 +1,18 @@
+// { dg-do run }
+// { dg-options "-std=c++1z" }
+
+template<typename T>
+  concept bool Class () { return __is_class(T); }
+
+struct Test {
+  void f(auto a) requires Class<decltype(a)>();
+} test;
+
+struct S { }s;
+
+int main() {
+  test.f(s);
+}
+
+void Test::f(auto a) requires Class<decltype(a)>() { }
+
Index: gcc/testsuite/g++.dg/concepts/test.C
===================================================================
--- gcc/testsuite/g++.dg/concepts/test.C	(revision 212100)
+++ gcc/testsuite/g++.dg/concepts/test.C	(working copy)
@@ -1,17 +0,0 @@
-// { dg-options "-I/home/faculty/asutton/Code/origin -std=c++1z" }
-
-#include <algorithm>
-
-// #include <origin/range/stream.hpp>
-
-// int main() {
-//   std::string s = "1 2 3 4 5";
-//   std::istringstream ss(s);
-//   auto is = origin::make_istream<int>(ss);
-
-//   for(int x : is) {
-//      std::cout << x << '\n';
-//   }
-
-//   static_assert(not origin::Range<decltype(is)>(), "");
-// }
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 212456)
+++ gcc/cp/parser.c	(working copy)
@@ -16982,14 +16982,22 @@ struct cp_manage_requirements {
 static tree
 cp_parser_trailing_requirements (cp_parser *parser, cp_declarator *decl) 
 {
-  // A function declaration may have a trailing requires-clause.
   if (function_declarator_p (decl))
-    if (tree reqs = cp_parser_requires_clause_opt (parser))
-      current_template_reqs = save_trailing_requirements (reqs);
+    {
+      if (cp_lexer_next_token_is_keyword (parser->lexer, RID_REQUIRES))
+        {
+          ++cp_unevaluated_operand;
+          push_function_parms (decl);
+          cp_lexer_consume_token (parser->lexer);
+          tree reqs = cp_parser_requires_clause (parser);
+          current_template_reqs = save_trailing_requirements (reqs);
+          finish_scope();
+          --cp_unevaluated_operand;
+        }
+    }
   return current_template_reqs;
 }
 
-
 /* Declarators [gram.dcl.decl] */
 
 /* Parse an init-declarator.
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 212456)
+++ gcc/cp/decl.c	(working copy)
@@ -13864,6 +13864,30 @@ store_parm_decls (tree current_function_
     current_eh_spec_block = begin_eh_spec_block ();
 }
 
+// Bring the parameters of a function declaration back into 
+// scope without entering the function body. The declarator 
+// must be a function declarator. The caller is responsible 
+// for calling finish_scope.
+void
+push_function_parms (cp_declarator *declarator)
+{
+  // Find the actual function declarator.
+  while (declarator)
+    {
+      if (declarator->kind == cdk_function)
+        break;
+      declarator = declarator->declarator;
+    }
+
+  begin_scope (sk_function_parms, NULL_TREE);
+  tree p = declarator->u.function.parameters;
+  while (p != NULL_TREE && !VOID_TYPE_P (TREE_VALUE (p)))
+    {
+      pushdecl (TREE_VALUE (p));
+      p = TREE_CHAIN (p);
+    }
+}
+
 
 /* We have finished doing semantic analysis on DECL, but have not yet
    generated RTL for its body.  Save away our current state, so that
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 213130)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -5432,6 +5432,7 @@ extern bool defer_mark_used_calls;
 extern GTY(()) vec<tree, va_gc> *deferred_mark_used_calls;
 extern tree finish_case_label			(location_t, tree, tree);
 extern tree cxx_maybe_build_cleanup		(tree, tsubst_flags_t);
+extern void push_function_parms                (cp_declarator *);
 
 /* in decl2.c */
 extern bool check_java_method			(tree);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]