aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>2004-11-15 10:34:06 +0000
committerKriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org>2004-11-15 10:34:06 +0000
commit461c6fce5605433279d0d67efa907b87a53db54e (patch)
tree7d0dde0911de811100f87808e5c389d6fecd8f85
parente24b3cc0aa9b5e8d9c37e21ca974fe89a7a04021 (diff)
downloadgcc-461c6fce5605433279d0d67efa907b87a53db54e.zip
gcc-461c6fce5605433279d0d67efa907b87a53db54e.tar.gz
gcc-461c6fce5605433279d0d67efa907b87a53db54e.tar.bz2
Friend class name lookup 1/n, PR c++/18471
Friend class name lookup 1/n, PR c++/18471 * decl.c (lookup_and_check_tag): New function. (xref_tag, start_enum): Use it. (check_elaborated_type_specifier): Move TEMPLATE_TYPE_PARM check before !DECL_IMPLICIT_TYPEDEF_P. Also display previously declared location. * name-lookup.c (lookup_name_current_level): Rename to ... (lookup_name_innermost_nonclass_level): ... this. (lookup_type_scope): New function. * name-lookup.h (lookup_name_current_level): Rename to ... (lookup_name_innermost_nonclass_level): ... this. (lookup_type_scope): Add declaration. * g++.dg/lookup/struct1.C: Adjust expected error. * g++.dg/parse/elab1.C: Likewise. * g++.dg/parse/elab2.C: Likewise. * g++.dg/parse/int-as-enum1.C: Likewise. * g++.dg/parse/struct-as-enum1.C: Likewise. * g++.dg/parse/typedef1.C: Likewise. * g++.dg/parse/typedef3.C: Likewise. * g++.dg/parse/typedef4.C: Likewise. * g++.dg/parse/typedef5.C: Likewise. * g++.dg/template/nontype4.C: Likewise. * g++.old-deja/g++.benjamin/typedef01.C: Likewise. * g++.old-deja/g++.other/elab1.C: Likewise. * g++.old-deja/g++.other/syntax4.C: Likewise. From-SVN: r90657
-rw-r--r--gcc/cp/ChangeLog15
-rw-r--r--gcc/cp/decl.c191
-rw-r--r--gcc/cp/name-lookup.c93
-rw-r--r--gcc/cp/name-lookup.h1
-rw-r--r--gcc/testsuite/ChangeLog18
-rw-r--r--gcc/testsuite/g++.dg/lookup/struct1.C4
-rw-r--r--gcc/testsuite/g++.dg/parse/elab1.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/elab2.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/int-as-enum1.C4
-rw-r--r--gcc/testsuite/g++.dg/parse/struct-as-enum1.C4
-rw-r--r--gcc/testsuite/g++.dg/parse/typedef1.C4
-rw-r--r--gcc/testsuite/g++.dg/parse/typedef3.C4
-rw-r--r--gcc/testsuite/g++.dg/parse/typedef4.C4
-rw-r--r--gcc/testsuite/g++.dg/parse/typedef5.C4
-rw-r--r--gcc/testsuite/g++.dg/template/crash26.C8
-rw-r--r--gcc/testsuite/g++.dg/template/nontype4.C6
-rw-r--r--gcc/testsuite/g++.old-deja/g++.benjamin/typedef01.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/elab1.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/syntax4.C2
19 files changed, 255 insertions, 115 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 9ca645a..23d6b6a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,18 @@
+2004-11-15 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ Friend class name lookup 1/n, PR c++/18471
+ * decl.c (lookup_and_check_tag): New function.
+ (xref_tag, start_enum): Use it.
+ (check_elaborated_type_specifier): Move TEMPLATE_TYPE_PARM check
+ before !DECL_IMPLICIT_TYPEDEF_P. Also display previously declared
+ location.
+ * name-lookup.c (lookup_name_current_level): Rename to ...
+ (lookup_name_innermost_nonclass_level): ... this.
+ (lookup_type_scope): New function.
+ * name-lookup.h (lookup_name_current_level): Rename to ...
+ (lookup_name_innermost_nonclass_level): ... this.
+ (lookup_type_scope): Add declaration.
+
2004-11-14 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/17344
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 472b1f9..f82ec87 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -81,7 +81,8 @@ static hashval_t typename_hash (const void *);
static int typename_compare (const void *, const void *);
static tree local_variable_p_walkfn (tree *, int *, void *);
static tree record_builtin_java_type (const char *, int);
-static const char *tag_name (enum tag_types code);
+static const char *tag_name (enum tag_types);
+static tree lookup_and_check_tag (enum tag_types, tree, bool globalize, bool);
static int walk_namespaces_r (tree, walk_namespaces_fn, void *);
static int walk_globals_r (tree, void*);
static int walk_vtables_r (tree, void*);
@@ -9056,6 +9057,14 @@ check_elaborated_type_specifier (enum tag_types tag_code,
type = TREE_TYPE (decl);
+ /* Check TEMPLATE_TYPE_PARM first because DECL_IMPLICIT_TYPEDEF_P
+ is false for this case as well. */
+ if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+ {
+ error ("using template type parameter %qT after %qs",
+ type, tag_name (tag_code));
+ return error_mark_node;
+ }
/* [dcl.type.elab]
If the identifier resolves to a typedef-name or a template
@@ -9064,16 +9073,10 @@ check_elaborated_type_specifier (enum tag_types tag_code,
In other words, the only legitimate declaration to use in the
elaborated type specifier is the implicit typedef created when
the type is declared. */
- if (!DECL_IMPLICIT_TYPEDEF_P (decl))
+ else if (!DECL_IMPLICIT_TYPEDEF_P (decl))
{
error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
- return IS_AGGR_TYPE (type) ? type : error_mark_node;
- }
-
- if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
- {
- error ("using template type parameter %qT after %qs",
- type, tag_name (tag_code));
+ cp_error_at ("%qD has a previous declaration here", decl);
return error_mark_node;
}
else if (TREE_CODE (type) != RECORD_TYPE
@@ -9081,12 +9084,14 @@ check_elaborated_type_specifier (enum tag_types tag_code,
&& tag_code != enum_type)
{
error ("%qT referred to as %qs", type, tag_name (tag_code));
+ cp_error_at ("%qT has a previous declaration here", type);
return error_mark_node;
}
else if (TREE_CODE (type) != ENUMERAL_TYPE
&& tag_code == enum_type)
{
error ("%qT referred to as enum", type);
+ cp_error_at ("%qT has a previous declaration here", type);
return error_mark_node;
}
else if (!allow_template_p
@@ -9110,6 +9115,53 @@ check_elaborated_type_specifier (enum tag_types tag_code,
return type;
}
+/* Lookup NAME in elaborate type specifier in scope according to
+ GLOBALIZE and issue diagnostics if necessary.
+ Return *_TYPE node upon success, NULL_TREE when the NAME is not
+ found, and ERROR_MARK_NODE for type error. */
+
+static tree
+lookup_and_check_tag (enum tag_types tag_code, tree name,
+ bool globalize, bool template_header_p)
+{
+ tree t;
+ tree decl;
+ if (globalize)
+ decl = lookup_name (name, 2);
+ else
+ decl = lookup_type_scope (name);
+
+ if (decl && DECL_CLASS_TEMPLATE_P (decl))
+ decl = DECL_TEMPLATE_RESULT (decl);
+
+ if (decl && TREE_CODE (decl) == TYPE_DECL)
+ {
+ /* Two cases we need to consider when deciding if a class
+ template is allowed as an elaborated type specifier:
+ 1. It is a self reference to its own class.
+ 2. It comes with a template header.
+
+ For example:
+
+ template <class T> class C {
+ class C *c1; // DECL_SELF_REFERENCE_P is true
+ class D;
+ };
+ template <class U> class C; // template_header_p is true
+ template <class T> class C<T>::D {
+ class C *c2; // DECL_SELF_REFERENCE_P is true
+ }; */
+
+ t = check_elaborated_type_specifier (tag_code,
+ decl,
+ template_header_p
+ | DECL_SELF_REFERENCE_P (decl));
+ return t;
+ }
+ else
+ return NULL_TREE;
+}
+
/* Get the struct, enum or union (TAG_CODE says which) with tag NAME.
Define the tag as a forward-reference if it is not defined.
@@ -9129,7 +9181,6 @@ xref_tag (enum tag_types tag_code, tree name,
{
enum tree_code code;
tree t;
- struct cp_binding_level *b = current_binding_level;
tree context = NULL_TREE;
timevar_push (TV_NAME_LOOKUP);
@@ -9152,90 +9203,59 @@ xref_tag (enum tag_types tag_code, tree name,
gcc_unreachable ();
}
- if (! globalize)
- {
- /* If we know we are defining this tag, only look it up in
- this scope and don't try to find it as a type. */
- t = lookup_tag (code, name, b, 1);
- }
+ /* In case of anonymous name, xref_tag is only called to
+ make type node and push name. Name lookup is not required. */
+ if (ANON_AGGRNAME_P (name))
+ t = NULL_TREE;
else
- {
- tree decl = lookup_name (name, 2);
+ t = lookup_and_check_tag (tag_code, name,
+ globalize, template_header_p);
- if (decl && DECL_CLASS_TEMPLATE_P (decl))
- decl = DECL_TEMPLATE_RESULT (decl);
+ if (t == error_mark_node)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
- if (decl && TREE_CODE (decl) == TYPE_DECL)
- {
- /* Two cases we need to consider when deciding if a class
- template is allowed as an elaborated type specifier:
- 1. It is a self reference to its own class.
- 2. It comes with a template header.
-
- For example:
-
- template <class T> class C {
- class C *c1; // DECL_SELF_REFERENCE_P is true
- class D;
- };
- template <class U> class C; // template_header_p is true
- template <class T> class C<T>::D {
- class C *c2; // DECL_SELF_REFERENCE_P is true
- }; */
-
- t = check_elaborated_type_specifier (tag_code,
- decl,
- template_header_p
- | DECL_SELF_REFERENCE_P (decl));
- if (t == error_mark_node)
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
- }
- else
- t = NULL_TREE;
-
- if (t && current_class_type
- && template_class_depth (current_class_type)
- && template_header_p)
- {
- /* Since GLOBALIZE is nonzero, we are not looking at a
- definition of this tag. Since, in addition, we are currently
- processing a (member) template declaration of a template
- class, we must be very careful; consider:
+ if (globalize && t && current_class_type
+ && template_class_depth (current_class_type)
+ && template_header_p)
+ {
+ /* Since GLOBALIZE is nonzero, we are not looking at a
+ definition of this tag. Since, in addition, we are currently
+ processing a (member) template declaration of a template
+ class, we must be very careful; consider:
- template <class X>
- struct S1
+ template <class X>
+ struct S1
- template <class U>
- struct S2
- { template <class V>
- friend struct S1; };
+ template <class U>
+ struct S2
+ { template <class V>
+ friend struct S1; };
- Here, the S2::S1 declaration should not be confused with the
- outer declaration. In particular, the inner version should
- have a template parameter of level 2, not level 1. This
- would be particularly important if the member declaration
- were instead:
+ Here, the S2::S1 declaration should not be confused with the
+ outer declaration. In particular, the inner version should
+ have a template parameter of level 2, not level 1. This
+ would be particularly important if the member declaration
+ were instead:
- template <class V = U> friend struct S1;
+ template <class V = U> friend struct S1;
- say, when we should tsubst into `U' when instantiating
- S2. On the other hand, when presented with:
+ say, when we should tsubst into `U' when instantiating
+ S2. On the other hand, when presented with:
- template <class T>
- struct S1 {
- template <class U>
- struct S2 {};
- template <class U>
- friend struct S2;
- };
+ template <class T>
+ struct S1 {
+ template <class U>
+ struct S2 {};
+ template <class U>
+ friend struct S2;
+ };
- we must find the inner binding eventually. We
- accomplish this by making sure that the new type we
- create to represent this declaration has the right
- TYPE_CONTEXT. */
- context = TYPE_CONTEXT (t);
- t = NULL_TREE;
- }
+ we must find the inner binding eventually. We
+ accomplish this by making sure that the new type we
+ create to represent this declaration has the right
+ TYPE_CONTEXT. */
+ context = TYPE_CONTEXT (t);
+ t = NULL_TREE;
}
if (! t)
@@ -9482,14 +9502,13 @@ tree
start_enum (tree name)
{
tree enumtype = NULL_TREE;
- struct cp_binding_level *b = current_binding_level;
/* If this is the real definition for a previous forward reference,
fill in the contents in the same object that used to be the
forward reference. */
if (name != NULL_TREE)
- enumtype = lookup_tag (ENUMERAL_TYPE, name, b, 1);
+ enumtype = lookup_and_check_tag (enum_type, name, 0, 0);
if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE)
{
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 9031f05..0abe1ec 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -43,7 +43,7 @@ struct scope_binding {
static cxx_scope *innermost_nonclass_level (void);
static tree select_decl (const struct scope_binding *, int);
static cxx_binding *binding_for_name (cxx_scope *, tree);
-static tree lookup_name_current_level (tree);
+static tree lookup_name_innermost_nonclass_level (tree);
static tree push_overloaded_decl (tree, int);
static bool lookup_using_namespace (tree, struct scope_binding *, tree,
tree, int);
@@ -678,7 +678,7 @@ pushdecl (tree x)
if (DECL_NAMESPACE_SCOPE_P (x) && namespace_bindings_p ())
t = namespace_binding (name, DECL_CONTEXT (x));
else
- t = lookup_name_current_level (name);
+ t = lookup_name_innermost_nonclass_level (name);
/* [basic.link] If there is a visible declaration of an entity
with linkage having the same name and type, ignoring entities
@@ -1111,7 +1111,7 @@ push_local_binding (tree id, tree decl, int flags)
push_local_binding with a friend decl of a local class. */
b = innermost_nonclass_level ();
- if (lookup_name_current_level (id))
+ if (lookup_name_innermost_nonclass_level (id))
{
/* Supplement the existing binding. */
if (!supplement_binding (IDENTIFIER_BINDING (id), decl))
@@ -1998,7 +1998,7 @@ push_overloaded_decl (tree decl, int flags)
if (doing_global)
old = namespace_binding (name, DECL_CONTEXT (decl));
else
- old = lookup_name_current_level (name);
+ old = lookup_name_innermost_nonclass_level (name);
if (old)
{
@@ -2286,7 +2286,7 @@ do_local_using_decl (tree decl, tree scope, tree name)
&& at_function_scope_p ())
add_decl_expr (decl);
- oldval = lookup_name_current_level (name);
+ oldval = lookup_name_innermost_nonclass_level (name);
oldtype = lookup_type_current_level (name);
do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
@@ -4122,11 +4122,90 @@ lookup_name (tree name, int prefer_type)
0, LOOKUP_COMPLAIN);
}
+/* Look up NAME for type used in elaborated name specifier in
+ the current scope (possibly more if cleanup or template parameter
+ scope is encounter). Unlike lookup_name_real, we make sure that
+ NAME is actually declared in the desired scope, not from inheritance,
+ using declaration, nor using directive. A TYPE_DECL best matching
+ the NAME is returned. Catching error and issuing diagnostics are
+ caller's responsibility. */
+
+tree
+lookup_type_scope (tree name)
+{
+ cxx_binding *iter = NULL;
+ tree val = NULL_TREE;
+
+ timevar_push (TV_NAME_LOOKUP);
+
+ /* Look in non-namespace scope first. */
+ if (current_binding_level->kind != sk_namespace)
+ iter = outer_binding (name, NULL, /*class_p=*/ true);
+ for (; iter; iter = outer_binding (name, iter, /*class_p=*/ true))
+ {
+ /* Check if this is the kind of thing we're looking for.
+ Make sure it doesn't come from base class. For ITER->VALUE,
+ we can simply use INHERITED_VALUE_BINDING_P. For ITER->TYPE,
+ we have to use our own check.
+
+ We check ITER->TYPE before ITER->VALUE in order to handle
+ typedef struct C {} C;
+ correctly. */
+
+ if (qualify_lookup (iter->type, LOOKUP_PREFER_TYPES)
+ && (LOCAL_BINDING_P (iter)
+ || DECL_CONTEXT (iter->type) == iter->scope->this_entity))
+ val = iter->type;
+ else if (!INHERITED_VALUE_BINDING_P (iter)
+ && qualify_lookup (iter->value, LOOKUP_PREFER_TYPES))
+ val = iter->value;
+
+ if (val)
+ break;
+ }
+
+ /* Look in namespace scope. */
+ if (!val)
+ {
+ iter = cxx_scope_find_binding_for_name
+ (NAMESPACE_LEVEL (current_decl_namespace ()), name);
+
+ if (iter)
+ {
+ /* If this is the kind of thing we're looking for, we're done. */
+ if (qualify_lookup (iter->type, LOOKUP_PREFER_TYPES))
+ val = iter->type;
+ else if (qualify_lookup (iter->value, LOOKUP_PREFER_TYPES))
+ val = iter->value;
+ }
+
+ }
+
+ /* Type found, check if it is in the current scope, ignoring cleanup
+ and template parameter scopes. */
+ if (val)
+ {
+ struct cp_binding_level *b = current_binding_level;
+ while (b)
+ {
+ if (iter->scope == b)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
+
+ if (b->kind == sk_cleanup || b->kind == sk_template_parms)
+ b = b->level_chain;
+ else
+ break;
+ }
+ }
+
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
+}
+
/* Similar to `lookup_name' but look only in the innermost non-class
binding level. */
static tree
-lookup_name_current_level (tree name)
+lookup_name_innermost_nonclass_level (tree name)
{
struct cp_binding_level *b;
tree t = NULL_TREE;
@@ -4164,7 +4243,7 @@ lookup_name_current_level (tree name)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
-/* Like lookup_name_current_level, but for types. */
+/* Like lookup_name_innermost_nonclass_level, but for types. */
static tree
lookup_type_current_level (tree name)
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index 7c73f3f..b43fa1e 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -303,6 +303,7 @@ extern tree lookup_tag (enum tree_code, tree, cxx_scope *, int);
extern tree lookup_tag_reverse (tree, tree);
extern tree lookup_name (tree, int);
extern tree lookup_name_real (tree, int, int, bool, int, int);
+extern tree lookup_type_scope (tree);
extern tree namespace_binding (tree, tree);
extern void set_namespace_binding (tree, tree, tree);
extern tree lookup_namespace_name (tree, tree);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index cc7cb25..d365371 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,21 @@
+2004-11-15 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
+
+ Friend class name lookup 1/n, PR c++/18471
+ * g++.dg/template/crash26.C: New test.
+ * g++.dg/lookup/struct1.C: Adjust expected error.
+ * g++.dg/parse/elab1.C: Likewise.
+ * g++.dg/parse/elab2.C: Likewise.
+ * g++.dg/parse/int-as-enum1.C: Likewise.
+ * g++.dg/parse/struct-as-enum1.C: Likewise.
+ * g++.dg/parse/typedef1.C: Likewise.
+ * g++.dg/parse/typedef3.C: Likewise.
+ * g++.dg/parse/typedef4.C: Likewise.
+ * g++.dg/parse/typedef5.C: Likewise.
+ * g++.dg/template/nontype4.C: Likewise.
+ * g++.old-deja/g++.benjamin/typedef01.C: Likewise.
+ * g++.old-deja/g++.other/elab1.C: Likewise.
+ * g++.old-deja/g++.other/syntax4.C: Likewise.
+
2004-11-15 Eric Botcazou <ebotcazou@libertysurf.fr>
* gcc.dg/intmax_t-1.c: XFAIL on Solaris 2.5.1.
diff --git a/gcc/testsuite/g++.dg/lookup/struct1.C b/gcc/testsuite/g++.dg/lookup/struct1.C
index dd8d54b..f4b83ec 100644
--- a/gcc/testsuite/g++.dg/lookup/struct1.C
+++ b/gcc/testsuite/g++.dg/lookup/struct1.C
@@ -3,10 +3,10 @@
struct A;
typedef struct A B; // { dg-error "previous declaration" }
-struct B; // { dg-error "conflicting declaration" }
+struct B; // { dg-error "using typedef-name" }
typedef struct { int i; } C; // { dg-error "previous declaration" }
-struct C; // { dg-error "conflicting declaration" }
+struct C; // { dg-error "using typedef-name" }
struct D;
typedef struct D D;
diff --git a/gcc/testsuite/g++.dg/parse/elab1.C b/gcc/testsuite/g++.dg/parse/elab1.C
index 2997eef..92fcd1c 100644
--- a/gcc/testsuite/g++.dg/parse/elab1.C
+++ b/gcc/testsuite/g++.dg/parse/elab1.C
@@ -1,6 +1,6 @@
namespace Name {
- typedef void *(*Function)( void *, int );
+ typedef void *(*Function)( void *, int ); // { dg-error "previous declaration" }
struct Foo {
struct Function xyz[5]; // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/parse/elab2.C b/gcc/testsuite/g++.dg/parse/elab2.C
index 69273a3..6b42aed 100644
--- a/gcc/testsuite/g++.dg/parse/elab2.C
+++ b/gcc/testsuite/g++.dg/parse/elab2.C
@@ -2,6 +2,6 @@ struct A {};
struct B
{
- typedef A T;
+ typedef A T; // { dg-error "previous declaration" }
friend struct T; // { dg-error "" }
};
diff --git a/gcc/testsuite/g++.dg/parse/int-as-enum1.C b/gcc/testsuite/g++.dg/parse/int-as-enum1.C
index 2bf9cc0..7c37eb0 100644
--- a/gcc/testsuite/g++.dg/parse/int-as-enum1.C
+++ b/gcc/testsuite/g++.dg/parse/int-as-enum1.C
@@ -2,5 +2,5 @@
// Origin: <wanderer@rsu.ru>
// { dg-do compile }
-typedef int A;
-enum ::A {}; // { dg-error "" }
+typedef int A; // { dg-error "previous" }
+enum ::A {}; // { dg-error "typedef-name|expected unqualified-id" }
diff --git a/gcc/testsuite/g++.dg/parse/struct-as-enum1.C b/gcc/testsuite/g++.dg/parse/struct-as-enum1.C
index 016c603..bc8c5b5 100644
--- a/gcc/testsuite/g++.dg/parse/struct-as-enum1.C
+++ b/gcc/testsuite/g++.dg/parse/struct-as-enum1.C
@@ -4,7 +4,7 @@
namespace N
{
- struct A {};
+ struct A {}; // { dg-error "previous declaration" }
}
-typedef enum N::A B; // { dg-error "enum" }
+typedef enum N::A B; // { dg-error "enum" }
diff --git a/gcc/testsuite/g++.dg/parse/typedef1.C b/gcc/testsuite/g++.dg/parse/typedef1.C
index a01a66c..c4fbb95 100644
--- a/gcc/testsuite/g++.dg/parse/typedef1.C
+++ b/gcc/testsuite/g++.dg/parse/typedef1.C
@@ -1,3 +1,3 @@
// PR c++/6477
-typedef struct A_ *A;
-typedef struct A B; // { dg-error "" }
+typedef struct A_ *A; // { dg-error "previous declaration" }
+typedef struct A B; // { dg-error "typedef|invalid type" }
diff --git a/gcc/testsuite/g++.dg/parse/typedef3.C b/gcc/testsuite/g++.dg/parse/typedef3.C
index 380b753..6b4e531 100644
--- a/gcc/testsuite/g++.dg/parse/typedef3.C
+++ b/gcc/testsuite/g++.dg/parse/typedef3.C
@@ -2,6 +2,6 @@
// Origin: Travis J.I. Corcoran <tjic@permabit.com>
// { dg-do compile }
-struct A { typedef A* Ptr; };
+struct A { typedef A* Ptr; }; // { dg-error "previous declaration" }
-struct A::Ptr; // { dg-error "" }
+struct A::Ptr; // { dg-error "typedef|not declare anything" }
diff --git a/gcc/testsuite/g++.dg/parse/typedef4.C b/gcc/testsuite/g++.dg/parse/typedef4.C
index 03f709a..8599fd1 100644
--- a/gcc/testsuite/g++.dg/parse/typedef4.C
+++ b/gcc/testsuite/g++.dg/parse/typedef4.C
@@ -7,6 +7,6 @@
template<class T> class smart_ptr2 {
T* real_ptr;
public:
- typedef typename T::subT td;
- friend class td; // { dg-error "typedef" }
+ typedef typename T::subT td; // { dg-error "previous declaration" }
+ friend class td; // { dg-error "typedef|not name a class" }
};
diff --git a/gcc/testsuite/g++.dg/parse/typedef5.C b/gcc/testsuite/g++.dg/parse/typedef5.C
index 5f6b18c..22ba85e 100644
--- a/gcc/testsuite/g++.dg/parse/typedef5.C
+++ b/gcc/testsuite/g++.dg/parse/typedef5.C
@@ -1,6 +1,6 @@
namespace A
{
- typedef int T;
+ typedef int T; // { dg-error "previous declaration" }
}
-class A::T x; // { dg-error "" }
+class A::T x; // { dg-error "using typedef-name" }
diff --git a/gcc/testsuite/g++.dg/template/crash26.C b/gcc/testsuite/g++.dg/template/crash26.C
new file mode 100644
index 0000000..f1bc399
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/crash26.C
@@ -0,0 +1,8 @@
+// { dg-do compile }
+
+// Origin: Volker Reichelt <reichelt@gcc.gnu.org>
+
+// PR c++/18471: ICE redeclaration of typedef as class template
+
+typedef int X; // { dg-error "previous" }
+template<X> struct X {}; // { dg-error "typedef-name" }
diff --git a/gcc/testsuite/g++.dg/template/nontype4.C b/gcc/testsuite/g++.dg/template/nontype4.C
index 43ef2b0..ab39ed4 100644
--- a/gcc/testsuite/g++.dg/template/nontype4.C
+++ b/gcc/testsuite/g++.dg/template/nontype4.C
@@ -7,8 +7,8 @@
template <int> struct A
{
- typedef A<0> B; // { dg-error "not a valid type|conflict" }
- template <B> struct B {}; // { dg-error "not a valid type|declaration" }
+ typedef A<0> B; // { dg-error "previous declaration" }
+ template <B> struct B {}; // { dg-error "not a valid type|typedef" }
};
-A<0> a; // { dg-error "instantiated" }
+A<0> a;
diff --git a/gcc/testsuite/g++.old-deja/g++.benjamin/typedef01.C b/gcc/testsuite/g++.old-deja/g++.benjamin/typedef01.C
index 466b866..79a965b 100644
--- a/gcc/testsuite/g++.old-deja/g++.benjamin/typedef01.C
+++ b/gcc/testsuite/g++.old-deja/g++.benjamin/typedef01.C
@@ -37,7 +37,7 @@ struct S {
~S();
};
-typedef struct S T;
+typedef struct S T; // { dg-error "previous declaration" }
S a = T(); // OK
struct T * p; // { dg-error "" } using typedef after struct
diff --git a/gcc/testsuite/g++.old-deja/g++.other/elab1.C b/gcc/testsuite/g++.old-deja/g++.other/elab1.C
index f5f266c..5588651 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/elab1.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/elab1.C
@@ -1,5 +1,5 @@
// { dg-do assemble }
-typedef struct {} S;
+typedef struct {} S; // { dg-error "" } Previous declaration of S
S s1;
struct S* s2; // { dg-error "" } S is a typedef name
diff --git a/gcc/testsuite/g++.old-deja/g++.other/syntax4.C b/gcc/testsuite/g++.old-deja/g++.other/syntax4.C
index d323ff0..7aed1f5 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/syntax4.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/syntax4.C
@@ -17,7 +17,7 @@ class X {
class Y {
public:
- typedef ::X W;
+ typedef ::X W; // { dg-error "" } previous declaration
class Z;
};