This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Fix PR8442, 8806
- From: Kriang Lerdsuwanakij <lerdsuwa at users dot sourceforge dot net>
- To: <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 16 May 2003 22:34:23 +0700 (ICT)
- Subject: [C++ PATCH] Fix PR8442, 8806
- Reply-to: <lerdsuwa at users dot sourceforge dot net>
Hi
This patch fixes PR8442 and 8806. It is a revised version of
http://gcc.gnu.org/ml/gcc-patches/2003-01/msg02100.html
with name lookup change in the patch
http://gcc.gnu.org/ml/gcc-patches/2003-01/msg00136.html
also included.
One major change is the xref_tag function (most of the patch
just adjust the xref_tag callers). The name lookup change makes
the lookup_name behavior consistent allowing xref_tag to rely
solely on this function rather than using 3 different methods
(IDENTIFIER_TYPE_VALUE, lookup_tag, and lookup_name) when
'globalize' is true. A new parameter 'template_header_p' is
added to simplify various checks inside this function. Another
check about the deprecate implicit typename is also removed.
Another piece of change is the convert_template_argument,
this is simply the same as original version of the patch.
Tested on i686-pc-linux-gnu. OK for the main trunk?
--Kriang
2003-05-16 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.
* 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-05-16 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.
diff -cprN gcc-main-save/gcc/cp/NEWS gcc-main-new/gcc/cp/NEWS
*** gcc-main-save/gcc/cp/NEWS Mon Jan 27 16:59:56 2003
--- gcc-main-new/gcc/cp/NEWS Fri May 16 22:15:33 2003
***************
*** 70,75 ****
--- 70,88 ----
X x __attribute__((...)) (1);
+ * 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)".
diff -cprN gcc-main-save/gcc/cp/class.c gcc-main-new/gcc/cp/class.c
*** gcc-main-save/gcc/cp/class.c Sat May 10 18:16:21 2003
--- gcc-main-new/gcc/cp/class.c Fri May 16 21:41:05 2003
*************** get_enclosing_class (tree type)
*** 6401,6421 ****
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. */
--- 6401,6406 ----
diff -cprN gcc-main-save/gcc/cp/cp-tree.h gcc-main-new/gcc/cp/cp-tree.h
*** gcc-main-save/gcc/cp/cp-tree.h Sat May 10 18:16:21 2003
--- gcc-main-new/gcc/cp/cp-tree.h Fri May 16 21:41:03 2003
*************** extern int same_signature_p (tree, tre
*** 3558,3564 ****
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);
--- 3558,3563 ----
*************** extern tree get_scope_of_declarator
*** 3686,3692 ****
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_from_type (tree, tree, int);
extern void xref_basetypes (tree, tree);
extern tree start_enum (tree);
--- 3685,3691 ----
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, bool);
extern tree xref_tag_from_type (tree, tree, int);
extern void xref_basetypes (tree, tree);
extern tree start_enum (tree);
diff -cprN gcc-main-save/gcc/cp/decl.c gcc-main-new/gcc/cp/decl.c
*** gcc-main-save/gcc/cp/decl.c Wed May 14 22:27:25 2003
--- gcc-main-new/gcc/cp/decl.c Fri May 16 21:50:01 2003
*************** qualify_lookup (tree val, int flags)
*** 5712,5718 ****
return val;
if ((flags & LOOKUP_PREFER_NAMESPACES) && TREE_CODE (val) == NAMESPACE_DECL)
return val;
! if ((flags & LOOKUP_PREFER_TYPES) && TREE_CODE (val) == TYPE_DECL)
return val;
if (flags & (LOOKUP_PREFER_NAMESPACES | LOOKUP_PREFER_TYPES))
return NULL_TREE;
--- 5712,5719 ----
return val;
if ((flags & LOOKUP_PREFER_NAMESPACES) && TREE_CODE (val) == NAMESPACE_DECL)
return val;
! 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;
*************** cxx_init_decl_processing (void)
*** 6302,6308 ****
push_namespace (std_identifier);
bad_alloc_type_node
= xref_tag (class_type, get_identifier ("bad_alloc"),
! /*attributes=*/NULL_TREE, 1);
pop_namespace ();
ptr_ftype_sizetype
= build_function_type (ptr_type_node,
--- 6303,6309 ----
push_namespace (std_identifier);
bad_alloc_type_node
= xref_tag (class_type, get_identifier ("bad_alloc"),
! /*attributes=*/NULL_TREE, true, false);
pop_namespace ();
ptr_ftype_sizetype
= build_function_type (ptr_type_node,
*************** tag_name (enum tag_types code)
*** 12526,12536 ****
/* 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. */
static tree
check_elaborated_type_specifier (enum tag_types tag_code,
! tree type)
{
tree t;
--- 12527,12539 ----
/* 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.
! 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,
! bool allow_template_p)
{
tree t;
*************** check_elaborated_type_specifier (enum ta
*** 12551,12577 ****
type, tag_name (tag_code));
t = error_mark_node;
}
return t;
}
! /* Get the struct, enum or union (CODE says which) with tag NAME.
Define the tag as a forward-reference if it is not defined.
! If this is a definition, come in through xref_tag and only look in
the current frame for the name (since C++ allows new names in any
! scope.) */
tree
xref_tag (enum tag_types tag_code, tree name, tree attributes,
! bool globalize)
{
enum tree_code code;
! register tree ref, t;
struct cp_binding_level *b = current_binding_level;
tree context = NULL_TREE;
timevar_push (TV_NAME_LOOKUP);
switch (tag_code)
{
case record_type:
--- 12554,12619 ----
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 `%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 elaborate 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 (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. ATTRIBUTE is the attribute
! appeared in this declaration.
!
! 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, tree attributes,
! bool globalize, bool template_header_p)
{
enum tree_code code;
! 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:
*************** xref_tag (enum tag_types tag_code, tree
*** 12588,12680 ****
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);
}
else
{
! if (t)
! {
! ref = check_elaborated_type_specifier (tag_code, t);
! if (ref == error_mark_node)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
else
! ref = lookup_tag (code, name, b, 0);
! 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
&& template_class_depth (current_class_type)
! && PROCESSING_REAL_TEMPLATE_DECL_P ())
{
/* Since GLOBALIZE is nonzero, we are not looking at a
definition of this tag. Since, in addition, we are currently
--- 12630,12683 ----
abort ();
}
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
{
! tree decl = lookup_name (name, 1);
!
! /* True if DECL is an implicit typedef created inside a class. */
! bool implicit_typedef_p = (decl && TREE_CODE (decl) == TYPE_DECL
! && DECL_ARTIFICIAL (decl));
!
! if (decl && DECL_CLASS_TEMPLATE_P (decl))
! decl = DECL_TEMPLATE_RESULT (decl);
!
! if (decl && TREE_CODE (decl) == TYPE_DECL)
! {
! /* Two cases needed to be consider when deciding if a
! class template is allowed as an elaborated type specifier:
! 1. It's an implicit typedef.
! 2. It comes with a template header.
!
! For example:
!
! template <class T> class C {
! class C *c1; // implicit_typedef_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; // implicit_typedef_p is true
! }; */
!
! t = check_elaborated_type_specifier (tag_code,
! TREE_TYPE (decl),
! template_header_p
! | implicit_typedef_p);
! 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
*************** xref_tag (enum tag_types tag_code, tree
*** 12712,12723 ****
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;
}
}
! if (! ref)
{
/* If no such tag is yet defined, create a forward-reference node
and record it as the "definition".
--- 12715,12726 ----
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)
{
/* If no such tag is yet defined, create a forward-reference node
and record it as the "definition".
*************** xref_tag (enum tag_types tag_code, tree
*** 12727,12775 ****
{
error ("use of enum `%#D' without previous declaration", name);
! ref = 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);
/* 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);
}
else
{
struct cp_binding_level *old_b = class_binding_level;
! ref = make_aggr_type (code);
! TYPE_CONTEXT (ref) = context;
#ifdef NONNESTED_CLASSES
/* Class types don't nest the way enums do. */
class_binding_level = (struct cp_binding_level *)0;
#endif
! pushtag (name, ref, globalize);
class_binding_level = old_b;
}
}
else
{
! if (!globalize && processing_template_decl && IS_AGGR_TYPE (ref))
! redeclare_class_template (ref, current_template_parms);
}
! TYPE_ATTRIBUTES (ref) = attributes;
! POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ref);
}
tree
--- 12730,12778 ----
{
error ("use of enum `%#D' without previous declaration", name);
! 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 (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, t, globalize);
}
else
{
struct cp_binding_level *old_b = class_binding_level;
! t = make_aggr_type (code);
! TYPE_CONTEXT (t) = context;
#ifdef NONNESTED_CLASSES
/* Class types don't nest the way enums do. */
class_binding_level = (struct cp_binding_level *)0;
#endif
! pushtag (name, t, globalize);
class_binding_level = old_b;
}
}
else
{
! if (!globalize && processing_template_decl && IS_AGGR_TYPE (t))
! redeclare_class_template (t, current_template_parms);
}
! TYPE_ATTRIBUTES (t) = attributes;
! POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
tree
*************** xref_tag_from_type (tree old, tree id, i
*** 12785,12791 ****
if (id == NULL_TREE)
id = TYPE_IDENTIFIER (old);
! return xref_tag (tag_kind, id, /*attributes=*/NULL_TREE, globalize);
}
/* REF is a type (named NAME), for which we have just seen some
--- 12788,12794 ----
if (id == NULL_TREE)
id = TYPE_IDENTIFIER (old);
! return xref_tag (tag_kind, id, /*attributes=*/NULL_TREE, globalize, false);
}
/* REF is a type (named NAME), for which we have just seen some
diff -cprN gcc-main-save/gcc/cp/decl2.c gcc-main-new/gcc/cp/decl2.c
*** gcc-main-save/gcc/cp/decl2.c Sat May 3 18:55:25 2003
--- gcc-main-new/gcc/cp/decl2.c Wed May 14 20:54:10 2003
*************** handle_class_head (enum tag_types tag_ki
*** 4679,4685 ****
if (!decl)
{
! decl = xref_tag (tag_kind, id, attributes, false);
if (decl == error_mark_node)
return error_mark_node;
decl = TYPE_MAIN_DECL (decl);
--- 4679,4685 ----
if (!decl)
{
! decl = xref_tag (tag_kind, id, attributes, false, false);
if (decl == error_mark_node)
return error_mark_node;
decl = TYPE_MAIN_DECL (decl);
diff -cprN gcc-main-save/gcc/cp/parser.c gcc-main-new/gcc/cp/parser.c
*** gcc-main-save/gcc/cp/parser.c Sat May 10 18:16:21 2003
--- gcc-main-new/gcc/cp/parser.c Wed May 14 20:59:33 2003
*************** cp_parser_elaborated_type_specifier (cp_
*** 8931,8937 ****
(is_friend
|| !is_declaration
|| cp_lexer_next_token_is_not (parser->lexer,
! CPP_SEMICOLON)));
}
}
if (tag_type != enum_type)
--- 8931,8938 ----
(is_friend
|| !is_declaration
|| cp_lexer_next_token_is_not (parser->lexer,
! CPP_SEMICOLON)),
! parser->num_template_parameter_lists);
}
}
if (tag_type != enum_type)
*************** cp_parser_class_head (cp_parser* parser,
*** 11754,11760 ****
/* If the class was unnamed, create a dummy name. */
if (!id)
id = make_anon_name ();
! type = xref_tag (class_key, id, attributes, /*globalize=*/0);
}
else
{
--- 11755,11762 ----
/* If the class was unnamed, create a dummy name. */
if (!id)
id = make_anon_name ();
! type = xref_tag (class_key, id, attributes, /*globalize=*/false,
! parser->num_template_parameter_lists);
}
else
{
diff -cprN gcc-main-save/gcc/cp/pt.c gcc-main-new/gcc/cp/pt.c
*** gcc-main-save/gcc/cp/pt.c Sun May 11 16:41:28 2003
--- gcc-main-new/gcc/cp/pt.c Tue May 13 21:31:26 2003
*************** convert_template_argument (parm, arg, ar
*** 3527,3559 ****
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;
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;
--- 3527,3541 ----
requires_type = (TREE_CODE (parm) == TYPE_DECL
|| requires_tmpl_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);
if (is_tmpl_type
&& (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE))
arg = TYPE_STUB_DECL (arg);
is_type = TYPE_P (arg) || is_tmpl_type;
diff -cprN gcc-main-save/gcc/cp/rtti.c gcc-main-new/gcc/cp/rtti.c
*** gcc-main-save/gcc/cp/rtti.c Sun Apr 27 19:10:57 2003
--- gcc-main-new/gcc/cp/rtti.c Wed May 14 20:53:04 2003
*************** init_rtti_processing (void)
*** 119,125 ****
push_namespace (std_identifier);
type_info_type_node
= xref_tag (class_type, get_identifier ("type_info"),
! /*attributes=*/NULL_TREE, 1);
pop_namespace ();
const_type_info_type = build_qualified_type (type_info_type_node,
TYPE_QUAL_CONST);
--- 119,125 ----
push_namespace (std_identifier);
type_info_type_node
= xref_tag (class_type, get_identifier ("type_info"),
! /*attributes=*/NULL_TREE, true, false);
pop_namespace ();
const_type_info_type = build_qualified_type (type_info_type_node,
TYPE_QUAL_CONST);
*************** build_dynamic_cast_1 (tree type, tree ex
*** 644,650 ****
tinfo_ptr = xref_tag (class_type,
get_identifier ("__class_type_info"),
/*attributes=*/NULL_TREE,
! 1);
tinfo_ptr = build_pointer_type
(build_qualified_type
--- 644,650 ----
tinfo_ptr = xref_tag (class_type,
get_identifier ("__class_type_info"),
/*attributes=*/NULL_TREE,
! true, false);
tinfo_ptr = build_pointer_type
(build_qualified_type
*************** tinfo_base_init (tree desc, tree target)
*** 781,787 ****
push_nested_namespace (abi_node);
real_type = xref_tag (class_type, TINFO_REAL_NAME (desc),
! /*attributes=*/NULL_TREE, 1);
pop_nested_namespace (abi_node);
if (!COMPLETE_TYPE_P (real_type))
--- 781,787 ----
push_nested_namespace (abi_node);
real_type = xref_tag (class_type, TINFO_REAL_NAME (desc),
! /*attributes=*/NULL_TREE, true, false);
pop_nested_namespace (abi_node);
if (!COMPLETE_TYPE_P (real_type))
*************** emit_support_tinfos (void)
*** 1379,1385 ****
bltn_type = xref_tag (class_type,
get_identifier ("__fundamental_type_info"),
/*attributes=*/NULL_TREE,
! 1);
pop_nested_namespace (abi_node);
if (!COMPLETE_TYPE_P (bltn_type))
return;
--- 1379,1385 ----
bltn_type = xref_tag (class_type,
get_identifier ("__fundamental_type_info"),
/*attributes=*/NULL_TREE,
! true, false);
pop_nested_namespace (abi_node);
if (!COMPLETE_TYPE_P (bltn_type))
return;
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/elab1.C gcc-main-new/gcc/testsuite/g++.dg/template/elab1.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/elab1.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/elab1.C Fri May 16 21:45:06 2003
***************
*** 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;
+ };
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/ttp3.C gcc-main-new/gcc/testsuite/g++.dg/template/ttp3.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/ttp3.C Mon Jan 27 16:59:56 2003
--- gcc-main-new/gcc/testsuite/g++.dg/template/ttp3.C Tue May 13 21:28:55 2003
*************** class OUTER {
*** 14,26 ****
template <class T>
class List { };
! vector<class List> data; // { dg-error "type/value mismatch|expected a type|ISO C" "" }
};
template <class T>
! class List { }; // { dg-bogus "previous declaration" "" { xfail *-*-* } }
// 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 *-*-* } }
--- 14,26 ----
template <class T>
class List { };
! vector<class List> data; // { dg-error "invalid|required|ISO C" "" }
};
template <class T>
! 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-error "invalid|required|expected" "" }
diff -cprN gcc-main-save/gcc/testsuite/g++.dg/template/type2.C gcc-main-new/gcc/testsuite/g++.dg/template/type2.C
*** gcc-main-save/gcc/testsuite/g++.dg/template/type2.C Thu Jan 1 07:00:00 1970
--- gcc-main-new/gcc/testsuite/g++.dg/template/type2.C Tue May 13 21:28:55 2003
***************
*** 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;
diff -cprN gcc-main-save/gcc/testsuite/g++.old-deja/g++.law/visibility13.C gcc-main-new/gcc/testsuite/g++.old-deja/g++.law/visibility13.C
*** gcc-main-save/gcc/testsuite/g++.old-deja/g++.law/visibility13.C Thu May 1 18:35:03 2003
--- gcc-main-new/gcc/testsuite/g++.old-deja/g++.law/visibility13.C Tue May 13 21:29:52 2003
*************** void Array<Type>::init(const Type *array
*** 65,71 ****
// --------------- Array_RC.h && Array_RC.cc ----------------
template <class Type>
! class Array_RC : public Array<Type> {// { dg-error "" } previous declaration.*
public:
Array_RC(const Type *ar, int sz);
Type& operator[](int ix);
--- 65,71 ----
// --------------- Array_RC.h && Array_RC.cc ----------------
template <class Type>
! class Array_RC : public Array<Type> {
public:
Array_RC(const Type *ar, int sz);
Type& operator[](int ix);
diff -cprN gcc-main-save/gcc/testsuite/g++.old-deja/g++.niklas/t135.C gcc-main-new/gcc/testsuite/g++.old-deja/g++.niklas/t135.C
*** gcc-main-save/gcc/testsuite/g++.old-deja/g++.niklas/t135.C Thu May 1 18:35:10 2003
--- gcc-main-new/gcc/testsuite/g++.old-deja/g++.niklas/t135.C Thu May 15 19:51:27 2003
***************
*** 1,7 ****
! // { dg-do assemble }
// GROUPS niklas pt friend
template <class T> class C1
! { // { dg-error "" }
public:
void diddle_C2 ();
};
--- 1,7 ----
! // { dg-do compile }
// GROUPS niklas pt friend
template <class T> class C1
! {
public:
void diddle_C2 ();
};
diff -cprN gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp41.C gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp41.C
*** gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp41.C Thu May 1 18:35:31 2003
--- gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp41.C Thu May 15 19:50:58 2003
***************
*** 1,4 ****
! // { dg-do run }
template<template<class> class D,class E> class C
{
public:
--- 1,4 ----
! // { dg-do compile }
template<template<class> class D,class E> class C
{
public:
*************** template<class T> class D
*** 13,20 ****
template<class T> int D<T>::f()
{
! C<D,D> c;
! return c.g();
}
int main()
--- 13,20 ----
template<class T> int D<T>::f()
{
! C<D,D> c; // { dg-error "" }
! return c.g(); // { dg-error "" }
}
int main()
diff -cprN gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp43.C gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp43.C
*** gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp43.C Thu May 1 18:35:31 2003
--- gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp43.C Tue May 13 21:28:55 2003
*************** struct Lit {
*** 20,30 ****
template < class T >
struct Id {
! 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));
}
};
--- 20,30 ----
template < class T >
struct Id {
! 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));
}
};
diff -cprN gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp44.C gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp44.C
*** gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp44.C Thu May 1 18:35:31 2003
--- gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp44.C Tue May 13 21:28:55 2003
*************** public:
*** 9,16 ****
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);
}
};
--- 9,16 ----
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);
}
};