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
This commit is contained in:
parent
e24b3cc0aa
commit
461c6fce56
19 changed files with 256 additions and 116 deletions
|
@ -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>
|
2004-11-14 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
|
||||||
|
|
||||||
PR c++/17344
|
PR c++/17344
|
||||||
|
|
143
gcc/cp/decl.c
143
gcc/cp/decl.c
|
@ -81,7 +81,8 @@ static hashval_t typename_hash (const void *);
|
||||||
static int typename_compare (const void *, const void *);
|
static int typename_compare (const void *, const void *);
|
||||||
static tree local_variable_p_walkfn (tree *, int *, void *);
|
static tree local_variable_p_walkfn (tree *, int *, void *);
|
||||||
static tree record_builtin_java_type (const char *, int);
|
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_namespaces_r (tree, walk_namespaces_fn, void *);
|
||||||
static int walk_globals_r (tree, void*);
|
static int walk_globals_r (tree, void*);
|
||||||
static int walk_vtables_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);
|
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]
|
/* [dcl.type.elab]
|
||||||
|
|
||||||
If the identifier resolves to a typedef-name or a template
|
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
|
In other words, the only legitimate declaration to use in the
|
||||||
elaborated type specifier is the implicit typedef created when
|
elaborated type specifier is the implicit typedef created when
|
||||||
the type is declared. */
|
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));
|
error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
|
||||||
return IS_AGGR_TYPE (type) ? type : error_mark_node;
|
cp_error_at ("%qD has a previous declaration here", decl);
|
||||||
}
|
|
||||||
|
|
||||||
if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
|
|
||||||
{
|
|
||||||
error ("using template type parameter %qT after %qs",
|
|
||||||
type, tag_name (tag_code));
|
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
else if (TREE_CODE (type) != RECORD_TYPE
|
else if (TREE_CODE (type) != RECORD_TYPE
|
||||||
|
@ -9081,12 +9084,14 @@ check_elaborated_type_specifier (enum tag_types tag_code,
|
||||||
&& tag_code != enum_type)
|
&& tag_code != enum_type)
|
||||||
{
|
{
|
||||||
error ("%qT referred to as %qs", type, tag_name (tag_code));
|
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;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
else if (TREE_CODE (type) != ENUMERAL_TYPE
|
else if (TREE_CODE (type) != ENUMERAL_TYPE
|
||||||
&& tag_code == enum_type)
|
&& tag_code == enum_type)
|
||||||
{
|
{
|
||||||
error ("%qT referred to as enum", type);
|
error ("%qT referred to as enum", type);
|
||||||
|
cp_error_at ("%qT has a previous declaration here", type);
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
else if (!allow_template_p
|
else if (!allow_template_p
|
||||||
|
@ -9110,57 +9115,21 @@ check_elaborated_type_specifier (enum tag_types tag_code,
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the struct, enum or union (TAG_CODE says which) with tag NAME.
|
/* Lookup NAME in elaborate type specifier in scope according to
|
||||||
Define the tag as a forward-reference if it is not defined.
|
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. */
|
||||||
|
|
||||||
If a declaration is given, process it here, and report an error if
|
static tree
|
||||||
multiple declarations are not identical.
|
lookup_and_check_tag (enum tag_types tag_code, tree name,
|
||||||
|
|
||||||
GLOBALIZE is false when this is also a definition. Only look in
|
|
||||||
the current frame for the name (since C++ allows new names in any
|
|
||||||
scope.)
|
|
||||||
|
|
||||||
TEMPLATE_HEADER_P is true when this declaration is preceded by
|
|
||||||
a set of template parameters. */
|
|
||||||
|
|
||||||
tree
|
|
||||||
xref_tag (enum tag_types tag_code, tree name,
|
|
||||||
bool globalize, bool template_header_p)
|
bool globalize, bool template_header_p)
|
||||||
{
|
{
|
||||||
enum tree_code code;
|
|
||||||
tree t;
|
tree t;
|
||||||
struct cp_binding_level *b = current_binding_level;
|
tree decl;
|
||||||
tree context = NULL_TREE;
|
if (globalize)
|
||||||
|
decl = lookup_name (name, 2);
|
||||||
timevar_push (TV_NAME_LOOKUP);
|
|
||||||
|
|
||||||
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
|
|
||||||
|
|
||||||
switch (tag_code)
|
|
||||||
{
|
|
||||||
case record_type:
|
|
||||||
case class_type:
|
|
||||||
code = RECORD_TYPE;
|
|
||||||
break;
|
|
||||||
case union_type:
|
|
||||||
code = UNION_TYPE;
|
|
||||||
break;
|
|
||||||
case enum_type:
|
|
||||||
code = ENUMERAL_TYPE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
decl = lookup_type_scope (name);
|
||||||
tree decl = lookup_name (name, 2);
|
|
||||||
|
|
||||||
if (decl && DECL_CLASS_TEMPLATE_P (decl))
|
if (decl && DECL_CLASS_TEMPLATE_P (decl))
|
||||||
decl = DECL_TEMPLATE_RESULT (decl);
|
decl = DECL_TEMPLATE_RESULT (decl);
|
||||||
|
@ -9187,13 +9156,65 @@ xref_tag (enum tag_types tag_code, tree name,
|
||||||
decl,
|
decl,
|
||||||
template_header_p
|
template_header_p
|
||||||
| DECL_SELF_REFERENCE_P (decl));
|
| DECL_SELF_REFERENCE_P (decl));
|
||||||
if (t == error_mark_node)
|
return t;
|
||||||
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
t = NULL_TREE;
|
return NULL_TREE;
|
||||||
|
}
|
||||||
|
|
||||||
if (t && current_class_type
|
/* 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.
|
||||||
|
|
||||||
|
If a declaration is given, process it here, and report an error if
|
||||||
|
multiple declarations are not identical.
|
||||||
|
|
||||||
|
GLOBALIZE is false when this is also a definition. Only look in
|
||||||
|
the current frame for the name (since C++ allows new names in any
|
||||||
|
scope.)
|
||||||
|
|
||||||
|
TEMPLATE_HEADER_P is true when this declaration is preceded by
|
||||||
|
a set of template parameters. */
|
||||||
|
|
||||||
|
tree
|
||||||
|
xref_tag (enum tag_types tag_code, tree name,
|
||||||
|
bool globalize, bool template_header_p)
|
||||||
|
{
|
||||||
|
enum tree_code code;
|
||||||
|
tree t;
|
||||||
|
tree context = NULL_TREE;
|
||||||
|
|
||||||
|
timevar_push (TV_NAME_LOOKUP);
|
||||||
|
|
||||||
|
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
|
||||||
|
|
||||||
|
switch (tag_code)
|
||||||
|
{
|
||||||
|
case record_type:
|
||||||
|
case class_type:
|
||||||
|
code = RECORD_TYPE;
|
||||||
|
break;
|
||||||
|
case union_type:
|
||||||
|
code = UNION_TYPE;
|
||||||
|
break;
|
||||||
|
case enum_type:
|
||||||
|
code = ENUMERAL_TYPE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gcc_unreachable ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
t = lookup_and_check_tag (tag_code, name,
|
||||||
|
globalize, template_header_p);
|
||||||
|
|
||||||
|
if (t == error_mark_node)
|
||||||
|
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
|
||||||
|
|
||||||
|
if (globalize && t && current_class_type
|
||||||
&& template_class_depth (current_class_type)
|
&& template_class_depth (current_class_type)
|
||||||
&& template_header_p)
|
&& template_header_p)
|
||||||
{
|
{
|
||||||
|
@ -9236,7 +9257,6 @@ xref_tag (enum tag_types tag_code, tree name,
|
||||||
context = TYPE_CONTEXT (t);
|
context = TYPE_CONTEXT (t);
|
||||||
t = NULL_TREE;
|
t = NULL_TREE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (! t)
|
if (! t)
|
||||||
{
|
{
|
||||||
|
@ -9482,14 +9502,13 @@ tree
|
||||||
start_enum (tree name)
|
start_enum (tree name)
|
||||||
{
|
{
|
||||||
tree enumtype = NULL_TREE;
|
tree enumtype = NULL_TREE;
|
||||||
struct cp_binding_level *b = current_binding_level;
|
|
||||||
|
|
||||||
/* If this is the real definition for a previous forward reference,
|
/* If this is the real definition for a previous forward reference,
|
||||||
fill in the contents in the same object that used to be the
|
fill in the contents in the same object that used to be the
|
||||||
forward reference. */
|
forward reference. */
|
||||||
|
|
||||||
if (name != NULL_TREE)
|
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)
|
if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE)
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,7 +43,7 @@ struct scope_binding {
|
||||||
static cxx_scope *innermost_nonclass_level (void);
|
static cxx_scope *innermost_nonclass_level (void);
|
||||||
static tree select_decl (const struct scope_binding *, int);
|
static tree select_decl (const struct scope_binding *, int);
|
||||||
static cxx_binding *binding_for_name (cxx_scope *, tree);
|
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 tree push_overloaded_decl (tree, int);
|
||||||
static bool lookup_using_namespace (tree, struct scope_binding *, tree,
|
static bool lookup_using_namespace (tree, struct scope_binding *, tree,
|
||||||
tree, int);
|
tree, int);
|
||||||
|
@ -678,7 +678,7 @@ pushdecl (tree x)
|
||||||
if (DECL_NAMESPACE_SCOPE_P (x) && namespace_bindings_p ())
|
if (DECL_NAMESPACE_SCOPE_P (x) && namespace_bindings_p ())
|
||||||
t = namespace_binding (name, DECL_CONTEXT (x));
|
t = namespace_binding (name, DECL_CONTEXT (x));
|
||||||
else
|
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
|
/* [basic.link] If there is a visible declaration of an entity
|
||||||
with linkage having the same name and type, ignoring entities
|
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. */
|
push_local_binding with a friend decl of a local class. */
|
||||||
b = innermost_nonclass_level ();
|
b = innermost_nonclass_level ();
|
||||||
|
|
||||||
if (lookup_name_current_level (id))
|
if (lookup_name_innermost_nonclass_level (id))
|
||||||
{
|
{
|
||||||
/* Supplement the existing binding. */
|
/* Supplement the existing binding. */
|
||||||
if (!supplement_binding (IDENTIFIER_BINDING (id), decl))
|
if (!supplement_binding (IDENTIFIER_BINDING (id), decl))
|
||||||
|
@ -1998,7 +1998,7 @@ push_overloaded_decl (tree decl, int flags)
|
||||||
if (doing_global)
|
if (doing_global)
|
||||||
old = namespace_binding (name, DECL_CONTEXT (decl));
|
old = namespace_binding (name, DECL_CONTEXT (decl));
|
||||||
else
|
else
|
||||||
old = lookup_name_current_level (name);
|
old = lookup_name_innermost_nonclass_level (name);
|
||||||
|
|
||||||
if (old)
|
if (old)
|
||||||
{
|
{
|
||||||
|
@ -2286,7 +2286,7 @@ do_local_using_decl (tree decl, tree scope, tree name)
|
||||||
&& at_function_scope_p ())
|
&& at_function_scope_p ())
|
||||||
add_decl_expr (decl);
|
add_decl_expr (decl);
|
||||||
|
|
||||||
oldval = lookup_name_current_level (name);
|
oldval = lookup_name_innermost_nonclass_level (name);
|
||||||
oldtype = lookup_type_current_level (name);
|
oldtype = lookup_type_current_level (name);
|
||||||
|
|
||||||
do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
|
do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
|
||||||
|
@ -4122,11 +4122,90 @@ lookup_name (tree name, int prefer_type)
|
||||||
0, LOOKUP_COMPLAIN);
|
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
|
/* Similar to `lookup_name' but look only in the innermost non-class
|
||||||
binding level. */
|
binding level. */
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
lookup_name_current_level (tree name)
|
lookup_name_innermost_nonclass_level (tree name)
|
||||||
{
|
{
|
||||||
struct cp_binding_level *b;
|
struct cp_binding_level *b;
|
||||||
tree t = NULL_TREE;
|
tree t = NULL_TREE;
|
||||||
|
@ -4164,7 +4243,7 @@ lookup_name_current_level (tree name)
|
||||||
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
|
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
|
static tree
|
||||||
lookup_type_current_level (tree name)
|
lookup_type_current_level (tree name)
|
||||||
|
|
|
@ -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_tag_reverse (tree, tree);
|
||||||
extern tree lookup_name (tree, int);
|
extern tree lookup_name (tree, int);
|
||||||
extern tree lookup_name_real (tree, int, int, bool, int, 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 tree namespace_binding (tree, tree);
|
||||||
extern void set_namespace_binding (tree, tree, tree);
|
extern void set_namespace_binding (tree, tree, tree);
|
||||||
extern tree lookup_namespace_name (tree, tree);
|
extern tree lookup_namespace_name (tree, tree);
|
||||||
|
|
|
@ -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>
|
2004-11-15 Eric Botcazou <ebotcazou@libertysurf.fr>
|
||||||
|
|
||||||
* gcc.dg/intmax_t-1.c: XFAIL on Solaris 2.5.1.
|
* gcc.dg/intmax_t-1.c: XFAIL on Solaris 2.5.1.
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
|
|
||||||
struct A;
|
struct A;
|
||||||
typedef struct A B; // { dg-error "previous declaration" }
|
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" }
|
typedef struct { int i; } C; // { dg-error "previous declaration" }
|
||||||
struct C; // { dg-error "conflicting declaration" }
|
struct C; // { dg-error "using typedef-name" }
|
||||||
|
|
||||||
struct D;
|
struct D;
|
||||||
typedef struct D D;
|
typedef struct D D;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace Name {
|
namespace Name {
|
||||||
|
|
||||||
typedef void *(*Function)( void *, int );
|
typedef void *(*Function)( void *, int ); // { dg-error "previous declaration" }
|
||||||
|
|
||||||
struct Foo {
|
struct Foo {
|
||||||
struct Function xyz[5]; // { dg-error "" }
|
struct Function xyz[5]; // { dg-error "" }
|
||||||
|
|
|
@ -2,6 +2,6 @@ struct A {};
|
||||||
|
|
||||||
struct B
|
struct B
|
||||||
{
|
{
|
||||||
typedef A T;
|
typedef A T; // { dg-error "previous declaration" }
|
||||||
friend struct T; // { dg-error "" }
|
friend struct T; // { dg-error "" }
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,5 +2,5 @@
|
||||||
// Origin: <wanderer@rsu.ru>
|
// Origin: <wanderer@rsu.ru>
|
||||||
// { dg-do compile }
|
// { dg-do compile }
|
||||||
|
|
||||||
typedef int A;
|
typedef int A; // { dg-error "previous" }
|
||||||
enum ::A {}; // { dg-error "" }
|
enum ::A {}; // { dg-error "typedef-name|expected unqualified-id" }
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
namespace N
|
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" }
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
// PR c++/6477
|
// PR c++/6477
|
||||||
typedef struct A_ *A;
|
typedef struct A_ *A; // { dg-error "previous declaration" }
|
||||||
typedef struct A B; // { dg-error "" }
|
typedef struct A B; // { dg-error "typedef|invalid type" }
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
// Origin: Travis J.I. Corcoran <tjic@permabit.com>
|
// Origin: Travis J.I. Corcoran <tjic@permabit.com>
|
||||||
// { dg-do compile }
|
// { 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" }
|
||||||
|
|
|
@ -7,6 +7,6 @@
|
||||||
template<class T> class smart_ptr2 {
|
template<class T> class smart_ptr2 {
|
||||||
T* real_ptr;
|
T* real_ptr;
|
||||||
public:
|
public:
|
||||||
typedef typename T::subT td;
|
typedef typename T::subT td; // { dg-error "previous declaration" }
|
||||||
friend class td; // { dg-error "typedef" }
|
friend class td; // { dg-error "typedef|not name a class" }
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace A
|
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" }
|
||||||
|
|
8
gcc/testsuite/g++.dg/template/crash26.C
Normal file
8
gcc/testsuite/g++.dg/template/crash26.C
Normal file
|
@ -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" }
|
|
@ -7,8 +7,8 @@
|
||||||
|
|
||||||
template <int> struct A
|
template <int> struct A
|
||||||
{
|
{
|
||||||
typedef A<0> B; // { dg-error "not a valid type|conflict" }
|
typedef A<0> B; // { dg-error "previous declaration" }
|
||||||
template <B> struct B {}; // { dg-error "not a valid type|declaration" }
|
template <B> struct B {}; // { dg-error "not a valid type|typedef" }
|
||||||
};
|
};
|
||||||
|
|
||||||
A<0> a; // { dg-error "instantiated" }
|
A<0> a;
|
||||||
|
|
|
@ -37,7 +37,7 @@ struct S {
|
||||||
~S();
|
~S();
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct S T;
|
typedef struct S T; // { dg-error "previous declaration" }
|
||||||
|
|
||||||
S a = T(); // OK
|
S a = T(); // OK
|
||||||
struct T * p; // { dg-error "" } using typedef after struct
|
struct T * p; // { dg-error "" } using typedef after struct
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// { dg-do assemble }
|
// { dg-do assemble }
|
||||||
typedef struct {} S;
|
typedef struct {} S; // { dg-error "" } Previous declaration of S
|
||||||
|
|
||||||
S s1;
|
S s1;
|
||||||
struct S* s2; // { dg-error "" } S is a typedef name
|
struct S* s2; // { dg-error "" } S is a typedef name
|
||||||
|
|
|
@ -17,7 +17,7 @@ class X {
|
||||||
|
|
||||||
class Y {
|
class Y {
|
||||||
public:
|
public:
|
||||||
typedef ::X W;
|
typedef ::X W; // { dg-error "" } previous declaration
|
||||||
class Z;
|
class Z;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue