Patch for local classes

Mark Mitchell mmitchell@usa.net
Sun Jan 11 19:17:00 GMT 1998


The attached patch improves support for local classes, and fixes a few
other issues.  In partciular,
 
  o Member functions of local classes are now given internal linkage.
    This avoids the bug that resulted from:

    test1.C
    -------
    static void f() { struct S { int g() {} }; }

    test2.C
    -------
    static void f() { struct S { int g() {} }; }

    int main() {}

    supernova% g++ test1.C test2.C
    /tmp/cca128672.o: In function `f__Fv.0::S::g(void)':
    /tmp/cca128672.o(.text+0x0): multiple definition of `f__Fv.0::S::g(void)'
    /tmp/cca128671.o(.text+0x0): first defined here

  o The linkage specifiers on template declarations are now obeyed, as
    required in the standard.  So, for example, on:

    test.C
    ------
    template <class T> static void f(T t) {}

    void g() { f(3); }
    
    we used to give:

      supernova% g++ -c test.C
      supernova% nm test.o
      00000000 W f__H1Zi_X01_v

    and now give:

      supernova% test-g++ -c test.C
      supernova% nm test.o
      00000018 t f__H1Zi_X01_v

  o Local classes in template functions are now implemented, and seem
    to work at least in the simple cases.  This fixes the internal
    errors reported by Raymond Nijssen on 12/19 and Hans-Helmut
    Buehmann in http://www.cygnus.com/ml/egcs-bugs/1997-Dec/0423.html .

The patch below may not apply directly to the latest snapshot, but
should apply after the other patches I have submitted.  (Not all of
these made it to the list.)

-- 
Mark Mitchell		mmitchell@usa.net
Stanford University	http://www.stanford.edu

Index: gcc/cp/class.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/class.c,v
retrieving revision 1.2
diff -c -p -r1.2 class.c
*** class.c	1998/01/01 01:17:05	1.2
--- class.c	1998/01/11 23:31:53
*************** build_self_reference ()
*** 5511,5513 ****
--- 5511,5531 ----
    pushdecl_class_level (value);
    return value;
  }
+ 
+ 
+ /* Returns non-zero iff the TYPE is a local class; i.e., if it is
+    declared in a function context, or within a local class.  */
+ 
+ int
+ is_local_class (type)
+      tree type;
+ {
+   if (type == NULL_TREE || TYPE_CONTEXT (type) == NULL_TREE)
+     return 0;
+ 
+   if (TREE_CODE (TYPE_CONTEXT (type)) == FUNCTION_DECL)
+     return 1;
+ 
+   return is_local_class (TYPE_CONTEXT (type));
+ }
+ 
Index: gcc/cp/cp-tree.h
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.6
diff -c -p -r1.6 cp-tree.h
*** cp-tree.h	1998/01/01 01:17:06	1.6
--- cp-tree.h	1998/01/11 22:02:06
*************** extern tree null_node;
*** 1537,1542 ****
--- 1537,1543 ----
  
  extern tree current_template_parms;
  extern HOST_WIDE_INT processing_template_decl;
+ extern tree last_tree;
  
  /* The template currently being instantiated, and where the instantiation
     was triggered.  */
*************** extern void maybe_push_cache_obstack		PR
*** 1981,1986 ****
--- 1982,1988 ----
  extern unsigned HOST_WIDE_INT skip_rtti_stuff	PROTO((tree *));
  extern tree build_self_reference		PROTO((void));
  extern void warn_hidden				PROTO((tree));
+ extern int is_local_class                       PROTO((tree));
  
  /* in cvt.c */
  extern tree convert_to_reference		PROTO((tree, tree, int, int, tree));
*************** extern tree end_template_parm_list		PROT
*** 2325,2331 ****
  extern void end_template_decl			PROTO((void));
  extern tree current_template_args		PROTO((void));
  extern void push_template_decl			PROTO((tree));
! extern tree lookup_template_class		PROTO((tree, tree, tree));
  extern tree lookup_template_function            PROTO((tree, tree));
  extern int uses_template_parms			PROTO((tree));
  extern tree instantiate_class_template		PROTO((tree));
