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
This commit is contained in:
Jason Merrill 2014-08-25 08:48:22 -04:00 committed by Jason Merrill
parent 2167dc924b
commit 3749134042
7 changed files with 75 additions and 12 deletions

View File

@ -1,3 +1,10 @@
2014-08-25 Jason Merrill <jason@redhat.com>
* 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 <paolo.carlini@oracle.com>
PR c++/34938

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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" }

View File

@ -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>;
}

View File

@ -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" }