diff options
author | Mark Mitchell <mark@codesourcery.com> | 2003-06-20 02:40:37 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2003-06-20 02:40:37 +0000 |
commit | f139561cce27d9b662b0a3b22d3dd6aa56ae1854 (patch) | |
tree | f39921e4f96d4b307cb115c1a2e04b29f5a15ee4 /gcc | |
parent | 170b020fe4be4eadea27d389257778d952fb5a13 (diff) | |
download | gcc-f139561cce27d9b662b0a3b22d3dd6aa56ae1854.zip gcc-f139561cce27d9b662b0a3b22d3dd6aa56ae1854.tar.gz gcc-f139561cce27d9b662b0a3b22d3dd6aa56ae1854.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 4 | ||||
-rw-r--r-- | gcc/cp/decl.c | 44 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/static4.C | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.other/anon7.C | 4 |
7 files changed, 61 insertions, 25 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 30e01f2..ba7bc03 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index bfb7e0f..6bc6f6f 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index d025a6f..d73c0d0 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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 diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index b400e4d..a95c957 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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); } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index dd5c992..2b4942c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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. diff --git a/gcc/testsuite/g++.dg/template/static4.C b/gcc/testsuite/g++.dg/template/static4.C new file mode 100644 index 0000000..c548632 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/static4.C @@ -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> { }; diff --git a/gcc/testsuite/g++.old-deja/g++.other/anon7.C b/gcc/testsuite/g++.old-deja/g++.other/anon7.C index 3131c6b..ebc3780 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/anon7.C +++ b/gcc/testsuite/g++.old-deja/g++.other/anon7.C @@ -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 + }; }; |