PR c++/8442, c++/8806
PR c++/8442, c++/8806 * decl.c (qualify_lookup): Accept TEMPLATE_DECL if types are preferred. (check_elaborated_type_specifier): Add allow_template_p parameter. Check tag mismatch and class template. (xref_tag): Add template_header_p parameter. Add assertion that name is an IDENTIFIER_NODE. Remove implicit typename warning. Simplify lookup process if globalize is true. (cxx_init_decl_processing): Adjust call to xref_tag. (xref_tag_from_type): Likewise. * decl2.c (handle_class_head): Likewise. * parser.c (cp_parser_elaborated_type_specifier, cp_parser_class_head): Likewise. * rtti.c (init_rtti_processing, build_dynamic_cast1, tinfo_base_init, emit_support_tinfos): Likewise. * class.c (is_base_of_enclosing_class): Remove. * pt.c (convert_template_argument): Don't accept RECORD_TYPE as template template argument. * cp-tree.h (xref_tag): Adjust declaration. (is_base_of_enclosing_class): Remove. * NEWS: Document template template argument change. * g++.dg/template/elab1.C: Likewise. * g++.dg/template/type2.C: Likewise. * g++.dg/template/ttp3.C: Adjust expected error message. * g++.old-deja/g++.law/visibility13.C: Likewise. * g++.old-deja/g++.niklas/t135.C: Likewise. * g++.old-deja/g++.pt/ttp41.C: Likewise. * g++.old-deja/g++.pt/ttp43.C: Use qualified name for template template argument. * g++.old-deja/g++.pt/ttp44.C: Likewise. From-SVN: r70048
This commit is contained in:
parent
ee3071efe5
commit
cbd63935d8
@ -1,3 +1,27 @@
|
||||
2003-08-01 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
|
||||
|
||||
PR c++/8442, c++/8806
|
||||
* decl.c (qualify_lookup): Accept TEMPLATE_DECL if types are
|
||||
preferred.
|
||||
(check_elaborated_type_specifier): Add allow_template_p
|
||||
parameter. Check tag mismatch and class template.
|
||||
(xref_tag): Add template_header_p parameter. Add assertion
|
||||
that name is an IDENTIFIER_NODE. Remove implicit typename
|
||||
warning. Simplify lookup process if globalize is true.
|
||||
(cxx_init_decl_processing): Adjust call to xref_tag.
|
||||
(xref_tag_from_type): Likewise.
|
||||
* decl2.c (handle_class_head): Likewise.
|
||||
* parser.c (cp_parser_elaborated_type_specifier,
|
||||
cp_parser_class_head): Likewise.
|
||||
* rtti.c (init_rtti_processing, build_dynamic_cast1,
|
||||
tinfo_base_init, emit_support_tinfos): Likewise.
|
||||
* class.c (is_base_of_enclosing_class): Remove.
|
||||
* pt.c (convert_template_argument): Don't accept RECORD_TYPE as
|
||||
template template argument.
|
||||
* cp-tree.h (xref_tag): Adjust declaration.
|
||||
(is_base_of_enclosing_class): Remove.
|
||||
* NEWS: Document template template argument change.
|
||||
|
||||
2003-08-01 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* parser.c (cp_parser_init_declarator,
|
||||
|
13
gcc/cp/NEWS
13
gcc/cp/NEWS
@ -76,6 +76,19 @@ removed.
|
||||
* Covariant returns are implemented for all but varadic functions that
|
||||
require an adjustment.
|
||||
|
||||
* Inside the scope of a template class, the name of the class itself
|
||||
is no longer a valid template template argument. Instead, you now have
|
||||
to qualify the name by its scope. For example:
|
||||
|
||||
template <template <class> class TT> class X {};
|
||||
template <class T> class Y {
|
||||
X<Y> x; // Invalid.
|
||||
};
|
||||
|
||||
The valid code for the above example is:
|
||||
|
||||
X< ::Y> x; // Valid. Note that `<:' is a digraph and means `['.
|
||||
|
||||
*** Changes in GCC 3.3:
|
||||
|
||||
* The "new X = 3" extension has been removed; you must now use "new X(3)".
|
||||
|
@ -6333,21 +6333,6 @@ get_enclosing_class (tree type)
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Return 1 if TYPE or one of its enclosing classes is derived from BASE. */
|
||||
|
||||
int
|
||||
is_base_of_enclosing_class (tree base, tree type)
|
||||
{
|
||||
while (type)
|
||||
{
|
||||
if (lookup_base (type, base, ba_any, NULL))
|
||||
return 1;
|
||||
|
||||
type = get_enclosing_class (type);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Note that NAME was looked up while the current class was being
|
||||
defined and that the result of that lookup was DECL. */
|
||||
|
||||
|
@ -3603,7 +3603,6 @@ extern int same_signature_p (tree, tree);
|
||||
extern void warn_hidden (tree);
|
||||
extern void maybe_add_class_template_decl_list (tree, tree, int);
|
||||
extern tree get_enclosing_class (tree);
|
||||
int is_base_of_enclosing_class (tree, tree);
|
||||
extern void unreverse_member_declarations (tree);
|
||||
extern void invalidate_class_lookup_cache (void);
|
||||
extern void maybe_note_name_used_in_class (tree, tree);
|
||||
@ -3731,7 +3730,7 @@ extern tree get_scope_of_declarator (tree);
|
||||
extern void grok_special_member_properties (tree);
|
||||
extern int grok_ctor_properties (tree, tree);
|
||||
extern void grok_op_properties (tree, int);
|
||||
extern tree xref_tag (enum tag_types, tree, tree, bool);
|
||||
extern tree xref_tag (enum tag_types, tree, tree, bool, bool);
|
||||
extern tree xref_tag_from_type (tree, tree, int);
|
||||
extern void xref_basetypes (tree, tree);
|
||||
extern tree start_enum (tree);
|
||||
|
214
gcc/cp/decl.c
214
gcc/cp/decl.c
@ -5753,7 +5753,8 @@ qualify_lookup (tree val, int flags)
|
||||
return val;
|
||||
if ((flags & LOOKUP_PREFER_NAMESPACES) && TREE_CODE (val) == NAMESPACE_DECL)
|
||||
return val;
|
||||
if ((flags & LOOKUP_PREFER_TYPES) && TREE_CODE (val) == TYPE_DECL)
|
||||
if ((flags & LOOKUP_PREFER_TYPES)
|
||||
&& (TREE_CODE (val) == TYPE_DECL || TREE_CODE (val) == TEMPLATE_DECL))
|
||||
return val;
|
||||
if (flags & (LOOKUP_PREFER_NAMESPACES | LOOKUP_PREFER_TYPES))
|
||||
return NULL_TREE;
|
||||
@ -6339,7 +6340,7 @@ cxx_init_decl_processing (void)
|
||||
push_namespace (std_identifier);
|
||||
bad_alloc_type_node
|
||||
= xref_tag (class_type, get_identifier ("bad_alloc"),
|
||||
/*attributes=*/NULL_TREE, 1);
|
||||
/*attributes=*/NULL_TREE, true, false);
|
||||
pop_namespace ();
|
||||
ptr_ftype_sizetype
|
||||
= build_function_type (ptr_type_node,
|
||||
@ -12553,15 +12554,15 @@ tag_name (enum tag_types code)
|
||||
/* Name lookup in an elaborated-type-specifier (after the keyword
|
||||
indicated by TAG_CODE) has found TYPE. If the
|
||||
elaborated-type-specifier is invalid, issue a diagnostic and return
|
||||
error_mark_node; otherwise, return TYPE itself. */
|
||||
error_mark_node; otherwise, return TYPE itself.
|
||||
If ALLOW_TEMPLATE_P is true, TYPE may be a class template. */
|
||||
|
||||
static tree
|
||||
check_elaborated_type_specifier (enum tag_types tag_code,
|
||||
tree type)
|
||||
tree type,
|
||||
bool allow_template_p)
|
||||
{
|
||||
tree t;
|
||||
|
||||
t = follow_tag_typedef (type);
|
||||
tree t = follow_tag_typedef (type);
|
||||
|
||||
/* [dcl.type.elab] If the identifier resolves to a typedef-name or a
|
||||
template type-parameter, the elaborated-type-specifier is
|
||||
@ -12578,30 +12579,67 @@ check_elaborated_type_specifier (enum tag_types tag_code,
|
||||
type, tag_name (tag_code));
|
||||
t = error_mark_node;
|
||||
}
|
||||
else if (TREE_CODE (type) != RECORD_TYPE
|
||||
&& TREE_CODE (type) != UNION_TYPE
|
||||
&& tag_code != enum_type)
|
||||
{
|
||||
error ("`%T' referred to as `%s'", type, tag_name (tag_code));
|
||||
t = error_mark_node;
|
||||
}
|
||||
else if (TREE_CODE (type) != ENUMERAL_TYPE
|
||||
&& tag_code == enum_type)
|
||||
{
|
||||
error ("`%T' referred to as enum", type);
|
||||
t = error_mark_node;
|
||||
}
|
||||
else if (!allow_template_p
|
||||
&& TREE_CODE (type) == RECORD_TYPE
|
||||
&& CLASSTYPE_IS_TEMPLATE (type))
|
||||
{
|
||||
/* If a class template appears as elaborated type specifier
|
||||
without a template header such as:
|
||||
|
||||
template <class T> class C {};
|
||||
void f(class C); // No template header here
|
||||
|
||||
then the required template argument is missing. */
|
||||
|
||||
error ("template argument required for `%s %T'",
|
||||
tag_name (tag_code),
|
||||
DECL_NAME (CLASSTYPE_TI_TEMPLATE (type)));
|
||||
t = error_mark_node;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Get the struct, enum or union (CODE says which) with tag NAME.
|
||||
/* 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.
|
||||
|
||||
C++: If a class derivation is given, process it here, and report
|
||||
an error if multiple derivation declarations are not identical.
|
||||
If a declaration is given, process it here, and report an error if
|
||||
multiple declarations are not identical. ATTRIBUTE is the attribute
|
||||
appeared in this declaration.
|
||||
|
||||
If this is a definition, come in through xref_tag and only look in
|
||||
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.) */
|
||||
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, tree attributes,
|
||||
bool globalize)
|
||||
bool globalize, bool template_header_p)
|
||||
{
|
||||
enum tree_code code;
|
||||
register tree ref, t;
|
||||
register tree t;
|
||||
struct cp_binding_level *b = current_binding_level;
|
||||
tree context = NULL_TREE;
|
||||
|
||||
timevar_push (TV_NAME_LOOKUP);
|
||||
|
||||
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0);
|
||||
|
||||
switch (tag_code)
|
||||
{
|
||||
case record_type:
|
||||
@ -12618,93 +12656,50 @@ xref_tag (enum tag_types tag_code, tree name, tree attributes,
|
||||
abort ();
|
||||
}
|
||||
|
||||
/* If a cross reference is requested, look up the type
|
||||
already defined for this tag and return it. */
|
||||
if (TYPE_P (name))
|
||||
{
|
||||
t = name;
|
||||
name = TYPE_IDENTIFIER (t);
|
||||
}
|
||||
else
|
||||
t = IDENTIFIER_TYPE_VALUE (name);
|
||||
|
||||
/* Warn about 'friend struct Inherited;' doing the wrong thing. */
|
||||
if (t && globalize && TREE_CODE (t) == TYPENAME_TYPE)
|
||||
{
|
||||
static int explained;
|
||||
tree shadowed;
|
||||
|
||||
warning ("`%s %T' declares a new type at namespace scope",
|
||||
tag_name (tag_code), name);
|
||||
if (!explained++)
|
||||
warning (" names from dependent base classes are not visible to unqualified name lookup - to refer to the inherited type, say `%s %T::%T'",
|
||||
tag_name (tag_code),
|
||||
constructor_name (current_class_type),
|
||||
TYPE_IDENTIFIER (t));
|
||||
|
||||
/* We need to remove the class scope binding for the
|
||||
TYPENAME_TYPE as otherwise poplevel_class gets confused. */
|
||||
for (shadowed = b->class_shadowed;
|
||||
shadowed;
|
||||
shadowed = TREE_CHAIN (shadowed))
|
||||
if (TREE_TYPE (shadowed) == TYPE_NAME (t))
|
||||
{
|
||||
TREE_PURPOSE (shadowed) = NULL_TREE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (t && TREE_CODE (t) != code && TREE_CODE (t) != TEMPLATE_TYPE_PARM
|
||||
&& TREE_CODE (t) != BOUND_TEMPLATE_TEMPLATE_PARM)
|
||||
t = NULL_TREE;
|
||||
|
||||
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. */
|
||||
ref = lookup_tag (code, name, b, 1);
|
||||
t = lookup_tag (code, name, b, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t)
|
||||
tree decl = lookup_name (name, 1);
|
||||
|
||||
if (decl && DECL_CLASS_TEMPLATE_P (decl))
|
||||
decl = DECL_TEMPLATE_RESULT (decl);
|
||||
|
||||
if (decl && TREE_CODE (decl) == TYPE_DECL)
|
||||
{
|
||||
ref = check_elaborated_type_specifier (tag_code, t);
|
||||
if (ref == error_mark_node)
|
||||
/* 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,
|
||||
TREE_TYPE (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
|
||||
ref = lookup_tag (code, name, b, 0);
|
||||
t = NULL_TREE;
|
||||
|
||||
if (! ref)
|
||||
{
|
||||
/* Try finding it as a type declaration. If that wins,
|
||||
use it. */
|
||||
ref = lookup_name (name, 1);
|
||||
|
||||
if (ref != NULL_TREE
|
||||
&& processing_template_decl
|
||||
&& DECL_CLASS_TEMPLATE_P (ref)
|
||||
&& template_class_depth (current_class_type) == 0)
|
||||
/* Since GLOBALIZE is true, we're declaring a global
|
||||
template, so we want this type. */
|
||||
ref = DECL_TEMPLATE_RESULT (ref);
|
||||
|
||||
if (ref && TREE_CODE (ref) == TYPE_DECL)
|
||||
{
|
||||
ref = check_elaborated_type_specifier (tag_code,
|
||||
TREE_TYPE (ref));
|
||||
if (ref == error_mark_node)
|
||||
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
|
||||
if (ref && TREE_CODE (ref) != code)
|
||||
ref = NULL_TREE;
|
||||
}
|
||||
else
|
||||
ref = NULL_TREE;
|
||||
}
|
||||
|
||||
if (ref && current_class_type
|
||||
if (t && current_class_type
|
||||
&& template_class_depth (current_class_type)
|
||||
&& PROCESSING_REAL_TEMPLATE_DECL_P ())
|
||||
&& template_header_p)
|
||||
{
|
||||
/* Since GLOBALIZE is nonzero, we are not looking at a
|
||||
definition of this tag. Since, in addition, we are currently
|
||||
@ -12742,12 +12737,12 @@ xref_tag (enum tag_types tag_code, tree name, tree attributes,
|
||||
accomplish this by making sure that the new type we
|
||||
create to represent this declaration has the right
|
||||
TYPE_CONTEXT. */
|
||||
context = TYPE_CONTEXT (ref);
|
||||
ref = NULL_TREE;
|
||||
context = TYPE_CONTEXT (t);
|
||||
t = NULL_TREE;
|
||||
}
|
||||
}
|
||||
|
||||
if (! ref)
|
||||
if (! t)
|
||||
{
|
||||
/* If no such tag is yet defined, create a forward-reference node
|
||||
and record it as the "definition".
|
||||
@ -12757,44 +12752,41 @@ xref_tag (enum tag_types tag_code, tree name, tree attributes,
|
||||
{
|
||||
error ("use of enum `%#D' without previous declaration", name);
|
||||
|
||||
ref = make_node (ENUMERAL_TYPE);
|
||||
t = make_node (ENUMERAL_TYPE);
|
||||
|
||||
/* Give the type a default layout like unsigned int
|
||||
to avoid crashing if it does not get defined. */
|
||||
TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node);
|
||||
TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
|
||||
TYPE_USER_ALIGN (ref) = 0;
|
||||
TREE_UNSIGNED (ref) = 1;
|
||||
TYPE_PRECISION (ref) = TYPE_PRECISION (unsigned_type_node);
|
||||
TYPE_MIN_VALUE (ref) = TYPE_MIN_VALUE (unsigned_type_node);
|
||||
TYPE_MAX_VALUE (ref) = TYPE_MAX_VALUE (unsigned_type_node);
|
||||
TYPE_MODE (t) = TYPE_MODE (unsigned_type_node);
|
||||
TYPE_ALIGN (t) = TYPE_ALIGN (unsigned_type_node);
|
||||
TYPE_USER_ALIGN (t) = 0;
|
||||
TREE_UNSIGNED (t) = 1;
|
||||
TYPE_PRECISION (t) = TYPE_PRECISION (unsigned_type_node);
|
||||
TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (unsigned_type_node);
|
||||
TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (unsigned_type_node);
|
||||
|
||||
/* Enable us to recognize when a type is created in class context.
|
||||
To do nested classes correctly, this should probably be cleared
|
||||
out when we leave this classes scope. Currently this in only
|
||||
done in `start_enum'. */
|
||||
|
||||
pushtag (name, ref, globalize);
|
||||
pushtag (name, t, globalize);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct cp_binding_level *old_b = class_binding_level;
|
||||
|
||||
ref = make_aggr_type (code);
|
||||
TYPE_CONTEXT (ref) = context;
|
||||
pushtag (name, ref, globalize);
|
||||
class_binding_level = old_b;
|
||||
t = make_aggr_type (code);
|
||||
TYPE_CONTEXT (t) = context;
|
||||
pushtag (name, t, globalize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!globalize && processing_template_decl && IS_AGGR_TYPE (ref))
|
||||
redeclare_class_template (ref, current_template_parms);
|
||||
if (!globalize && processing_template_decl && IS_AGGR_TYPE (t))
|
||||
redeclare_class_template (t, current_template_parms);
|
||||
}
|
||||
|
||||
TYPE_ATTRIBUTES (ref) = attributes;
|
||||
TYPE_ATTRIBUTES (t) = attributes;
|
||||
|
||||
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ref);
|
||||
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
|
||||
}
|
||||
|
||||
tree
|
||||
@ -12810,7 +12802,7 @@ xref_tag_from_type (tree old, tree id, int globalize)
|
||||
if (id == NULL_TREE)
|
||||
id = TYPE_IDENTIFIER (old);
|
||||
|
||||
return xref_tag (tag_kind, id, /*attributes=*/NULL_TREE, globalize);
|
||||
return xref_tag (tag_kind, id, /*attributes=*/NULL_TREE, globalize, false);
|
||||
}
|
||||
|
||||
/* REF is a type (named NAME), for which we have just seen some
|
||||
|
@ -4278,7 +4278,7 @@ handle_class_head (enum tag_types tag_kind, tree scope, tree id,
|
||||
|
||||
if (!decl)
|
||||
{
|
||||
decl = xref_tag (tag_kind, id, attributes, false);
|
||||
decl = xref_tag (tag_kind, id, attributes, false, false);
|
||||
if (decl == error_mark_node)
|
||||
return error_mark_node;
|
||||
decl = TYPE_MAIN_DECL (decl);
|
||||
|
@ -8553,7 +8553,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
|
||||
(is_friend
|
||||
|| !is_declaration
|
||||
|| cp_lexer_next_token_is_not (parser->lexer,
|
||||
CPP_SEMICOLON)));
|
||||
CPP_SEMICOLON)),
|
||||
parser->num_template_parameter_lists);
|
||||
}
|
||||
}
|
||||
if (tag_type != enum_type)
|
||||
@ -11380,7 +11381,8 @@ cp_parser_class_head (cp_parser* parser,
|
||||
/* If the class was unnamed, create a dummy name. */
|
||||
if (!id)
|
||||
id = make_anon_name ();
|
||||
type = xref_tag (class_key, id, attributes, /*globalize=*/0);
|
||||
type = xref_tag (class_key, id, attributes, /*globalize=*/false,
|
||||
parser->num_template_parameter_lists);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
26
gcc/cp/pt.c
26
gcc/cp/pt.c
@ -3431,33 +3431,15 @@ convert_template_argument (tree parm,
|
||||
requires_type = (TREE_CODE (parm) == TYPE_DECL
|
||||
|| requires_tmpl_type);
|
||||
|
||||
if (TREE_CODE (arg) != RECORD_TYPE)
|
||||
is_tmpl_type = ((TREE_CODE (arg) == TEMPLATE_DECL
|
||||
&& TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
|
||||
|| TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
|
||||
|| TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE);
|
||||
else if (CLASSTYPE_TEMPLATE_INFO (arg) && !CLASSTYPE_USE_TEMPLATE (arg)
|
||||
&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (arg)))
|
||||
{
|
||||
if (is_base_of_enclosing_class (arg, current_class_type))
|
||||
/* This is a template name used within the scope of the
|
||||
template. It could be the template, or it could be the
|
||||
instantiation. Choose whichever makes sense. */
|
||||
is_tmpl_type = requires_tmpl_type;
|
||||
else
|
||||
is_tmpl_type = 1;
|
||||
}
|
||||
else
|
||||
/* It is a non-template class, or a specialization of a template
|
||||
class, or a non-template member of a template class. */
|
||||
is_tmpl_type = 0;
|
||||
is_tmpl_type = ((TREE_CODE (arg) == TEMPLATE_DECL
|
||||
&& TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
|
||||
|| TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
|
||||
|| TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE);
|
||||
|
||||
if (is_tmpl_type
|
||||
&& (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
|
||||
|| TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE))
|
||||
arg = TYPE_STUB_DECL (arg);
|
||||
else if (is_tmpl_type && TREE_CODE (arg) == RECORD_TYPE)
|
||||
arg = CLASSTYPE_TI_TEMPLATE (arg);
|
||||
|
||||
is_type = TYPE_P (arg) || is_tmpl_type;
|
||||
|
||||
|
@ -120,7 +120,7 @@ init_rtti_processing (void)
|
||||
push_namespace (std_identifier);
|
||||
type_info_type_node
|
||||
= xref_tag (class_type, get_identifier ("type_info"),
|
||||
/*attributes=*/NULL_TREE, 1);
|
||||
/*attributes=*/NULL_TREE, true, false);
|
||||
pop_namespace ();
|
||||
const_type_info_type = build_qualified_type (type_info_type_node,
|
||||
TYPE_QUAL_CONST);
|
||||
@ -639,7 +639,7 @@ build_dynamic_cast_1 (tree type, tree expr)
|
||||
tinfo_ptr = xref_tag (class_type,
|
||||
get_identifier ("__class_type_info"),
|
||||
/*attributes=*/NULL_TREE,
|
||||
1);
|
||||
true, false);
|
||||
|
||||
tinfo_ptr = build_pointer_type
|
||||
(build_qualified_type
|
||||
@ -774,7 +774,7 @@ tinfo_base_init (tree desc, tree target)
|
||||
|
||||
push_nested_namespace (abi_node);
|
||||
real_type = xref_tag (class_type, TINFO_REAL_NAME (desc),
|
||||
/*attributes=*/NULL_TREE, 1);
|
||||
/*attributes=*/NULL_TREE, true, false);
|
||||
pop_nested_namespace (abi_node);
|
||||
|
||||
if (!COMPLETE_TYPE_P (real_type))
|
||||
@ -1371,7 +1371,7 @@ emit_support_tinfos (void)
|
||||
bltn_type = xref_tag (class_type,
|
||||
get_identifier ("__fundamental_type_info"),
|
||||
/*attributes=*/NULL_TREE,
|
||||
1);
|
||||
true, false);
|
||||
pop_nested_namespace (abi_node);
|
||||
if (!COMPLETE_TYPE_P (bltn_type))
|
||||
return;
|
||||
|
@ -1,3 +1,16 @@
|
||||
2003-08-01 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
|
||||
|
||||
PR c++/8442, c++/8806
|
||||
* g++.dg/template/elab1.C: New test.
|
||||
* g++.dg/template/type2.C: Likewise.
|
||||
* g++.dg/template/ttp3.C: Adjust expected error message.
|
||||
* g++.old-deja/g++.law/visibility13.C: Likewise.
|
||||
* g++.old-deja/g++.niklas/t135.C: Likewise.
|
||||
* g++.old-deja/g++.pt/ttp41.C: Likewise.
|
||||
* g++.old-deja/g++.pt/ttp43.C: Use qualified name for template
|
||||
template argument.
|
||||
* g++.old-deja/g++.pt/ttp44.C: Likewise.
|
||||
|
||||
2003-08-01 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
PR c++/11295
|
||||
|
13
gcc/testsuite/g++.dg/template/elab1.C
Normal file
13
gcc/testsuite/g++.dg/template/elab1.C
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright (C) 2003 Free Software Foundation
|
||||
// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
|
||||
// { dg-do compile }
|
||||
|
||||
// Elaborate type specifier of class template
|
||||
|
||||
template <class T> class A {
|
||||
class B;
|
||||
};
|
||||
|
||||
template <class T> class A<T>::B {
|
||||
friend class A;
|
||||
};
|
@ -14,13 +14,13 @@ class OUTER {
|
||||
template <class T>
|
||||
class List { };
|
||||
|
||||
vector<class List> data; // { dg-error "type/value mismatch|expected a type|ISO C" "" }
|
||||
vector<class List> data; // { dg-error "invalid|required|ISO C" "" }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class List { }; // { dg-bogus "previous declaration" "" { xfail *-*-* } }
|
||||
class List { };
|
||||
|
||||
// This next line should just do a lookup of 'class List', and then
|
||||
// get a type/value mismatch. Instead we try and push 'class List'
|
||||
// into the global namespace and get a redeclaration error.
|
||||
vector<class List > data; // { dg-bogus "`struct List' redeclared|type/value mismatch" "" { xfail *-*-* } }
|
||||
vector<class List > data; // { dg-error "invalid|required|expected" "" }
|
||||
|
16
gcc/testsuite/g++.dg/template/type2.C
Normal file
16
gcc/testsuite/g++.dg/template/type2.C
Normal file
@ -0,0 +1,16 @@
|
||||
// { dg-do compile }
|
||||
// Origin: Juan Carlos Arevalo-Baeza <jcab@JCABs-Rumblings.com>
|
||||
|
||||
// PR c++/8442
|
||||
// Type template parameter incorrectly treated as template template
|
||||
// parameter.
|
||||
|
||||
template <typename T> struct A {};
|
||||
|
||||
template <typename T> struct B
|
||||
{
|
||||
template <typename U> struct C {};
|
||||
template <typename U> A<C<U> > foo(U);
|
||||
};
|
||||
|
||||
B<void> b;
|
@ -65,7 +65,7 @@ void Array<Type>::init(const Type *array, int sz)
|
||||
// --------------- Array_RC.h && Array_RC.cc ----------------
|
||||
|
||||
template <class Type>
|
||||
class Array_RC : public Array<Type> {// { dg-error "" } previous declaration.*
|
||||
class Array_RC : public Array<Type> {
|
||||
public:
|
||||
Array_RC(const Type *ar, int sz);
|
||||
Type& operator[](int ix);
|
||||
|
@ -1,7 +1,7 @@
|
||||
// { dg-do assemble }
|
||||
// { dg-do compile }
|
||||
// GROUPS niklas pt friend
|
||||
template <class T> class C1
|
||||
{ // { dg-error "" }
|
||||
{
|
||||
public:
|
||||
void diddle_C2 ();
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
// { dg-do run }
|
||||
// { dg-do compile }
|
||||
template<template<class> class D,class E> class C
|
||||
{
|
||||
public:
|
||||
@ -13,8 +13,8 @@ template<class T> class D
|
||||
|
||||
template<class T> int D<T>::f()
|
||||
{
|
||||
C<D,D> c;
|
||||
return c.g();
|
||||
C<D,D> c; // { dg-error "" }
|
||||
return c.g(); // { dg-error "" }
|
||||
}
|
||||
|
||||
int main()
|
||||
|
@ -20,11 +20,11 @@ struct Lit {
|
||||
|
||||
template < class T >
|
||||
struct Id {
|
||||
Add < T, Id, Lit > operator+(const T& t) const {
|
||||
return Add < T, Id, Lit >(*this, Lit<T>(t));
|
||||
Add < T, ::Id, Lit > operator+(const T& t) const {
|
||||
return Add < T, ::Id, Lit >(*this, Lit<T>(t));
|
||||
}
|
||||
|
||||
Mul < T, Id, Lit > operator*(const T& t) const {
|
||||
return Mul < T, Id, Lit >(*this, Lit<T>(t));
|
||||
Mul < T, ::Id, Lit > operator*(const T& t) const {
|
||||
return Mul < T, ::Id, Lit >(*this, Lit<T>(t));
|
||||
}
|
||||
};
|
||||
|
@ -9,8 +9,8 @@ public:
|
||||
template < class T >
|
||||
struct Id {
|
||||
template < template < class > class E >
|
||||
Add < T, Id, E > operator+(const E<T>& e) const {
|
||||
return Add < T, Id, E >(*this, e);
|
||||
Add < T, ::Id, E > operator+(const E<T>& e) const {
|
||||
return Add < T, ::Id, E >(*this, e);
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user