Explicit template argument specification patch

Mark Mitchell mmitchell@usa.net
Wed Sep 10 22:50:00 GMT 1997


Below is a patch that implements explicit arguments for template
functions, as described in [ temp.arg.explicit ].  No additional tests
fail, and even relatively pathological examples, like:

    #include <iostream.h>

    template <class U>
    struct S 
    {
      template <class T>
      void foo(T t) { cout << t << "\n"; }

      template <class T>
      void bar(T t) { this->template foo<U>(3.74); }
    };

    void main()
    {
      S<int> s;
      s.bar(3);
    }

compile.  (This example, outputs "3" as it should, rather than "3.74"
as it would if the call were simply this->foo(3.74). )

There are two limitations that I know of: 

  o You must specify *all* the template arguments; you cannot 
    specify some of them, and let argument deduction occur for the
    rest. 

  o We still can't do functions that have more template parameters
    than actually show up in their argument lists, because they 
    are mangled the same way.  It should be easy to fix this,
    in principle, but I haven't done it.  Does anyone have a good
    idea about how we should mangle these guys?

I'm also disturbed that I have introduced a few new shift-reduce
conflicts into the parser.  I'm not too familiar with the parser, so
I'm not sure if bison's default behavior (shift) is right in all those
cases.  If anyone is willing to look at my changes to parse.y below,
and provide suggestions or comments, I would be grateful.

The diffs below are against 970907 with the patches I have already
posted.  I have checked that will apply directly to 970907, but not
that the resulting beast works correctly.

Please report bugs and problems to me.

Thanks,

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

Wed Sep 10 00:07:38 1997  Mark Mitchell  <mmitchell@usa.net>

	* call.c (build_explicit_method_call): New function.
	* cp-tree.h (build_explicit_method_call): Declare it.
	
	* cp-tree.h (type_unification): Change prototype.
	* pt.c (type_unification): Likewise.
	(fn_type_unification): Call it.
	* call.c (build_overload_call_real): Likewise.
	* class.c (instantiate_type): Likewise.
		 
	* pt.c (type_unification_real): New function.

	* cp-tree.def (EXPLICIT_TEMPLATE_EXPR, EXPLICIT_METHOD_CALL):
	New tree codes.
	* decl2.c (build_expr_from_tree): Handle them.
	* pt.c (tsubst_copy): Likewise.
	
	* parse.y (template_id, object_template_id): New non-terminals. 
	(primary): Use them.
	(PFUNCTYPE): New terminal.
	
	* pt.c (lookup_template_function): New function.
	* cp_tree.h (lookup_template_function): Declare it.
	
	* tree.c (get_first_fn): Handle the case that fn is a template
	function. 

	* typeck.c (mark_addressable): If a template function is marked
	as addressed, it must be instantiated.

	* lex.c (identifier_type): Handle function templates by returning
	PFUNCNAME. 

Index: call.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/call.c,v
retrieving revision 1.5
diff -c -p -r1.5 call.c
*** call.c	1997/09/08 09:22:40	1.5
--- call.c	1997/09/10 23:29:13
*************** build_overload_call_real (fnname, parms,
*** 2847,2853 ****
  	  i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (function),
  				&TREE_VEC_ELT (targs, 0),
  				TYPE_ARG_TYPES (TREE_TYPE (function)),
! 				parms, &template_cost, 0, 0);
  	  if (i == 0)
  	    {
  	      function = instantiate_template (function, targs);
--- 2847,2853 ----
  	  i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (function),
  				&TREE_VEC_ELT (targs, 0),
  				TYPE_ARG_TYPES (TREE_TYPE (function)),
! 				parms, NULL_TREE, &template_cost, 0);
  	  if (i == 0)
  	    {
  	      function = instantiate_template (function, targs);
*************** build_over_call (fn, convs, args, flags)
*** 5421,5426 ****
--- 5421,5524 ----
      fn = build_cplus_new (TREE_TYPE (fn), fn);
    return convert_from_reference (require_complete_type (fn));
  }
+ 
+ 
+ tree
+ build_explicit_method_call (instance, fn, name, args)
+      tree instance, fn, name, args;
+ {
+   struct z_candidate *candidates = 0, *cand;
+   tree basetype, basetype_path;
+   tree instance_ptr;
+   tree mem_args;
+   tree pretty_name;
+   int flags = LOOKUP_NORMAL;
+ 
+   if (instance == error_mark_node
+       || name == error_mark_node
+       || args == error_mark_node
+       || (instance != NULL_TREE && TREE_TYPE (instance) == error_mark_node))
+     return error_mark_node;
+ 
+   if (processing_template_decl) 
+     return build_min_nt (EXPLICIT_METHOD_CALL, instance, fn, name, args);
+ 
+   args = resolve_args (args);
+ 
+   if (args == error_mark_node)
+     return error_mark_node;
+ 
+   if (TREE_CODE (instance) == OFFSET_REF)
+     instance = resolve_offset_ref (instance);
+   if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
+     instance = convert_from_reference (instance);
+   basetype = TREE_TYPE (instance);
+   
+   /* XXX this should be handled before we get here.  */
+   if (! IS_AGGR_TYPE (basetype)
+       && ! (TYPE_LANG_SPECIFIC (basetype)
+ 	    && (IS_SIGNATURE_POINTER (basetype)
+ 		|| IS_SIGNATURE_REFERENCE (basetype))))
+     {
+       if (basetype != error_mark_node)
+ 	cp_error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
+ 		  name, instance, basetype);
+       
+       return error_mark_node;
+     }
+ 
+   basetype_path = TYPE_BINFO (basetype);
+   instance_ptr = build_this (instance);
+   mem_args = tree_cons (NULL_TREE, instance_ptr, args);
+ 
+   candidates = add_function_candidate (candidates, fn,
+ 				       mem_args, LOOKUP_NORMAL);
+   if (candidates)
+     candidates->basetype_path = basetype_path;
+ 
+   pretty_name
+     = (name == ctor_identifier ? constructor_name_full (basetype) : name);
+ 
+   if (! any_viable (candidates))
+     {
+       cp_error ("no matching function for call to `%T::%D (%A)%V'", basetype,
+ 		pretty_name, args, TREE_TYPE (TREE_TYPE (instance_ptr)));
+       print_z_candidates (candidates);
+       return error_mark_node;
+     }
+   
+   cand = tourney (candidates);
+ 
+   if (cand == 0)
+     {
+       cp_error ("call of overloaded `%D(%A)' is ambiguous", pretty_name,
+ 		args);
+       print_z_candidates (candidates);
+       return error_mark_node;
+     }
+ 
+   enforce_access (cand->basetype_path, cand->fn);
+   if (DECL_ABSTRACT_VIRTUAL_P (cand->fn)
+       && instance == current_class_ref
+       && DECL_CONSTRUCTOR_P (current_function_decl)
+       && value_member (cand->fn, get_abstract_virtuals (basetype)))
+     cp_error ("abstract virtual `%#D' called from constructor", cand->fn);
+   if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
+       && TREE_CODE (instance_ptr) == NOP_EXPR
+       && TREE_OPERAND (instance_ptr, 0) == error_mark_node)
+     cp_error ("cannot call member function `%D' without object", cand->fn);
+ 
+   if (DECL_VINDEX (cand->fn) 
+       && ((instance == current_class_ref && (dtor_label || ctor_label))
+ 	  || resolves_to_fixed_type_p (instance, 0)))
+     flags |= LOOKUP_NONVIRTUAL;
+ 
+   return build_over_call
+     (cand->fn, cand->convs,
+      TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE ? mem_args : args,
+      flags);
+ }
+ 
  
  static tree
  build_new_method_call (instance, name, args, basetype_path, flags)
