From 3ac1760d587b5eef110c2ad278419a565e72d166 Mon Sep 17 00:00:00 2001 From: asutton Date: Tue, 12 May 2015 12:21:04 +0000 Subject: [PATCH] 2015-05-08 Andrew Sutton PR66091 * gcc/cp/cp-tree.h (get_function_declarator): New. * gcc/cp/decl.c (get_trailing_requires_clause): Use get_function_declarator. * gcc/cp/parser.c (function_declarator_p): Likewise. (cp_parser_declarator): Stop invoking undefined behavior and install the requires clause on the found function declarator. * gcc/testsuite/g++.dg/concepts/pr66091.C: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/c++-concepts@223061 138bc75d-0d04-0410-961f-82ee72b054a4 --- ChangeLog.concepts | 12 ++++++++++++ gcc/cp/cp-tree.h | 26 ++++++++++++++++++++++++++ gcc/cp/decl.c | 11 ++++++----- gcc/cp/parser.c | 16 +++------------- gcc/testsuite/g++.dg/concepts/pr66091.C | 19 +++++++++++++++++++ 5 files changed, 66 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/g++.dg/concepts/pr66091.C diff --git a/ChangeLog.concepts b/ChangeLog.concepts index f5f3f62ce7f..e371a4ec818 100644 --- a/ChangeLog.concepts +++ b/ChangeLog.concepts @@ -1,5 +1,17 @@ 2015-05-08 Andrew Sutton + PR66091 + * gcc/cp/cp-tree.h (get_function_declarator): New. + * gcc/cp/decl.c (get_trailing_requires_clause): Use + get_function_declarator. + * gcc/cp/parser.c (function_declarator_p): Likewise. + (cp_parser_declarator): Stop invoking undefined behavior + and install the requires clause on the found function + declarator. + * gcc/testsuite/g++.dg/concepts/pr66091.C: New. + +2015-05-08 Andrew Sutton + Addressing review comments. * gcc/cp/call.c (build_new_function_call): Don't check for template parameters when we're not processing a template decl. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 5b45c70c7aa..1434c3a2951 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5283,6 +5283,32 @@ struct cp_declarator { } u; }; +/* Returns the declarator for a function declaration or NULL + if the declarator does not declare a function. */ + +inline cp_declarator * +get_function_declarator (cp_declarator *declarator) +{ + while (declarator) + { + if (declarator->kind == cdk_function + && declarator->declarator + && declarator->declarator->kind == cdk_id) + return declarator; + if (declarator->kind == cdk_id + || declarator->kind == cdk_error) + return NULL; + declarator = declarator->declarator; + } + return NULL; +} + +inline const cp_declarator * +get_function_declarator (const cp_declarator *declarator) +{ + return get_function_declarator(const_cast(declarator)); +} + /* A level of template instantiation. */ struct GTY((chain_next ("%h.next"))) tinst_level { /* The immediately deeper level in the chain. */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 0bc39b99bc0..9cc1cf26b12 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -8985,14 +8985,15 @@ check_var_type (tree identifier, tree type) return type; } -// Return a trailing requires clause for a function declarator, or -// NULL_TREE if there is no trailing requires clause or the declarator -// is some other kind. +/* Return a trailing requires clause for a function declarator, or + NULL_TREE if there is no trailing requires clause or the declarator + is some other kind. */ + static inline tree get_trailing_requires_clause (const cp_declarator *declarator) { - if (declarator && declarator->kind == cdk_function) - return declarator->u.function.requires_clause; + if (const cp_declarator *d = get_function_declarator (declarator)) + return d->u.function.requires_clause; else return NULL_TREE; } diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 2cfb9bda202..4aa0f42e29c 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1661,17 +1661,7 @@ make_parameter_declarator (cp_decl_specifier_seq *decl_specifiers, static bool function_declarator_p (const cp_declarator *declarator) { - while (declarator) - { - if (declarator->kind == cdk_function - && declarator->declarator->kind == cdk_id) - return true; - if (declarator->kind == cdk_id - || declarator->kind == cdk_error) - return false; - declarator = declarator->declarator; - } - return false; + return get_function_declarator (declarator) != NULL; } /* The parser. */ @@ -18107,8 +18097,8 @@ cp_parser_declarator (cp_parser* parser, declaration and not the abstract declarator. */ if (flag_concepts && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT) { - if (function_declarator_p (declarator)) - declarator->u.function.requires_clause + if (cp_declarator *fndecl = get_function_declarator (declarator)) + fndecl->u.function.requires_clause = cp_parser_trailing_requires_clause (parser, declarator); } return declarator; diff --git a/gcc/testsuite/g++.dg/concepts/pr66091.C b/gcc/testsuite/g++.dg/concepts/pr66091.C new file mode 100644 index 00000000000..ce0eb33bac0 --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/pr66091.C @@ -0,0 +1,19 @@ +// { dg-options "-std=c++1z" } + +template +concept bool C1() +{ + return requires() { typename T::type1; }; +} + +template +concept bool C2() +{ + return C1() && requires() { typename T::type2; }; +} + +template +struct S { + S& operator++() { return *this; } + S& operator++() requires C2() { return *this; } +}; -- 2.11.4.GIT