This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

(C++) more small fixes


1998-12-04  Jason Merrill  <jason@yorick.cygnus.com>

	* pt.c (check_template_shadow): New fn.
	* decl2.c (grokfield): Use it.
	* decl.c (pushdecl): Likewise.
	(pushdecl_class_level): Likewise.
	(start_method): Likewise.
	(xref_tag): Don't try to use 't' if we're defining.
To consolidate the code for checking re-use of template parm names, and to
catch missed cases.  Fixes Perennial Sec14/7/C14387.cm.

	* call.c (check_dtor_name): Just return an error_mark_node.
	* pt.c (lookup_template_class): Complain about using non-template here.
	* parse.y (apparent_template_type): Not here.
Fixes crash on Perennial Sec14/C14339.cm.

	* pt.c (check_explicit_specialization): Complain about specialization
	with C linkage.
Fixes Perennial Sec14/C14340.cm.

	* lang-options.h: Add -f{no-,}implicit-inline-templates.
I added this option to decl2.c a while back, but forgot to add it here...

	* pt.c (convert_nontype_argument): Don't assume that any integer
	argument is intended to be a constant-expression.
Fixes Perennial Sec14/7/P14245.C.

Index: call.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/call.c,v
retrieving revision 1.123
diff -c -p -r1.123 call.c
*** call.c	1998/11/25 00:28:47	1.123
--- call.c	1998/12/04 19:10:06
*************** check_dtor_name (basetype, name)
*** 347,352 ****
--- 347,355 ----
  {
    name = TREE_OPERAND (name, 0);
  
+   if (name == error_mark_node)
+     return error_mark_node;
+ 
    if (TREE_CODE (name) == TYPE_DECL)
      name = TREE_TYPE (name);
    else if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
Index: decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.277
diff -c -p -r1.277 decl.c
*** decl.c	1998/12/03 16:58:01	1.277
--- decl.c	1998/12/04 19:10:07
*************** pushdecl (x)
*** 3452,3457 ****
--- 3452,3459 ----
  	    }
  	}
  
+       check_template_shadow (x);
+ 
        if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x))
  	{
  	  t = push_overloaded_decl (x, 1);
*************** pushdecl (x)
*** 3671,3686 ****
  	      if (warnstring)
  		warning (warnstring, IDENTIFIER_POINTER (name));
  	    }
- 	  /* Check to see if decl redeclares a template parameter. */
-  	  if (oldlocal && (current_class_type || current_function_decl) 
-  	      && current_template_parms)
-  	    {
-  	      if (decl_template_parm_p (oldlocal))
-  		{
- 		  cp_error ("re-using name of template parameter `%T' in this scope", name);
-  		  cp_error_at (" previously declared here `%#D'", oldlocal);
-  		}
-  	    }
  	}
  
        if (TREE_CODE (x) == FUNCTION_DECL)
--- 3673,3678 ----
*************** pushdecl_class_level (x)
*** 3816,3822 ****
  	     Types, enums, and static vars are checked here; other
  	     members are checked in finish_struct.  */
  	  tree icv = IDENTIFIER_CLASS_VALUE (name);
- 	  tree ilv = IDENTIFIER_LOCAL_VALUE (name);
  
  	  if (icv && icv != x
  	      && flag_optional_diags
--- 3808,3813 ----
*************** pushdecl_class_level (x)
*** 3831,3847 ****
  			     icv);
  	    }
  
! 	  /* Check to see if decl redeclares a template parameter. */
! 	  if (ilv && ! decls_match (ilv, x)
! 	      && (current_class_type || current_function_decl) 
! 	      && current_template_parms)
! 	    {
! 	      if (decl_template_parm_p (ilv))
! 		{
! 		  cp_error ("re-using name of template parameter `%T' in this scope", name);
! 		  cp_error_at (" previously declared here `%#D'", ilv);
! 		}
! 	    }
  	}
  
        push_class_level_binding (name, x);
--- 3822,3828 ----
  			     icv);
  	    }
  
! 	  check_template_shadow (x);
  	}
  
        push_class_level_binding (name, x);
*************** xref_tag (code_type_node, name, globaliz
*** 11842,11860 ****
  
    if (! globalize)
      {
!       if (t && (TREE_CODE (t) == TEMPLATE_TYPE_PARM 
! 			    || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM))
! 	{
! 	  cp_error ("redeclaration of template type-parameter `%T'", name);
! 	  cp_error_at ("  previously declared here `%#D'", 
! 		       TEMPLATE_TYPE_DECL (t));
! 	}
!       if (t && TYPE_CONTEXT (t) && got_type)
! 	ref = t;
!       else
! 	/* 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
      {
--- 11823,11831 ----
  
    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
      {
*************** start_method (declspecs, declarator, att
*** 13783,13788 ****
--- 13754,13761 ----
  	}
        return void_type_node;
      }
+ 
+   check_template_shadow (fndecl);
  
    DECL_THIS_INLINE (fndecl) = 1;
  
Index: decl2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl2.c,v
retrieving revision 1.161
diff -c -p -r1.161 decl2.c
*** decl2.c	1998/12/02 10:12:18	1.161
--- decl2.c	1998/12/04 19:10:07
*************** grokfield (declarator, declspecs, init, 
*** 1642,1659 ****
        && (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == FUNCTION_DECL))
      value = push_template_decl (value);
  
!   /* Check to see if a field redeclares a template parameter. */
!   if (current_template_parms 
!       && TREE_CODE (declarator) == IDENTIFIER_NODE
!       && IDENTIFIER_LOCAL_VALUE (declarator))
!       {
! 	tree olddecl = IDENTIFIER_LOCAL_VALUE (declarator);
! 	if (decl_template_parm_p (olddecl))
! 	  {
! 	    cp_error ("redeclaration of template parameter `%T'", declarator);
! 	    cp_error_at (" previously declared here `%#D'", olddecl);
! 	  }
!       }
  
    if (attrlist)
      cplus_decl_attributes (value, TREE_PURPOSE (attrlist),
--- 1642,1648 ----
        && (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == FUNCTION_DECL))
      value = push_template_decl (value);
  
!   check_template_shadow (value);
  
    if (attrlist)
      cplus_decl_attributes (value, TREE_PURPOSE (attrlist),
Index: error.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/error.c,v
retrieving revision 1.61
diff -c -p -r1.61 error.c
*** error.c	1998/11/17 12:51:01	1.61
--- error.c	1998/12/04 19:10:08
*************** cp_line_of (t)
*** 1849,1855 ****
    int line = 0;
    if (TREE_CODE (t) == PARM_DECL && DECL_CONTEXT (t))
      line = DECL_SOURCE_LINE (DECL_CONTEXT (t));
!   if (TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t))
      t = TREE_TYPE (t);
  
    if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
--- 1849,1856 ----
    int line = 0;
    if (TREE_CODE (t) == PARM_DECL && DECL_CONTEXT (t))
      line = DECL_SOURCE_LINE (DECL_CONTEXT (t));
!   if (TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t)
!       && TYPE_MAIN_DECL (TREE_TYPE (t)))
      t = TREE_TYPE (t);
  
    if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
Index: lang-options.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/lang-options.h,v
retrieving revision 1.20
diff -c -p -r1.20 lang-options.h
*** lang-options.h	1998/11/23 03:12:18	1.20
--- lang-options.h	1998/12/04 19:10:08
*************** DEFINE_LANG_NAME ("C++")
*** 63,70 ****
    { "-fno-huge-objects", "" },
    { "-fimplement-inlines", "" },
    { "-fno-implement-inlines", "Export functions even if they can be inlined" },
!   { "-fimplicit-templates", "Emit implicit template instatiations when used" },
!   { "-fno-implicit-templates", "" },
    { "-finit-priority", "Handle the init_priority attribute" },
    { "-fno-init-priority", "" },
    { "-flabels-ok", "Labels can be used as first class objects" },
--- 63,72 ----
    { "-fno-huge-objects", "" },
    { "-fimplement-inlines", "" },
    { "-fno-implement-inlines", "Export functions even if they can be inlined" },
!   { "-fimplicit-templates", "" },
!   { "-fno-implicit-templates", "Only emit explicit template instatiations" },
!   { "-fimplicit-inline-templates", "" },
!   { "-fno-implicit-inline-templates", "Only emit explicit instatiations of inline templates" },
    { "-finit-priority", "Handle the init_priority attribute" },
    { "-fno-init-priority", "" },
    { "-flabels-ok", "Labels can be used as first class objects" },
Index: parse.y
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/parse.y,v
retrieving revision 1.104
diff -c -p -r1.104 parse.y
*** parse.y	1998/11/23 03:16:06	1.104
--- parse.y	1998/12/04 19:10:09
*************** apparent_template_type:
*** 913,922 ****
  	  template_type
  	| identifier '<' template_arg_list_opt '>'
  	    .finish_template_type
! 		{
! 		  cp_error ("template class %T was not declared yet", $1);
! 		  $$ = $5;
! 		}
  
  self_template_type:
  	  SELFNAME  '<' template_arg_list_opt template_close_bracket
--- 913,919 ----
  	  template_type
  	| identifier '<' template_arg_list_opt '>'
  	    .finish_template_type
! 		{ $$ = $5; }
  
  self_template_type:
  	  SELFNAME  '<' template_arg_list_opt template_close_bracket
Index: pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.242
diff -c -p -r1.242 pt.c
*** pt.c	1998/11/29 15:30:30	1.242
--- pt.c	1998/12/04 19:10:10
*************** check_explicit_specialization (declarato
*** 1206,1211 ****
--- 1206,1213 ----
  	      ("default argument specified in explicit specialization");
  	    break;
  	  }
+       if (current_lang_name == lang_name_c)
+ 	cp_error ("template specialization with C linkage");
      }
  
    if (specialization || member_specialization || explicit_instantiation)
