Commit cbd63935 by Kriang Lerdsuwanakij Committed by Kriang Lerdsuwanakij

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
parent ee3071ef
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> 2003-08-01 Nathan Sidwell <nathan@codesourcery.com>
* parser.c (cp_parser_init_declarator, * parser.c (cp_parser_init_declarator,
......
...@@ -76,6 +76,19 @@ removed. ...@@ -76,6 +76,19 @@ removed.
* Covariant returns are implemented for all but varadic functions that * Covariant returns are implemented for all but varadic functions that
require an adjustment. 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: *** Changes in GCC 3.3:
* The "new X = 3" extension has been removed; you must now use "new X(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) ...@@ -6333,21 +6333,6 @@ get_enclosing_class (tree type)
return NULL_TREE; 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 /* Note that NAME was looked up while the current class was being
defined and that the result of that lookup was DECL. */ defined and that the result of that lookup was DECL. */
......
...@@ -3603,7 +3603,6 @@ extern int same_signature_p (tree, tree); ...@@ -3603,7 +3603,6 @@ extern int same_signature_p (tree, tree);
extern void warn_hidden (tree); extern void warn_hidden (tree);
extern void maybe_add_class_template_decl_list (tree, tree, int); extern void maybe_add_class_template_decl_list (tree, tree, int);
extern tree get_enclosing_class (tree); extern tree get_enclosing_class (tree);
int is_base_of_enclosing_class (tree, tree);
extern void unreverse_member_declarations (tree); extern void unreverse_member_declarations (tree);
extern void invalidate_class_lookup_cache (void); extern void invalidate_class_lookup_cache (void);
extern void maybe_note_name_used_in_class (tree, tree); extern void maybe_note_name_used_in_class (tree, tree);
...@@ -3731,7 +3730,7 @@ extern tree get_scope_of_declarator (tree); ...@@ -3731,7 +3730,7 @@ extern tree get_scope_of_declarator (tree);
extern void grok_special_member_properties (tree); extern void grok_special_member_properties (tree);
extern int grok_ctor_properties (tree, tree); extern int grok_ctor_properties (tree, tree);
extern void grok_op_properties (tree, int); 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 tree xref_tag_from_type (tree, tree, int);
extern void xref_basetypes (tree, tree); extern void xref_basetypes (tree, tree);
extern tree start_enum (tree); extern tree start_enum (tree);
......
...@@ -5753,7 +5753,8 @@ qualify_lookup (tree val, int flags) ...@@ -5753,7 +5753,8 @@ qualify_lookup (tree val, int flags)
return val; return val;
if ((flags & LOOKUP_PREFER_NAMESPACES) && TREE_CODE (val) == NAMESPACE_DECL) if ((flags & LOOKUP_PREFER_NAMESPACES) && TREE_CODE (val) == NAMESPACE_DECL)
return val; 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; return val;
if (flags & (LOOKUP_PREFER_NAMESPACES | LOOKUP_PREFER_TYPES)) if (flags & (LOOKUP_PREFER_NAMESPACES | LOOKUP_PREFER_TYPES))
return NULL_TREE; return NULL_TREE;
...@@ -6339,7 +6340,7 @@ cxx_init_decl_processing (void) ...@@ -6339,7 +6340,7 @@ cxx_init_decl_processing (void)
push_namespace (std_identifier); push_namespace (std_identifier);
bad_alloc_type_node bad_alloc_type_node
= xref_tag (class_type, get_identifier ("bad_alloc"), = xref_tag (class_type, get_identifier ("bad_alloc"),
/*attributes=*/NULL_TREE, 1); /*attributes=*/NULL_TREE, true, false);
pop_namespace (); pop_namespace ();
ptr_ftype_sizetype ptr_ftype_sizetype
= build_function_type (ptr_type_node, = build_function_type (ptr_type_node,
...@@ -12553,15 +12554,15 @@ tag_name (enum tag_types code) ...@@ -12553,15 +12554,15 @@ tag_name (enum tag_types code)
/* Name lookup in an elaborated-type-specifier (after the keyword /* Name lookup in an elaborated-type-specifier (after the keyword
indicated by TAG_CODE) has found TYPE. If the indicated by TAG_CODE) has found TYPE. If the
elaborated-type-specifier is invalid, issue a diagnostic and return 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 static tree
check_elaborated_type_specifier (enum tag_types tag_code, check_elaborated_type_specifier (enum tag_types tag_code,
tree type) tree type,
bool allow_template_p)
{ {
tree t; tree t = follow_tag_typedef (type);
t = follow_tag_typedef (type);
/* [dcl.type.elab] If the identifier resolves to a typedef-name or a /* [dcl.type.elab] If the identifier resolves to a typedef-name or a
template type-parameter, the elaborated-type-specifier is template type-parameter, the elaborated-type-specifier is
...@@ -12578,30 +12579,67 @@ check_elaborated_type_specifier (enum tag_types tag_code, ...@@ -12578,30 +12579,67 @@ check_elaborated_type_specifier (enum tag_types tag_code,
type, tag_name (tag_code)); type, tag_name (tag_code));
t = error_mark_node; 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; 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. Define the tag as a forward-reference if it is not defined.
C++: If a class derivation is given, process it here, and report If a declaration is given, process it here, and report an error if
an error if multiple derivation declarations are not identical. 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 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 tree
xref_tag (enum tag_types tag_code, tree name, tree attributes, xref_tag (enum tag_types tag_code, tree name, tree attributes,
bool globalize) bool globalize, bool template_header_p)
{ {
enum tree_code code; enum tree_code code;
register tree ref, t; register tree t;
struct cp_binding_level *b = current_binding_level; struct cp_binding_level *b = current_binding_level;
tree context = NULL_TREE; tree context = NULL_TREE;
timevar_push (TV_NAME_LOOKUP); timevar_push (TV_NAME_LOOKUP);
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0);
switch (tag_code) switch (tag_code)
{ {
case record_type: case record_type:
...@@ -12618,93 +12656,50 @@ xref_tag (enum tag_types tag_code, tree name, tree attributes, ...@@ -12618,93 +12656,50 @@ xref_tag (enum tag_types tag_code, tree name, tree attributes,
abort (); 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 (! globalize)
{ {
/* If we know we are defining this tag, only look it up in /* 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. */ 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 else
{ {
if (t) tree decl = lookup_name (name, 1);
{
ref = check_elaborated_type_specifier (tag_code, t); if (decl && DECL_CLASS_TEMPLATE_P (decl))
if (ref == error_mark_node) decl = DECL_TEMPLATE_RESULT (decl);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
else
ref = lookup_tag (code, name, b, 0);
if (! ref) if (decl && TREE_CODE (decl) == TYPE_DECL)
{ {
/* Try finding it as a type declaration. If that wins, /* Two cases we need to consider when deciding if a class
use it. */ template is allowed as an elaborated type specifier:
ref = lookup_name (name, 1); 1. It is a self reference to its own class.
2. It comes with a template header.
if (ref != NULL_TREE For example:
&& 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) template <class T> class C {
{ class C *c1; // DECL_SELF_REFERENCE_P is true
ref = check_elaborated_type_specifier (tag_code, class D;
TREE_TYPE (ref)); };
if (ref == error_mark_node) template <class U> class C; // template_header_p is true
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node); template <class T> class C<T>::D {
if (ref && TREE_CODE (ref) != code) class C *c2; // DECL_SELF_REFERENCE_P is true
ref = NULL_TREE; }; */
}
else t = check_elaborated_type_specifier (tag_code,
ref = NULL_TREE; 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
t = NULL_TREE;
if (ref && current_class_type if (t && current_class_type
&& template_class_depth (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 /* Since GLOBALIZE is nonzero, we are not looking at a
definition of this tag. Since, in addition, we are currently 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, ...@@ -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 accomplish this by making sure that the new type we
create to represent this declaration has the right create to represent this declaration has the right
TYPE_CONTEXT. */ TYPE_CONTEXT. */
context = TYPE_CONTEXT (ref); context = TYPE_CONTEXT (t);
ref = NULL_TREE; t = NULL_TREE;
} }
} }
if (! ref) if (! t)
{ {
/* If no such tag is yet defined, create a forward-reference node /* If no such tag is yet defined, create a forward-reference node
and record it as the "definition". and record it as the "definition".
...@@ -12757,44 +12752,41 @@ xref_tag (enum tag_types tag_code, tree name, tree attributes, ...@@ -12757,44 +12752,41 @@ xref_tag (enum tag_types tag_code, tree name, tree attributes,
{ {
error ("use of enum `%#D' without previous declaration", name); 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 /* Give the type a default layout like unsigned int
to avoid crashing if it does not get defined. */ to avoid crashing if it does not get defined. */
TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node); TYPE_MODE (t) = TYPE_MODE (unsigned_type_node);
TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node); TYPE_ALIGN (t) = TYPE_ALIGN (unsigned_type_node);
TYPE_USER_ALIGN (ref) = 0; TYPE_USER_ALIGN (t) = 0;
TREE_UNSIGNED (ref) = 1; TREE_UNSIGNED (t) = 1;
TYPE_PRECISION (ref) = TYPE_PRECISION (unsigned_type_node); TYPE_PRECISION (t) = TYPE_PRECISION (unsigned_type_node);
TYPE_MIN_VALUE (ref) = TYPE_MIN_VALUE (unsigned_type_node); TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (unsigned_type_node);
TYPE_MAX_VALUE (ref) = TYPE_MAX_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. /* Enable us to recognize when a type is created in class context.
To do nested classes correctly, this should probably be cleared To do nested classes correctly, this should probably be cleared
out when we leave this classes scope. Currently this in only out when we leave this classes scope. Currently this in only
done in `start_enum'. */ done in `start_enum'. */
pushtag (name, ref, globalize); pushtag (name, t, globalize);
} }
else else
{ {
struct cp_binding_level *old_b = class_binding_level; t = make_aggr_type (code);
TYPE_CONTEXT (t) = context;
ref = make_aggr_type (code); pushtag (name, t, globalize);
TYPE_CONTEXT (ref) = context;
pushtag (name, ref, globalize);
class_binding_level = old_b;
} }
} }
else else
{ {
if (!globalize && processing_template_decl && IS_AGGR_TYPE (ref)) if (!globalize && processing_template_decl && IS_AGGR_TYPE (t))
redeclare_class_template (ref, current_template_parms); 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 tree
...@@ -12810,7 +12802,7 @@ xref_tag_from_type (tree old, tree id, int globalize) ...@@ -12810,7 +12802,7 @@ xref_tag_from_type (tree old, tree id, int globalize)
if (id == NULL_TREE) if (id == NULL_TREE)
id = TYPE_IDENTIFIER (old); 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 /* 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, ...@@ -4278,7 +4278,7 @@ handle_class_head (enum tag_types tag_kind, tree scope, tree id,
if (!decl) if (!decl)
{ {
decl = xref_tag (tag_kind, id, attributes, false); decl = xref_tag (tag_kind, id, attributes, false, false);
if (decl == error_mark_node) if (decl == error_mark_node)
return error_mark_node; return error_mark_node;
decl = TYPE_MAIN_DECL (decl); decl = TYPE_MAIN_DECL (decl);
......
...@@ -8553,7 +8553,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, ...@@ -8553,7 +8553,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
(is_friend (is_friend
|| !is_declaration || !is_declaration
|| cp_lexer_next_token_is_not (parser->lexer, || cp_lexer_next_token_is_not (parser->lexer,
CPP_SEMICOLON))); CPP_SEMICOLON)),
parser->num_template_parameter_lists);
} }
} }
if (tag_type != enum_type) if (tag_type != enum_type)
...@@ -11380,7 +11381,8 @@ cp_parser_class_head (cp_parser* parser, ...@@ -11380,7 +11381,8 @@ cp_parser_class_head (cp_parser* parser,
/* If the class was unnamed, create a dummy name. */ /* If the class was unnamed, create a dummy name. */
if (!id) if (!id)
id = make_anon_name (); 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 else
{ {
......
...@@ -3431,33 +3431,15 @@ convert_template_argument (tree parm, ...@@ -3431,33 +3431,15 @@ convert_template_argument (tree parm,
requires_type = (TREE_CODE (parm) == TYPE_DECL requires_type = (TREE_CODE (parm) == TYPE_DECL
|| requires_tmpl_type); || requires_tmpl_type);
if (TREE_CODE (arg) != RECORD_TYPE) is_tmpl_type = ((TREE_CODE (arg) == TEMPLATE_DECL
is_tmpl_type = ((TREE_CODE (arg) == TEMPLATE_DECL && TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
&& TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL) || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE);
|| 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;
if (is_tmpl_type if (is_tmpl_type
&& (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM && (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE)) || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE))
arg = TYPE_STUB_DECL (arg); 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; is_type = TYPE_P (arg) || is_tmpl_type;
......
...@@ -120,7 +120,7 @@ init_rtti_processing (void) ...@@ -120,7 +120,7 @@ init_rtti_processing (void)
push_namespace (std_identifier); push_namespace (std_identifier);
type_info_type_node type_info_type_node
= xref_tag (class_type, get_identifier ("type_info"), = xref_tag (class_type, get_identifier ("type_info"),
/*attributes=*/NULL_TREE, 1); /*attributes=*/NULL_TREE, true, false);
pop_namespace (); pop_namespace ();
const_type_info_type = build_qualified_type (type_info_type_node, const_type_info_type = build_qualified_type (type_info_type_node,
TYPE_QUAL_CONST); TYPE_QUAL_CONST);
...@@ -639,7 +639,7 @@ build_dynamic_cast_1 (tree type, tree expr) ...@@ -639,7 +639,7 @@ build_dynamic_cast_1 (tree type, tree expr)
tinfo_ptr = xref_tag (class_type, tinfo_ptr = xref_tag (class_type,
get_identifier ("__class_type_info"), get_identifier ("__class_type_info"),
/*attributes=*/NULL_TREE, /*attributes=*/NULL_TREE,
1); true, false);
tinfo_ptr = build_pointer_type tinfo_ptr = build_pointer_type
(build_qualified_type (build_qualified_type
...@@ -774,7 +774,7 @@ tinfo_base_init (tree desc, tree target) ...@@ -774,7 +774,7 @@ tinfo_base_init (tree desc, tree target)
push_nested_namespace (abi_node); push_nested_namespace (abi_node);
real_type = xref_tag (class_type, TINFO_REAL_NAME (desc), real_type = xref_tag (class_type, TINFO_REAL_NAME (desc),
/*attributes=*/NULL_TREE, 1); /*attributes=*/NULL_TREE, true, false);
pop_nested_namespace (abi_node); pop_nested_namespace (abi_node);
if (!COMPLETE_TYPE_P (real_type)) if (!COMPLETE_TYPE_P (real_type))
...@@ -1371,7 +1371,7 @@ emit_support_tinfos (void) ...@@ -1371,7 +1371,7 @@ emit_support_tinfos (void)
bltn_type = xref_tag (class_type, bltn_type = xref_tag (class_type,
get_identifier ("__fundamental_type_info"), get_identifier ("__fundamental_type_info"),
/*attributes=*/NULL_TREE, /*attributes=*/NULL_TREE,
1); true, false);
pop_nested_namespace (abi_node); pop_nested_namespace (abi_node);
if (!COMPLETE_TYPE_P (bltn_type)) if (!COMPLETE_TYPE_P (bltn_type))
return; return;
......
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> 2003-08-01 Nathan Sidwell <nathan@codesourcery.com>
PR c++/11295 PR c++/11295
......
// 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 { ...@@ -14,13 +14,13 @@ class OUTER {
template <class T> template <class T>
class List { }; 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> 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 // 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' // get a type/value mismatch. Instead we try and push 'class List'
// into the global namespace and get a redeclaration error. // 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" "" }
// { 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) ...@@ -65,7 +65,7 @@ void Array<Type>::init(const Type *array, int sz)
// --------------- Array_RC.h && Array_RC.cc ---------------- // --------------- Array_RC.h && Array_RC.cc ----------------
template <class Type> template <class Type>
class Array_RC : public Array<Type> {// { dg-error "" } previous declaration.* class Array_RC : public Array<Type> {
public: public:
Array_RC(const Type *ar, int sz); Array_RC(const Type *ar, int sz);
Type& operator[](int ix); Type& operator[](int ix);
......
// { dg-do assemble } // { dg-do compile }
// GROUPS niklas pt friend // GROUPS niklas pt friend
template <class T> class C1 template <class T> class C1
{ // { dg-error "" } {
public: public:
void diddle_C2 (); void diddle_C2 ();
}; };
......
// { dg-do run } // { dg-do compile }
template<template<class> class D,class E> class C template<template<class> class D,class E> class C
{ {
public: public:
...@@ -13,8 +13,8 @@ template<class T> class D ...@@ -13,8 +13,8 @@ template<class T> class D
template<class T> int D<T>::f() template<class T> int D<T>::f()
{ {
C<D,D> c; C<D,D> c; // { dg-error "" }
return c.g(); return c.g(); // { dg-error "" }
} }
int main() int main()
......
...@@ -20,11 +20,11 @@ struct Lit { ...@@ -20,11 +20,11 @@ struct Lit {
template < class T > template < class T >
struct Id { struct Id {
Add < T, Id, Lit > operator+(const T& t) const { Add < T, ::Id, Lit > operator+(const T& t) const {
return Add < T, Id, Lit >(*this, Lit<T>(t)); return Add < T, ::Id, Lit >(*this, Lit<T>(t));
} }
Mul < T, Id, Lit > operator*(const T& t) const { Mul < T, ::Id, Lit > operator*(const T& t) const {
return Mul < T, Id, Lit >(*this, Lit<T>(t)); return Mul < T, ::Id, Lit >(*this, Lit<T>(t));
} }
}; };
...@@ -9,8 +9,8 @@ public: ...@@ -9,8 +9,8 @@ public:
template < class T > template < class T >
struct Id { struct Id {
template < template < class > class E > template < template < class > class E >
Add < T, Id, E > operator+(const E<T>& e) const { Add < T, ::Id, E > operator+(const E<T>& e) const {
return Add < T, Id, E >(*this, e); return Add < T, ::Id, E >(*this, e);
} }
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment