diff options
author | Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> | 2004-11-15 10:34:06 +0000 |
---|---|---|
committer | Kriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org> | 2004-11-15 10:34:06 +0000 |
commit | 461c6fce5605433279d0d67efa907b87a53db54e (patch) | |
tree | 7d0dde0911de811100f87808e5c389d6fecd8f85 | |
parent | e24b3cc0aa9b5e8d9c37e21ca974fe89a7a04021 (diff) | |
download | gcc-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/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/cp/decl.c | 191 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 93 | ||||
-rw-r--r-- | gcc/cp/name-lookup.h | 1 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/lookup/struct1.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/elab1.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/elab2.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/int-as-enum1.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/struct-as-enum1.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/typedef1.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/typedef3.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/typedef4.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/typedef5.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/crash26.C | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/nontype4.C | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.benjamin/typedef01.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.other/elab1.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.other/syntax4.C | 2 |
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; }; |