*************** int decl_template_parm_p (old_decl)
*** 1513,1520 ****
    return 0;
  }
  
  
!  /* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
     ORIG_LEVEL, DECL, and TYPE.  */
  
  static tree
--- 1515,1547 ----
    return 0;
  }
  
+ /* Complain if DECL shadows a template parameter.
+ 
+    [temp.local]: A template-parameter shall not be redeclared within its
+    scope (including nested scopes).  */
+ 
+ void
+ check_template_shadow (decl)
+      tree decl;
+ {
+   if (current_template_parms 
+       && IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl)))
+     {
+       tree olddecl = IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl));
+ 
+       /* We check for decl != olddecl to avoid bogus errors for using a
+ 	 name inside a class.  We check TPFI to avoid duplicate errors for
+ 	 inline member templates.  */
+       if (decl != olddecl && decl_template_parm_p (olddecl)
+ 	  && ! TEMPLATE_PARMS_FOR_INLINE (current_template_parms))
+ 	{
+ 	  cp_error_at ("declaration of `%#D'", decl);
+ 	  cp_error_at (" shadows template parm `%#D'", olddecl);
+ 	}
+     }
+ }
  
! /* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
     ORIG_LEVEL, DECL, and TYPE.  */
  
  static tree
*************** convert_nontype_argument (type, expr)
*** 2471,2492 ****
         Check this first since if expr_type is the unknown_type_node
         we would otherwise complain below.  */
      ;
!   else if (INTEGRAL_TYPE_P (expr_type) 
! 	   || TYPE_PTRMEM_P (expr_type) 
! 	   || TYPE_PTRMEMFUNC_P (expr_type)
! 	   /* The next two are g++ extensions.  */
! 	   || TREE_CODE (expr_type) == REAL_TYPE
! 	   || TREE_CODE (expr_type) == COMPLEX_TYPE)
!     {
!       if (! TREE_CONSTANT (expr))
! 	{
! 	non_constant:
! 	  cp_error ("non-constant `%E' cannot be used as template argument",
! 		    expr);
! 	  return NULL_TREE;
! 	}
!     }
!   else if (TYPE_PTR_P (expr_type) 
  	   /* If expr is the address of an overloaded function, we
  	      will get the unknown_type_node at this point.  */
  	   || expr_type == unknown_type_node)
--- 2498,2506 ----
         Check this first since if expr_type is the unknown_type_node
         we would otherwise complain below.  */
      ;
!   else if (TYPE_PTR_P (expr_type)
! 	   || TREE_CODE (expr_type) == ARRAY_TYPE
! 	   || TREE_CODE (type) == REFERENCE_TYPE
  	   /* If expr is the address of an overloaded function, we
  	      will get the unknown_type_node at this point.  */
  	   || expr_type == unknown_type_node)
*************** convert_nontype_argument (type, expr)
*** 2495,2515 ****
        tree e = expr;
        STRIP_NOPS (e);
  
!       if (TREE_CODE (e) != ADDR_EXPR)
  	{
! 	bad_argument:
! 	  cp_error ("`%E' is not a valid template argument", expr);
! 	  error ("it must be %s%s with external linkage",
! 		 TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE
! 		 ? "a pointer to " : "",
! 		 TREE_CODE (TREE_TYPE (TREE_TYPE (expr))) == FUNCTION_TYPE
! 		 ? "a function" : "an object");
! 	  return NULL_TREE;
  	}
  
