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
This commit is contained in:
parent
170b020fe4
commit
f139561cce
7 changed files with 61 additions and 25 deletions
|
@ -1,5 +1,15 @@
|
|||
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
|
||||
* call.c (initialize_reference): Do not use cp_finish_decl to emit
|
||||
temporary variables.
|
||||
|
|
|
@ -3638,11 +3638,11 @@ extern int decls_match (tree, tree);
|
|||
extern int duplicate_decls (tree, tree);
|
||||
extern tree pushdecl_top_level (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 push_using_decl (tree, 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 declare_local_label (tree);
|
||||
extern tree define_label (const char *, int, tree);
|
||||
|
|
|
@ -964,11 +964,18 @@ add_binding (tree id, tree decl)
|
|||
type to which it already refers. */
|
||||
ok = 0;
|
||||
/* 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
|
||||
&& TREE_CODE (BINDING_VALUE (binding)) == VAR_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));
|
||||
ok = 0;
|
||||
|
@ -4179,10 +4186,11 @@ pushdecl_top_level_and_finish (tree x, tree init)
|
|||
|
||||
/* Make the declaration of X appear in CLASS scope. */
|
||||
|
||||
void
|
||||
bool
|
||||
pushdecl_class_level (tree x)
|
||||
{
|
||||
tree name;
|
||||
bool is_valid = true;
|
||||
|
||||
timevar_push (TV_NAME_LOOKUP);
|
||||
/* Get the name of X. */
|
||||
|
@ -4193,7 +4201,7 @@ pushdecl_class_level (tree x)
|
|||
|
||||
if (name)
|
||||
{
|
||||
push_class_level_binding (name, x);
|
||||
is_valid = push_class_level_binding (name, x);
|
||||
if (TREE_CODE (x) == TYPE_DECL)
|
||||
set_identifier_type_value (name, TREE_TYPE (x));
|
||||
}
|
||||
|
@ -4205,9 +4213,16 @@ pushdecl_class_level (tree x)
|
|||
tree 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);
|
||||
|
||||
return is_valid;
|
||||
}
|
||||
|
||||
/* Enter DECL into the symbol table, if that's appropriate. Returns
|
||||
|
@ -4239,21 +4254,19 @@ maybe_push_decl (tree decl)
|
|||
return pushdecl (decl);
|
||||
}
|
||||
|
||||
/* Make the declaration(s) of X appear in CLASS scope
|
||||
under the name NAME. */
|
||||
/* Make the declaration(s) of X appear in CLASS scope under the name
|
||||
NAME. Returns true if the binding is valid. */
|
||||
|
||||
void
|
||||
bool
|
||||
push_class_level_binding (tree name, tree x)
|
||||
{
|
||||
cxx_binding *binding;
|
||||
|
||||
timevar_push (TV_NAME_LOOKUP);
|
||||
/* The class_binding_level will be NULL if x is a template
|
||||
parameter name in a member template. */
|
||||
if (!class_binding_level)
|
||||
{
|
||||
timevar_pop (TV_NAME_LOOKUP);
|
||||
return;
|
||||
}
|
||||
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
|
||||
|
||||
/* Make sure that this new member does not have the same name
|
||||
as a template parameter. */
|
||||
|
@ -4303,8 +4316,7 @@ push_class_level_binding (tree name, tree x)
|
|||
INHERITED_VALUE_BINDING_P (binding) = 0;
|
||||
TREE_TYPE (shadow) = x;
|
||||
IDENTIFIER_CLASS_VALUE (name) = x;
|
||||
timevar_pop (TV_NAME_LOOKUP);
|
||||
return;
|
||||
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
what to pop later. */
|
||||
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
|
||||
|
|
|
@ -1862,8 +1862,6 @@ finish_member_declaration (tree decl)
|
|||
if (DECL_LANG_SPECIFIC (decl) && DECL_LANGUAGE (decl) == lang_c)
|
||||
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
|
||||
TYPE_FIELDS list. Note that these are built up in reverse order.
|
||||
We reverse them (to obtain declaration order) in finish_struct. */
|
||||
|
@ -1876,8 +1874,12 @@ finish_member_declaration (tree decl)
|
|||
|
||||
TREE_CHAIN (decl) = TYPE_METHODS (current_class_type);
|
||||
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
|
||||
go at the beginning. The reason is that lookup_field_1
|
||||
|
@ -1905,9 +1907,8 @@ finish_member_declaration (tree decl)
|
|||
TYPE_FIELDS (current_class_type) = decl;
|
||||
}
|
||||
|
||||
/* Enter the DECL into the scope of the class. */
|
||||
if (TREE_CODE (decl) != USING_DECL)
|
||||
pushdecl_class_level (decl);
|
||||
maybe_add_class_template_decl_list (current_class_type, decl,
|
||||
/*friend_p=*/0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
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
|
||||
* g++.dg/init/ref7.C: New test.
|
||||
|
||||
|
|
7
gcc/testsuite/g++.dg/template/static4.C
Normal file
7
gcc/testsuite/g++.dg/template/static4.C
Normal file
|
@ -0,0 +1,7 @@
|
|||
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 {
|
|||
int b; // { dg-error "" } conflicts with previous declaration
|
||||
union {
|
||||
int b; // { dg-error "" } duplicate member
|
||||
}; // { dg-error "" } declaration of
|
||||
};
|
||||
};
|
||||
|
||||
struct C {
|
||||
|
@ -20,5 +20,5 @@ struct C {
|
|||
};
|
||||
union {
|
||||
int c; // { dg-error "" } duplicate member
|
||||
}; // { dg-error "" } declaration of
|
||||
};
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue