diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f1c25a4d4ff..013b826b8c2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2002-03-02 Nathan Sidwell + + PR c++/775 + * decl.c (lookup_tag): Only reject enum/class mismatch, not + class/union mismatch. + * parse.y (check_class_key): New function. + (structsp): Call it. + 2002-03-01 Michael Matz * typeck.c (cp_pointer_int_sum): Complete inner type which is diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index d4ea80df979..854a2c2a9fa 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5345,7 +5345,7 @@ lookup_tag (form, name, binding_level, thislevel_only) if (old && DECL_ORIGINAL_TYPE (TYPE_NAME (old))) old = NULL_TREE; if (old && TREE_CODE (old) != form - && !(form != ENUMERAL_TYPE && TREE_CODE (old) == TEMPLATE_DECL)) + && (form == ENUMERAL_TYPE || TREE_CODE (old) == ENUMERAL_TYPE)) { error ("`%#D' redeclared as %C", old, form); return NULL_TREE; @@ -5361,14 +5361,12 @@ lookup_tag (form, name, binding_level, thislevel_only) if (TREE_PURPOSE (tail) == name) { enum tree_code code = TREE_CODE (TREE_VALUE (tail)); - /* Should tighten this up; it'll probably permit - UNION_TYPE and a struct template, for example. */ + if (code != form - && !(form != ENUMERAL_TYPE && code == TEMPLATE_DECL)) + && (form == ENUMERAL_TYPE || code == ENUMERAL_TYPE)) { /* Definition isn't the kind we were looking for. */ - error ("`%#D' redeclared as %C", TREE_VALUE (tail), - form); + error ("`%#D' redeclared as %C", TREE_VALUE (tail), form); return NULL_TREE; } return TREE_VALUE (tail); diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index e6bdc9a1f2e..fd53a850cb2 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -87,7 +87,8 @@ static tree parse_field PARAMS ((tree, tree, tree, tree)); static tree parse_bitfield0 PARAMS ((tree, tree, tree, tree, tree)); static tree parse_bitfield PARAMS ((tree, tree, tree)); static tree parse_method PARAMS ((tree, tree, tree)); -static void frob_specs PARAMS ((tree, tree)); +static void frob_specs PARAMS ((tree, tree)); +static void check_class_key PARAMS ((tree, tree)); /* Cons up an empty parameter list. */ static inline tree @@ -208,6 +209,17 @@ parse_method (declarator, specs_attrs, lookups) return d; } +static void +check_class_key (key, aggr) + tree key; + tree aggr; +{ + if ((key == union_type_node) != (TREE_CODE (aggr) == UNION_TYPE)) + pedwarn ("`%s' tag used in naming `%#T'", + key == union_type_node ? "union" + : key == record_type_node ? "struct" : "class", aggr); +} + void cp_parse_init () { @@ -2292,6 +2304,7 @@ structsp: xref_basetypes (current_aggr, $1.t, type, $2); } $1.t = begin_class_definition (TREE_TYPE ($1.t)); + check_class_key (current_aggr, $1.t); current_aggr = NULL_TREE; } opt.component_decl_list '}' maybe_attribute { @@ -2326,6 +2339,7 @@ structsp: { $$.t = TREE_TYPE ($1.t); $$.new_type_flag = $1.new_type_flag; + check_class_key (current_aggr, $$.t); } ; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6dabbc7d4d5..5be459f6110 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2002-03-02 Nathan Sidwell + + * g++.dg/other/classkey1.C: New test. + 2002-03-01 Richard Henderson * gcc.c-torture/compile/981223-1.x: New. diff --git a/gcc/testsuite/g++.dg/other/classkey1.C b/gcc/testsuite/g++.dg/other/classkey1.C new file mode 100644 index 00000000000..17fb54065d0 --- /dev/null +++ b/gcc/testsuite/g++.dg/other/classkey1.C @@ -0,0 +1,17 @@ +// { dg-do compile } + +// Copyright (C) 2002 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 28 Feb 2002 + +// PR 775. Some mismatches which were broken. + +template struct A {}; +union A a; // { dg-error "`union' tag" "" } + +template <> union A {}; // { dg-error "`union' tag" "" } + +struct B {}; +union B b; // { dg-error "`union' tag" "" } + +union C {}; +class C c; // { dg-error "`class' tag" "" }