Commit f139561c by Mark Mitchell Committed by Mark Mitchell

re PR c++/9649 (ICE in finish_member_declaration at cp/semantics.c:1850 when…

re PR c++/9649 (ICE in finish_member_declaration at cp/semantics.c:1850 when redeclaring a static member variable)

	PR c++/9649
	* cp-tree.h (pushdecl_class_level): Change prototype.
	(push_class_level_binding): Likewise.
	* decl.c (add_binding): Reject duplicate static data members.
	(pushdecl_class_level): Return a value indicating whether or not
	the binding was valid.
	(push_class_level_binding): Likewise.
	* semantics.c (finish_member_declaration): Don't keep invalid
	declarations.

	PR c++/9649
	* g++.dg/template/static4.C: New test.
	* g++.old-deja/g++.other/anon7.C: Remove spurious error messages.

From-SVN: r68240
parent 170b020f
2003-06-19 Mark Mitchell <mark@codesourcery.com> 2003-06-19 Mark Mitchell <mark@codesourcery.com>
PR c++/9649
* cp-tree.h (pushdecl_class_level): Change prototype.
(push_class_level_binding): Likewise.
* decl.c (add_binding): Reject duplicate static data members.
(pushdecl_class_level): Return a value indicating whether or not
the binding was valid.
(push_class_level_binding): Likewise.
* semantics.c (finish_member_declaration): Don't keep invalid
declarations.
PR c++/11041 PR c++/11041
* call.c (initialize_reference): Do not use cp_finish_decl to emit * call.c (initialize_reference): Do not use cp_finish_decl to emit
temporary variables. temporary variables.
......
...@@ -3638,11 +3638,11 @@ extern int decls_match (tree, tree); ...@@ -3638,11 +3638,11 @@ extern int decls_match (tree, tree);
extern int duplicate_decls (tree, tree); extern int duplicate_decls (tree, tree);
extern tree pushdecl_top_level (tree); extern tree pushdecl_top_level (tree);
extern tree pushdecl_top_level_and_finish (tree, tree); extern tree pushdecl_top_level_and_finish (tree, tree);
extern void pushdecl_class_level (tree); extern bool pushdecl_class_level (tree);
extern tree pushdecl_namespace_level (tree); extern tree pushdecl_namespace_level (tree);
extern tree push_using_decl (tree, tree); extern tree push_using_decl (tree, tree);
extern tree push_using_directive (tree); extern tree push_using_directive (tree);
extern void push_class_level_binding (tree, tree); extern bool push_class_level_binding (tree, tree);
extern tree implicitly_declare (tree); extern tree implicitly_declare (tree);
extern tree declare_local_label (tree); extern tree declare_local_label (tree);
extern tree define_label (const char *, int, tree); extern tree define_label (const char *, int, tree);
......
...@@ -964,11 +964,18 @@ add_binding (tree id, tree decl) ...@@ -964,11 +964,18 @@ add_binding (tree id, tree decl)
type to which it already refers. */ type to which it already refers. */
ok = 0; ok = 0;
/* There can be two block-scope declarations of the same variable, /* There can be two block-scope declarations of the same variable,
so long as they are `extern' declarations. */ so long as they are `extern' declarations. However, there cannot
be two declarations of the same static data member:
[class.mem]
A member shall not be declared twice in the
member-specification. */
else if (TREE_CODE (decl) == VAR_DECL else if (TREE_CODE (decl) == VAR_DECL
&& TREE_CODE (BINDING_VALUE (binding)) == VAR_DECL && TREE_CODE (BINDING_VALUE (binding)) == VAR_DECL
&& DECL_EXTERNAL (decl) && DECL_EXTERNAL (decl)
&& DECL_EXTERNAL (BINDING_VALUE (binding))) && DECL_EXTERNAL (BINDING_VALUE (binding))
&& !DECL_CLASS_SCOPE_P (decl))
{ {
duplicate_decls (decl, BINDING_VALUE (binding)); duplicate_decls (decl, BINDING_VALUE (binding));
ok = 0; ok = 0;
...@@ -4179,10 +4186,11 @@ pushdecl_top_level_and_finish (tree x, tree init) ...@@ -4179,10 +4186,11 @@ pushdecl_top_level_and_finish (tree x, tree init)
/* Make the declaration of X appear in CLASS scope. */ /* Make the declaration of X appear in CLASS scope. */
void bool
pushdecl_class_level (tree x) pushdecl_class_level (tree x)
{ {
tree name; tree name;
bool is_valid = true;
timevar_push (TV_NAME_LOOKUP); timevar_push (TV_NAME_LOOKUP);
/* Get the name of X. */ /* Get the name of X. */
...@@ -4193,7 +4201,7 @@ pushdecl_class_level (tree x) ...@@ -4193,7 +4201,7 @@ pushdecl_class_level (tree x)
if (name) if (name)
{ {
push_class_level_binding (name, x); is_valid = push_class_level_binding (name, x);
if (TREE_CODE (x) == TYPE_DECL) if (TREE_CODE (x) == TYPE_DECL)
set_identifier_type_value (name, TREE_TYPE (x)); set_identifier_type_value (name, TREE_TYPE (x));
} }
...@@ -4205,9 +4213,16 @@ pushdecl_class_level (tree x) ...@@ -4205,9 +4213,16 @@ pushdecl_class_level (tree x)
tree f; tree f;
for (f = TYPE_FIELDS (TREE_TYPE (x)); f; f = TREE_CHAIN (f)) for (f = TYPE_FIELDS (TREE_TYPE (x)); f; f = TREE_CHAIN (f))
pushdecl_class_level (f); {
push_srcloc (DECL_SOURCE_FILE (f), DECL_SOURCE_LINE (f));
if (!pushdecl_class_level (f))
is_valid = false;
pop_srcloc ();
}
} }
timevar_pop (TV_NAME_LOOKUP); timevar_pop (TV_NAME_LOOKUP);
return is_valid;
} }
/* Enter DECL into the symbol table, if that's appropriate. Returns /* Enter DECL into the symbol table, if that's appropriate. Returns
...@@ -4239,21 +4254,19 @@ maybe_push_decl (tree decl) ...@@ -4239,21 +4254,19 @@ maybe_push_decl (tree decl)
return pushdecl (decl); return pushdecl (decl);
} }
/* Make the declaration(s) of X appear in CLASS scope /* Make the declaration(s) of X appear in CLASS scope under the name
under the name NAME. */ NAME. Returns true if the binding is valid. */
void bool
push_class_level_binding (tree name, tree x) push_class_level_binding (tree name, tree x)
{ {
cxx_binding *binding; cxx_binding *binding;
timevar_push (TV_NAME_LOOKUP); timevar_push (TV_NAME_LOOKUP);
/* The class_binding_level will be NULL if x is a template /* The class_binding_level will be NULL if x is a template
parameter name in a member template. */ parameter name in a member template. */
if (!class_binding_level) if (!class_binding_level)
{ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
timevar_pop (TV_NAME_LOOKUP);
return;
}
/* Make sure that this new member does not have the same name /* Make sure that this new member does not have the same name
as a template parameter. */ as a template parameter. */
...@@ -4303,8 +4316,7 @@ push_class_level_binding (tree name, tree x) ...@@ -4303,8 +4316,7 @@ push_class_level_binding (tree name, tree x)
INHERITED_VALUE_BINDING_P (binding) = 0; INHERITED_VALUE_BINDING_P (binding) = 0;
TREE_TYPE (shadow) = x; TREE_TYPE (shadow) = x;
IDENTIFIER_CLASS_VALUE (name) = x; IDENTIFIER_CLASS_VALUE (name) = x;
timevar_pop (TV_NAME_LOOKUP); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
return;
} }
} }
...@@ -4318,8 +4330,10 @@ push_class_level_binding (tree name, tree x) ...@@ -4318,8 +4330,10 @@ push_class_level_binding (tree name, tree x)
/* Record the value we are binding NAME to so that we can know /* Record the value we are binding NAME to so that we can know
what to pop later. */ what to pop later. */
TREE_TYPE (class_binding_level->class_shadowed) = x; TREE_TYPE (class_binding_level->class_shadowed) = x;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
} }
timevar_pop (TV_NAME_LOOKUP);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, false);
} }
/* Insert another USING_DECL into the current binding level, returning /* Insert another USING_DECL into the current binding level, returning
......
...@@ -1862,8 +1862,6 @@ finish_member_declaration (tree decl) ...@@ -1862,8 +1862,6 @@ finish_member_declaration (tree decl)
if (DECL_LANG_SPECIFIC (decl) && DECL_LANGUAGE (decl) == lang_c) if (DECL_LANG_SPECIFIC (decl) && DECL_LANGUAGE (decl) == lang_c)
SET_DECL_LANGUAGE (decl, lang_cplusplus); SET_DECL_LANGUAGE (decl, lang_cplusplus);
maybe_add_class_template_decl_list (current_class_type, decl, /*friend_p=*/0);
/* Put functions on the TYPE_METHODS list and everything else on the /* Put functions on the TYPE_METHODS list and everything else on the
TYPE_FIELDS list. Note that these are built up in reverse order. TYPE_FIELDS list. Note that these are built up in reverse order.
We reverse them (to obtain declaration order) in finish_struct. */ We reverse them (to obtain declaration order) in finish_struct. */
...@@ -1876,8 +1874,12 @@ finish_member_declaration (tree decl) ...@@ -1876,8 +1874,12 @@ finish_member_declaration (tree decl)
TREE_CHAIN (decl) = TYPE_METHODS (current_class_type); TREE_CHAIN (decl) = TYPE_METHODS (current_class_type);
TYPE_METHODS (current_class_type) = decl; TYPE_METHODS (current_class_type) = decl;
maybe_add_class_template_decl_list (current_class_type, decl,
/*friend_p=*/0);
} }
else /* Enter the DECL into the scope of the class. */
else if (TREE_CODE (decl) == USING_DECL || pushdecl_class_level (decl))
{ {
/* All TYPE_DECLs go at the end of TYPE_FIELDS. Ordinary fields /* All TYPE_DECLs go at the end of TYPE_FIELDS. Ordinary fields
go at the beginning. The reason is that lookup_field_1 go at the beginning. The reason is that lookup_field_1
...@@ -1905,9 +1907,8 @@ finish_member_declaration (tree decl) ...@@ -1905,9 +1907,8 @@ finish_member_declaration (tree decl)
TYPE_FIELDS (current_class_type) = decl; TYPE_FIELDS (current_class_type) = decl;
} }
/* Enter the DECL into the scope of the class. */ maybe_add_class_template_decl_list (current_class_type, decl,
if (TREE_CODE (decl) != USING_DECL) /*friend_p=*/0);
pushdecl_class_level (decl);
} }
} }
......
2003-06-19 Mark Mitchell <mark@codesourcery.com> 2003-06-19 Mark Mitchell <mark@codesourcery.com>
PR c++/9649
* g++.dg/template/static4.C: New test.
* g++.old-deja/g++.other/anon7.C: Remove spurious error messages.
PR c++/11041 PR c++/11041
* g++.dg/init/ref7.C: New test. * g++.dg/init/ref7.C: New test.
......
template <class R>
struct A {
static int _test; // { dg-error "" }
static int _test; // { dg-error "" }
};
template <class R> int A<R>::_test = 0;
struct B : public A <int> { };
...@@ -11,7 +11,7 @@ struct B { ...@@ -11,7 +11,7 @@ struct B {
int b; // { dg-error "" } conflicts with previous declaration int b; // { dg-error "" } conflicts with previous declaration
union { union {
int b; // { dg-error "" } duplicate member int b; // { dg-error "" } duplicate member
}; // { dg-error "" } declaration of };
}; };
struct C { struct C {
...@@ -20,5 +20,5 @@ struct C { ...@@ -20,5 +20,5 @@ struct C {
}; };
union { union {
int c; // { dg-error "" } duplicate member int c; // { dg-error "" } duplicate member
}; // { dg-error "" } declaration of };
}; };
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment