[C++ PATCH] Fix PR8442, 8806
Kriang Lerdsuwanakij
lerdsuwa@users.sourceforge.net
Thu Jul 31 14:59:00 GMT 2003
Hi
This is the third revision of my patch to fix PR8442 (regression
in 3.4) and PR8806.
In the previous version, the code was updated to reflect various
changes to frontend. However some part of the patch still refers
to old code, like variable name implicit_typedef_p.
Explanation of changes can be found here (2nd revision)
http://gcc.gnu.org/ml/gcc-patches/2003-07/msg01960.html
here (1st revision)
http://gcc.gnu.org/ml/gcc-patches/2003-05/msg01475.html
and here (original)
http://gcc.gnu.org/ml/gcc-patches/2003-01/msg02100.html
Tested on i686-pc-linux-gnu. OK for the mainline?
(A patch to update the web page gcc-3.4/changes.html will be
prepared when this is approved.)
--Kriang
2003-07-31 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-07-31 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/8442, c++/8806
* 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.
diff -cprN gcc-main-save/gcc/cp/NEWS gcc-main-new/gcc/cp/NEWS
*** gcc-main-save/gcc/cp/NEWS Sun Jul 13 22:17:33 2003
--- gcc-main-new/gcc/cp/NEWS Wed Jul 23 22:16:58 2003
***************
*** 73,78 ****
--- 73,91 ----
* 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)".
diff -cprN gcc-main-save/gcc/cp/class.c gcc-main-new/gcc/cp/class.c
*** gcc-main-save/gcc/cp/class.c Wed Jul 23 20:49:53 2003
--- gcc-main-new/gcc/cp/class.c Wed Jul 23 22:16:58 2003
*************** get_enclosing_class (tree type)
*** 6337,6357 ****
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. */
--- 6337,6342 ----
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 Wed Jul 23 20:49:53 2003
--- gcc-main-new/gcc/cp/cp-tree.h Wed Jul 23 22:16:58 2003
*************** extern int same_signature_p (tree, tre
*** 3595,3601 ****
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);
--- 3595,3600 ----
*************** extern tree get_scope_of_declarator
*** 3723,3729 ****
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);
--- 3722,3728 ----
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 Jul 23 20:49:54 2003
--- gcc-main-new/gcc/cp/decl.c Thu Jul 24 21:57:23 2003
*************** qualify_lookup (tree val, int flags)
*** 5748,5754 ****
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;
--- 5748,5755 ----
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)
*** 6340,6346 ****
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,
--- 6341,6347 ----
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)
*** 12565,12579 ****
/* 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;
!
! 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
--- 12566,12580 ----
/* 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 = 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
*************** check_elaborated_type_specifier (enum ta
*** 12590,12619 ****
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.
! C++: If a class derivation is given, process it here, and report
! an error if multiple derivation declarations are not identical.
! 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:
--- 12591,12657 ----
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 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
*** 12630,12722 ****
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
--- 12668,12717 ----
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);
!
! 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 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
! 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
*** 12754,12765 ****
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".
--- 12749,12760 ----
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
*** 12769,12812 ****
{
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;
! 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
--- 12764,12804 ----
{
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
{
! t = make_aggr_type (code);
! TYPE_CONTEXT (t) = context;
! pushtag (name, t, globalize);
}
}
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
*** 12822,12828 ****
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
--- 12814,12820 ----
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 Tue Jul 22 19:37:25 2003
--- gcc-main-new/gcc/cp/decl2.c Wed Jul 23 22:16:58 2003
*************** handle_class_head (enum tag_types tag_ki
*** 4307,4313 ****
if (!decl)
{
! decl = xref_tag (tag_kind, id, attributes, false);
if (decl == error_mark_node)
return error_mark_node;
decl = TYPE_MAIN_DECL (decl);
--- 4307,4313 ----
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 Wed Jul 23 20:49:54 2003
--- gcc-main-new/gcc/cp/parser.c Wed Jul 23 22:16:58 2003
*************** cp_parser_elaborated_type_specifier (cp_
*** 8552,8558 ****
(is_friend
|| !is_declaration
|| cp_lexer_next_token_is_not (parser->lexer,
! CPP_SEMICOLON)));
}
}
if (tag_type != enum_type)
--- 8552,8559 ----
(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,
*** 11379,11385 ****
/* 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
{
--- 11380,11387 ----
/* 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 Wed Jul 23 20:49:54 2003
--- gcc-main-new/gcc/cp/pt.c Wed Jul 23 22:16:58 2003
*************** convert_template_argument (tree parm,
*** 3433,3465 ****
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;
--- 3433,3447 ----
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 Wed Jul 23 20:49:54 2003
--- gcc-main-new/gcc/cp/rtti.c Wed Jul 23 22:16:58 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
*** 638,644 ****
tinfo_ptr = xref_tag (class_type,
get_identifier ("__class_type_info"),
/*attributes=*/NULL_TREE,
! 1);
tinfo_ptr = build_pointer_type
(build_qualified_type
--- 638,644 ----
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)
*** 773,779 ****
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))
--- 773,779 ----
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)
*** 1370,1376 ****
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;
--- 1370,1376 ----
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 Wed Jul 23 22:16:58 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 Wed Jul 23 22:16:58 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 Wed Jul 23 22:16:58 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 Wed Jul 23 22:16:58 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 Wed Jul 23 22:16:58 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 Wed Jul 23 22:16: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 Wed Jul 23 22:16:58 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 Wed Jul 23 22:16:58 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);
}
};
More information about the Gcc-patches
mailing list