Message ID | 53FB305E.1040901@redhat.com |
---|---|
State | New |
Headers | show |
On Mon Aug 25 2014 15:47:26 GMT+0300 (EEST), Jason Merrill wrote: > On 08/25/2014 05:24 AM, Ville Voutilainen wrote: > > Well, it's a bit premature to add tests when the implementation itself is not > > quite complete, I guess. :) Having ICEs makes it hard to add tests, too. :P > > But tests are how you verify that the implementation is complete. > > Anyway, here's a fix for your recent test. Thanks, I'll take a look at the tests and will send a patch if something seems missing; static member variable templates of a class template and explicit specializations thereof are the likely starting point.
On 25 August 2014 17:08, <ville.voutilainen@gmail.com> wrote: >> Anyway, here's a fix for your recent test. > > Thanks, I'll take a look at the tests and will send a patch if something seems missing; static member variable templates of a class template and explicit specializations thereof are the likely starting point. Another ICE (should we just add these test-for-valid cases as new tests? Or should they become bug reports instead? Please advise how to best handle these.): template <class T> struct Y { template <class U> static U x; }; template <class T> template <class U> U Y<T>::x = U(); int main() { int y = Y<int>::x<int>; } variable-template.cpp:9:3: warning: too many template headers for Y<T>::x (should be 1) U Y<T>::x = U(); ^ variable-template.cpp: In instantiation of ‘int Y<int>::x’: variable-template.cpp:13:19: required from here variable-template.cpp:13:19: internal compiler error: in template_for_substitution, at cp/pt.c:19714 int y = Y<int>::x<int>; ^ 0x5c4bf9 template_for_substitution(tree_node*) ../../gcc/cp/pt.c:19714 0x5d0874 instantiate_decl(tree_node*, int, bool) ../../gcc/cp/pt.c:19891 0x6521c2 mark_used(tree_node*, int) ../../gcc/cp/decl2.c:5035 0x707f5b finish_id_expression(tree_node*, tree_node*, tree_node*, cp_id_kind*, bool, bool, bool*, bool, bool, bool, bool, char const**, unsigned int) ../../gcc/cp/semantics.c:3515 0x67f13b cp_parser_primary_expression ../../gcc/cp/parser.c:4654 0x6804e7 cp_parser_postfix_expression ../../gcc/cp/parser.c:6008 0x6832b9 cp_parser_unary_expression ../../gcc/cp/parser.c:7285 0x683ef4 cp_parser_binary_expression ../../gcc/cp/parser.c:8028 0x68449b cp_parser_assignment_expression ../../gcc/cp/parser.c:8270 0x684935 cp_parser_assignment_expression ../../gcc/cp/parser.c:8320 0x684935 cp_parser_constant_expression ../../gcc/cp/parser.c:8524 0x69557e cp_parser_init_declarator ../../gcc/cp/parser.c:16996 0x696b65 cp_parser_simple_declaration ../../gcc/cp/parser.c:11406 0x67a6a3 cp_parser_block_declaration ../../gcc/cp/parser.c:11287 0x67b821 cp_parser_declaration_statement ../../gcc/cp/parser.c:10934 0x67bf0b cp_parser_statement ../../gcc/cp/parser.c:9649 0x67cd39 cp_parser_statement_seq_opt ../../gcc/cp/parser.c:9927 0x67cea6 cp_parser_compound_statement ../../gcc/cp/parser.c:9881 0x68e11b cp_parser_function_body ../../gcc/cp/parser.c:18952 0x68e11b cp_parser_ctor_initializer_opt_and_function_body ../../gcc/cp/parser.c:18988 Please submit a full bug report, with preprocessed source if appropriate. Please include the complete backtrace with any bug report. See <http://gcc.gnu.org/bugs.html> for instructions.
On 08/25/2014 03:15 PM, Ville Voutilainen wrote: > should we just add these test-for-valid cases as new > tests? Or should they become > bug reports instead? Please advise how to best handle these. Bug reports, please. Or perhaps multiple testcases on one bug report, for now. :) Jason
commit e79c51a68ae5ace45a191bf95350a68c7ce386d3 Author: Jason Merrill <jason@redhat.com> Date: Mon Aug 25 00:17:55 2014 -0400 * decl.c (start_decl): Look through member variable template. * pt.c (tsubst_decl) [VAR_DECL]: Handle member variable templates. * decl2.c (grokfield): Set DECL_CONTEXT earlier on variables. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index e83192a..80696dd 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4650,13 +4650,37 @@ start_decl (const cp_declarator *declarator, if (TYPE_P (context) && COMPLETE_TYPE_P (complete_type (context))) { + bool this_tmpl = (processing_template_decl + > template_class_depth (context)); if (VAR_P (decl)) { tree field = lookup_field (context, DECL_NAME (decl), 0, false); - if (field == NULL_TREE || !VAR_P (field)) - error ("%q#D is not a static member of %q#T", decl, context); + if (field == NULL_TREE + || !(VAR_P (field) || variable_template_p (field))) + error ("%q+#D is not a static data member of %q#T", decl, context); else { + if (variable_template_p (field)) + { + if (!this_tmpl) + { + error_at (DECL_SOURCE_LOCATION (decl), + "non-member-template declaration of %qD", decl); + inform (DECL_SOURCE_LOCATION (field), "does not match " + "member template declaration here"); + return error_mark_node; + } + field = DECL_TEMPLATE_RESULT (field); + } + else if (this_tmpl) + { + error_at (DECL_SOURCE_LOCATION (decl), + "member template declaration of %qD", decl); + inform (DECL_SOURCE_LOCATION (field), "does not match " + "non-member-template declaration here"); + return error_mark_node; + } + if (DECL_CONTEXT (field) != context) { if (!same_type_p (DECL_CONTEXT (field), context)) @@ -4683,8 +4707,7 @@ start_decl (const cp_declarator *declarator, else { tree field = check_classfn (context, decl, - (processing_template_decl - > template_class_depth (context)) + this_tmpl ? current_template_parms : NULL_TREE); if (field && field != error_mark_node diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 74a10fb..5b1313e 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -994,6 +994,10 @@ grokfield (const cp_declarator *declarator, && DECL_CONTEXT (value) != current_class_type) return value; + /* Need to set this before push_template_decl. */ + if (TREE_CODE (value) == VAR_DECL) + DECL_CONTEXT (value) = current_class_type; + if (processing_template_decl && VAR_OR_FUNCTION_DECL_P (value)) { value = push_template_decl (value); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index a40f9d2..3e6d777 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -11127,13 +11127,12 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) same_type_p, because DECL_CONTEXT is always canonical... */ if (ctx == DECL_CONTEXT (t) - && (TREE_CODE (t) != TYPE_DECL - /* ... unless T is a member template; in which - case our caller can be willing to create a - specialization of that template represented - by T. */ - || !(DECL_TI_TEMPLATE (t) - && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (t))))) + /* ... unless T is a member template; in which + case our caller can be willing to create a + specialization of that template represented + by T. */ + && !(DECL_TI_TEMPLATE (t) + && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (t)))) spec = t; } diff --git a/gcc/testsuite/g++.dg/cpp1y/pr60626.C b/gcc/testsuite/g++.dg/cpp1y/pr60626.C index 686db73..3114644 100644 --- a/gcc/testsuite/g++.dg/cpp1y/pr60626.C +++ b/gcc/testsuite/g++.dg/cpp1y/pr60626.C @@ -4,4 +4,4 @@ struct A {}; -void (*A::p)(auto) = 0; // { dg-error "static member|template" } +void (*A::p)(auto) = 0; // { dg-error "static data member|template" } diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ8.C b/gcc/testsuite/g++.dg/cpp1y/var-templ8.C new file mode 100644 index 0000000..8e3d34a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ8.C @@ -0,0 +1,15 @@ +// { dg-do compile { target c++14 } } +// { dg-final { scan-assembler "_ZN1X1xIiEE" } } + +struct X +{ + template <class T> static T x; +}; + +template <class T> +T X::x = T(); + +int main() +{ + int x = X::x<int>; +} diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ9.C b/gcc/testsuite/g++.dg/cpp1y/var-templ9.C new file mode 100644 index 0000000..2ffb007 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ9.C @@ -0,0 +1,15 @@ +// { dg-do compile { target c++14 } } + +struct X +{ + template <class T> static int x; +}; + +int X::x = 42; // { dg-error "template" } + +struct Y +{ + static int y; +}; + +template <class T> int Y::y = 42; // { dg-error "template" }