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:
parent
2167dc924b
commit
3749134042
|
@ -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>
|
2014-08-25 Paolo Carlini <paolo.carlini@oracle.com>
|
||||||
|
|
||||||
PR c++/34938
|
PR c++/34938
|
||||||
|
|
|
@ -4650,13 +4650,37 @@ start_decl (const cp_declarator *declarator,
|
||||||
|
|
||||||
if (TYPE_P (context) && COMPLETE_TYPE_P (complete_type (context)))
|
if (TYPE_P (context) && COMPLETE_TYPE_P (complete_type (context)))
|
||||||
{
|
{
|
||||||
|
bool this_tmpl = (processing_template_decl
|
||||||
|
> template_class_depth (context));
|
||||||
if (VAR_P (decl))
|
if (VAR_P (decl))
|
||||||
{
|
{
|
||||||
tree field = lookup_field (context, DECL_NAME (decl), 0, false);
|
tree field = lookup_field (context, DECL_NAME (decl), 0, false);
|
||||||
if (field == NULL_TREE || !VAR_P (field))
|
if (field == NULL_TREE
|
||||||
error ("%q#D is not a static member of %q#T", decl, context);
|
|| !(VAR_P (field) || variable_template_p (field)))
|
||||||
|
error ("%q+#D is not a static data member of %q#T", decl, context);
|
||||||
else
|
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 (DECL_CONTEXT (field) != context)
|
||||||
{
|
{
|
||||||
if (!same_type_p (DECL_CONTEXT (field), context))
|
if (!same_type_p (DECL_CONTEXT (field), context))
|
||||||
|
@ -4683,8 +4707,7 @@ start_decl (const cp_declarator *declarator,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tree field = check_classfn (context, decl,
|
tree field = check_classfn (context, decl,
|
||||||
(processing_template_decl
|
this_tmpl
|
||||||
> template_class_depth (context))
|
|
||||||
? current_template_parms
|
? current_template_parms
|
||||||
: NULL_TREE);
|
: NULL_TREE);
|
||||||
if (field && field != error_mark_node
|
if (field && field != error_mark_node
|
||||||
|
|
|
@ -994,6 +994,10 @@ grokfield (const cp_declarator *declarator,
|
||||||
&& DECL_CONTEXT (value) != current_class_type)
|
&& DECL_CONTEXT (value) != current_class_type)
|
||||||
return value;
|
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))
|
if (processing_template_decl && VAR_OR_FUNCTION_DECL_P (value))
|
||||||
{
|
{
|
||||||
value = push_template_decl (value);
|
value = push_template_decl (value);
|
||||||
|
|
13
gcc/cp/pt.c
13
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
|
same_type_p, because DECL_CONTEXT is always
|
||||||
canonical... */
|
canonical... */
|
||||||
if (ctx == DECL_CONTEXT (t)
|
if (ctx == DECL_CONTEXT (t)
|
||||||
&& (TREE_CODE (t) != TYPE_DECL
|
/* ... unless T is a member template; in which
|
||||||
/* ... unless T is a member template; in which
|
case our caller can be willing to create a
|
||||||
case our caller can be willing to create a
|
specialization of that template represented
|
||||||
specialization of that template represented
|
by T. */
|
||||||
by T. */
|
&& !(DECL_TI_TEMPLATE (t)
|
||||||
|| !(DECL_TI_TEMPLATE (t)
|
&& DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (t))))
|
||||||
&& DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (t)))))
|
|
||||||
spec = t;
|
spec = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,4 +4,4 @@
|
||||||
|
|
||||||
struct A {};
|
struct A {};
|
||||||
|
|
||||||
void (*A::p)(auto) = 0; // { dg-error "static member|template" }
|
void (*A::p)(auto) = 0; // { dg-error "static data member|template" }
|
||||||
|
|
|
@ -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>;
|
||||||
|
}
|
|
@ -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" }
|
Loading…
Reference in New Issue