--- 2327,2333 ----
  extern void end_template_decl			PROTO((void));
  extern tree current_template_args		PROTO((void));
  extern void push_template_decl			PROTO((tree));
! extern tree lookup_template_class		PROTO((tree, tree, tree, tree));
  extern tree lookup_template_function            PROTO((tree, tree));
  extern int uses_template_parms			PROTO((tree));
  extern tree instantiate_class_template		PROTO((tree));
*************** extern tree do_poplevel				PROTO((void))
*** 2345,2350 ****
--- 2347,2354 ----
  extern tree get_bindings			PROTO((tree, tree));
  /* CONT ... */
  extern void add_tree				PROTO((tree));
+ extern void begin_tree                          PROTO((void));
+ extern void end_tree                            PROTO((void));
  extern void add_maybe_template			PROTO((tree, tree));
  extern void pop_tinst_level			PROTO((void));
  extern tree most_specialized			PROTO((tree, tree));
Index: gcc/cp/decl.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/decl.c,v
retrieving revision 1.12
diff -c -p -r1.12 decl.c
*** decl.c	1998/01/07 07:39:42	1.12
--- decl.c	1998/01/12 02:19:38
*************** cp_finish_decl (decl, init, asmspec_tree
*** 6468,6476 ****
        if (minimal_parse_mode && ! DECL_ARTIFICIAL (decl))
  	{
  	  tree stmt = DECL_VINDEX (decl);
! 	  DECL_VINDEX (decl) = NULL_TREE;
! 	  TREE_OPERAND (stmt, 2) = copy_to_permanent (init);
! 	  add_tree (stmt);
  	}
  
        goto finish_end0;
--- 6468,6479 ----
        if (minimal_parse_mode && ! DECL_ARTIFICIAL (decl))
  	{
  	  tree stmt = DECL_VINDEX (decl);
! 	  if (stmt != NULL_TREE)
! 	    {
! 	      DECL_VINDEX (decl) = NULL_TREE;
! 	      TREE_OPERAND (stmt, 2) = copy_to_permanent (init);
! 	      add_tree (stmt);
! 	    }
  	}
  
        goto finish_end0;
*************** cp_finish_decl (decl, init, asmspec_tree
*** 6756,6762 ****
        || TREE_CODE (decl) == RESULT_DECL)
      {
        /* ??? FIXME: What about nested classes?  */
!       int toplev = toplevel_bindings_p () || pseudo_global_level_p ();
        int was_temp
  	= (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type)
  	   && allocation_temporary_p ());
--- 6759,6769 ----
        || TREE_CODE (decl) == RESULT_DECL)
      {
        /* ??? FIXME: What about nested classes?  */
!       /* We check for FUNCTION_DECL here so that member functions of
! 	 local classes, which will have internal linkage, are not
! 	 given bizarre names by make_decl_rtl.  */
!       int toplev = toplevel_bindings_p () || pseudo_global_level_p ()
! 	|| TREE_CODE (decl) == FUNCTION_DECL;
        int was_temp
  	= (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type)
  	   && allocation_temporary_p ());
*************** grokdeclarator (declarator, declspecs, d
*** 9685,9691 ****
  	      }
  
  	    /* Tell grokfndecl if it needs to set TREE_PUBLIC on the node.  */
! 	    publicp = (! friendp || ! staticp);
  	    decl = grokfndecl (ctype, type, 
  			       TREE_CODE (declarator) != TEMPLATE_ID_EXPR
  			       ? declarator : dname,
--- 9692,9698 ----
  	      }
  
  	    /* Tell grokfndecl if it needs to set TREE_PUBLIC on the node.  */
