Re: Patch for constexpr variable templates
Oohh... I can commit to trunk? Yes, you're on the write-after-approval list in MAINTAINERS. :) True, but it's my first commit to trunk :) Incidentally, that's committed now. Andrew
Re: Patch for constexpr variable templates
* pt.c (lookup_template_variable): Make the type unspecified if any template arguments are dependent. This hunk is OK. Hi Jason, did you apply this hunk of the patch, or should I just resend this by itself? Andrew
Re: Patch for constexpr variable templates
On 08/12/2014 04:21 PM, Andrew Sutton wrote: * pt.c (lookup_template_variable): Make the type unspecified if any template arguments are dependent. This hunk is OK. Hi Jason, did you apply this hunk of the patch, or should I just resend this by itself? I thought you would apply it, but I can if you'd rather. Jason
Re: Patch for constexpr variable templates
Oohh... I can commit to trunk? I can do it tomorrow morning. Andrew Sutton On Tue, Aug 12, 2014 at 4:59 PM, Jason Merrill ja...@redhat.com wrote: On 08/12/2014 04:21 PM, Andrew Sutton wrote: * pt.c (lookup_template_variable): Make the type unspecified if any template arguments are dependent. This hunk is OK. Hi Jason, did you apply this hunk of the patch, or should I just resend this by itself? I thought you would apply it, but I can if you'd rather. Jason
Re: Patch for constexpr variable templates
On 08/12/2014 05:17 PM, Andrew Sutton wrote: Oohh... I can commit to trunk? Yes, you're on the write-after-approval list in MAINTAINERS. :) Jason
Re: Patch for constexpr variable templates
On 08/07/2014 09:22 AM, Andrew Sutton wrote: * pt.c (lookup_template_variable): Make the type unspecified if any template arguments are dependent. This hunk is OK. * decl.c (cp_finish_decl): Don't check the initializer if it is value-dependent. Why is this needed? Jason
Re: Patch for constexpr variable templates
* decl.c (cp_finish_decl): Don't check the initializer if it is value-dependent. Why is this needed? I thought that check_initializer was evaluating the constant expression, and was resulting in errors because a template-id referring to a variable template with a concrete type wasn't being marked as dependent. Taking a second look, this change doesn't appear to be needed. The change to lookup_template_variable seems to do enough. I just reran the tests and it seems to behave correctly without it. Andrew
Re: Patch for constexpr variable templates
Hi, On 08/06/2014 06:41 AM, Braden Obrzut wrote: I can confirm that this is caused by a change to pt.c that happened, I think, the day before my last patch. This can be fixed by first checking that the template is a function template at that line in pt.c. Since variable templates can't be friends, it might also be suitable to skip that entire block if it is a function template. Patch looks simple, then. Should I submit that as a patch? I suppose Jason would be glad to review and apply it! Thanks, Paolo.
Re: Patch for constexpr variable templates
Here's a patch for the more conservative option. - Braden Obrzut 2014-08-06 Braden Obrzut ad...@maniacsvault.net * pt.c (check_explicit_specialization): Ensure tmpl is a function template before checking if it is inline for COMDAT. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 57e7216..3bc3961 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -2817,7 +2817,7 @@ check_explicit_specialization (tree declarator, It's just the name of an instantiation. But, it's not a request for an instantiation, either. */ SET_DECL_IMPLICIT_INSTANTIATION (decl); - else + else if (DECL_FUNCTION_TEMPLATE_P (tmpl)) /* A specialization is not necessarily COMDAT. */ DECL_COMDAT (decl) = DECL_DECLARED_INLINE_P (decl);
Re: Patch for constexpr variable templates
On 08/05/2014 04:06 PM, Paolo Carlini wrote: Great. I will double check but var-templ4.C fails for me with an ICE. Hunh, I wonder how I missed that. Here's what I'm checking in; we want to unset DECL_COMDAT for variable templates, too. commit b79ecb5928b875ba38b78a3fadb0dd70d6262513 Author: Jason Merrill ja...@redhat.com Date: Wed Aug 6 11:14:55 2014 -0400 * pt.c (check_explicit_specialization): Don't test DECL_DECLARED_INLINE_P for a variable template. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 57e7216..998ace2 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -2817,9 +2817,11 @@ check_explicit_specialization (tree declarator, It's just the name of an instantiation. But, it's not a request for an instantiation, either. */ SET_DECL_IMPLICIT_INSTANTIATION (decl); - else + else if (TREE_CODE (decl) == FUNCTION_DECL) /* A specialization is not necessarily COMDAT. */ DECL_COMDAT (decl) = DECL_DECLARED_INLINE_P (decl); + else if (TREE_CODE (decl) == VAR_DECL) + DECL_COMDAT (decl) = false; /* Register this specialization so that we can find it again. */
Re: Patch for constexpr variable templates
Applied with a few formatting/comment tweaks, thanks! Jason
Re: Patch for constexpr variable templates
Hi, On 08/05/2014 08:26 PM, Jason Merrill wrote: Applied with a few formatting/comment tweaks, thanks! Great. I will double check but var-templ4.C fails for me with an ICE. Can anybody reproduce? Thanks! Paolo. /.../gcc/testsuite/g++.dg/cpp1y/var-templ4.C:8:17: internal compiler error: tree check: expected function_decl, have var_decl in check_explicit_specialization, at cp/pt.c:2822 0xde05a4 tree_check_failed(tree_node const*, char const*, int, char const*, ...) ../../trunk/gcc/tree.c:9174 0x5f9dd9 tree_check(tree_node*, char const*, int, char const*, tree_code) ../../trunk/gcc/tree.h:2729 0x5f9dd9 check_explicit_specialization(tree_node*, tree_node*, int, int) ../../trunk/gcc/cp/pt.c:2822 0x5af6e1 grokvardecl ../../trunk/gcc/cp/decl.c:8079 0x5af6e1 grokdeclarator(cp_declarator const*, cp_decl_specifier_seq*, decl_context, int, tree_node**) ../../trunk/gcc/cp/decl.c:10918 0x5b24b4 start_decl(cp_declarator const*, cp_decl_specifier_seq*, int, tree_node*, tree_node*, tree_node**) ../../trunk/gcc/cp/decl.c:4572 0x68ff5f cp_parser_init_declarator ../../trunk/gcc/cp/parser.c:16920 0x690b0a cp_parser_single_declaration ../../trunk/gcc/cp/parser.c:23494 0x69160d cp_parser_explicit_specialization ../../trunk/gcc/cp/parser.c:14418 0x69bfaf cp_parser_declaration ../../trunk/gcc/cp/parser.c:11152 0x69ab18 cp_parser_declaration_seq_opt ../../trunk/gcc/cp/parser.c:11085 0x69c3b3 cp_parser_translation_unit ../../trunk/gcc/cp/parser.c:4061 0x69c3b3 c_parse_file() ../../trunk/gcc/cp/parser.c:31954 0x7c0712 c_common_parse_file() ../../trunk/gcc/c-family/c-opts.c:1115
Re: Patch for constexpr variable templates
I can confirm that this is caused by a change to pt.c that happened, I think, the day before my last patch. This can be fixed by first checking that the template is a function template at that line in pt.c. Since variable templates can't be friends, it might also be suitable to skip that entire block if it is a function template. Should I submit that as a patch? - Braden Obrzut On 08/05/2014 04:06 PM, Paolo Carlini wrote: Hi, On 08/05/2014 08:26 PM, Jason Merrill wrote: Applied with a few formatting/comment tweaks, thanks! Great. I will double check but var-templ4.C fails for me with an ICE. Can anybody reproduce? Thanks! Paolo. /.../gcc/testsuite/g++.dg/cpp1y/var-templ4.C:8:17: internal compiler error: tree check: expected function_decl, have var_decl in check_explicit_specialization, at cp/pt.c:2822 0xde05a4 tree_check_failed(tree_node const*, char const*, int, char const*, ...) ../../trunk/gcc/tree.c:9174 0x5f9dd9 tree_check(tree_node*, char const*, int, char const*, tree_code) ../../trunk/gcc/tree.h:2729 0x5f9dd9 check_explicit_specialization(tree_node*, tree_node*, int, int) ../../trunk/gcc/cp/pt.c:2822 0x5af6e1 grokvardecl ../../trunk/gcc/cp/decl.c:8079 0x5af6e1 grokdeclarator(cp_declarator const*, cp_decl_specifier_seq*, decl_context, int, tree_node**) ../../trunk/gcc/cp/decl.c:10918 0x5b24b4 start_decl(cp_declarator const*, cp_decl_specifier_seq*, int, tree_node*, tree_node*, tree_node**) ../../trunk/gcc/cp/decl.c:4572 0x68ff5f cp_parser_init_declarator ../../trunk/gcc/cp/parser.c:16920 0x690b0a cp_parser_single_declaration ../../trunk/gcc/cp/parser.c:23494 0x69160d cp_parser_explicit_specialization ../../trunk/gcc/cp/parser.c:14418 0x69bfaf cp_parser_declaration ../../trunk/gcc/cp/parser.c:11152 0x69ab18 cp_parser_declaration_seq_opt ../../trunk/gcc/cp/parser.c:11085 0x69c3b3 cp_parser_translation_unit ../../trunk/gcc/cp/parser.c:4061 0x69c3b3 c_parse_file() ../../trunk/gcc/cp/parser.c:31954 0x7c0712 c_common_parse_file() ../../trunk/gcc/c-family/c-opts.c:1115
Re: Patch for constexpr variable templates
On 07/31/2014 08:53 AM, Jason Merrill wrote: In the original mail you mentioned doing it in cp_parser_template_id; I agree that we probably don't want to do it there because of the complications you are seeing. I was thinking about doing it when we normally resolve an id-expression that refers to a variable, once we know we're looking at an expression and not a declarator-id. But I think my suggestion of cp_parser_id_expression was wrong, and it would be better in finish_id_expression. Jason Ahh sorry, I misread the function name you gave. finish_id_expression works just fine and doesn't require any extra work. How does this patch look? - Braden Obrzut 2014-08-01 Braden Obrzut ad...@maniacsvault.net * decl.c (grokvardecl): Handle specializations of variable templates. (grokdeclarator): Handle variable template id expressions and NULL_TREE return from grokvardecl. * decl2.c (check_member_template): Allow declaration of template member variables. * parser.c (cp_parser_template_id): Build a TEMPLATE_ID_EXPR for variable templates. * pt.c (determine_specialization): Accept variable templates. (check_template_variable): Fixed wanted template header count and change non static data member error to variable template warning. (check_explicit_specialization): Handle and check for malformed variable template specializations. (lookup_template_variable): New. (tsubst_decl): Handle variable template specializations. (do_decl_instantiation): Handle template variables. (instantiate_decl): Handle template variables. * semantics.c (finish_template_variable): New. (finish_id_expression): Instantiate variable templates. 2014-08-01 Braden Obrzut ad...@maniacsvault.net * g++.dg/cpp1y/var-templ1.C: New. * g++.dg/cpp1y/var-templ2.C: New. * g++.dg/cpp1y/var-templ3.C: New. * g++.dg/cpp1y/var-templ4.C: New. * g++.dg/cpp1y/var-templ5.C: New. * g++.dg/cpp1y/pr59638.C: Marked xfail for template variables as function pointers taking auto are considered templates at the moment. * g++.dg/parse/error50.C: Malformed statements look like variable templ. * g++.dg/template/crash71.C: Looks like variable templ. * g++.old-deja/g++.oliva/template10.C: Looks like variable templ. * g++.old-deja/g++.pt/var1.C: Non-constexpr variable templ. 2013-03-29 Gabriel Dos Reis g...@integrable-solutions.net * cp-tree.h (variable_template_p): Do not check scope. * pt.c (check_template_variable): Fix thinko from previous change. (push_template_decl_real): Fix formatting. 2013-03-29 Gabriel Dos Reis g...@integrable-solutions.net * cp-tree.h (variable_template_p): New. * pt.c (check_template_variable): Accept variable temploids at non-class scope. (push_template_decl_real): The current instantiation of a template can be a VAR_DECL. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4a5cb98..c6c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5027,6 +5027,17 @@ class_of_this_parm (const_tree fntype) return TREE_TYPE (type_of_this_parm (fntype)); } +/* True if T designates a variable template declaration. */ +inline bool +variable_template_p (tree t) +{ + if (TREE_CODE (t) != TEMPLATE_DECL) +return false; + if (tree r = DECL_TEMPLATE_RESULT (t)) +return VAR_P (r); + return false; +} + /* A parameter list indicating for a function with no parameters, e.g int f(void). */ extern cp_parameter_declarator *no_parameters; @@ -5554,6 +5565,7 @@ extern bool redeclare_class_template (tree, tree); extern tree lookup_template_class (tree, tree, tree, tree, int, tsubst_flags_t); extern tree lookup_template_function (tree, tree); +extern tree lookup_template_variable (tree, tree); extern int uses_template_parms (tree); extern int uses_template_parms_level (tree, int); extern bool in_template_function (void); @@ -5816,6 +5828,7 @@ extern tree perform_koenig_lookup (tree, vectree, va_gc *, tsubst_flags_t); extern tree finish_call_expr (tree, vectree, va_gc **, bool, bool, tsubst_flags_t); +extern tree finish_template_variable (tree); extern tree finish_increment_expr (tree, enum tree_code); extern tree finish_this_expr (void); extern tree finish_pseudo_destructor_expr (tree, tree, tree, location_t); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index dae85c2..2ac0472 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -80,8 +80,8 @@ static int ambi_op_p (enum tree_code); static int unary_op_p (enum tree_code); static void push_local_name (tree); static tree grok_reference_init (tree, tree, tree, int); -static tree grokvardecl (tree, tree, const cp_decl_specifier_seq *, - int, int, tree); +static tree grokvardecl (tree, tree, tree, const cp_decl_specifier_seq *, + int, int, int, tree); static int check_static_variable_definition (tree, tree); static void record_unknown_type (tree, const char *);
Re: Patch for constexpr variable templates
Here's an updated patch with cp_parser_id_expression instantiating the variable templates if this is indeed what we want to do. The previous implementation did seem to make the distinction between static template class member variables and variable templates a bit more obvious. See the first change to check_explicit_specialization. Related to that, grokvardecl might be using build_lang_decl more often than it did previously. I might be able to narrow that down a little, but I'm not sure. - Braden Obrzut 2014-07-31 Braden Obrzut ad...@maniacsvault.net * decl.c (grokvardecl): Handle specializations of variable templates. (grokdeclarator): Handle variable template id expressions and NULL_TREE return from grokvardecl. * decl2.c (check_member_template): Allow declaration of template member variables. * parser.c (make_id_declarator): Accept VAR_DECL for variable templates. (cp_parser_template_id): Handle variable templates and return a VAR_DECL. (cp_parser_lookup_name): May now be passed a VAR_DECL which is already resolved. * pt.c (determine_specialization): Accept variable templates. (check_template_variable): Fixed wanted template header count and change non static data member error to variable template warning. (check_explicit_specialization): Handle variable templates. (lookup_template_variable): New. (tsubst_decl): Handle variable template specializations. (do_decl_instantiation): Handle template variables. (instantiate_decl): Handle template variables. * semantics.c (finish_template_variable): New. 2014-07-31 Braden Obrzut ad...@maniacsvault.net * g++.dg/cpp1y/var-templ1.C: New. * g++.dg/cpp1y/var-templ2.C: New. * g++.dg/cpp1y/var-templ3.C: New. * g++.dg/cpp1y/var-templ4.C: New. * g++.dg/cpp1y/var-templ5.C: New. * g++.dg/cpp1y/pr59638.C: Marked xfail for template variables as function pointers taking auto are considered templates at the moment. * g++.dg/parse/error50.C: Malformed statements look like variable templ. * g++.dg/template/crash71.C: Looks like variable templ. * g++.old-deja/g++.oliva/template10.C: Looks like variable templ. * g++.old-deja/g++.pt/var1.C: Non-constexpr variable templ. 2013-03-29 Gabriel Dos Reis g...@integrable-solutions.net * cp-tree.h (variable_template_p): Do not check scope. * pt.c (check_template_variable): Fix thinko from previous change. (push_template_decl_real): Fix formatting. 2013-03-29 Gabriel Dos Reis g...@integrable-solutions.net * cp-tree.h (variable_template_p): New. * pt.c (check_template_variable): Accept variable temploids at non-class scope. (push_template_decl_real): The current instantiation of a template can be a VAR_DECL. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4a5cb98..c6c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5027,6 +5027,17 @@ class_of_this_parm (const_tree fntype) return TREE_TYPE (type_of_this_parm (fntype)); } +/* True if T designates a variable template declaration. */ +inline bool +variable_template_p (tree t) +{ + if (TREE_CODE (t) != TEMPLATE_DECL) +return false; + if (tree r = DECL_TEMPLATE_RESULT (t)) +return VAR_P (r); + return false; +} + /* A parameter list indicating for a function with no parameters, e.g int f(void). */ extern cp_parameter_declarator *no_parameters; @@ -5554,6 +5565,7 @@ extern bool redeclare_class_template (tree, tree); extern tree lookup_template_class (tree, tree, tree, tree, int, tsubst_flags_t); extern tree lookup_template_function (tree, tree); +extern tree lookup_template_variable (tree, tree); extern int uses_template_parms (tree); extern int uses_template_parms_level (tree, int); extern bool in_template_function (void); @@ -5816,6 +5828,7 @@ extern tree perform_koenig_lookup (tree, vectree, va_gc *, tsubst_flags_t); extern tree finish_call_expr (tree, vectree, va_gc **, bool, bool, tsubst_flags_t); +extern tree finish_template_variable (tree); extern tree finish_increment_expr (tree, enum tree_code); extern tree finish_this_expr (void); extern tree finish_pseudo_destructor_expr (tree, tree, tree, location_t); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index dae85c2..c9c36d8 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -80,8 +80,8 @@ static int ambi_op_p (enum tree_code); static int unary_op_p (enum tree_code); static void push_local_name (tree); static tree grok_reference_init (tree, tree, tree, int); -static tree grokvardecl (tree, tree, const cp_decl_specifier_seq *, - int, int, tree); +static tree grokvardecl (tree, tree, tree, const cp_decl_specifier_seq *, + int, int, int, tree); static int check_static_variable_definition (tree, tree); static void record_unknown_type (tree, const char *); static tree builtin_function_1 (tree, tree, bool); @@ -7943,9 +7943,11 @@
Re: Patch for constexpr variable templates
On 07/30/2014 05:33 PM, Braden Obrzut wrote: On 07/30/2014 04:44 PM, Jason Merrill wrote: Why not do this in cp_parser_id_expression? I did mention this in the original mail, is this definitely the way it should be done? In the original mail you mentioned doing it in cp_parser_template_id; I agree that we probably don't want to do it there because of the complications you are seeing. I was thinking about doing it when we normally resolve an id-expression that refers to a variable, once we know we're looking at an expression and not a declarator-id. But I think my suggestion of cp_parser_id_expression was wrong, and it would be better in finish_id_expression. Jason
Re: Patch for constexpr variable templates
On 07/29/2014 07:56 AM, Braden Obrzut wrote: @@ -6289,6 +6289,14 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, break; default: + /* Convert variable template into VAR_DECL. */ + if (TREE_CODE (postfix_expression) == TEMPLATE_ID_EXPR + variable_template_p (TREE_OPERAND (postfix_expression, 0))) + { + postfix_expression = finish_template_variable (postfix_expression); + } Why not do this in cp_parser_id_expression? + if (DECL_FUNCTION_TEMPLATE_P (tmpl) + DECL_STATIC_FUNCTION_P (tmpl) Indentation mismatch. Jason
Re: Patch for constexpr variable templates
On 07/30/2014 04:44 PM, Jason Merrill wrote: Why not do this in cp_parser_id_expression? I did mention this in the original mail, is this definitely the way it should be done? Andrew pointed this out to me before sending in the patch, my initial investigation into doing so seemed to show it would require more changes than doing it later since that would mean that cp_parser_id_expression has another possible return type (to be fair, I didn't carry out a full implementation). What I'm doing is equivalent to the point where function templates are instantiated so it could go either way, but from what I understand the only reason function templates are handled like that is because of overload resolution? My implementation strategy thus far has been to mirror function templates as long as possible. - Braden Obrzut
Re: Patch for constexpr variable templates
This version of the patch should pass the entire test suite. g++.dg/parse/error50.C noted that wasn't handling the case of empty template parameters properly (accepted silently). As a result, grokvardecl now calls check_explicit_specialization more liberally and may return NULL_TREE. The other changes to test cases are a result of this change causing additional errors on certain, variable template like constructs to be thrown. - Braden Obrzut 2014-07-29 Braden Obrzut ad...@maniacsvault.net * decl.c (grokvardecl): Handle specializations of variable templates. (grokdeclarator): Handle variable template id expressions and NULL_TREE return from grokvardecl. * decl2.c (check_member_template): Allow declaration of template member variables. * parser.c (cp_parser_postfix_expression): Resolve VAR_DECLs from TEMPLATE_ID_EXPRs. (cp_parser_template_id): Build a TEMPLATE_ID_EXPR for variable templates. * pt.c (register_specialization): Accept variable templates. (determine_specialization): Accept variable templates. (check_template_variable): Fixed wanted template header count and change non static data member error to variable template warning. (lookup_template_variable): New. (do_decl_instantiation): Handle template variables. (instantiate_decl): Handle template variables. * semantics.c (finish_template_variable): New. 2014-07-29 Braden Obrzut ad...@maniacsvault.net * g++.dg/cpp1y/var-templ1.C: New. * g++.dg/cpp1y/var-templ2.C: New. * g++.dg/cpp1y/var-templ3.C: New. * g++.dg/cpp1y/var-templ4.C: New. * g++.dg/cpp1y/var-templ5.C: New. * g++.dg/cpp1y/pr59638.C: Marked xfail for template variables as function pointers taking auto are considered templates at the moment. * g++.dg/parse/error50.C: Malformed statements look like variable templ. * g++.dg/template/crash71.C: Looks like variable templ. * g++.old-deja/g++.oliva/template10.C: Looks like variable templ. * g++.old-deja/g++.pt/var1.C: Non-constexpr variable templ. 2013-03-29 Gabriel Dos Reis g...@integrable-solutions.net * cp-tree.h (variable_template_p): Do not check scope. * pt.c (check_template_variable): Fix thinko from previous change. (push_template_decl_real): Fix formatting. 2013-03-29 Gabriel Dos Reis g...@integrable-solutions.net * cp-tree.h (variable_template_p): New. * pt.c (check_template_variable): Accept variable temploids at non-class scope. (push_template_decl_real): The current instantiation of a template can be a VAR_DECL. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4a5cb98..c6c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5027,6 +5027,17 @@ class_of_this_parm (const_tree fntype) return TREE_TYPE (type_of_this_parm (fntype)); } +/* True if T designates a variable template declaration. */ +inline bool +variable_template_p (tree t) +{ + if (TREE_CODE (t) != TEMPLATE_DECL) +return false; + if (tree r = DECL_TEMPLATE_RESULT (t)) +return VAR_P (r); + return false; +} + /* A parameter list indicating for a function with no parameters, e.g int f(void). */ extern cp_parameter_declarator *no_parameters; @@ -5554,6 +5565,7 @@ extern bool redeclare_class_template (tree, tree); extern tree lookup_template_class (tree, tree, tree, tree, int, tsubst_flags_t); extern tree lookup_template_function (tree, tree); +extern tree lookup_template_variable (tree, tree); extern int uses_template_parms (tree); extern int uses_template_parms_level (tree, int); extern bool in_template_function (void); @@ -5816,6 +5828,7 @@ extern tree perform_koenig_lookup (tree, vectree, va_gc *, tsubst_flags_t); extern tree finish_call_expr (tree, vectree, va_gc **, bool, bool, tsubst_flags_t); +extern tree finish_template_variable (tree); extern tree finish_increment_expr (tree, enum tree_code); extern tree finish_this_expr (void); extern tree finish_pseudo_destructor_expr (tree, tree, tree, location_t); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index dae85c2..2ac0472 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -80,8 +80,8 @@ static int ambi_op_p (enum tree_code); static int unary_op_p (enum tree_code); static void push_local_name (tree); static tree grok_reference_init (tree, tree, tree, int); -static tree grokvardecl (tree, tree, const cp_decl_specifier_seq *, - int, int, tree); +static tree grokvardecl (tree, tree, tree, const cp_decl_specifier_seq *, + int, int, int, tree); static int check_static_variable_definition (tree, tree); static void record_unknown_type (tree, const char *); static tree builtin_function_1 (tree, tree, bool); @@ -7943,9 +7943,11 @@ set_linkage_for_static_data_member (tree decl) static tree grokvardecl (tree type, tree name, + tree orig_declarator, const cp_decl_specifier_seq *declspecs, int initialized, int constp, + int
Re: Patch for constexpr variable templates
On 2014-07-28 3:06, Braden Obrzut wrote: So given this, should I leave the test cases that fail for this reason alone or should I still change them to dg-message? I'm not sure what GCC's policy is here, Jason will. It sounds like GCC's behavior with auto in function parameters needs to be changed, but that definitely sounds like a separate patch to me. I think so. It's definitely a different patch. I've been thinking about a simple way for your patch to add to the constraints for 'auto_is_implicit_function_template_parm_p' in 'cp_parser_parameter_declaration_clause' but this is happening incrementally at parse time and I can't see how to distinguish between the following 'auto' parameters: 1) auto f(auto);// generic function 'f'; transformed into template by 'auto' in parameter list. 2) auto (*f) (auto);// plain variable 'f' (should have an initializer for deduction of 'auto's. 3) auto (*f (auto)) (auto); // generic function 'f' constrained to returning a unary function pointer deduced from the return expression. Ultimately, the last two would require the generalized 'auto' type deduction behavior. The difficulty is that there doesn't appear to be any existing means for determining, at parse time of the first (auto, whether we're forming a function or variable declaration. Maybe such state would fall out of a generalized 'auto' solution. Ever since generic functions were implemented, (2) has always been seen as an attempt to declare a variable template. Previously we've thrown these out. As your patch now allows them, it seems like something should be done here prior to a final solution of fixing the behavior. Maybe marking as expected failures would be OK for now then raising a new issue to address this properly. Jason, what do you think? Adam
Re: Patch for constexpr variable templates
It sounds like GCC's behavior with auto in function parameters needs to be changed, but that definitely sounds like a separate patch to me. I think so. It's definitely a different patch. Agreed. I've been thinking about a simple way for your patch to add to the constraints for 'auto_is_implicit_function_template_parm_p' in 'cp_parser_parameter_declaration_clause' but this is happening incrementally at parse time and I can't see how to distinguish between the following 'auto' parameters: 1) auto f(auto);// generic function 'f'; transformed into template by 'auto' in parameter list. 2) auto (*f) (auto);// plain variable 'f' (should have an initializer for deduction of 'auto's. 3) auto (*f (auto)) (auto); // generic function 'f' constrained to returning a unary function pointer deduced from the return expression. Really? I've read the comment and I'm still not sure how to read this declaration. Ultimately, the last two would require the generalized 'auto' type deduction behavior. The difficulty is that there doesn't appear to be any existing means for determining, at parse time of the first (auto, whether we're forming a function or variable declaration. Maybe such state would fall out of a generalized 'auto' solution. I was wondering about this on the drive to work this morning. Maybe trying to pin down semantics at parse time isn't the right approach. That is, always parse declarations like variables, and then build up template parameters as needed during grorkdecl or grokfndecl. Or maybe that's too late. I don't know. Whatever the solution for auto, it will be the same for concepts. We'll just add constraints to the auto-type whenever we find a constrained-type-specifier. Andrew
Re: Patch for constexpr variable templates
On 07/27/2014 10:06 PM, Braden Obrzut wrote: So given this, should I leave the test cases that fail for this reason alone or should I still change them to dg-message? It sounds like GCC's behavior with auto in function parameters needs to be changed, but that definitely sounds like a separate patch to me. I think let's leave them as dg-error, remove the expected error text, and mark them as xfail, i.e. // { dg-error { xfail *-*-* } } Then a patch to treat these as variables with deduced type can fill in the appropriate error text. Jason
Re: Patch for constexpr variable templates
On 2014-07-28 13:09, Andrew Sutton wrote: 3) auto (*f (auto)) (auto); // generic function 'f' constrained to returning a unary function pointer deduced from the return expression. Really? I've read the comment and I'm still not sure how to read this declaration. The first and last 'auto' in the line would be resolved by return type deduction, the second, in the parameter list, would be a synthesized template argument. E.g. If the function were defined as auto (*crazy (auto f)) (auto) { return f; } then it is only well formed if instantiated with an 'f' that is convertible to some ptr-to-function type of the form R (*) (A). At which point return type deduction would subst 'R' for the first 'auto' and 'A' for the last. If it were passed a pointer to the following function int F(float); then it should be instantiated as int (*crazy (int (*f) (float))) (float) { return f; } My point with case (3) is that it contains two function parameter lists that contain 'auto' but they need to be dealt with differently for generic function template argument synthesis and for return type deduction. Ultimately, the last two would require the generalized 'auto' type deduction behavior. The difficulty is that there doesn't appear to be any existing means for determining, at parse time of the first (auto, whether we're forming a function or variable declaration. Maybe such state would fall out of a generalized 'auto' solution. I was wondering about this on the drive to work this morning. Maybe trying to pin down semantics at parse time isn't the right approach. I have a feeling you may be right. That is, always parse declarations like variables, and then build up template parameters as needed during grorkdecl or grokfndecl. Or maybe that's too late. I don't know. My thinking was going the other way other initially (assuming a function until you know it isn't). But I think deduced return types would cause problems with this so I'm thinking the assume variable route might be better. We'd have to generate some form of parametric type tree for the variable type before deduction from the initializer anyway and it may be that such a tree could be transformed into the function type should the decl turn out to be a function. I recall my initial experience of implementing generic functions: I tried to work in the grok*decl space, but found that so many cases had to be handled explicitly and types rebuilt afterwards potentially after errors about 'auto' had already been issued (which needed additional cases to avoid). I remember it being nasty. But it was my first hack on the GCC code base; so that was probably a factor (still is!). Switching to the parsing route allowed to transform the code on the fly as if it had been written with the full template header from the start; making all the existing code happy. I would like to eliminate the possibility of making the during parsing route work before diving back in to a post-parse solution. Whatever the solution for auto, it will be the same for concepts. We'll just add constraints to the auto-type whenever we find a constrained-type-specifier. Agreed. Adam
Re: Patch for constexpr variable templates
On 2014-07-26 17:14, Jason Merrill wrote: On 07/26/2014 12:11 PM, Jason Merrill wrote: On 07/26/2014 03:04 AM, Braden Obrzut wrote: On 07/25/2014 05:24 PM, Jason Merrill wrote: Fair enough, but in that case let's use 'sorry' rather then 'error' to be clear that it's a missing feature. Tests like g++.dg/cpp1y/pr59638.C produce extra failures if this is changed. Is there something I'm supposed to do to account for that? Changing dg-error to dg-message should cover it. Actually, we shouldn't be treating that testcase as declaring variable templates at all. Adam, any thoughts? In the 59638 case, the declarations void (*a)(auto); void (*b)(auto) = 0; are shorthand for template typename T void (*a)(T); template typename T void (*b)(T) = 0; which, unless there's some constraint with variable templates that I'm not aware of, ought to define two variable templates 'a' and 'b' to be ptr-to-function-taking-T. So I think it's correct that the variable template stuff should be triggering here. Prefixing the two decls with constexpr does allow them to compile (albeit with an uninitialized const 'a' permerror in the first case). The issue with 59638 was that the errors were not correctly unwinding the template scope so declarations further down the file were considered templates when the weren't. There may be similar recovery issues with not supporting non-constexpr variable templates defined with 'auto' (if that's permitted at all). Cheers, Adam
Re: Patch for constexpr variable templates
In the 59638 case, the declarations void (*a)(auto); void (*b)(auto) = 0; are shorthand for template typename T void (*a)(T); template typename T void (*b)(T) = 0; which, unless there's some constraint with variable templates that I'm not aware of, ought to define two variable templates 'a' and 'b' to be ptr-to-function-taking-T. So I think it's correct that the variable template stuff should be triggering here. There isn't, but this interpretation isn't consistent with the use of auto in variable declarations. For example, this: const auto x = 0; does not mean: templatetypename T const T x = 0; So I would be surprised if any of: void (*p1)(auto); auto (*p2)(int); vectorauto x; did mean create a template instead of deduce the type of x. Also, if we did have this interpretation of auto for some (but not all?) variable declarations, we would have to know to write those as template-ids: void (*p)(auto); pint = some_f; since one cannot refer to a template specialization without arguments. I'm much, much happier if, for variable templates, we always deduce the type from the initializer.. Besides, that wording (or some approximation thereof) is already in the TS for concepts. A question came up during the CWG review as to whether we could declare function parameters as void (*p)(auto), and EWG said, sure, go for it. We also have the ability to declare function parameters as, e.g., vectorauto or pairconst auto, auto*. I applied that to variable templates as well, since it would have been a bit inconsistent, otherwise. Andrew
Re: Patch for constexpr variable templates
On 2014-07-27 19:01, Andrew Sutton wrote: In the 59638 case, the declarations void (*a)(auto); void (*b)(auto) = 0; are shorthand for template typename T void (*a)(T); template typename T void (*b)(T) = 0; which, unless there's some constraint with variable templates that I'm not aware of, ought to define two variable templates 'a' and 'b' to be ptr-to-function-taking-T. So I think it's correct that the variable template stuff should be triggering here. There isn't, but this interpretation isn't consistent with the use of auto in variable declarations. True. It's just what GCC currently does when it see's 'auto' in a function parameter list. Sounds like it needs to be prevented from doing that in [at least] this case. For example, this: const auto x = 0; does not mean: templatetypename T const T x = 0; So I would be surprised if any of: void (*p1)(auto); auto (*p2)(int); vectorauto x; did mean create a template instead of deduce the type of x. Indeed. I accept the argument. The only reason GCC does this is that it has a general implementation that introduces a template parameter list to the primary declaration whenever it sees 'auto' in a function parameter list; including a function parameter list in a function type. If we know that we are not declaring a function (or know that we are declaring a variable), then we can prevent 'auto' from having the currently implemented meaning. That would be an alternative resolution to 59638 (and friends) too. Also, if we did have this interpretation of auto for some (but not all?) variable declarations, we would have to know to write those as template-ids: void (*p)(auto); pint = some_f; since one cannot refer to a template specialization without arguments. Agreed. That's not pleasant. And I question whether there's a motivating use case for variable templates that are function pointers (but I confess I haven't thought much about it). I'm much, much happier if, for variable templates, we always deduce the type from the initializer.. Besides, that wording (or some approximation thereof) is already in the TS for concepts. A question came up during the CWG review as to whether we could declare function parameters as void (*p)(auto), and EWG said, sure, go for it. We also have the ability to declare function parameters as, e.g., vectorauto or pairconst auto, auto*. I applied that to variable templates as well, since it would have been a bit inconsistent, otherwise. Sounds good. For function parameters this is implemented in GCC by introducing a template declaration; i.e. making the function in question a function template. For variables we want a different solution that relies on doing some sort of tsubst of an initializer expression into the 'auto'-expressed variable type; effectively generalizing the handling of 'auto x = ...'. We could probably leverage the current behavior to get the generalized (generic) type including template parameters, then do a substitution using the initializer expression to determine what they are (and error if no initializer is given). Adam
Re: Patch for constexpr variable templates
So given this, should I leave the test cases that fail for this reason alone or should I still change them to dg-message? It sounds like GCC's behavior with auto in function parameters needs to be changed, but that definitely sounds like a separate patch to me. - Braden Obrzut
Re: Patch for constexpr variable templates
Ed, I looked into partial specializations and it looks like, while not trivial, it would be easy enough for me to do them. However, it is not required for concepts (which can not be specialized), so should I fix them for this patch or as a separate patch later? On 07/25/2014 05:24 PM, Jason Merrill wrote: Fair enough, but in that case let's use 'sorry' rather then 'error' to be clear that it's a missing feature. Tests like g++.dg/cpp1y/pr59638.C produce extra failures if this is changed. Is there something I'm supposed to do to account for that? - Braden Obrzut
Re: Patch for constexpr variable templates
On 07/26/2014 03:04 AM, Braden Obrzut wrote: On 07/25/2014 05:24 PM, Jason Merrill wrote: Fair enough, but in that case let's use 'sorry' rather then 'error' to be clear that it's a missing feature. Tests like g++.dg/cpp1y/pr59638.C produce extra failures if this is changed. Is there something I'm supposed to do to account for that? Changing dg-error to dg-message should cover it. Jason
Re: Patch for constexpr variable templates
On 07/26/2014 12:11 PM, Jason Merrill wrote: On 07/26/2014 03:04 AM, Braden Obrzut wrote: On 07/25/2014 05:24 PM, Jason Merrill wrote: Fair enough, but in that case let's use 'sorry' rather then 'error' to be clear that it's a missing feature. Tests like g++.dg/cpp1y/pr59638.C produce extra failures if this is changed. Is there something I'm supposed to do to account for that? Changing dg-error to dg-message should cover it. Actually, we shouldn't be treating that testcase as declaring variable templates at all. Adam, any thoughts? Jason
Re: Patch for constexpr variable templates
On 07/26/2014 03:04 AM, Braden Obrzut wrote: Ed, I looked into partial specializations and it looks like, while not trivial, it would be easy enough for me to do them. However, it is not required for concepts (which can not be specialized), so should I fix them for this patch or as a separate patch later? I see no reason why we can't add features in stages. I just wondered if you had already given it a look. Certainly constexpr variable templates are useful on their own. On 07/25/2014 05:24 PM, Jason Merrill wrote: Fair enough, but in that case let's use 'sorry' rather then 'error' to be clear that it's a missing feature. Tests like g++.dg/cpp1y/pr59638.C produce extra failures if this is changed. Is there something I'm supposed to do to account for that? - Braden Obrzut
Re: Patch for constexpr variable templates
On 07/24/2014 04:56 PM, Jason Merrill wrote: + /* Variable templates will need to have the class context. */ + if (VAR_P (value)) +DECL_CONTEXT (value) = current_class_type; Why isn't this covered by grokvardecl? Oops, as the changelog indicated, this was to satisfy the old version of variable_template_p which checked the scope. I forgot to apply Gaby's second patch initially. It's no longer needed so I've removed it. + else if (VAR_P (decl)) +{ + if (!DECL_DECLARED_CONSTEXPR_P (decl)) +error (template declaration of non-constexpr variable %qD, decl); +} As Ed and Andrew pointed out, non-constexpr variable templates are fine. This patch only covers constexpr variable templates, so it makes sense to produce an error for now. Otherwise more confusing linker errors will be thrown regarding duplicate or missing symbols. I do not believe it would be too difficult to extend this patch to do non-constexpr variables since it looks like the issue is assigning names, but it's outside of the scope of what is required for concepts which is what I'm assigned to for GSoC. Other than that, the other issues you mentioned should be fixed. - Braden Obrzut 2014-07-25 Braden Obrzut ad...@maniacsvault.net * decl.c (grokvardecl): Handle specializations of variable templates. (grokdeclarator): Handle variable template id expressions. * decl2.c (check_member_template): Allow declaration of template member variables. * parser.c (cp_parser_postfix_expression): Resolve VAR_DECLs from TEMPLATE_ID_EXPRs. (cp_parser_template_id): Build a TEMPLATE_ID_EXPR for variable templates. * pt.c (register_specialization): Accept variable templates. (determine_specialization): Accept variable templates. (check_template_variable): Fixed wanted template header count and change non static data member error to variable template warning. (lookup_template_variable): New. (do_decl_instantiation): Handle template variables. (instantiate_decl): Handle template variables. * semantics.c (finish_template_variable): New. 2014-07-25 Braden Obrzut ad...@maniacsvault.net * g++.dg/cpp1y/var-templ1.C: New. * g++.dg/cpp1y/var-templ2.C: New. * g++.dg/cpp1y/var-templ3.C: New. * g++.dg/cpp1y/var-templ4.C: New. * g++.dg/cpp1y/var-templ5.C: New. 2013-03-29 Gabriel Dos Reis g...@integrable-solutions.net * cp-tree.h (variable_template_p): Do not check scope. * pt.c (check_template_variable): Fix thinko from previous change. (push_template_decl_real): Fix formatting. 2013-03-29 Gabriel Dos Reis g...@integrable-solutions.net * cp-tree.h (variable_template_p): New. * pt.c (check_template_variable): Accept variable temploids at non-class scope. (push_template_decl_real): The current instantiation of a template can be a VAR_DECL. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4a5cb98..c6c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5027,6 +5027,17 @@ class_of_this_parm (const_tree fntype) return TREE_TYPE (type_of_this_parm (fntype)); } +/* True if T designates a variable template declaration. */ +inline bool +variable_template_p (tree t) +{ + if (TREE_CODE (t) != TEMPLATE_DECL) +return false; + if (tree r = DECL_TEMPLATE_RESULT (t)) +return VAR_P (r); + return false; +} + /* A parameter list indicating for a function with no parameters, e.g int f(void). */ extern cp_parameter_declarator *no_parameters; @@ -5554,6 +5565,7 @@ extern bool redeclare_class_template (tree, tree); extern tree lookup_template_class (tree, tree, tree, tree, int, tsubst_flags_t); extern tree lookup_template_function (tree, tree); +extern tree lookup_template_variable (tree, tree); extern int uses_template_parms (tree); extern int uses_template_parms_level (tree, int); extern bool in_template_function (void); @@ -5816,6 +5828,7 @@ extern tree perform_koenig_lookup (tree, vectree, va_gc *, tsubst_flags_t); extern tree finish_call_expr (tree, vectree, va_gc **, bool, bool, tsubst_flags_t); +extern tree finish_template_variable (tree); extern tree finish_increment_expr (tree, enum tree_code); extern tree finish_this_expr (void); extern tree finish_pseudo_destructor_expr (tree, tree, tree, location_t); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index dae85c2..eea2775 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -80,8 +80,8 @@ static int ambi_op_p (enum tree_code); static int unary_op_p (enum tree_code); static void push_local_name (tree); static tree grok_reference_init (tree, tree, tree, int); -static tree grokvardecl (tree, tree, const cp_decl_specifier_seq *, - int, int, tree); +static tree grokvardecl (tree, tree, tree, const cp_decl_specifier_seq *, + int, int, int, tree); static int check_static_variable_definition (tree, tree); static void record_unknown_type
Re: Patch for constexpr variable templates
How difficult would it be to make partial specializations work: // Write n*pi once for every possible type templatetypename Tp, std::size_t N constexpr Tp npi = N * Tp(3.1415926535897932385L); // Partial specialization for int type. templatestd::size_t N constexpr double npiint, N = N * double(3.1415926535897932385L);
Re: Patch for constexpr variable templates
On 07/25/2014 07:43 AM, Braden Obrzut wrote: This patch only covers constexpr variable templates, so it makes sense to produce an error for now. Fair enough, but in that case let's use 'sorry' rather then 'error' to be clear that it's a missing feature. I ran the testsuite with your patch applied and got a bunch of failures. For instance, +FAIL: g++.old-deja/g++.other/anon2.C -std=c++11 (internal compiler error) is crashing here: + || TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)) because orig_declarator is null. Please fix this and the other failures. + Variable templates only available with Diagnostics aren't capitalized. gcc_assert (decl == error_mark_node + || variable_template_p (tmpl) || !(DECL_CONSTRUCTOR_P (decl) Indentation mismatch. DECL_EXTERNAL (d) = 0; - /* Enter the scope of D so that access-checking works correctly. */ - push_nested_class (DECL_CONTEXT (d)); + /* Enter the scope of D so that access-checking works correctly. */ + bool enter_context = DECL_CLASS_SCOPE_P (d); Indentation mismatch. Jason
Re: Patch for constexpr variable templates
First of all, thanks a lot for taking this on! A few nitpicks: On 07/21/2014 11:06 PM, Braden Obrzut wrote: grokvardecl (tree type, tree name, +tree orig_declarator, const cp_decl_specifier_seq *declspecs, int initialized, int constp, +int template_count, Indentation mismatch. + if (orig_declarator (processing_template_decl + || TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)) The indentation is wrong, since the || is part of the inner parenthesized expression. + /* Variable templates will need to have the class context. */ + if (VAR_P (value)) +DECL_CONTEXT (value) = current_class_type; Why isn't this covered by grokvardecl? - if (!is_overloaded_fn (fns)) + bool var_templ = variable_template_p (fns); + if (!is_overloaded_fn (fns) !var_templ) { error (%qD is not a function template, fns); I think here we should check whether 'fns' and 'decl' are both variables or both functions so that we can give a better diagnostic. + if (cxx_dialect cxx1y) +permerror (DECL_SOURCE_LOCATION (decl), + %qD is not a static data member of a class template, decl); It's customary to use pedwarn and mention the relevant -std= flag. + if ((specialization || member_specialization) + /* Variable templates don't apply. */ + (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE + || TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)) Indentation mismatch. + // Namespace scope variable templates should have a template header. Namespace-scope + if (!variable_template_p (tmpl) + DECL_STATIC_FUNCTION_P (tmpl) ... + if (!variable_template_p (tmpl)) + copy_default_args_to_explicit_spec (decl); I'd prefer to check for a function template here rather than not a variable template. + else if (VAR_P (decl)) +{ + if (!DECL_DECLARED_CONSTEXPR_P (decl)) +error (template declaration of non-constexpr variable %qD, decl); +} As Ed and Andrew pointed out, non-constexpr variable templates are fine. + bool var_templ = DECL_TEMPLATE_INFO (decl) +variable_template_p (DECL_TI_TEMPLATE (decl)); An expression on multiple lines should be parenthesized to preserve indentation. + bool enter_context = CLASS_TYPE_P (DECL_CONTEXT (d)); You can use DECL_CLASS_SCOPE_P. + return instantiate_template (TREE_OPERAND (var, 0), TREE_OPERAND (var, 1), tf_error); Line too long. Jason
Re: Patch for constexpr variable templates
Braden, Great work on this. In addition to helping with constraints there is at least one new library feature that depends on constexpr variable templates. For my two cents it would be good to get just the constexpr variable templates, aka n3651, in now as a first stage - it's quite usable. But someday we'll want non-constexpr too. I have only seen a sentence somewhere stating that non-constexpr variable templates are allowed but have seen no paper or wording anywhere. Does anyone know where such exists? Ed
Re: Patch for constexpr variable templates
But someday we'll want non-constexpr too. I have only seen a sentence somewhere stating that non-constexpr variable templates are allowed but have seen no paper or wording anywhere. Does anyone know where such exists? When variable templates were proposed, EWG decided they wanted non-constexpr variable templates also. I think that the current draft reflects that, since I can't find anything that says variable templates shall be declared constexpr. There's also an implied requirement for partial specialization of variable templates (14.3.3p2), but no elaboration of that. Core issue 1711 specifically addresses this. A quick search shows that Clang already implements it. Andrew
Re: Patch for constexpr variable templates
Braden, I've played with this and it seems to work nicely. Only one comment: Could you put the test cases in the C++14 subdirectory? g++.dg/template/cpp1y/var-templ1.C ^ We should CC Jason on all this. Also, do you have your FSF paperwork in place? Thanks, Ed
Re: Patch for constexpr variable templates
Sure, test cases moved. My FSF paperwork is in place. I don't have write access to the repository though of course. - Braden Obrzut 2014-07-21 Braden Obrzut ad...@maniacsvault.net * decl.c (grokvardecl): Handle specializations of variable templates. (grokdeclarator): Handle variable template id expressions. * decl2.c (check_member_template): Allow declaration of template member variables. (grokfield): Assign class context to template member variables in order that variable_template_p to detect them properly. * parser.c (cp_parser_postfix_expression): Resolve VAR_DECLs from TEMPLATE_ID_EXPRs. (cp_parser_template_id): Build a TEMPLATE_ID_EXPR for variable templates. * pt.c (register_specialization): Accept variable templates. (determine_specialization): Accept variable templates. (check_template_variable): Fixed wanted template header count. (lookup_template_variable): New. (do_decl_instantiation): Handle templat variables. (instantiate_decl): Handle template variables. * semantics.c (finish_template_variable): New. 2014-07-21 Braden Obrzut ad...@maniacsvault.net * g++.dg/cpp1y/var-templ1.C: New. * g++.dg/cpp1y/var-templ2.C: New. * g++.dg/cpp1y/var-templ3.C: New. * g++.dg/cpp1y/var-templ4.C: New. * g++.dg/cpp1y/var-templ5.C: New. 2013-03-29 Gabriel Dos Reis g...@integrable-solutions.net * cp-tree.h (variable_template_p): Do not check scope. * pt.c (check_template_variable): Fix thinko from previous change. (push_template_decl_real): Fix formatting. 2013-03-29 Gabriel Dos Reis g...@integrable-solutions.net * cp-tree.h (variable_template_p): New. * pt.c (check_template_variable): Accept variable temploids at non-class scope. (push_template_decl_real): The current instantiation of a template can be a VAR_DECL. On 07/21/2014 07:39 AM, Ed Smith-Rowland wrote: Braden, I've played with this and it seems to work nicely. Only one comment: Could you put the test cases in the C++14 subdirectory? g++.dg/template/cpp1y/var-templ1.C ^ We should CC Jason on all this. Also, do you have your FSF paperwork in place? Thanks, Ed diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4a5cb98..c6c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5027,6 +5027,17 @@ class_of_this_parm (const_tree fntype) return TREE_TYPE (type_of_this_parm (fntype)); } +/* True if T designates a variable template declaration. */ +inline bool +variable_template_p (tree t) +{ + if (TREE_CODE (t) != TEMPLATE_DECL) +return false; + if (tree r = DECL_TEMPLATE_RESULT (t)) +return VAR_P (r); + return false; +} + /* A parameter list indicating for a function with no parameters, e.g int f(void). */ extern cp_parameter_declarator *no_parameters; @@ -5554,6 +5565,7 @@ extern bool redeclare_class_template (tree, tree); extern tree lookup_template_class (tree, tree, tree, tree, int, tsubst_flags_t); extern tree lookup_template_function (tree, tree); +extern tree lookup_template_variable (tree, tree); extern int uses_template_parms (tree); extern int uses_template_parms_level (tree, int); extern bool in_template_function (void); @@ -5816,6 +5828,7 @@ extern tree perform_koenig_lookup (tree, vectree, va_gc *, tsubst_flags_t); extern tree finish_call_expr (tree, vectree, va_gc **, bool, bool, tsubst_flags_t); +extern tree finish_template_variable (tree); extern tree finish_increment_expr (tree, enum tree_code); extern tree finish_this_expr (void); extern tree finish_pseudo_destructor_expr (tree, tree, tree, location_t); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index dae85c2..0b6fa54 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -80,8 +80,8 @@ static int ambi_op_p (enum tree_code); static int unary_op_p (enum tree_code); static void push_local_name (tree); static tree grok_reference_init (tree, tree, tree, int); -static tree grokvardecl (tree, tree, const cp_decl_specifier_seq *, - int, int, tree); +static tree grokvardecl (tree, tree, tree, const cp_decl_specifier_seq *, + int, int, int, tree); static int check_static_variable_definition (tree, tree); static void record_unknown_type (tree, const char *); static tree builtin_function_1 (tree, tree, bool); @@ -7943,9 +7943,11 @@ set_linkage_for_static_data_member (tree decl) static tree grokvardecl (tree type, tree name, + tree orig_declarator, const cp_decl_specifier_seq *declspecs, int initialized, int constp, + int template_count, tree scope) { tree decl; @@ -7975,7 +7977,9 @@ grokvardecl (tree type, || (TREE_CODE (scope) == NAMESPACE_DECL current_lang_name != lang_name_cplusplus) /* Similarly for static data members. */ - || TYPE_P (scope))) + || TYPE_P (scope) + /* Similarly for explicit specializations. */ + || TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR))
Re: Patch for constexpr variable templates
While working on variable concepts, I noticed that one of the added blocks of code was no longer needed due to a previous simplification and caused problems. Also included a new test case which triggered the problem, and fixed a minor formatting issue. As before, if the plan is to revive the existing variable template branch, I can redo the patch without Gabriel's changes. 2014-07-19 Braden Obrzut ad...@maniacsvault.net * decl.c (grokvardecl): Handle specializations of variable templates. (grokdeclarator): Handle variable template id expressions. * decl2.c (check_member_template): Allow declaration of template member variables. (grokfield): Assign class context to template member variables in order that variable_template_p to detect them properly. * parser.c (cp_parser_postfix_expression): Resolve VAR_DECLs from TEMPLATE_ID_EXPRs. (cp_parser_template_id): Build a TEMPLATE_ID_EXPR for variable templates. * pt.c (register_specialization): Accept variable templates. (determine_specialization): Accept variable templates. (check_template_variable): Fixed wanted template header count. (lookup_template_variable): New. (do_decl_instantiation): Handle templat variables. (instantiate_decl): Handle template variables. * semantics.c (finish_template_variable): New. 2014-07-19 Braden Obrzut ad...@maniacsvault.net * g++.dg/template/var-templ1.C: New. * g++.dg/template/var-templ2.C: New. * g++.dg/template/var-templ3.C: New. * g++.dg/template/var-templ4.C: New. * g++.dg/template/var-templ5.C: New. 2013-03-29 Gabriel Dos Reis g...@integrable-solutions.net * cp-tree.h (variable_template_p): Do not check scope. * pt.c (check_template_variable): Fix thinko from previous change. (push_template_decl_real): Fix formatting. 2013-03-29 Gabriel Dos Reis g...@integrable-solutions.net * cp-tree.h (variable_template_p): New. * pt.c (check_template_variable): Accept variable temploids at non-class scope. (push_template_decl_real): The current instantiation of a template can be a VAR_DECL. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4a5cb98..c6c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5027,6 +5027,17 @@ class_of_this_parm (const_tree fntype) return TREE_TYPE (type_of_this_parm (fntype)); } +/* True if T designates a variable template declaration. */ +inline bool +variable_template_p (tree t) +{ + if (TREE_CODE (t) != TEMPLATE_DECL) +return false; + if (tree r = DECL_TEMPLATE_RESULT (t)) +return VAR_P (r); + return false; +} + /* A parameter list indicating for a function with no parameters, e.g int f(void). */ extern cp_parameter_declarator *no_parameters; @@ -5554,6 +5565,7 @@ extern bool redeclare_class_template (tree, tree); extern tree lookup_template_class (tree, tree, tree, tree, int, tsubst_flags_t); extern tree lookup_template_function (tree, tree); +extern tree lookup_template_variable (tree, tree); extern int uses_template_parms (tree); extern int uses_template_parms_level (tree, int); extern bool in_template_function (void); @@ -5816,6 +5828,7 @@ extern tree perform_koenig_lookup (tree, vectree, va_gc *, tsubst_flags_t); extern tree finish_call_expr (tree, vectree, va_gc **, bool, bool, tsubst_flags_t); +extern tree finish_template_variable (tree); extern tree finish_increment_expr (tree, enum tree_code); extern tree finish_this_expr (void); extern tree finish_pseudo_destructor_expr (tree, tree, tree, location_t); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index dae85c2..0b6fa54 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -80,8 +80,8 @@ static int ambi_op_p (enum tree_code); static int unary_op_p (enum tree_code); static void push_local_name (tree); static tree grok_reference_init (tree, tree, tree, int); -static tree grokvardecl (tree, tree, const cp_decl_specifier_seq *, - int, int, tree); +static tree grokvardecl (tree, tree, tree, const cp_decl_specifier_seq *, + int, int, int, tree); static int check_static_variable_definition (tree, tree); static void record_unknown_type (tree, const char *); static tree builtin_function_1 (tree, tree, bool); @@ -7943,9 +7943,11 @@ set_linkage_for_static_data_member (tree decl) static tree grokvardecl (tree type, tree name, + tree orig_declarator, const cp_decl_specifier_seq *declspecs, int initialized, int constp, + int template_count, tree scope) { tree decl; @@ -7975,7 +7977,9 @@ grokvardecl (tree type, || (TREE_CODE (scope) == NAMESPACE_DECL current_lang_name != lang_name_cplusplus) /* Similarly for static data members. */ - || TYPE_P (scope))) + || TYPE_P (scope) + /* Similarly for explicit specializations. */ + || TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)) decl = build_lang_decl (VAR_DECL, name, type); else decl =
Patch for constexpr variable templates
Here is a patch that expands on Gabriel Dos Reis's initial var-template patch ( https://gcc.gnu.org/ml/gcc-patches/2013-03/msg01295.html ). I just noticed now that those patches were committed to a branch, so if need be I can resubmit the patch with Gaby's changes not included. The purpose of the patch is to implement the subset of variable templates that is a prerequisite for concept variables in the c++-concepts branch. With that said, only constexpr variables are supported (both in namespace and class scopes). There is no handling for generating symbols for these variables so they are only supported in contexts where they can be evaluated at compile time (I believe that would be only as an rvalue). On that note, explicit instantiations of variable templates do work, but will generate duplicate symbol errors if more than one exists in the file. Other than those issues, the should work as expected. I would like to call attention to the changes in parser.c. Andrew pointed out to me that it may be a good idea to have cp_parser_template_id return the instantiated VAR_DECL directly instead of deferring it to cp_parser_postfix_expression like function templates. Since this would produce a new possible return type for the function, I've found that would require more widespread changes (although I can't accurately say by how much). By deferring the instantiation, some code can be shared between function templates and variable templates. 2014-07-12 Braden Obrzut ad...@maniacsvault.net * decl.c (grokvardecl): Handle specializations of variable templates. (grokdeclarator): Handle variable template id expressions. * decl2.c (check_member_template): Allow declaration of template member variables. (grokfield): Assign class context to template member variables in order that variable_template_p to detect them properly. * parser.c (cp_parser_postfix_expression): Resolve VAR_DECLs from TEMPLATE_ID_EXPRs. (cp_parser_template_id): Build a TEMPLATE_ID_EXPR for variable templates. * pt.c (register_specialization): Accept variable templates. (determine_specialization): Accept variable templates. (check_template_variable): Fixed wanted template header count. (lookup_template_variable): New. (instantiate_template_1): Evaluate initializer for variable templates. (do_decl_instantiation): Handle templat variables. (instantiate_decl): Handle template variables. * semantics.c (finish_template_variable): New. 2014-07-12 Braden Obrzut ad...@maniacsvault.net * g++.dg/template/var-templ1.C: New. * g++.dg/template/var-templ2.C: New. * g++.dg/template/var-templ3.C: New. * g++.dg/template/var-templ4.C: New. 2013-03-29 Gabriel Dos Reis g...@integrable-solutions.net * cp-tree.h (variable_template_p): Do not check scope. * pt.c (check_template_variable): Fix thinko from previous change. (push_template_decl_real): Fix formatting. 2013-03-29 Gabriel Dos Reis g...@integrable-solutions.net * cp-tree.h (variable_template_p): New. * pt.c (check_template_variable): Accept variable temploids at non-class scope. (push_template_decl_real): The current instantiation of a template can be a VAR_DECL. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4a5cb98..c6c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5027,6 +5027,17 @@ class_of_this_parm (const_tree fntype) return TREE_TYPE (type_of_this_parm (fntype)); } +/* True if T designates a variable template declaration. */ +inline bool +variable_template_p (tree t) +{ + if (TREE_CODE (t) != TEMPLATE_DECL) +return false; + if (tree r = DECL_TEMPLATE_RESULT (t)) +return VAR_P (r); + return false; +} + /* A parameter list indicating for a function with no parameters, e.g int f(void). */ extern cp_parameter_declarator *no_parameters; @@ -5554,6 +5565,7 @@ extern bool redeclare_class_template (tree, tree); extern tree lookup_template_class (tree, tree, tree, tree, int, tsubst_flags_t); extern tree lookup_template_function (tree, tree); +extern tree lookup_template_variable (tree, tree); extern int uses_template_parms (tree); extern int uses_template_parms_level (tree, int); extern bool in_template_function (void); @@ -5816,6 +5828,7 @@ extern tree perform_koenig_lookup (tree, vectree, va_gc *, tsubst_flags_t); extern tree finish_call_expr (tree, vectree, va_gc **, bool, bool, tsubst_flags_t); +extern tree finish_template_variable (tree); extern tree finish_increment_expr (tree, enum tree_code); extern tree finish_this_expr (void); extern tree finish_pseudo_destructor_expr (tree, tree, tree, location_t); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index dae85c2..62cc256 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -80,8 +80,8 @@ static int ambi_op_p (enum tree_code); static int unary_op_p (enum tree_code); static void push_local_name (tree);