From 3749134042ab5f54d0c30af1ec336e7132ac9bc8 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 25 Aug 2014 08:48:22 -0400 Subject: [PATCH] decl.c (start_decl): Look through member variable template. * 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. From-SVN: r214420 --- gcc/cp/ChangeLog | 7 ++++++ gcc/cp/decl.c | 31 +++++++++++++++++++++---- gcc/cp/decl2.c | 4 ++++ gcc/cp/pt.c | 13 +++++------ gcc/testsuite/g++.dg/cpp1y/pr60626.C | 2 +- gcc/testsuite/g++.dg/cpp1y/var-templ8.C | 15 ++++++++++++ gcc/testsuite/g++.dg/cpp1y/var-templ9.C | 15 ++++++++++++ 7 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ8.C create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ9.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 18a281b0a58..d9bf9058f7e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2014-08-25 Jason Merrill + + * 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. + 2014-08-25 Paolo Carlini PR c++/34938 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index e83192ad749..80696ddb216 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 74a10fb74fb..5b1313efa26 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 a40f9d2ad7c..3e6d777e72d 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 686db7306b9..311464472da 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 00000000000..8e3d34a7b8f --- /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 static T x; +}; + +template +T X::x = T(); + +int main() +{ + int x = X::x; +} 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 00000000000..2ffb007addc --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ9.C @@ -0,0 +1,15 @@ +// { dg-do compile { target c++14 } } + +struct X +{ + template static int x; +}; + +int X::x = 42; // { dg-error "template" } + +struct Y +{ + static int y; +}; + +template int Y::y = 42; // { dg-error "template" } -- 2.30.2