! 	    publicp = (! friendp || ! staticp) && !is_local_class (ctype);
  	    decl = grokfndecl (ctype, type, 
  			       TREE_CODE (declarator) != TEMPLATE_ID_EXPR
  			       ? declarator : dname,
*************** start_function (declspecs, declarator, a
*** 11730,11736 ****
  
    if (processing_template_decl)
      {
-       extern tree last_tree;
        ++minimal_parse_mode;
        last_tree = DECL_SAVED_TREE (decl1)
  	= build_nt (EXPR_STMT, void_zero_node);
--- 11737,11742 ----
*************** finish_function (lineno, call_poplevel, 
*** 12454,12462 ****
--- 12460,12480 ----
  
    if (! processing_template_decl)
      {
+       int saved_flag_keep_inline_functions =
+ 	flag_keep_inline_functions;
+ 
        /* So we can tell if jump_optimize sets it to 1.  */
        can_reach_end = 0;
  
+       if (DECL_CONTEXT (fndecl) != NULL_TREE
+ 	  && is_local_class (DECL_CONTEXT (fndecl)))
+ 	/* Trick rest_of_compilation into not deferring output of this
+ 	   function, even if it is inline, since the rtl_obstack for
+ 	   this function is the function_obstack of the enclosing
+ 	   function and will be deallocated when the enclosing
+ 	   function is gone.  See save_tree_status.  */
+ 	flag_keep_inline_functions = 1;
+ 
        /* Run the optimizers and output the assembler code for this
           function.  */
  
*************** finish_function (lineno, call_poplevel, 
*** 12477,12482 ****
--- 12495,12502 ----
        else
  	rest_of_compilation (fndecl);
  
+       flag_keep_inline_functions = saved_flag_keep_inline_functions;
+ 
        if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl))
  	{
  	  /* Set DECL_EXTERNAL so that assemble_external will be called as
*************** start_method (declspecs, declarator)
*** 12622,12628 ****
    if (flag_default_inline)
      DECL_INLINE (fndecl) = 1;
  
!   if (processing_template_decl && ! current_function_decl)
      push_template_decl (fndecl);
  
    /* We read in the parameters on the maybepermanent_obstack,
--- 12642,12648 ----
    if (flag_default_inline)
      DECL_INLINE (fndecl) = 1;
  
!   if (processing_template_decl)
      push_template_decl (fndecl);
  
    /* We read in the parameters on the maybepermanent_obstack,
Index: gcc/cp/decl2.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/decl2.c,v
retrieving revision 1.1.1.7
diff -c -p -r1.1.1.7 decl2.c
*** decl2.c	1998/01/01 01:04:29	1.1.1.7
--- decl2.c	1998/01/11 23:20:14
*************** import_export_decl (decl)
*** 2788,2794 ****
        if (DECL_IMPLICIT_INSTANTIATION (decl)
  	  && (flag_implicit_templates || DECL_THIS_INLINE (decl)))
  	{
! 	  if (TREE_CODE (decl) == FUNCTION_DECL)
  	    comdat_linkage (decl);
  	  else
  	    DECL_COMDAT (decl) = 1;
--- 2788,2798 ----
        if (DECL_IMPLICIT_INSTANTIATION (decl)
  	  && (flag_implicit_templates || DECL_THIS_INLINE (decl)))
  	{
! 	  if (!TREE_PUBLIC (decl))
! 	    /* Templates are allowed to have internal linkage.  See 
! 	       [basic.link].  */
! 	    ;
! 	  else if (TREE_CODE (decl) == FUNCTION_DECL)
  	    comdat_linkage (decl);
  	  else
  	    DECL_COMDAT (decl) = 1;
Index: gcc/cp/parse.y
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/parse.y,v
retrieving revision 1.7
diff -c -p -r1.7 parse.y
*** parse.y	1998/01/01 01:17:14	1.7
--- parse.y	1998/01/11 21:44:11
*************** extern int errno;
*** 56,62 ****
  
  extern int end_of_file;
  extern int current_class_depth;
- extern tree last_tree;
  
  /* FSF LOCAL dje prefix attributes */
  extern tree strip_attrs		PROTO((tree));
--- 56,61 ----
*************** end_explicit_instantiation: 
*** 900,912 ****
  template_type:
  	  PTYPENAME '<' template_arg_list_opt template_close_bracket
  		{
! 		  $$ = lookup_template_class ($1, $3, NULL_TREE);
  		  if ($$ != error_mark_node)
  		    $$ = TYPE_STUB_DECL ($$);
  		}
  	| TYPENAME  '<' template_arg_list_opt template_close_bracket
  		{
! 		  $$ = lookup_template_class ($1, $3, NULL_TREE);
  		  if ($$ != error_mark_node)
  		    $$ = TYPE_STUB_DECL ($$);
  		}
--- 899,911 ----
  template_type:
  	  PTYPENAME '<' template_arg_list_opt template_close_bracket
  		{
! 		  $$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE);
  		  if ($$ != error_mark_node)
  		    $$ = TYPE_STUB_DECL ($$);
  		}
  	| TYPENAME  '<' template_arg_list_opt template_close_bracket
  		{
! 		  $$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE);
  		  if ($$ != error_mark_node)
  		    $$ = TYPE_STUB_DECL ($$);
  		}
*************** template_type:
*** 916,922 ****
  self_template_type:
  	  SELFNAME  '<' template_arg_list_opt template_close_bracket
  		{
! 		  $$ = lookup_template_class ($1, $3, NULL_TREE);
  		  if ($$ != error_mark_node)
  		    $$ = TYPE_STUB_DECL ($$);
  		}
--- 915,921 ----
  self_template_type:
  	  SELFNAME  '<' template_arg_list_opt template_close_bracket
  		{
! 		  $$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE);
  		  if ($$ != error_mark_node)
  		    $$ = TYPE_STUB_DECL ($$);
  		}
*************** structsp:
*** 2269,2275 ****
  		  $$.new_type_flag = 0; }
  	/* C++ extensions, merged with C to avoid shift/reduce conflicts */
  	| class_head left_curly 
-                 { reset_specialization(); }
            opt.component_decl_list '}' maybe_attribute
  		{
  		  int semi;
--- 2268,2273 ----
*************** structsp:
*** 2293,2299 ****
  		    ;
  		  else
  		    {
! 		      $<ttype>$ = finish_struct ($1, $4, $6, semi);
  		      if (semi) note_got_semicolon ($<ttype>$);
  		    }
  
--- 2291,2297 ----
  		    ;
  		  else
  		    {
! 		      $<ttype>$ = finish_struct ($1, $3, $5, semi);
  		      if (semi) note_got_semicolon ($<ttype>$);
  		    }
  
*************** structsp:
*** 2312,2321 ****
  		}
  	  pending_inlines
  		{ 
! 		  $$.t = $<ttype>7;
  		  $$.new_type_flag = 1; 
  		  if (current_class_type == NULL_TREE)
  		    clear_inline_text_obstack (); 
  		}
  	| class_head  %prec EMPTY
  		{
--- 2310,2322 ----
  		}
  	  pending_inlines
  		{ 
! 		  $$.t = $<ttype>6;
  		  $$.new_type_flag = 1; 
  		  if (current_class_type == NULL_TREE)
  		    clear_inline_text_obstack (); 
+ 
+ 		  /* Undo the begin_tree in left_curly.  */
+ 		  end_tree ();
  		}
  	| class_head  %prec EMPTY
  		{
*************** left_curly:
*** 2678,2683 ****
--- 2679,2690 ----
  		  if (t && IDENTIFIER_TEMPLATE (t))
  		    overload_template_name (t, 1);
  #endif
+ 		  reset_specialization();
+ 
+ 		  /* In case this is a local class within a template
+ 		     function, we save the current tree structure so
+ 		     that we can get it back later.  */
+ 		  begin_tree ();
  		}
  	;
  
Index: gcc/cp/pt.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/pt.c,v
retrieving revision 1.12
diff -c -p -r1.12 pt.c
*** pt.c	1998/01/06 23:12:15	1.12
--- pt.c	1998/01/12 03:03:48
*************** int processing_specialization;
*** 64,69 ****
--- 64,71 ----
  int processing_explicit_instantiation;
  static int template_header_count;
  
+ static tree saved_trees;
+ 
  #define obstack_chunk_alloc xmalloc
  #define obstack_chunk_free free
  
*************** static int unify PROTO((tree, tree *, in
*** 71,77 ****
  static void add_pending_template PROTO((tree));
  static int push_tinst_level PROTO((tree));
  static tree classtype_mangled_name PROTO((tree));
! static char *mangle_class_name_for_template PROTO((char *, tree, tree));
  static tree tsubst_expr_values PROTO((tree, tree));
  static int comp_template_args PROTO((tree, tree));
  static int list_eq PROTO((tree, tree));
--- 73,79 ----
  static void add_pending_template PROTO((tree));
  static int push_tinst_level PROTO((tree));
  static tree classtype_mangled_name PROTO((tree));
! static char *mangle_class_name_for_template PROTO((char *, tree, tree, tree));
  static tree tsubst_expr_values PROTO((tree, tree));
  static int comp_template_args PROTO((tree, tree));
  static int list_eq PROTO((tree, tree));
*************** push_template_decl (decl)
*** 1154,1160 ****
  
    args = current_template_args ();
  
!   if (! ctx || TYPE_BEING_DEFINED (ctx))
      {
        tmpl = build_template_decl (decl, current_template_parms);
        
--- 1156,1163 ----
  
    args = current_template_args ();
  
!   if (! ctx || TREE_CODE (ctx) == FUNCTION_DECL 
!       || TYPE_BEING_DEFINED (ctx))
      {
        tmpl = build_template_decl (decl, current_template_parms);
        
*************** push_template_decl (decl)
*** 1273,1279 ****
    if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
      {
        CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (tmpl)) = info;
!       DECL_NAME (decl) = classtype_mangled_name (TREE_TYPE (decl));
      }
    else if (! DECL_LANG_SPECIFIC (decl))
      cp_error ("template declaration of `%#D'", decl);
--- 1276,1283 ----
    if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
      {
        CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (tmpl)) = info;
!       if (!ctx || TREE_CODE (ctx) != FUNCTION_DECL)
! 	DECL_NAME (decl) = classtype_mangled_name (TREE_TYPE (decl));
      }
    else if (! DECL_LANG_SPECIFIC (decl))
      cp_error ("template declaration of `%#D'", decl);
*************** convert_nontype_parameter (type, expr)
*** 1575,1580 ****
--- 1579,1593 ----
  	    expr_type != unknown_type_node)
  	  return error_mark_node;
  
+ 	if (TREE_CODE (expr) == CONSTRUCTOR)
+ 	  {
+ 	    /* A ptr-to-member constant.  */
+ 	    if (!comptypes (type, expr_type, 1))
+ 	      return error_mark_node;
+ 	    else 
+ 	      return expr;
+ 	  }
+ 
  	if (TREE_CODE (expr) != ADDR_EXPR)
  	  return error_mark_node;
  
*************** comp_template_args (oldargs, newargs)
*** 1835,1843 ****
     for the instantiation.  */
  
  static char *
! mangle_class_name_for_template (name, parms, arglist)
       char *name;
       tree parms, arglist;
  {
    static struct obstack scratch_obstack;
    static char *scratch_firstobj;
--- 1848,1857 ----
     for the instantiation.  */
  
  static char *
! mangle_class_name_for_template (name, parms, arglist, ctx)
       char *name;
       tree parms, arglist;
+      tree ctx;
  {
    static struct obstack scratch_obstack;
    static char *scratch_firstobj;
*************** mangle_class_name_for_template (name, pa
*** 1862,1867 ****
--- 1876,1887 ----
  #define cat(s)	obstack_grow (&scratch_obstack, (s), strlen (s))
  #endif
  
+   if (ctx)
+     {
+       char* s = fndecl_as_string(ctx, 0);
+       cat (s);
+       cat ("::");
+     }
    cat (name);
    ccat ('<');
    nparms = TREE_VEC_LENGTH (parms);
*************** classtype_mangled_name (t)
*** 1927,1933 ****
        char *mangled_name = mangle_class_name_for_template
  	(IDENTIFIER_POINTER (name),
  	 DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (t)),
! 	 CLASSTYPE_TI_ARGS (t));
        tree id = get_identifier (mangled_name);
        IDENTIFIER_TEMPLATE (id) = name;
        return id;
--- 1947,1955 ----
        char *mangled_name = mangle_class_name_for_template
  	(IDENTIFIER_POINTER (name),
  	 DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (t)),
! 	 CLASSTYPE_TI_ARGS (t), 
! 	 (DECL_CONTEXT (t) && TREE_CODE (t) == FUNCTION_DECL) ? 
! 	 DECL_CONTEXT (t) : NULL_TREE);
        tree id = get_identifier (mangled_name);
        IDENTIFIER_TEMPLATE (id) = name;
        return id;
*************** lookup_template_function (fns, arglist)
*** 1989,2000 ****
     to keep it from being reclaimed when the decl storage is reclaimed.
  
     IN_DECL, if non-NULL, is the template declaration we are trying to
!    instantiate.  */
  
  tree
! lookup_template_class (d1, arglist, in_decl)
       tree d1, arglist;
       tree in_decl;
  {
    tree template, parmlist;
    char *mangled_name;
--- 2011,2027 ----
     to keep it from being reclaimed when the decl storage is reclaimed.
  
     IN_DECL, if non-NULL, is the template declaration we are trying to
!    instantiate.  
! 
!    If the template class is really a local class in a template
!    function, then the FUNCTION_CONTEXT is the function in which it is
!    being instantiated.  */
  
  tree
! lookup_template_class (d1, arglist, in_decl, function_context)
       tree d1, arglist;
       tree in_decl;
+      tree function_context;
  {
    tree template, parmlist;
    char *mangled_name;
*************** lookup_template_class (d1, arglist, in_d
*** 2069,2086 ****
  	}
  
        mangled_name = mangle_class_name_for_template (IDENTIFIER_POINTER (d1),
! 						     parmlist, arglist);
        id = get_identifier (mangled_name);
        IDENTIFIER_TEMPLATE (id) = d1;
  
        maybe_push_to_top_level (uses_template_parms (arglist));
        t = xref_tag_from_type (TREE_TYPE (template), id, 1);
        pop_from_top_level ();
      }
    else
      {
        tree ctx = lookup_template_class (TYPE_CONTEXT (TREE_TYPE (template)),
! 					arglist, in_decl);
        id = d1;
        arglist = CLASSTYPE_TI_ARGS (ctx);
  
--- 2096,2130 ----
  	}
  
        mangled_name = mangle_class_name_for_template (IDENTIFIER_POINTER (d1),
! 						     parmlist,
! 						     arglist,
! 						     function_context);
        id = get_identifier (mangled_name);
        IDENTIFIER_TEMPLATE (id) = d1;
  
        maybe_push_to_top_level (uses_template_parms (arglist));
        t = xref_tag_from_type (TREE_TYPE (template), id, 1);
+ 
+       if (function_context != NULL_TREE)
+ 	{
+ 	  /* Set up the context for the type_decl correctly.  Note
+ 	     that we must clear DECL_ASSEMBLER_NAME to fool
+ 	     build_overload_name into creating a new name.  */
+ 	  tree type_decl = TYPE_STUB_DECL (t);
+ 
+ 	  TYPE_CONTEXT (t) = function_context;
+ 	  DECL_CONTEXT (type_decl) = function_context;
+ 	  DECL_ASSEMBLER_NAME (type_decl) = DECL_NAME (type_decl);
+ 	  DECL_ASSEMBLER_NAME (type_decl) = 
+ 	    get_identifier (build_overload_name (t, 1, 1));
+ 	}
+ 
        pop_from_top_level ();
      }
    else
      {
        tree ctx = lookup_template_class (TYPE_CONTEXT (TREE_TYPE (template)),
! 					arglist, in_decl, NULL_TREE);
        id = d1;
        arglist = CLASSTYPE_TI_ARGS (ctx);
  
*************** tsubst (t, args, nargs, in_decl)
*** 2758,2764 ****
        if (uses_template_parms (t))
  	{
  	  tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, nargs, in_decl);
! 	  tree r = lookup_template_class (t, argvec, in_decl);
  	  return cp_build_type_variant (r, TYPE_READONLY (t),
  					TYPE_VOLATILE (t));
  	}
--- 2802,2816 ----
        if (uses_template_parms (t))
  	{
  	  tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, nargs, in_decl);
! 	  tree context;
! 	  tree r;
! 
! 	  context = (TYPE_CONTEXT (t) 
! 		     && TREE_CODE (TYPE_CONTEXT (t)) == FUNCTION_DECL)
! 	    ? tsubst (TYPE_CONTEXT (t), args, nargs, in_decl) : NULL_TREE;
! 
! 	  r = lookup_template_class (t, argvec, in_decl, context);
! 
  	  return cp_build_type_variant (r, TYPE_READONLY (t),
  					TYPE_VOLATILE (t));
  	}
*************** tsubst (t, args, nargs, in_decl)
*** 3142,3148 ****
  	DECL_INITIAL (r) = NULL_TREE;
  
  	TREE_STATIC (r) = 0;
! 	TREE_PUBLIC (r) = 1;
  	DECL_EXTERNAL (r) = 1;
  	DECL_INTERFACE_KNOWN (r) = 0;
  	DECL_DEFER_OUTPUT (r) = 0;
--- 3194,3200 ----
  	DECL_INITIAL (r) = NULL_TREE;
  
  	TREE_STATIC (r) = 0;
! 	TREE_PUBLIC (r) = TREE_PUBLIC (t);
  	DECL_EXTERNAL (r) = 1;
  	DECL_INTERFACE_KNOWN (r) = 0;
  	DECL_DEFER_OUTPUT (r) = 0;
*************** mark_decl_instantiated (result, extern_p
*** 4771,4777 ****
  {
    if (DECL_TEMPLATE_INSTANTIATION (result))
      SET_DECL_EXPLICIT_INSTANTIATION (result);
!   TREE_PUBLIC (result) = 1;
  
    if (! extern_p)
      {
--- 4823,4833 ----
  {
    if (DECL_TEMPLATE_INSTANTIATION (result))
      SET_DECL_EXPLICIT_INSTANTIATION (result);
! 
!   if (TREE_CODE (result) != FUNCTION_DECL)
!     /* The TREE_PUBLIC flag for function declarations will have been
!        set correctly by tsubst.  */
!     TREE_PUBLIC (result) = 1;
  
    if (! extern_p)
      {
*************** mark_decl_instantiated (result, extern_p
*** 4780,4786 ****
  
        /* For WIN32 we also want to put explicit instantiations in
  	 linkonce sections.  */
!       if (supports_one_only () && ! SUPPORTS_WEAK)
  	make_decl_one_only (result);
      }
    else if (TREE_CODE (result) == FUNCTION_DECL)
--- 4836,4842 ----
  
        /* For WIN32 we also want to put explicit instantiations in
  	 linkonce sections.  */
!       if (supports_one_only () && ! SUPPORTS_WEAK && TREE_PUBLIC (result))
  	make_decl_one_only (result);
      }
    else if (TREE_CODE (result) == FUNCTION_DECL)
*************** add_tree (t)
*** 5462,5467 ****
--- 5518,5541 ----
       tree t;
  {
    last_tree = TREE_CHAIN (last_tree) = t;
+ }
+ 
+ 
+ void
+ begin_tree ()
+ {
+   saved_trees = tree_cons (NULL_TREE, last_tree, saved_trees);
+   last_tree = NULL_TREE;
+ }
+ 
+ 
+ void 
+ end_tree ()
+ {
+   my_friendly_assert (saved_trees != NULL_TREE, 0);
+ 
+   last_tree = TREE_VALUE (saved_trees);
+   saved_trees = TREE_CHAIN (saved_trees);
  }
  
  /* D is an undefined function declaration in the presence of templates with
Index: gcc/testsuite/g++.old-deja/g++.mike/p5840.C
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/testsuite/g++.old-deja/g++.mike/p5840.C,v
retrieving revision 1.1.1.1
diff -c -p -r1.1.1.1 p5840.C
*** p5840.C	1997/11/08 17:54:14	1.1.1.1
--- p5840.C	1998/01/12 02:00:12
*************** public:
*** 17,33 ****
    int value (Foo* a) { return (a->*Id)(); }
  };
  
! template class Bar <Derived, &Signal::Name>;
  template class Bar <Signal, &Signal::Name>;
  template class Bar <Derived, &Derived::Name>;
  
  Derived a;
  
! Bar<Derived, &Signal::Name> dispatcher1;
  Bar<Derived, &Derived::Name> dispatcher2;
  
  main() {
!   int i1 = dispatcher1.value(&a);
    int i2 = dispatcher2.value(&a);
!   return i1 != 1 || i2 != 2;
  }
--- 17,35 ----
    int value (Foo* a) { return (a->*Id)(); }
  };
  
! /* The following line is illegal under the new rules for non-type
!    template arguments in the standard, so it is commented out.  */
! /* template class Bar <Derived, &Signal::Name>; */
  template class Bar <Signal, &Signal::Name>;
  template class Bar <Derived, &Derived::Name>;
  
  Derived a;
  
! /* Bar<Derived, &Signal::Name> dispatcher1; */
  Bar<Derived, &Derived::Name> dispatcher2;
  
  main() {
!   /* int i1 = dispatcher1.value(&a); */
    int i2 = dispatcher2.value(&a);
!   return /* i1 != 1 || */ i2 != 2;
  }
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.niklas
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.other
cvs diff: Diffing gcc/testsuite/g++.old-deja/g++.pt
Index: gcc/testsuite/g++.old-deja/g++.pt/local1.C
===================================================================
RCS file: local1.C
diff -N local1.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- local1.C	Wed Jan  7 12:24:47 1998
***************
*** 0 ****
--- 1,21 ----
+ template <class STRUCT, class MEMBER> inline STRUCT *
+ setback(MEMBER *bp, MEMBER STRUCT::*offset)
+ {
+         if(!bp) return 0;
+         union { int i; MEMBER STRUCT::*of; } u;
+         u.of = offset;
+         return (STRUCT *) ((int) bp - u.i);
+ }
+  
+ 
+ struct S
+ {
+   int i;
+ };
+ 
+ int main()
+ {
+   S s;
+ 
+   S* sp = setback (&s.i, &S::i);
+ }
Index: gcc/testsuite/g++.old-deja/g++.pt/local2.C
===================================================================
RCS file: local2.C
diff -N local2.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- local2.C	Wed Jan  7 10:34:21 1998
***************
*** 0 ****
--- 1,20 ----
+ extern "C" void abort();
+ 
+ template <class T>
+ void f(T)
+ {
+   struct S {
+     int i;
+   } s;
+ 
+   s.i = 3;
+ 
+   if (s.i != 3)
+     abort();
+ }
+ 
+ 
+ int main()
+ {
+   f(7);
+ }
Index: gcc/testsuite/g++.old-deja/g++.pt/local3.C
===================================================================
RCS file: local3.C
diff -N local3.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- local3.C	Wed Jan  7 11:09:39 1998
***************
*** 0 ****
--- 1,22 ----
+ extern "C" void abort();
+ 
+ template <class T>
+ void f(T)
+ {
+   struct S {
+     int i;
+   };
+ 
+   S s;
+ 
+   s.i = 3;
+ 
+   if (s.i != 3)
+     abort();
+ }
+ 
+ 
+ int main()
+ {
+   f(7);
+ }
Index: gcc/testsuite/g++.old-deja/g++.pt/local4.C
===================================================================
RCS file: local4.C
diff -N local4.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- local4.C	Sun Jan 11 13:33:27 1998
***************
*** 0 ****
--- 1,25 ----
+ extern "C" void abort();
+ 
+ template <class T>
+ struct S {};
+ 
+ S<int> si;
+ 
+ template <class T>
+ int f(T t)
+ {
+   struct S { 
+     int g(int i) { return i + 2; }
+   };
+ 
+   S s;
+ 
+   return s.g(t) + s.g(t);
+ }
+ 
+ 
+ int main()
+ {
+   if (f(3) != 10)
+     abort();
+ }
Index: gcc/testsuite/g++.old-deja/g++.pt/local5.C
===================================================================
RCS file: local5.C
diff -N local5.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- local5.C	Sun Jan 11 18:53:53 1998
***************
*** 0 ****
--- 1,24 ----
+ template <class INT>
+ class b
+ {
+ private:
+   char a(int x)
+   {
+     union {
+       int i;
+       char c;
+     } val;
+     val.i = x;
+     return val.c;
+   };
+ 
+ public:
+   b()  {
+   }
+ };
+ 
+ int main() {
+   b<int> n;
+   return 0;
+ }
+    



More information about the Gcc mailing list