[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