* [c++-concepts] Parsing for template requirements
@ 2013-03-01 16:13 Andrew Sutton
2013-03-01 17:09 ` Gabriel Dos Reis
0 siblings, 1 reply; 2+ messages in thread
From: Andrew Sutton @ 2013-03-01 16:13 UTC (permalink / raw)
To: gcc-patches; +Cc: Gabriel Dos Reis, Jason Merrill
[-- Attachment #1: Type: text/plain, Size: 1195 bytes --]
Two patches attached.
The reqs-parsing patch adds parsing support for template requirements
(i.e., requires clauses). This is supported for all template
declarations and non-template member functions of class templates.
Grammar changes are documented in comments. Semantic processing of
constraints is stubbed out for the time being.
The flags patch just enables -fconcepts by default.
The combined change log is:
2013-03-01 Andrew Sutton <andrew.n.sutton@gmail.com>
* cp-tree.h (saved_scope): Add template requirements.
(finish_template_requirements): Declare
* parser.c (cp_parser_template_requirement_opt): Declare.
(cp_parser_template_declaration): Document grammar extensions.
(cp_parser_type_parameter): Parse requirements for template
template parameters.
(cp_parser_member_declaration): Parse requirements for
members of class templates.
(cp_parser_template_requirement_opt): Define.
(cp_parser_template_declaration_after_exp): Parse requirements
for template declarations.
* semantics.c (finish_template_requirements): Define.
* lex.c (cxx_init): Enable concepts by default.
[-- Attachment #2: flags.patch --]
[-- Type: application/octet-stream, Size: 395 bytes --]
Index: gcc/cp/lex.c
===================================================================
--- gcc/cp/lex.c (revision 196385)
+++ gcc/cp/lex.c (working copy)
@@ -228,6 +228,8 @@ cxx_init (void)
EXPR_STMT
};
+ flag_concepts = true;
+
memset (&statement_code_p, 0, sizeof (statement_code_p));
for (i = 0; i < ARRAY_SIZE (stmt_codes); i++)
statement_code_p[stmt_codes[i]] = true;
[-- Attachment #3: reqs-parsing.patch --]
[-- Type: application/octet-stream, Size: 12800 bytes --]
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h (revision 196384)
+++ gcc/cp/cp-tree.h (working copy)
@@ -992,6 +992,7 @@ struct GTY(()) saved_scope {
vec<tree, va_gc> *lang_base;
tree lang_name;
tree template_parms;
+ tree template_reqs;
cp_binding_level *x_previous_class_level;
tree x_saved_tree;
@@ -1052,6 +1053,11 @@ struct GTY(()) saved_scope {
#define current_template_parms scope_chain->template_parms
+// When parsing a template declaration this node represents the
+// active template requirements. This includes the lists of
+// actual assumptions in the current scope.
+#define current_template_reqs scope_chain->template_reqs
+
#define processing_template_decl scope_chain->x_processing_template_decl
#define processing_specialization scope_chain->x_processing_specialization
#define processing_explicit_instantiation scope_chain->x_processing_explicit_instantiation
@@ -5725,6 +5731,7 @@ extern tree lambda_expr_this_capture
extern tree nonlambda_method_basetype (void);
extern void maybe_add_lambda_conv_op (tree);
extern bool is_lambda_ignored_entity (tree);
+extern tree finish_template_requirements (tree);
/* in tree.c */
extern int cp_tree_operand_length (const_tree);
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c (revision 196384)
+++ gcc/cp/parser.c (working copy)
@@ -2136,6 +2136,11 @@ static bool cp_parser_extension_opt
static void cp_parser_label_declaration
(cp_parser *);
+/* Concept Extensions */
+
+static tree cp_parser_template_requirement_opt
+ (cp_parser *);
+
/* Transactional Memory Extensions */
static tree cp_parser_transaction
@@ -12104,7 +12109,16 @@ cp_parser_operator (cp_parser* parser)
template-parameter-list-seq:
template-parameter-list-seq [opt]
- template < template-parameter-list > */
+ template < template-parameter-list >
+
+ Concept Extensions:
+
+ template-parameter-list-seq:
+ template < template-parameter-list > template-requirement [opt]
+
+ template-requirement:
+ requires logical-or-expression
+ */
static void
cp_parser_template_declaration (cp_parser* parser, bool member_p)
@@ -12442,7 +12456,21 @@ cp_parser_type_parameter (cp_parser* par
cp_parser_template_parameter_list (parser);
/* Look for the `>'. */
cp_parser_require (parser, CPP_GREATER, RT_GREATER);
- /* Look for the `class' keyword. */
+
+ // If template requirements are present, parse them.
+ tree saved_template_reqs = current_template_reqs;
+ if (flag_concepts)
+ {
+ if (tree req = cp_parser_template_requirement_opt (parser))
+ {
+ // The prameter's constraints are independent of
+ // the enclosing scope.
+ current_template_reqs = NULL_TREE;
+ current_template_reqs = finish_template_requirements (req);
+ }
+ }
+
+ /* Look for the `class' keyword. */
cp_parser_require_keyword (parser, RID_CLASS, RT_CLASS);
/* If the next token is an ellipsis, we have a template
argument pack. */
@@ -12474,6 +12502,8 @@ cp_parser_type_parameter (cp_parser* par
parameter = finish_template_template_parm (class_type_node,
identifier);
+ current_template_reqs = saved_template_reqs;
+
/* If the next token is an `=', then there is a
default-argument. */
if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
@@ -19024,7 +19054,20 @@ cp_parser_member_specification_opt (cp_p
C++0x Extensions:
member-declaration:
- static_assert-declaration */
+ static_assert-declaration
+
+
+ Concepts Extensions:
+
+ member-declaration:
+ constrained-member-declaration:
+
+ constrained-member-declaration:
+ requires logical-or-expression constrained-member-declarator
+
+ constrained-member-declarator:
+ decl-specifier-seq [opt] member-declarator-list [opt] ;
+ function-definition ; [opt] */
static void
cp_parser_member_declaration (cp_parser* parser)
@@ -19051,81 +19094,99 @@ cp_parser_member_declaration (cp_parser*
return;
}
- /* Check for a template-declaration. */
- if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE))
+ // If the declaration starts with a requires clause, parse a constrained
+ // member declaration. Note that we can only have constrained members
+ // in a template.
+ tree saved_template_reqs = current_template_reqs;
+ bool unconstrained = true;
+ if (flag_concepts && processing_template_decl)
{
- /* An explicit specialization here is an error condition, and we
- expect the specialization handler to detect and report this. */
- if (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_LESS
- && cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_GREATER)
- cp_parser_explicit_specialization (parser);
- else
- cp_parser_template_declaration (parser, /*member_p=*/true);
-
- return;
+ if (tree req = cp_parser_template_requirement_opt (parser))
+ {
+ current_template_reqs = finish_template_requirements (req);
+ unconstrained = false;
+ }
}
- /* Check for a using-declaration. */
- if (cp_lexer_next_token_is_keyword (parser->lexer, RID_USING))
+ if (unconstrained)
{
- if (cxx_dialect < cxx0x)
- {
- /* Parse the using-declaration. */
- cp_parser_using_declaration (parser,
- /*access_declaration_p=*/false);
- return;
- }
- else
- {
- tree decl;
- bool alias_decl_expected;
- cp_parser_parse_tentatively (parser);
- decl = cp_parser_alias_declaration (parser);
- /* Note that if we actually see the '=' token after the
- identifier, cp_parser_alias_declaration commits the
- tentative parse. In that case, we really expects an
- alias-declaration. Otherwise, we expect a using
- declaration. */
- alias_decl_expected =
- !cp_parser_uncommitted_to_tentative_parse_p (parser);
- cp_parser_parse_definitely (parser);
+ /* Check for a template-declaration. */
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE))
+ {
+ /* An explicit specialization here is an error condition, and we
+ expect the specialization handler to detect and report this. */
+ if (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_LESS
+ && cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_GREATER)
+ cp_parser_explicit_specialization (parser);
+ else
+ cp_parser_template_declaration (parser, /*member_p=*/true);
- if (alias_decl_expected)
- finish_member_declaration (decl);
- else
- cp_parser_using_declaration (parser,
- /*access_declaration_p=*/false);
- return;
- }
- }
+ return;
+ }
- /* Check for @defs. */
- if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_DEFS))
- {
- tree ivar, member;
- tree ivar_chains = cp_parser_objc_defs_expression (parser);
- ivar = ivar_chains;
- while (ivar)
- {
- member = ivar;
- ivar = TREE_CHAIN (member);
- TREE_CHAIN (member) = NULL_TREE;
- finish_member_declaration (member);
- }
- return;
- }
+ /* Check for a using-declaration. */
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_USING))
+ {
+ if (cxx_dialect < cxx0x)
+ {
+ /* Parse the using-declaration. */
+ cp_parser_using_declaration (parser,
+ /*access_declaration_p=*/false);
+ return;
+ }
+ else
+ {
+ tree decl;
+ bool alias_decl_expected;
+ cp_parser_parse_tentatively (parser);
+ decl = cp_parser_alias_declaration (parser);
+ /* Note that if we actually see the '=' token after the
+ identifier, cp_parser_alias_declaration commits the
+ tentative parse. In that case, we really expects an
+ alias-declaration. Otherwise, we expect a using
+ declaration. */
+ alias_decl_expected =
+ !cp_parser_uncommitted_to_tentative_parse_p (parser);
+ cp_parser_parse_definitely (parser);
+
+ if (alias_decl_expected)
+ finish_member_declaration (decl);
+ else
+ cp_parser_using_declaration (parser,
+ /*access_declaration_p=*/false);
+ return;
+ }
+ }
- /* If the next token is `static_assert' we have a static assertion. */
- if (cp_lexer_next_token_is_keyword (parser->lexer, RID_STATIC_ASSERT))
- {
- cp_parser_static_assert (parser, /*member_p=*/true);
- return;
+ /* Check for @defs. */
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_DEFS))
+ {
+ tree ivar, member;
+ tree ivar_chains = cp_parser_objc_defs_expression (parser);
+ ivar = ivar_chains;
+ while (ivar)
+ {
+ member = ivar;
+ ivar = TREE_CHAIN (member);
+ TREE_CHAIN (member) = NULL_TREE;
+ finish_member_declaration (member);
+ }
+ return;
+ }
+
+ /* If the next token is `static_assert' we have a static assertion. */
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_STATIC_ASSERT))
+ {
+ cp_parser_static_assert (parser, /*member_p=*/true);
+ return;
+ }
}
parser->colon_corrects_to_scope_p = false;
- if (cp_parser_using_declaration (parser, /*access_declaration=*/true))
- goto out;
+ if (unconstrained)
+ if (cp_parser_using_declaration (parser, /*access_declaration=*/true))
+ goto out;
/* Parse the decl-specifier-seq. */
decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
@@ -19501,6 +19562,7 @@ cp_parser_member_declaration (cp_parser*
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
out:
+ current_template_reqs = saved_template_reqs;
parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
}
@@ -20919,6 +20981,30 @@ cp_parser_label_declaration (cp_parser*
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
}
+
+// Parse an optional template requirement, returning NULL_TREE if no
+// 'requires' clause is found. The template requirement is required to
+// be a constant expression.
+static tree
+cp_parser_template_requirement_opt (cp_parser* parser)
+{
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_REQUIRES))
+ cp_lexer_consume_token (parser->lexer);
+ else
+ return NULL_TREE;
+
+ // Parse a logical-or-expression as a constant expression.
+ tree expression =
+ cp_parser_binary_expression (parser, false, false, PREC_NOT_OPERATOR, NULL);
+ if (!potential_rvalue_constant_expression (expression))
+ {
+ require_potential_rvalue_constant_expression (expression);
+ return error_mark_node;
+ }
+ return expression;
+}
+
+
/* Support Functions */
/* Looks up NAME in the current scope, as given by PARSER->SCOPE.
@@ -21778,6 +21864,15 @@ cp_parser_template_declaration_after_exp
cp_parser_skip_to_end_of_template_parameter_list (parser);
/* We just processed one more parameter list. */
++parser->num_template_parameter_lists;
+
+ // Parse template requirements if any have been given.
+ tree saved_template_reqs = current_template_reqs;
+ if (flag_concepts)
+ {
+ if (tree req = cp_parser_template_requirement_opt (parser))
+ current_template_reqs = finish_template_requirements (req);
+ }
+
/* If the next token is `template', there are more template
parameters. */
if (cp_lexer_next_token_is_keyword (parser->lexer,
@@ -21821,6 +21916,7 @@ cp_parser_template_declaration_after_exp
/* Finish up. */
finish_template_decl (parameter_list);
+ current_template_reqs = saved_template_reqs;
/* Check the template arguments for a literal operator template. */
if (decl
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c (revision 196384)
+++ gcc/cp/semantics.c (working copy)
@@ -9561,4 +9561,16 @@ is_lambda_ignored_entity (tree val)
return false;
}
+// Decompose the template requirements, given by EXPRESSION, into a set of
+// assumptions for the local scope.
+tree
+finish_template_requirements (tree expression)
+{
+ if (expression == error_mark_node)
+ return NULL_TREE;
+
+ sorry ("no template requirements yet");
+ return NULL_TREE;
+}
+
#include "gt-cp-semantics.h"
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [c++-concepts] Parsing for template requirements
2013-03-01 16:13 [c++-concepts] Parsing for template requirements Andrew Sutton
@ 2013-03-01 17:09 ` Gabriel Dos Reis
0 siblings, 0 replies; 2+ messages in thread
From: Gabriel Dos Reis @ 2013-03-01 17:09 UTC (permalink / raw)
To: Andrew Sutton; +Cc: gcc-patches, Gabriel Dos Reis, Jason Merrill
On Fri, Mar 1, 2013 at 10:12 AM, Andrew Sutton
<andrew.n.sutton@gmail.com> wrote:
> Two patches attached.
>
> The reqs-parsing patch adds parsing support for template requirements
> (i.e., requires clauses). This is supported for all template
> declarations and non-template member functions of class templates.
> Grammar changes are documented in comments. Semantic processing of
> constraints is stubbed out for the time being.
>
> The flags patch just enables -fconcepts by default.
>
> The combined change log is:
>
> 2013-03-01 Andrew Sutton <andrew.n.sutton@gmail.com>
Patch OK, thanks. Please adjust the paths in the log to include
the directories -- since everything is going in the toplevel ChangeLog.concepts.
-- Gaby
>
> * cp-tree.h (saved_scope): Add template requirements.
> (finish_template_requirements): Declare
> * parser.c (cp_parser_template_requirement_opt): Declare.
> (cp_parser_template_declaration): Document grammar extensions.
> (cp_parser_type_parameter): Parse requirements for template
> template parameters.
> (cp_parser_member_declaration): Parse requirements for
> members of class templates.
> (cp_parser_template_requirement_opt): Define.
> (cp_parser_template_declaration_after_exp): Parse requirements
> for template declarations.
> * semantics.c (finish_template_requirements): Define.
> * lex.c (cxx_init): Enable concepts by default.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2013-03-01 17:09 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-01 16:13 [c++-concepts] Parsing for template requirements Andrew Sutton
2013-03-01 17:09 ` Gabriel Dos Reis
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).