aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2003-06-20 02:40:37 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2003-06-20 02:40:37 +0000
commitf139561cce27d9b662b0a3b22d3dd6aa56ae1854 (patch)
treef39921e4f96d4b307cb115c1a2e04b29f5a15ee4 /gcc
parent170b020fe4be4eadea27d389257778d952fb5a13 (diff)
downloadgcc-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/ChangeLog10
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/decl.c44
-rw-r--r--gcc/cp/semantics.c13
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/template/static4.C7
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/anon7.C4
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
+ };
};