Index: class.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/class.c,v
retrieving revision 1.5
diff -c -p -r1.5 class.c
*** class.c	1997/09/08 09:22:41	1.5
--- class.c	1997/09/10 22:32:46
*************** instantiate_type (lhstype, rhs, complain
*** 5046,5052 ****
  		    i = type_unification
  		      (DECL_INNERMOST_TEMPLATE_PARMS (elem), 
  		       &TREE_VEC_ELT (t, 0), TYPE_ARG_TYPES (TREE_TYPE (elem)),
! 		       TYPE_ARG_TYPES (lhstype), &d, 0, 1);
  		    if (i == 0)
  		      {
  			if (save_elem)
--- 5046,5052 ----
  		    i = type_unification
  		      (DECL_INNERMOST_TEMPLATE_PARMS (elem), 
  		       &TREE_VEC_ELT (t, 0), TYPE_ARG_TYPES (TREE_TYPE (elem)),
! 		       TYPE_ARG_TYPES (lhstype), NULL_TREE, &d, 1);
  		    if (i == 0)
  		      {
  			if (save_elem)
Index: cp-tree.def
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/cp-tree.def,v
retrieving revision 1.2
diff -c -p -r1.2 cp-tree.def
*** cp-tree.def	1997/09/02 06:38:38	1.2
--- cp-tree.def	1997/09/10 23:27:54
*************** DEFTREECODE (SIZEOF_EXPR, "sizeof_expr",
*** 126,131 ****
--- 126,133 ----
  DEFTREECODE (ARROW_EXPR, "arrow_expr", "e", 1)
  DEFTREECODE (DOTSTAR_EXPR, "dotstar_expr", "e", 2)
  DEFTREECODE (TYPEID_EXPR, "typeid_expr", "e", 1)
+ DEFTREECODE (EXPLICIT_TEMPLATE_EXPR, "explicit_template_expr", "e", 3)
+ DEFTREECODE (EXPLICIT_METHOD_CALL, "explicit_method_call", "e", 4)
  
  DEFTREECODE (EXPR_STMT, "expr_stmt", "e", 1)
  DEFTREECODE (COMPOUND_STMT, "compound_stmt", "e", 1)
Index: cp-tree.h
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.4
diff -c -p -r1.4 cp-tree.h
*** cp-tree.h	1997/09/05 20:23:59	1.4
--- cp-tree.h	1997/09/10 23:03:10
*************** extern tree build_scoped_method_call		PR
*** 1948,1953 ****
--- 1948,1954 ----
  extern tree build_addr_func			PROTO((tree));
  extern tree build_call				PROTO((tree, tree, tree));
  extern tree build_method_call			PROTO((tree, tree, tree, tree, int));
+ extern tree build_explicit_method_call		PROTO((tree, tree, tree, tree));
  extern tree build_overload_call_real		PROTO((tree, tree, int, struct candidate *, int));
  extern tree build_overload_call			PROTO((tree, tree, int));
  extern int null_ptr_cst_p			PROTO((tree));
*************** extern void end_template_decl			PROTO((v
*** 2318,2329 ****
  extern tree current_template_args		PROTO((void));
  extern void push_template_decl			PROTO((tree));
  extern tree lookup_template_class		PROTO((tree, tree, tree));
  extern int uses_template_parms			PROTO((tree));
  extern tree instantiate_class_template		PROTO((tree));
  extern tree instantiate_template		PROTO((tree, tree));
  extern void overload_template_name		PROTO((tree));
  extern int fn_type_unification                  PROTO((tree, tree, tree, tree, int));
! extern int type_unification			PROTO((tree, tree *, tree, tree, int *, int, int));
  struct tinst_level *tinst_for_decl		PROTO((void));
  extern void mark_decl_instantiated		PROTO((tree, int));
  extern int more_specialized			PROTO((tree, tree));
--- 2319,2331 ----
  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, tree));
  extern int uses_template_parms			PROTO((tree));
  extern tree instantiate_class_template		PROTO((tree));
  extern tree instantiate_template		PROTO((tree, tree));
  extern void overload_template_name		PROTO((tree));
  extern int fn_type_unification                  PROTO((tree, tree, tree, tree, int));
! extern int type_unification			PROTO((tree, tree *, tree, tree, tree, int *, int));
  struct tinst_level *tinst_for_decl		PROTO((void));
  extern void mark_decl_instantiated		PROTO((tree, int));
  extern int more_specialized			PROTO((tree, tree));
Index: decl2.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/decl2.c,v
retrieving revision 1.4
diff -c -p -r1.4 decl2.c
*** decl2.c	1997/09/08 09:22:41	1.4
--- decl2.c	1997/09/10 23:29:32
*************** build_expr_from_tree (t)
*** 3368,3373 ****
--- 3368,3388 ----
        else
  	return do_identifier (TREE_OPERAND (t, 0), 0);
  
+     case EXPLICIT_TEMPLATE_EXPR:
+       return lookup_template_function (build_expr_from_tree
+ 				       (TREE_OPERAND (t, 0)),
+ 				       build_expr_from_tree
+ 				       (TREE_OPERAND (t, 1)),
+ 				       build_expr_from_tree
+ 				       (TREE_OPERAND (t, 2)));
+ 
+     case EXPLICIT_METHOD_CALL:
+       return build_explicit_method_call 
+ 	(build_expr_from_tree (TREE_OPERAND (t, 0)),
+ 	 build_expr_from_tree (TREE_OPERAND (t, 1)),
+ 	 TREE_OPERAND (t, 2),
+ 	 build_expr_from_tree (TREE_OPERAND (t, 3)));
+ 
      case INDIRECT_REF:
        return build_x_indirect_ref
  	(build_expr_from_tree (TREE_OPERAND (t, 0)), "unary *");
Index: lex.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/lex.c,v
retrieving revision 1.4
diff -c -p -r1.4 lex.c
*** lex.c	1997/09/08 09:22:42	1.4
--- lex.c	1997/09/11 00:25:15
*************** identifier_type (decl)
*** 2729,2734 ****
--- 2729,2743 ----
      {
        if (TREE_CODE (DECL_RESULT (decl)) == TYPE_DECL)
  	return PTYPENAME;
+       else
+ 	return PFUNCNAME;
+     }
+   if (really_overloaded_fn (decl))
+     {
+       tree t;
+       for (t = TREE_VALUE (decl); t != NULL_TREE; t = DECL_CHAIN (t))
+ 	if (DECL_FUNCTION_TEMPLATE_P (t))
+ 	  return PFUNCNAME;
      }
    if (TREE_CODE (decl) == NAMESPACE_DECL)
      return NSNAME;
Index: parse.y
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/parse.y,v
retrieving revision 1.3
diff -c -p -r1.3 parse.y
*** parse.y	1997/09/04 20:27:31	1.3
--- parse.y	1997/09/11 00:36:04
*************** empty_parms ()
*** 110,115 ****
--- 110,118 ----
  %token TYPENAME
  %token SELFNAME
  
+ /* The name of a template function.  Just like an identifier. */
+ %token PFUNCNAME
+ 
  /* Reserved words that specify storage class.
     yylval contains an IDENTIFIER_NODE which indicates which one.  */
  %token SCSPEC
*************** empty_parms ()
*** 193,198 ****
--- 196,202 ----
  %type <code> unop
  
  %type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist
+ %type <ttype> PFUNCNAME
  %type <ttype> paren_expr_or_null nontrivial_exprlist SELFNAME
  %type <ttype> expr_no_commas cast_expr unary_expr primary string STRING
  %type <ttype> reserved_declspecs boolean.literal
*************** empty_parms ()
*** 223,229 ****
  %type <ttype> identifiers_or_typenames
  %type <ttype> fcast_or_absdcl regcast_or_absdcl
  %type <ttype> expr_or_declarator complex_notype_declarator
! %type <ttype> notype_unqualified_id unqualified_id qualified_id
  %type <ttype> overqualified_id notype_qualified_id any_id
  %type <ttype> complex_direct_notype_declarator functional_cast
  %type <ttype> complex_parmlist parms_comma
--- 227,234 ----
  %type <ttype> identifiers_or_typenames
  %type <ttype> fcast_or_absdcl regcast_or_absdcl
  %type <ttype> expr_or_declarator complex_notype_declarator
! %type <ttype> notype_unqualified_id unqualified_id qualified_id 
! %type <ttype> template_id object_template_id
  %type <ttype> overqualified_id notype_qualified_id any_id
  %type <ttype> complex_direct_notype_declarator functional_cast
  %type <ttype> complex_parmlist parms_comma
*************** identifier:
*** 814,825 ****
--- 819,832 ----
  	| TYPENAME
  	| SELFNAME
  	| PTYPENAME
+ 	| PFUNCNAME
  	| NSNAME
  	;
  
  notype_identifier:
  	  IDENTIFIER
  	| PTYPENAME 
+ 	| PFUNCNAME
  	| NSNAME  %prec EMPTY
  	;
  
*************** nonnull_exprlist:
*** 1050,1056 ****
  
  unary_expr:
  	  primary  %prec UNARY
! 		{ $$ = $1; }
  	/* __extension__ turns off -pedantic for following primary.  */
  	| extension cast_expr  	  %prec UNARY
  		{ $$ = $2;
--- 1057,1063 ----
  
  unary_expr:
  	  primary  %prec UNARY
!               { $$ = $1; }
  	/* __extension__ turns off -pedantic for following primary.  */
  	| extension cast_expr  	  %prec UNARY
  		{ $$ = $2;
*************** notype_unqualified_id:
*** 1269,1277 ****
--- 1276,1305 ----
  	| operator_name
  	| IDENTIFIER
  	| PTYPENAME
+ 	| PFUNCNAME
  	| NSNAME  %prec EMPTY
  	;
  
+ template_id:
+         PFUNCNAME '<'
+                 { /* It is necessary to call do_identifier() right
+ 		     away, before yylex() is called to trash
+ 		     lastiddecl. */
+ 		  $<ttype>$ = do_identifier ($1, 1); 
+ 		} 
+           template_arg_list template_close_bracket
+                 { 
+ 		  $$ = lookup_template_function ($<ttype>3, $4,
+ 						 NULL_TREE); 
+ 		}
+ 	;
+        
+ object_template_id:
+         TEMPLATE IDENTIFIER '<' template_arg_list template_close_bracket
+                 { $$ = build_tree_list ($2, $4); }
+         | TEMPLATE PFUNCNAME '<' template_arg_list template_close_bracket
+                 { $$ = build_tree_list ($2, $4); }
+ 
  unqualified_id:
  	  notype_unqualified_id
  	| TYPENAME
*************** primary:
*** 1303,1308 ****
--- 1331,1337 ----
  		  else
  		    $$ = do_identifier ($$, 1);
  		}		
+         | template_id
  	| CONSTANT
  	| boolean.literal
  	| string
*************** primary:
*** 1482,1487 ****
--- 1511,1518 ----
  		  $$ = get_typeid (TYPE_MAIN_VARIANT (type)); }
  	| global_scope IDENTIFIER
  		{ $$ = do_scoped_id ($2, 1); }
+ 	| global_scope PFUNCNAME
+ 		{ $$ = do_scoped_id ($2, 1); }
  	| global_scope operator_name
  		{
  		  got_scope = NULL_TREE;
*************** primary:
*** 1503,1516 ****
  				       NULL_TREE, NULL_TREE);
  		  else
  		    $$ = build_member_call (OP0 ($$), OP1 ($$), NULL_TREE); }
! 	| object unqualified_id  %prec UNARY
  		{ $$ = build_x_component_ref ($$, $2, NULL_TREE, 1); }
  	| object overqualified_id  %prec UNARY
  		{ if (processing_template_decl)
  		    $$ = build_min_nt (COMPONENT_REF, $1, copy_to_permanent ($2));
  		  else
  		    $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
! 	| object unqualified_id '(' nonnull_exprlist ')'
  		{
  #if 0
  		  /* This is a future direction of this code, but because
--- 1534,1554 ----
  				       NULL_TREE, NULL_TREE);
  		  else
  		    $$ = build_member_call (OP0 ($$), OP1 ($$), NULL_TREE); }
! 	| object notype_unqualified_id  %prec UNARY
  		{ $$ = build_x_component_ref ($$, $2, NULL_TREE, 1); }
+         | object object_template_id %prec UNARY
+                 { 
+ 		  tree fn = 
+ 		    lookup_template_function (TREE_PURPOSE ($2),
+ 					      TREE_VALUE ($2), $1);
+ 		  $$ = build_x_component_ref ($$, fn, NULL_TREE, 1); 
+ 		}
  	| object overqualified_id  %prec UNARY
  		{ if (processing_template_decl)
  		    $$ = build_min_nt (COMPONENT_REF, $1, copy_to_permanent ($2));
  		  else
  		    $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
! 	| object notype_unqualified_id '(' nonnull_exprlist ')'
  		{
  #if 0
  		  /* This is a future direction of this code, but because
*************** primary:
*** 1525,1531 ****
  					  LOOKUP_NORMAL);
  #endif
  		}
! 	| object unqualified_id LEFT_RIGHT
  		{
  #if 0
  		  /* This is a future direction of this code, but because
--- 1563,1577 ----
  					  LOOKUP_NORMAL);
  #endif
  		}
!         | object object_template_id '(' nonnull_exprlist ')'
!                 {
! 		  tree fn = 
! 		    lookup_template_function (TREE_PURPOSE ($2),
! 					      TREE_VALUE ($2), $1);
! 		  $$ = build_explicit_method_call
! 		    ($1, fn, TREE_PURPOSE ($2), $4);
!                 }
! 	| object notype_unqualified_id LEFT_RIGHT
  		{
  #if 0
  		  /* This is a future direction of this code, but because
*************** primary:
*** 1540,1545 ****
--- 1586,1599 ----
  					  LOOKUP_NORMAL);
  #endif
  		}
+ 	| object object_template_id LEFT_RIGHT
+                 {
+ 		  tree fn = 
+ 		    lookup_template_function (TREE_PURPOSE ($2),
+ 					      TREE_VALUE ($2), $1);
+ 		  $$ = build_explicit_method_call
+ 		    ($1, fn, TREE_PURPOSE ($2), NULL_TREE);
+                 }
  	| object overqualified_id '(' nonnull_exprlist ')'
  		{
  		  if (IS_SIGNATURE (OP0 ($2)))
*************** label_colon:
*** 3878,3883 ****
--- 3932,3939 ----
  	| TYPENAME ':'
  		{ goto do_label; }
  	| SELFNAME ':'
+ 		{ goto do_label; }
+         | PFUNCNAME ':'
  		{ goto do_label; }
  	;
  
Index: pt.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/pt.c,v
retrieving revision 1.10
diff -c -p -r1.10 pt.c
*** pt.c	1997/09/09 15:18:21	1.10
--- pt.c	1997/09/11 01:16:43
*************** static tree get_class_bindings PROTO((tr
*** 78,83 ****
--- 78,85 ----
  static tree coerce_template_parms PROTO((tree, tree, tree));
  static tree tsubst_enum	PROTO((tree, tree, int, tree *));
  static tree add_to_template_args PROTO((tree, tree));
+ static int  type_unification_real PROTO((tree, tree *, tree, tree, int*,
+ 					 int, int));
  
  /* Restore the template parameter context. */
  
*************** add_pending_template (d)
*** 895,900 ****
--- 897,980 ----
    TI_PENDING_TEMPLATE_FLAG (ti) = 1;
  }
  
+ 
+ tree
+ lookup_template_function (fns, arglist, instance)
+      tree fns, arglist, instance;
+ {
+   tree args;
+   tree result;
+   tree templates = NULL_TREE;
+   int found_template = 0;
+   int l = list_length (arglist);
+ 
+   if (processing_template_decl)
+     {
+       push_obstacks (&permanent_obstack, &permanent_obstack);
+       arglist = copy_list (arglist);
+       pop_obstacks ();
+       return build_min_nt (EXPLICIT_TEMPLATE_EXPR,
+ 			   fns, arglist, instance);
+     }
+   
+   if (instance && TREE_CODE (fns) == IDENTIFIER_NODE) 
+     fns = lookup_fnfields (TYPE_BINFO (TREE_TYPE (instance)),
+ 			   fns, 
+ 			   0);
+ 
+   while (fns != NULL_TREE) 
+     {
+       tree fn;
+ 
+       fn = get_first_fn (fns);
+       fns = DECL_CHAIN (fn);
+ 
+       if (TREE_CODE (fn) == TEMPLATE_DECL &&
+ 	  DECL_NTPARMS (fn) == l)
+ 	{
+ 	  int dummy;
+ 	  args = make_tree_vec (DECL_NTPARMS (fn));
+ 	  found_template = 1;
+ 
+ 	  /* Call type_unification as if there were no arguments to
+ 	     the function.  */
+ 	  if (type_unification (DECL_INNERMOST_TEMPLATE_PARMS (fn),
+ 				&TREE_VEC_ELT (args, 0),
+ 				NULL_TREE, NULL_TREE,
+ 				arglist,
+ 				&dummy, 1) == 0)
+ 	    /* This template could be a match. */
+ 	    templates = tree_cons (args, fn, templates);
+ 	}
+     }
+ 
+   if (templates == NULL_TREE)
+     {
+       cp_error ("non-template used as template");
+       return NULL_TREE;
+     }
+ 
+   if (TREE_CHAIN (templates) != NULL_TREE)
+     {
+       tree t;
+ 
+       cp_error ("ambiguous explicit template argument specification");
+       cp_error ("candidates are:");
+ 
+       for (t = templates; t != NULL_TREE; t = TREE_CHAIN (t))
+ 	cp_error("%D", TREE_VALUE (t));
+ 
+       return NULL_TREE;
+     }
+ 
+   push_obstacks (&permanent_obstack, &permanent_obstack);
+ 
+   result = instantiate_template (TREE_VALUE (templates), 
+ 				 TREE_PURPOSE (templates));
+   pop_obstacks ();
+   return result;
+ }
+ 
  /* Given an IDENTIFIER_NODE (type TEMPLATE_DECL) and a chain of
     parameters, find the desired type.
  
*************** tsubst_copy (t, args, nargs, in_decl)
*** 2525,2530 ****
--- 2605,2631 ----
  	return r;
        }
  
+     case EXPLICIT_TEMPLATE_EXPR:
+       {
+ 	tree r = build_nt
+ 	  (code, 
+ 	   tsubst_copy (TREE_OPERAND (t, 0), args, nargs, in_decl),
+ 	   tsubst_copy (TREE_OPERAND (t, 1), args, nargs, in_decl),
+ 	   tsubst_copy (TREE_OPERAND (t, 2), args, nargs, in_decl));
+ 	return r;
+       }
+ 
+     case EXPLICIT_METHOD_CALL:
+       {
+ 	tree r = build_nt
+ 	  (code, 
+ 	   tsubst_copy (TREE_OPERAND (t, 0), args, nargs, in_decl),
+ 	   tsubst_copy (TREE_OPERAND (t, 1), args, nargs, in_decl),
+ 	   tsubst_copy (TREE_OPERAND (t, 2), args, nargs, in_decl),
+ 	   tsubst_copy (TREE_OPERAND (t, 3), args, nargs, in_decl));
+ 	return r;
+       }
+ 
      case TREE_LIST:
        {
  	tree purpose, value, chain;
*************** fn_type_unification (fn, targs, args, re
*** 2980,2986 ****
  			&TREE_VEC_ELT (targs, 0), 
  			fn_arg_types,
  			decl_arg_types,
! 			&dummy, 0, strict);
  
    return i;
  }
--- 3081,3088 ----
  			&TREE_VEC_ELT (targs, 0), 
  			fn_arg_types,
  			decl_arg_types,
! 			NULL_TREE,
! 			&dummy, strict);
  
    return i;
  }
*************** fn_type_unification (fn, targs, args, re
*** 3010,3016 ****
     addresses, explicit instantiation, and more_specialized).  */
  
  int
! type_unification (tparms, targs, parms, args, nsubsts, subr, strict)
       tree tparms, *targs, parms, args;
       int *nsubsts, subr, strict;
  {
--- 3112,3136 ----
     addresses, explicit instantiation, and more_specialized).  */
  
  int
! type_unification (tparms, targs, parms, args, targs_in, nsubsts, strict)
!      tree tparms, *targs, parms, args, targs_in;
!      int *nsubsts, strict;
! {
!   int ntparms = TREE_VEC_LENGTH (tparms);
!   tree t;
!   int i;
! 
!   bzero ((char *) targs, sizeof (tree) * ntparms);
!   for (i = 0, t = targs_in; t != NULL_TREE; t = TREE_CHAIN (t), ++i)
!     targs[i] = TREE_VALUE (t);
! 
!   return 
!     type_unification_real (tparms, targs, parms, args, nsubsts, 0, strict);
! }
! 
! 
! int
! type_unification_real (tparms, targs, parms, args, nsubsts, subr, strict)
       tree tparms, *targs, parms, args;
       int *nsubsts, subr, strict;
  {
*************** type_unification (tparms, targs, parms, 
*** 3019,3034 ****
    int ntparms = TREE_VEC_LENGTH (tparms);
  
    my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289);
!   my_friendly_assert (TREE_CODE (parms) == TREE_LIST, 290);
    /* ARGS could be NULL (via a call from parse.y to
       build_x_function_call).  */
    if (args)
      my_friendly_assert (TREE_CODE (args) == TREE_LIST, 291);
    my_friendly_assert (ntparms > 0, 292);
  
-   if (!subr)
-     bzero ((char *) targs, sizeof (tree) * ntparms);
- 
    while (parms
  	 && parms != void_list_node
  	 && args
--- 3139,3152 ----
    int ntparms = TREE_VEC_LENGTH (tparms);
  
    my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289);
!   my_friendly_assert (parms == NULL_TREE 
! 		      || TREE_CODE (parms) == TREE_LIST, 290);
    /* ARGS could be NULL (via a call from parse.y to
       build_x_function_call).  */
    if (args)
      my_friendly_assert (TREE_CODE (args) == TREE_LIST, 291);
    my_friendly_assert (ntparms > 0, 292);
  
    while (parms
  	 && parms != void_list_node
  	 && args
*************** type_unification (tparms, targs, parms, 
*** 3101,3110 ****
  	      ntparms = DECL_NTPARMS (arg);
  	      targs = (tree *) alloca (sizeof (tree) * ntparms);
  	      parm = tree_cons (NULL_TREE, parm, NULL_TREE);
! 	      return type_unification (DECL_INNERMOST_TEMPLATE_PARMS (arg), 
! 				       targs,
! 				       TYPE_ARG_TYPES (TREE_TYPE (arg)),
! 				       parm, &nsubsts, 0, strict);
  	    }
  	  arg = TREE_TYPE (arg);
  	}
--- 3219,3229 ----
  	      ntparms = DECL_NTPARMS (arg);
  	      targs = (tree *) alloca (sizeof (tree) * ntparms);
  	      parm = tree_cons (NULL_TREE, parm, NULL_TREE);
! 	      return 
! 		type_unification (DECL_INNERMOST_TEMPLATE_PARMS (arg), 
! 				  targs,
! 				  TYPE_ARG_TYPES (TREE_TYPE (arg)),
! 				  parm, NULL_TREE, &nsubsts, strict);
  	    }
  	  arg = TREE_TYPE (arg);
  	}
*************** unify (tparms, targs, ntparms, parm, arg
*** 3351,3358 ****
        if (unify (tparms, targs, ntparms, TREE_TYPE (parm),
  		 TREE_TYPE (arg), nsubsts, strict))
  	return 1;
!       return type_unification (tparms, targs, TYPE_ARG_TYPES (parm),
! 			       TYPE_ARG_TYPES (arg), nsubsts, 1, strict);
  
      case OFFSET_TYPE:
        if (TREE_CODE (arg) != OFFSET_TYPE)
--- 3470,3477 ----
        if (unify (tparms, targs, ntparms, TREE_TYPE (parm),
  		 TREE_TYPE (arg), nsubsts, strict))
  	return 1;
!       return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
! 				    TYPE_ARG_TYPES (arg), nsubsts, 1, strict);
  
      case OFFSET_TYPE:
        if (TREE_CODE (arg) != OFFSET_TYPE)
Index: spew.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/spew.c,v
retrieving revision 1.1.1.1
diff -c -p -r1.1.1.1 spew.c
*** spew.c	1997/08/26 06:23:57	1.1.1.1
--- spew.c	1997/09/11 00:27:44
*************** yylex ()
*** 316,321 ****
--- 316,322 ----
  	      if (got_scope)
  		tmp_token.yylval.ttype = trrr;
  	      break;
+ 	    case PFUNCNAME:
  	    case IDENTIFIER:
  	      lastiddecl = trrr;
  	      break;
Index: tree.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/tree.c,v
retrieving revision 1.2
diff -c -p -r1.2 tree.c
*** tree.c	1997/09/02 06:38:44	1.2
--- tree.c	1997/09/10 22:42:34
*************** tree
*** 1286,1292 ****
  get_first_fn (from)
       tree from;
  {
!   if (TREE_CODE (from) == FUNCTION_DECL)
      return from;
  
    my_friendly_assert (TREE_CODE (from) == TREE_LIST, 9);
--- 1286,1293 ----
  get_first_fn (from)
       tree from;
  {
!   if (TREE_CODE (from) == FUNCTION_DECL 
!       || DECL_FUNCTION_TEMPLATE_P (from))
      return from;
  
    my_friendly_assert (TREE_CODE (from) == TREE_LIST, 9);
Index: typeck.c
===================================================================
RCS file: /home/mitchell/Repository/egcs/gcc/cp/typeck.c,v
retrieving revision 1.3
diff -c -p -r1.3 typeck.c
*** typeck.c	1997/09/04 20:27:32	1.3
--- typeck.c	1997/09/10 22:12:32
*************** mark_addressable (exp)
*** 4753,4758 ****
--- 4753,4760 ----
  	    if (x == current_function_decl)
  	      DECL_EXTERNAL (x) = 0;
  	  }
+ 	else if (DECL_TEMPLATE_INFO (x))
+ 	  instantiate_decl (x);
  	TREE_ADDRESSABLE (x) = 1;
  	TREE_USED (x) = 1;
  	TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
cvs diff: Diffing inc



More information about the Gcc mailing list