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++ PATCH to fix --enable-checking problems



This patch fixes most of the problems revealed by running the C++
testsuite with --enable-checking.  We had an overactive check or two,
a bunch of cases where errors lead to subsequent crashes, and a few
cases where non-erroneous programs could lead to bizarre behavior.

Once again, kudos are due to the folks who implemented the
tree-checking.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

2000-01-12  Mark Mitchell  <mark@codesourcery.com>

	* call.c (convert_class_to_reference): Fix typos.
	(build_conditional_expr): Handle errors gracefully.
	* class.c (push_nested_class): Likewise.
	* cp-tree.h (VAR_FUNCTION_OR_PARM_DECL_CHECK): New macro.
	(DECL_THIS_EXTERN): Use it.
	(DECL_THIS_STATIC): Likewise.
	* cvt.c (convert_to_void): Handle errors gracefully.
	(build_expr_type_conversion): Likewise.
	* decl.c (maybe_push_decl): Likewise.
	(start_decl_1): Likewise.
	(require_complete_types_for_parms): Likewise.
	* parse.y (structsp): Likewise.
	(base_class): Likewise.
	* parse.c: Regenerated.
	* pt.c (finish_member_template_decl): Likewise.

Index: call.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/call.c,v
retrieving revision 1.185
diff -c -p -r1.185 call.c
*** call.c	2000/01/01 13:29:44	1.185
--- call.c	2000/01/12 23:19:57
*************** convert_class_to_reference (t, s, expr)
*** 928,937 ****
    if (!cand)
      return NULL_TREE;
  
!   conv = build_conv (IDENTITY_CONV, s, expr);
    conv = build_conv (USER_CONV,
  		     non_reference (TREE_TYPE (TREE_TYPE (cand->fn))),
! 		     expr);
    TREE_OPERAND (conv, 1) = build_expr_ptr_wrapper (cand);
    ICS_USER_FLAG (conv) = 1;
    if (cand->viable == -1)
--- 928,937 ----
    if (!cand)
      return NULL_TREE;
  
!   conv = build1 (IDENTITY_CONV, s, expr);
    conv = build_conv (USER_CONV,
  		     non_reference (TREE_TYPE (TREE_TYPE (cand->fn))),
! 		     conv);
    TREE_OPERAND (conv, 1) = build_expr_ptr_wrapper (cand);
    ICS_USER_FLAG (conv) = 1;
    if (cand->viable == -1)
*************** build_conditional_expr (arg1, arg2, arg3
*** 2770,2775 ****
--- 2770,2781 ----
        arg1 = arg2 = save_expr (arg1);
      }
  
+   /* [expr.cond]
+   
+      The first expr ession is implicitly converted to bool (clause
+      _conv_).  */
+   arg1 = cp_convert (boolean_type_node, arg1);
+ 
    /* If something has already gone wrong, just pass that fact up the
       tree.  */
    if (arg1 == error_mark_node 
*************** build_conditional_expr (arg1, arg2, arg3
*** 2779,2790 ****
        || TREE_TYPE (arg2) == error_mark_node
        || TREE_TYPE (arg3) == error_mark_node)
      return error_mark_node;
- 
-   /* [expr.cond]
-   
-      The first expr ession is implicitly converted to bool (clause
-      _conv_).  */
-   arg1 = cp_convert (boolean_type_node, arg1);
  
    /* Convert from reference types to ordinary types; no expressions
       really have reference type in C++.  */
--- 2785,2790 ----
Index: class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.230
diff -c -p -r1.230 class.c
*** class.c	2000/01/12 20:56:15	1.230
--- class.c	2000/01/12 23:20:01
*************** push_nested_class (type, modify)
*** 5279,5286 ****
    tree context;
  
    /* A namespace might be passed in error cases, like A::B:C.  */
!   if (type == NULL_TREE || type == error_mark_node || ! IS_AGGR_TYPE (type)
        || TREE_CODE (type) == NAMESPACE_DECL
        || TREE_CODE (type) == TEMPLATE_TYPE_PARM
        || TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
      return;
--- 5279,5288 ----
    tree context;
  
    /* A namespace might be passed in error cases, like A::B:C.  */
!   if (type == NULL_TREE 
!       || type == error_mark_node 
        || TREE_CODE (type) == NAMESPACE_DECL
+       || ! IS_AGGR_TYPE (type)
        || TREE_CODE (type) == TEMPLATE_TYPE_PARM
        || TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
      return;
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.382
diff -c -p -r1.382 cp-tree.h
*** cp-tree.h	2000/01/12 20:56:15	1.382
--- cp-tree.h	2000/01/12 23:20:04
*************** Boston, MA 02111-1307, USA.  */
*** 140,145 ****
--- 140,155 ----
  			 __LINE__, __PRETTY_FUNCTION__);	\
      __t; })
  