-       referent = TREE_OPERAND (e, 0);
-       STRIP_NOPS (referent);
-       
        if (TREE_CODE (referent) == STRING_CST)
  	{
  	  cp_error ("string literal %E is not a valid template argument", 
--- 2509,2535 ----
        tree e = expr;
        STRIP_NOPS (e);
  
!       if (TREE_CODE (type) == REFERENCE_TYPE
! 	  || TREE_CODE (expr_type) == ARRAY_TYPE)
! 	referent = e;
!       else
  	{
! 	  if (TREE_CODE (e) != ADDR_EXPR)
! 	    {
! 	    bad_argument:
! 	      cp_error ("`%E' is not a valid template argument", expr);
! 	      error ("it must be %s%s with external linkage",
! 		     TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE
! 		     ? "a pointer to " : "",
! 		     TREE_CODE (TREE_TYPE (TREE_TYPE (expr))) == FUNCTION_TYPE
! 		     ? "a function" : "an object");
! 	      return NULL_TREE;
! 	    }
! 
! 	  referent = TREE_OPERAND (e, 0);
! 	  STRIP_NOPS (referent);
  	}
  
        if (TREE_CODE (referent) == STRING_CST)
  	{
  	  cp_error ("string literal %E is not a valid template argument", 
*************** convert_nontype_argument (type, expr)
*** 2529,2538 ****
  	  return error_mark_node;
  	}
      }
!   else if (TREE_CODE (expr) == VAR_DECL)
      {
!       if (!TREE_PUBLIC (expr))
! 	goto bad_argument;
      }
    else 
      {
--- 2549,2568 ----
  	  return error_mark_node;
  	}
      }
!   else if (INTEGRAL_TYPE_P (expr_type) 
! 	   || TYPE_PTRMEM_P (expr_type) 
! 	   || TYPE_PTRMEMFUNC_P (expr_type)
! 	   /* The next two are g++ extensions.  */
! 	   || TREE_CODE (expr_type) == REAL_TYPE
! 	   || TREE_CODE (expr_type) == COMPLEX_TYPE)
      {
!       if (! TREE_CONSTANT (expr))
! 	{
! 	non_constant:
! 	  cp_error ("non-constant `%E' cannot be used as template argument",
! 		    expr);
! 	  return NULL_TREE;
! 	}
      }
    else 
      {
*************** convert_nontype_argument (type, expr)
*** 2556,2562 ****
        expr = digest_init (type, expr, (tree*) 0);
  
        if (TREE_CODE (expr) != INTEGER_CST)
! 	/* Curiously, some TREE_CONSTNAT integral expressions do not
  	   simplify to integer constants.  For example, `3 % 0',
  	   remains a TRUNC_MOD_EXPR.  */
  	goto non_constant;
--- 2586,2592 ----
        expr = digest_init (type, expr, (tree*) 0);
  
        if (TREE_CODE (expr) != INTEGER_CST)
! 	/* Curiously, some TREE_CONSTANT integral expressions do not
  	   simplify to integer constants.  For example, `3 % 0',
  	   remains a TRUNC_MOD_EXPR.  */
  	goto non_constant;
*************** lookup_template_class (d1, arglist, in_d
*** 3415,3424 ****
      }
    else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1)))
      {
!       if (CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (d1)) == NULL_TREE)
! 	return error_mark_node;
!       template = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (d1));
!       d1 = DECL_NAME (template);
      }
    else if (TREE_CODE (d1) == ENUMERAL_TYPE 
  	   || (TREE_CODE_CLASS (TREE_CODE (d1)) == 't' 
--- 3445,3455 ----
      }
    else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1)))
      {
!       if (CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (d1)))
! 	{
! 	  template = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (d1));
! 	  d1 = DECL_NAME (template);
! 	}
      }
    else if (TREE_CODE (d1) == ENUMERAL_TYPE 
  	   || (TREE_CODE_CLASS (TREE_CODE (d1)) == 't' 
*************** lookup_template_class (d1, arglist, in_d
*** 3442,3448 ****
       We don't want to do that, but we have to deal with the situation, so
       let's give them some syntax errors to chew on instead of a crash.  */
    if (! template)
!     return error_mark_node;
  
    if (context == NULL_TREE)
      context = global_namespace;
--- 3473,3482 ----
       We don't want to do that, but we have to deal with the situation, so
       let's give them some syntax errors to chew on instead of a crash.  */
    if (! template)
!     {
!       cp_error ("`%T' is not a template", d1);
!       return error_mark_node;
!     }
  
    if (context == NULL_TREE)
      context = global_namespace;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]