+ #define VAR_FUNCTION_OR_PARM_DECL_CHECK(NODE)			\
+ ({  const tree __t = NODE;					\
+     enum tree_code __c = TREE_CODE(__t);			\
+     if (__c != VAR_DECL 					\
+ 	&& __c != FUNCTION_DECL 				\
+         && __c != PARM_DECL)					\
+       tree_check_failed (__t, VAR_DECL, __FILE__,		\
+ 			 __LINE__, __PRETTY_FUNCTION__);	\
+     __t; })
+ 
  #define VAR_TEMPL_TYPE_OR_FUNCTION_DECL_CHECK(NODE)		\
  ({  const tree __t = NODE;					\
      enum tree_code __c = TREE_CODE(__t);			\
*************** Boston, MA 02111-1307, USA.  */
*** 162,167 ****
--- 172,178 ----
  #else /* not ENABLE_TREE_CHECKING, or not gcc */
  
  #define VAR_OR_FUNCTION_DECL_CHECK(NODE)	NODE
+ #define VAR_FUNCTION_OR_PARM_DECL_CHECK(NODE)   NODE
  #define VAR_TEMPL_TYPE_OR_FUNCTION_DECL_CHECK(NODE)	NODE
  #define RECORD_OR_UNION_TYPE_CHECK(NODE)	NODE
  
*************** extern int flag_new_for_scope;
*** 2380,2393 ****
  #define PTRMEM_CST_MEMBER(NODE) (((ptrmem_cst_t)PTRMEM_CST_CHECK (NODE))->member)
  
  /* Nonzero for VAR_DECL and FUNCTION_DECL node means that `extern' was
!    specified in its declaration.  */
  #define DECL_THIS_EXTERN(NODE) \
!   DECL_LANG_FLAG_2 (VAR_OR_FUNCTION_DECL_CHECK (NODE))
  
  /* Nonzero for VAR_DECL and FUNCTION_DECL node means that `static' was
!    specified in its declaration.  */
  #define DECL_THIS_STATIC(NODE) \
!   DECL_LANG_FLAG_6 (VAR_OR_FUNCTION_DECL_CHECK (NODE))
  
  /* Nonzero in FUNCTION_DECL means it is really an operator.
     Just used to communicate formatting information to dbxout.c.  */
--- 2391,2406 ----
  #define PTRMEM_CST_MEMBER(NODE) (((ptrmem_cst_t)PTRMEM_CST_CHECK (NODE))->member)
  
  /* Nonzero for VAR_DECL and FUNCTION_DECL node means that `extern' was
!    specified in its declaration.  This can also be set for an
!    erroneously declared PARM_DECL.  */
  #define DECL_THIS_EXTERN(NODE) \
!   DECL_LANG_FLAG_2 (VAR_FUNCTION_OR_PARM_DECL_CHECK (NODE))
  
  /* Nonzero for VAR_DECL and FUNCTION_DECL node means that `static' was
!    specified in its declaration.  This can also be set for an
!    erroneously declared PARM_DECL.  */
  #define DECL_THIS_STATIC(NODE) \
!   DECL_LANG_FLAG_6 (VAR_FUNCTION_OR_PARM_DECL_CHECK (NODE))
  
  /* Nonzero in FUNCTION_DECL means it is really an operator.
     Just used to communicate formatting information to dbxout.c.  */
Index: cvt.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cvt.c,v
retrieving revision 1.71
diff -c -p -r1.71 cvt.c
*** cvt.c	1999/11/14 20:29:02	1.71
--- cvt.c	2000/01/12 23:20:04
***************
*** 1,5 ****
  /* Language-level data type conversion for GNU C++.
!    Copyright (C) 1987-1988, 1992-1999 Free Software Foundation, Inc.
     Hacked by Michael Tiemann (tiemann@cygnus.com)
  
  This file is part of GNU CC.
--- 1,5 ----
  /* Language-level data type conversion for GNU C++.
!    Copyright (C) 1987-1988, 1992-2000 Free Software Foundation, Inc.
     Hacked by Michael Tiemann (tiemann@cygnus.com)
  
  This file is part of GNU CC.
*************** convert_to_void (expr, implicit)
*** 851,858 ****
       tree expr;
       const char *implicit;
  {
!   if (expr == error_mark_node)
!     return expr;
    if (!TREE_TYPE (expr))
      return expr;
    if (same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (expr)), void_type_node))
--- 851,859 ----
       tree expr;
       const char *implicit;
  {
!   if (expr == error_mark_node 
!       || TREE_TYPE (expr) == error_mark_node)
!     return error_mark_node;
    if (!TREE_TYPE (expr))
      return expr;
    if (same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (expr)), void_type_node))
*************** build_expr_type_conversion (desires, exp
*** 1091,1096 ****
--- 1092,1100 ----
      expr = resolve_offset_ref (expr);
    expr = convert_from_reference (expr);
    basetype = TREE_TYPE (expr);
+ 
+   if (basetype == error_mark_node)
+     return error_mark_node;
  
    if (! IS_AGGR_TYPE (basetype))
      switch (TREE_CODE (basetype))
Index: decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.529
diff -c -p -r1.529 decl.c
*** decl.c	2000/01/03 21:33:10	1.529
--- decl.c	2000/01/12 23:20:14
***************
*** 1,5 ****
  /* Process declarations and variables for C compiler.
!    Copyright (C) 1988, 92-98, 1999 Free Software Foundation, Inc.
     Contributed by Michael Tiemann (tiemann@cygnus.com)
  
  This file is part of GNU CC.
--- 1,5 ----
  /* Process declarations and variables for C compiler.
!    Copyright (C) 1988, 92-98, 1999, 2000 Free Software Foundation, Inc.
     Contributed by Michael Tiemann (tiemann@cygnus.com)
  
  This file is part of GNU CC.
*************** maybe_push_decl (decl)
*** 4169,4179 ****
    /* Add this decl to the current binding level, but not if it comes
       from another scope, e.g. a static member variable.  TEM may equal
       DECL or it may be a previous decl of the same name.  */
!   if ((TREE_CODE (decl) != PARM_DECL
!        && DECL_CONTEXT (decl) != NULL_TREE
!        /* Definitions of namespace members outside their namespace are
! 	  possible. */
!        && TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL)
        || (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ())
        || TREE_CODE (type) == UNKNOWN_TYPE
        /* The declaration of a template specialization does not affect
--- 4169,4180 ----
    /* Add this decl to the current binding level, but not if it comes
       from another scope, e.g. a static member variable.  TEM may equal
       DECL or it may be a previous decl of the same name.  */
!   if (decl == error_mark_node
!       || (TREE_CODE (decl) != PARM_DECL
! 	  && DECL_CONTEXT (decl) != NULL_TREE
! 	  /* Definitions of namespace members outside their namespace are
! 	     possible. */
! 	  && TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL)
        || (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ())
        || TREE_CODE (type) == UNKNOWN_TYPE
        /* The declaration of a template specialization does not affect
*************** start_decl_1 (decl)
*** 6871,6877 ****
    if (!initialized
        && TREE_CODE (decl) != TYPE_DECL
        && TREE_CODE (decl) != TEMPLATE_DECL
!       && IS_AGGR_TYPE (type) && ! DECL_EXTERNAL (decl))
      {
        if ((! processing_template_decl || ! uses_template_parms (type))
  	  && TYPE_SIZE (complete_type (type)) == NULL_TREE)
--- 6872,6880 ----
    if (!initialized
        && TREE_CODE (decl) != TYPE_DECL
        && TREE_CODE (decl) != TEMPLATE_DECL
!       && type != error_mark_node
!       && IS_AGGR_TYPE (type) 
!       && ! DECL_EXTERNAL (decl))
      {
        if ((! processing_template_decl || ! uses_template_parms (type))
  	  && TYPE_SIZE (complete_type (type)) == NULL_TREE)
*************** static void
*** 11309,11318 ****
  require_complete_types_for_parms (parms)
       tree parms;
  {
!   while (parms)
      {
        tree type = TREE_TYPE (parms);
!       if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
  	{
  	  if (DECL_NAME (parms))
  	    error ("parameter `%s' has incomplete type",
--- 11312,11328 ----
  require_complete_types_for_parms (parms)
       tree parms;
  {
!   for (; parms; parms = TREE_CHAIN (parms))
      {
        tree type = TREE_TYPE (parms);
! 
!       /* Try to complete the TYPE.  */
!       type = complete_type (type);
! 
!       if (type == error_mark_node)
! 	continue;
! 
!       if (TYPE_SIZE (type) == NULL_TREE)
  	{
  	  if (DECL_NAME (parms))
  	    error ("parameter `%s' has incomplete type",
*************** require_complete_types_for_parms (parms)
*** 11323,11330 ****
  	}
        else
  	layout_decl (parms, 0);
- 
-       parms = TREE_CHAIN (parms);
      }
  }
  
--- 11333,11338 ----
Index: parse.y
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/parse.y,v
retrieving revision 1.156
diff -c -p -r1.156 parse.y
*** parse.y	1999/11/16 03:42:26	1.156
--- parse.y	2000/01/12 23:20:26
***************
*** 1,5 ****
  /* YACC parser for C++ syntax.
!    Copyright (C) 1988, 89, 93-98, 1999 Free Software Foundation, Inc.
     Hacked by Michael Tiemann (tiemann@cygnus.com)
  
  This file is part of GNU CC.
--- 1,5 ----
  /* YACC parser for C++ syntax.
!    Copyright (C) 1988, 89, 93-98, 1999, 2000 Free Software Foundation, Inc.
     Hacked by Michael Tiemann (tiemann@cygnus.com)
  
  This file is part of GNU CC.
*************** structsp:
*** 2124,2130 ****
  		    {
  		      $$.t = $1.t;
  		      /* struct B: public A; is not accepted by the WP grammar.  */
! 		      if (TYPE_BINFO_BASETYPES ($$.t) && !TYPE_SIZE ($$.t)
  			  && ! TYPE_BEING_DEFINED ($$.t))
  			cp_error ("base clause without member specification for `%#T'",
  				  $$.t);
--- 2124,2132 ----
  		    {
  		      $$.t = $1.t;
  		      /* struct B: public A; is not accepted by the WP grammar.  */
! 		      if (CLASS_TYPE_P ($$.t)
! 			  && TYPE_BINFO_BASETYPES ($$.t) 
! 			  && !TYPE_SIZE ($$.t)
  			  && ! TYPE_BEING_DEFINED ($$.t))
  			cp_error ("base clause without member specification for `%#T'",
  				  $$.t);
*************** base_class:
*** 2298,2304 ****
  
  base_class.1:
  	  typename_sub
! 		{ if ($$ != error_mark_node) $$ = TYPE_MAIN_DECL ($1); }
  	| nonnested_type
  	;
  
--- 2300,2311 ----
  
  base_class.1:
  	  typename_sub
! 		{ if ($$ == error_mark_node)
! 		    ;
!                   else if (!TYPE_P ($$))
! 		    $$ = error_mark_node;
! 		  else 
! 		    $$ = TYPE_MAIN_DECL ($1); }
  	| nonnested_type
  	;
  
Index: pt.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/pt.c,v
retrieving revision 1.390
diff -c -p -r1.390 pt.c
*** pt.c	2000/01/07 07:06:59	1.390
--- pt.c	2000/01/12 23:20:33
***************
*** 1,5 ****
  /* Handle parameterized types (templates) for GNU C++.
!    Copyright (C) 1992, 93-97, 1998, 1999 Free Software Foundation, Inc.
     Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
     Rewritten by Jason Merrill (jason@cygnus.com).
  
--- 1,5 ----
  /* Handle parameterized types (templates) for GNU C++.
!    Copyright (C) 1992, 93-97, 1998, 1999, 2000 Free Software Foundation, Inc.
     Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
     Rewritten by Jason Merrill (jason@cygnus.com).
  
*************** finish_member_template_decl (decl)
*** 197,202 ****
--- 197,204 ----
  	}
        return NULL_TREE;
      }
+   else if (TREE_CODE (decl) == FIELD_DECL)
+     cp_error ("data member `%D' cannot be a member template", decl);
    else if (DECL_TEMPLATE_INFO (decl))
      {
        if (!DECL_TEMPLATE_SPECIALIZATION (decl))
*************** tsubst (t, args, complain, in_decl)
*** 6214,6220 ****
  	    if (pedantic)
  	      pedwarn ("creating array with size zero");
  	  }
! 	else if (integer_zerop (max) || INT_CST_LT (max, integer_zero_node))
  	  {
  	    /* [temp.deduct]
  
--- 6216,6224 ----
  	    if (pedantic)
  	      pedwarn ("creating array with size zero");
  	  }
! 	else if (integer_zerop (max) 
! 		 || (TREE_CODE (max) == INTEGER_CST 
! 		     && INT_CST_LT (max, integer_zero_node)))
  	  {
  	    /* [temp.deduct]
  
Index: typeck.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/typeck.c,v
retrieving revision 1.234
diff -c -p -r1.234 typeck.c
*** typeck.c	2000/01/05 10:10:53	1.234
--- typeck.c	2000/01/12 23:20:39
*************** decay_conversion (exp)
*** 1705,1710 ****
--- 1705,1713 ----
        code = TREE_CODE (type);
      }
  
+   if (type == error_mark_node)
+     return error_mark_node;
+ 
    /* Constants can be used directly unless they're not loadable.  */
    if (TREE_CODE (exp) == CONST_DECL)
      exp = DECL_INITIAL (exp);

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