Checker support refinements, bugfixes, test cases

Ken Raeburn raeburn@cygnus.com
Fri Oct 2 18:45:00 GMT 1998


For your approval:

These patches and files are combined from three I sent in for gcc2,
plus some new stuff.  But after six weeks of waiting (since I sent the
first patch), I'm giving up and submitting here also, rather than
hoping it'd get in via a gcc2 merge any time soon.

The changes are, briefly:

 * function-level control over -fcheck-memory-usage instrumentation
   with an attribute
 * bugfix: create symbols with Pmode, not VOIDmode (avoids crash on
   powerpc target)
 * bugfix: do check static VAR_DECL nodes, in case no memory
   management available, bad memcpy clobbers storage, etc
 * bugfix: don't abort dealing with BLKmode function arguments
   constructed on the stack (crashes for MIPS and Alpha targets,
   probably all others, with GNU C constructor syntax)
 * 10 C test cases for -fcheck-memory-usage (multiplied by
   optimization and multilib options), including one with BLKmode etc,
   in a new subdirectory of gcc.c-torture/execute

Currently, on alpha-linux, one of the test cases does fail (the
BLKmode one, which just aborted in the compiler before), when function
inlining is enabled.  One out of 120 isn't bad, when we weren't even
testing it before....

(Jim Wilson, I think you've seen all of this before, except for the
BLKmode bits; see gcc/17622.  Tristan Gingold, I don't remember if
I've sent you the test cases before, but I think you've seen the rest,
with the patch earlier today.)

Ken


Fri Oct  2 20:28:23 1998  Ken Raeburn  <raeburn@cygnus.com>

	* tree.h (DECL_NO_CHECK_MEMORY_USAGE): New macros.
	(struct tree_decl): New fields no_check_memory_usage.
	* c-common.c (enum attrs): Add A_NO_CHECK_MEMORY_USAGE.
	(init_attributes): Register it as a new attribute.
	(decl_attributes): Set flags on functions given that attribute.
	* c-decl.c (duplicate_decls): Merge new attribute.
	* expr.h (current_function_check_memory_usage): Declare new var.
	* calls.c, expr.c, function.c, stmt.c, alpha.c, clipper.c, m88k.c,
	pa.c, sparc.c: Replace uses of flag_check_memory_usage with
	current_function_check_memory_usage.
	* function.h: Add field to struct function.
	* function.c (current_function_check_memory_usage): Define it.
	(push_function_context_to, pop_function_context_from): Save and
	restore it.
	(expand_function_start): Set it, based on global flag and function
	attribute.

	* expr.c (expand_expr, case VAR_DECL): In memory-checking code, do
	check non-automatic variables, to permit detection of writes to
	read-only locations in embedded systems without memory management.
	* calls.c (store_one_arg): Use ARGS_SIZE_RTX to get size of argument
	when emitting chkr_set_right_libfunc call, even if the argument is
	BLKmode or variable-sized; don't abort.

	* optabs.c (init_optabs): Create Checker and __cyg_profile_*
	symbols in Pmode, not VOIDmode.

1998-10-02  Ken Raeburn  <raeburn@cygnus.com>

	* execute/memcheck: New directory of tests for
	-fcheck-memory-usage.

Index: c-common.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/c-common.c,v
retrieving revision 1.35
diff -p -u -r1.35 c-common.c
--- c-common.c	1998/10/01 10:50:08	1.35
+++ c-common.c	1998/10/03 01:30:02
@@ -51,7 +51,7 @@ extern struct obstack permanent_obstack;
 int skip_evaluation;
 
 enum attrs {A_PACKED, A_NOCOMMON, A_COMMON, A_NORETURN, A_CONST, A_T_UNION,
-	    A_NO_INSTRUMENT_FUNCTION,
+	    A_NO_CHECK_MEMORY_USAGE, A_NO_INSTRUMENT_FUNCTION,
 	    A_CONSTRUCTOR, A_DESTRUCTOR, A_MODE, A_SECTION, A_ALIGNED,
 	    A_UNUSED, A_FORMAT, A_FORMAT_ARG, A_WEAK, A_ALIAS,
 	    A_INIT_PRIORITY};
@@ -394,6 +394,7 @@ init_attributes ()
   add_attribute (A_ALIAS, "alias", 1, 1, 1);
   add_attribute (A_INIT_PRIORITY, "init_priority", 0, 1, 0);
   add_attribute (A_NO_INSTRUMENT_FUNCTION, "no_instrument_function", 0, 0, 1);
+  add_attribute (A_NO_CHECK_MEMORY_USAGE, "no_check_memory_usage", 0, 0, 1);
 }
 
 /* Process the attributes listed in ATTRIBUTES and PREFIX_ATTRIBUTES
@@ -887,6 +888,23 @@ decl_attributes (node, attributes, prefi
 	    }
 	  else
 	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+	  break;
+
+	case A_NO_CHECK_MEMORY_USAGE:
+	  if (TREE_CODE (decl) != FUNCTION_DECL)
+	    {
+	      error_with_decl (decl,
+			       "`%s' attribute applies only to functions",
+			       IDENTIFIER_POINTER (name));
+	    }
+	  else if (DECL_INITIAL (decl))
+	    {
+	      error_with_decl (decl,
+			       "can't set `%s' attribute after definition",
+			       IDENTIFIER_POINTER (name));
+	    }
+	  else
+	    DECL_NO_CHECK_MEMORY_USAGE (decl) = 1;
 	  break;
 
 	case A_INIT_PRIORITY:
Index: c-decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/c-decl.c,v
retrieving revision 1.46
diff -p -u -r1.46 c-decl.c
--- c-decl.c	1998/10/01 10:43:19	1.46
+++ c-decl.c	1998/10/03 01:30:06
@@ -1934,6 +1934,8 @@ duplicate_decls (newdecl, olddecl, diffe
 
 	  DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
 	    |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
+	  DECL_NO_CHECK_MEMORY_USAGE (newdecl)
+	    |= DECL_NO_CHECK_MEMORY_USAGE (olddecl);
 	}
 
       pop_obstacks ();
Index: calls.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/calls.c,v
retrieving revision 1.28
diff -p -u -r1.28 calls.c
--- calls.c	1998/10/01 13:00:16	1.28
+++ calls.c	1998/10/03 01:30:07
@@ -595,7 +595,7 @@ expand_call (exp, target, ignore)
      if -fcheck-memory-usage, code which invokes functions (and thus
      damages some hard registers) can be inserted before using the value.
      So, target is always a pseudo-register in that case.  */
-  if (flag_check_memory_usage)
+  if (current_function_check_memory_usage)
     target = 0;
 
   /* See if we can find a DECL-node for the actual function.
@@ -1625,7 +1625,7 @@ expand_call (exp, target, ignore)
       pop_temp_slots ();	/* FUNEXP can't be BLKmode */
 
       /* Check the function is executable.  */
-      if (flag_check_memory_usage)
+      if (current_function_check_memory_usage)
 	emit_library_call (chkr_check_exec_libfunc, 1,
 			   VOIDmode, 1,
 			   funexp, ptr_mode);
@@ -1864,7 +1864,7 @@ expand_call (exp, target, ignore)
 						NULL_RTX)));
 
       /* Mark the memory for the aggregate as write-only.  */
-      if (flag_check_memory_usage)
+      if (current_function_check_memory_usage)
 	emit_library_call (chkr_set_right_libfunc, 1,
 			   VOIDmode, 3,
 			   structure_value_addr, ptr_mode, 
@@ -3508,15 +3508,13 @@ store_one_arg (arg, argblock, may_be_all
 
   if (arg->value == arg->stack)
     {
-      /* If the value is already in the stack slot, we are done.  */
-      if (flag_check_memory_usage && GET_CODE (arg->stack) == MEM)
+      /* If the value is already in the stack slot, we are done moving
+	 data.  */
+      if (current_function_check_memory_usage && GET_CODE (arg->stack) == MEM)
 	{
-	  if (arg->mode == BLKmode)
-	    abort ();
-
 	  emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
 			     XEXP (arg->stack, 0), ptr_mode, 
-			     GEN_INT (GET_MODE_SIZE (arg->mode)),
+			     ARGS_SIZE_RTX (arg->size),
 			     TYPE_MODE (sizetype),
 			     GEN_INT (MEMORY_USE_RW),
 			     TYPE_MODE (integer_type_node));
Index: expr.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/expr.c,v
retrieving revision 1.100
diff -p -u -r1.100 expr.c
--- expr.c	1998/10/01 13:00:18	1.100
+++ expr.c	1998/10/03 01:30:10
@@ -110,8 +110,8 @@ static rtx apply_args_value;
 static int can_handle_constant_p;
 
 /* Don't check memory usage, since code is being emitted to check a memory
-   usage.  Used when flag_check_memory_usage is true, to avoid infinite
-   recursion.  */
+   usage.  Used when current_function_check_memory_usage is true, to avoid
+   infinite recursion.  */
 static int in_check_memory_usage;
 
 /* This structure is used by move_by_pieces to describe the move to
@@ -2846,7 +2846,7 @@ emit_push_insn (x, mode, type, size, ali
 	  move_by_pieces (gen_rtx_MEM (BLKmode, gen_push_operand ()), xinner,
 			  INTVAL (size) - used, align);
 
-	  if (flag_check_memory_usage && ! in_check_memory_usage)
+	  if (current_function_check_memory_usage && ! in_check_memory_usage)
 	    {
 	      rtx temp;
 	      
@@ -2903,7 +2903,7 @@ emit_push_insn (x, mode, type, size, ali
 								args_addr,
 								args_so_far),
 						  skip));
-	  if (flag_check_memory_usage && ! in_check_memory_usage)
+	  if (current_function_check_memory_usage && ! in_check_memory_usage)
 	    {
 	      rtx target;
 	      
@@ -3103,7 +3103,7 @@ emit_push_insn (x, mode, type, size, ali
 
       emit_move_insn (gen_rtx_MEM (mode, addr), x);
 
-      if (flag_check_memory_usage && ! in_check_memory_usage)
+      if (current_function_check_memory_usage && ! in_check_memory_usage)
 	{
 	  in_check_memory_usage = 1;
 	  if (target == 0)
@@ -3271,7 +3271,7 @@ expand_assignment (to, from, want_value,
 	}
 
       /* Check the access.  */
-      if (flag_check_memory_usage && GET_CODE (to_rtx) == MEM)
+      if (current_function_check_memory_usage && GET_CODE (to_rtx) == MEM)
 	{
 	  rtx to_addr;
 	  int size;
@@ -3397,7 +3397,7 @@ expand_assignment (to, from, want_value,
 			      EXPAND_MEMORY_USE_DONT);
 
       /* Copy the rights of the bitmap.  */
-      if (flag_check_memory_usage)
+      if (current_function_check_memory_usage)
 	emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
 			   XEXP (to_rtx, 0), ptr_mode,
 			   XEXP (from_rtx, 0), ptr_mode,
@@ -3619,7 +3619,7 @@ store_expr (exp, target, want_value)
     temp = convert_modes (GET_MODE (target), TYPE_MODE (TREE_TYPE (exp)),
 			  temp, TREE_UNSIGNED (TREE_TYPE (exp)));
 
-  if (flag_check_memory_usage
+  if (current_function_check_memory_usage
       && GET_CODE (target) == MEM
       && AGGREGATE_TYPE_P (TREE_TYPE (exp)))
     {
@@ -3723,7 +3723,7 @@ store_expr (exp, target, want_value)
 	      if (size != const0_rtx)
 		{
 		  /* Be sure we can write on ADDR.  */
-		  if (flag_check_memory_usage)
+		  if (current_function_check_memory_usage)
 		    emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
 				       addr, ptr_mode,
 				       size, TYPE_MODE (sizetype),
@@ -5565,13 +5565,16 @@ expand_expr (exp, target, tmode, modifie
 	  pop_obstacks ();
 	}
 
-      /* Only check automatic variables.  Currently, function arguments are
-         not checked (this can be done at compile-time with prototypes).
-         Aggregates are not checked.  */
-      if (flag_check_memory_usage && code == VAR_DECL
+      /* Although static-storage variables start off initialized, according to
+	 ANSI C, a memcpy could overwrite them with uninitialized values.  So
+	 we check them too.  This also lets us check for read-only variables
+	 accessed via a non-const declaration, in case it won't be detected
+	 any other way (e.g., in an embedded system or OS kernel without
+	 memory protection).
+
+	 Aggregates are not checked here; they're handled elsewhere.  */
+      if (current_function_check_memory_usage && code == VAR_DECL
 	  && GET_CODE (DECL_RTL (exp)) == MEM
-	  && DECL_CONTEXT (exp) != NULL_TREE
-	  && ! TREE_STATIC (exp)
 	  && ! AGGREGATE_TYPE_P (TREE_TYPE (exp)))
 	{
 	  enum memory_use_mode memory_usage;
@@ -6081,7 +6084,7 @@ expand_expr (exp, target, tmode, modifie
 	op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
 	op0 = memory_address (mode, op0);
 
-	if (flag_check_memory_usage && !AGGREGATE_TYPE_P (TREE_TYPE (exp)))
+	if (current_function_check_memory_usage && !AGGREGATE_TYPE_P (TREE_TYPE (exp)))
 	  {
 	    enum memory_use_mode memory_usage;
 	    memory_usage = get_memory_usage_from_modifier (modifier);
@@ -6385,7 +6388,7 @@ expand_expr (exp, target, tmode, modifie
 	  }
 
 	/* Check the access.  */
-	if (flag_check_memory_usage && GET_CODE (op0) == MEM)
+	if (current_function_check_memory_usage && GET_CODE (op0) == MEM)
           {
 	    enum memory_use_mode memory_usage;
 	    memory_usage = get_memory_usage_from_modifier (modifier);
@@ -9137,7 +9140,7 @@ expand_builtin (exp, target, subtarget, 
 	    src_rtx = copy_to_mode_reg (Pmode, src_rtx);
 
 	  /* Check the string is readable and has an end.  */
-	  if (flag_check_memory_usage)
+	  if (current_function_check_memory_usage)
 	    emit_library_call (chkr_check_str_libfunc, 1, VOIDmode, 2,
 			       src_rtx, ptr_mode,
 			       GEN_INT (MEMORY_USE_RO),
@@ -9230,7 +9233,7 @@ expand_builtin (exp, target, subtarget, 
 	  len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
 
 	  /* Just copy the rights of SRC to the rights of DEST.  */
-	  if (flag_check_memory_usage)
+	  if (current_function_check_memory_usage)
 	    emit_library_call (chkr_copy_bitmap_libfunc, 1, VOIDmode, 3,
 			       XEXP (dest_mem, 0), ptr_mode,
 			       XEXP (src_mem, 0), ptr_mode,
@@ -9301,7 +9304,7 @@ expand_builtin (exp, target, subtarget, 
 	  dest_mem = get_memory_rtx (dest);
 	   
 	  /* Just check DST is writable and mark it as readable.  */
-	  if (flag_check_memory_usage)
+	  if (current_function_check_memory_usage)
 	    emit_library_call (chkr_check_addr_libfunc, 1, VOIDmode, 3,
 			       XEXP (dest_mem, 0), ptr_mode,
 			       len_rtx, TYPE_MODE (sizetype),
@@ -9327,7 +9330,7 @@ expand_builtin (exp, target, subtarget, 
 	break;
 
       /* If we need to check memory accesses, call the library function.  */
-      if (flag_check_memory_usage)
+      if (current_function_check_memory_usage)
 	break;
 
       if (arglist == 0
@@ -9383,7 +9386,7 @@ expand_builtin (exp, target, subtarget, 
 	break;
 
       /* If we need to check memory accesses, call the library function.  */
-      if (flag_check_memory_usage)
+      if (current_function_check_memory_usage)
 	break;
 
       if (arglist == 0
@@ -10212,7 +10215,7 @@ expand_increment (exp, post, ignore)
 
   /* Increment however we can.  */
   op1 = expand_binop (mode, this_optab, value, op1,
-  		      flag_check_memory_usage ? NULL_RTX : op0,
+  		      current_function_check_memory_usage ? NULL_RTX : op0,
 		      TREE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN);
   /* Make sure the value is stored into OP0.  */
   if (op1 != op0)
Index: expr.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/expr.h,v
retrieving revision 1.24
diff -p -u -r1.24 expr.h
--- expr.h	1998/10/01 13:00:20	1.24
+++ expr.h	1998/10/03 01:30:10
@@ -91,6 +91,10 @@ extern int current_function_uses_pic_off
 /* The arg pointer hard register, or the pseudo into which it was copied.  */
 extern rtx current_function_internal_arg_pointer;
 
+/* This is nonzero if memory access checking be enabled in the current
+   function.  */
+extern int current_function_check_memory_usage;
+
 /* Nonzero means stack pops must not be deferred, and deferred stack
    pops must not be output.  It is nonzero inside a function call,
    inside a conditional expression, inside a statement expression,
Index: extend.texi
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/extend.texi,v
retrieving revision 1.14
diff -p -u -r1.14 extend.texi
--- extend.texi	1998/08/23 12:47:24	1.14
+++ extend.texi	1998/10/03 01:30:10
@@ -1518,6 +1518,19 @@ mangled name for the target must be used
 
 Not all target machines support this attribute.
 
+@item no_check_memory_usage
+@cindex @code{no_check_memory_usage} function attribute
+If @samp{-fcheck-memory-usage} is given, calls to support routines will
+be generated before most memory accesses, to permit support code to
+record usage and detect uses of uninitialized or unallocated storage.
+Since the compiler cannot handle them properly, @code{asm} statements
+are not allowed.  Declaring a function with this attribute disables the
+memory checking code for that function, permitting the use of @code{asm}
+statements without requiring separate compilation with different
+options, and allowing you to write support routines of your own if you
+wish, without getting infinite recursion if they get compiled with this
+option.
+
 @item regparm (@var{number})
 @cindex functions that are passed arguments in registers on the 386
 On the Intel 386, the @code{regparm} attribute causes the compiler to
Index: function.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/function.c,v
retrieving revision 1.45
diff -p -u -r1.45 function.c
--- function.c	1998/09/30 18:04:51	1.45
+++ function.c	1998/10/03 01:30:11
@@ -221,6 +221,9 @@ char *current_function_cannot_inline;
    generated.  */
 int current_function_instrument_entry_exit;
 
+/* Nonzero if memory access checking be enabled in the current function.  */
+int current_function_check_memory_usage;
+
 /* The FUNCTION_DECL for an inline function currently being expanded.  */
 tree inline_function_decl;
 
@@ -543,6 +546,7 @@ push_function_context_to (context)
   p->fixup_var_refs_queue = 0;
   p->epilogue_delay_list = current_function_epilogue_delay_list;
   p->args_info = current_function_args_info;
+  p->check_memory_usage = current_function_check_memory_usage;
   p->instrument_entry_exit = current_function_instrument_entry_exit;
 
   save_tree_status (p, context);
@@ -626,6 +630,7 @@ pop_function_context_from (context)
   current_function_epilogue_delay_list = p->epilogue_delay_list;
   reg_renumber = 0;
   current_function_args_info = p->args_info;
+  current_function_check_memory_usage = p->check_memory_usage;
   current_function_instrument_entry_exit = p->instrument_entry_exit;
 
   restore_tree_status (p, context);
@@ -1484,7 +1489,7 @@ put_var_into_stack (decl)
   else
     return;
   
-  if (flag_check_memory_usage)
+  if (current_function_check_memory_usage)
     emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
 		       XEXP (reg, 0), ptr_mode,
 		       GEN_INT (GET_MODE_SIZE (GET_MODE (reg))),
@@ -4376,7 +4381,7 @@ assign_parms (fndecl, second_time)
 
 	      store_expr (parm, copy, 0);
 	      emit_move_insn (parmreg, XEXP (copy, 0));
-	      if (flag_check_memory_usage)
+	      if (current_function_check_memory_usage)
 		emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
 				   XEXP (copy, 0), ptr_mode,
 				   GEN_INT (int_size_in_bytes (type)),
@@ -4541,7 +4546,7 @@ assign_parms (fndecl, second_time)
 		emit_move_insn (validize_mem (stack_parm),
 				validize_mem (entry_parm));
 	    }
-	  if (flag_check_memory_usage)
+	  if (current_function_check_memory_usage)
 	    {
 	      push_to_sequence (conversion_insns);
 	      emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
@@ -5561,6 +5566,11 @@ expand_function_start (subr, parms_have_
   /* Make sure volatile mem refs aren't considered
      valid operands of arithmetic insns.  */
   init_recog_no_volatile ();
+
+  /* Set this before generating any memory accesses.  */
+  current_function_check_memory_usage
+    = (flag_check_memory_usage
+       && ! DECL_NO_CHECK_MEMORY_USAGE (current_function_decl));
 
   current_function_instrument_entry_exit
     = (flag_instrument_function_entry_exit
Index: function.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/function.h,v
retrieving revision 1.11
diff -p -u -r1.11 function.h
--- function.h	1998/09/15 19:18:57	1.11
+++ function.h	1998/10/03 01:30:11
@@ -151,6 +151,7 @@ struct function
   rtx saveregs_value;
   rtx apply_args_value;
   rtx forced_labels;
+  int check_memory_usage;
 
   /* For emit-rtl.c.  */
   int reg_rtx_no;
Index: invoke.texi
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/invoke.texi,v
retrieving revision 1.71
diff -p -u -r1.71 invoke.texi
--- invoke.texi	1998/09/29 08:15:16	1.71
+++ invoke.texi	1998/10/03 01:30:13
@@ -5837,8 +5837,7 @@ the offsets of structure members won't a
 @item -fcheck-memory-usage
 Generate extra code to check each memory access.  GNU CC will generate
 code that is suitable for a detector of bad memory accesses such as
-@file{Checker}.  If you specify this option, you can not use the
-@code{asm} or @code{__asm__} keywords.
+@file{Checker}.
 
 You must also specify this option when you compile functions you call that
 have side effects.  If you do not, you may get erroneous messages from
@@ -5852,6 +5851,24 @@ your code and make other functions look 
 which are provided by the detector.  If you cannot find or build
 stubs for every function you call, you may have to specify
 @samp{-fcheck-memory-usage} without @samp{-fprefix-function-name}.
+
+If you specify this option, you can not use the @code{asm} or
+@code{__asm__} keywords in functions with memory checking enabled.  The
+compiler cannot understand what the @code{asm} statement will do, and
+therefore cannot generate the appropriate code, so it is rejected.
+However, the function attribute @code{no_check_memory_usage} will
+disable memory checking within a function, and @code{asm} statements can
+be put inside such functions.  Inline expansion of a non-checked
+function within a checked function is permitted; the inline function's
+memory accesses won't be checked, but the rest will.
+
+If you move your @code{asm} statements to non-checked inline functions,
+but they do access memory, you can add calls to the support code in your
+inline function, to indicate any reads, writes, or copies being done.
+These calls would be similar to those done in the stubs described above.
+
+@c FIXME: The support-routine interface is defined by the compiler and
+@c        should be documented!
 
 @item -fprefix-function-name
 Request GNU CC to add a prefix to the symbols generated for function names.
Index: optabs.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/optabs.c,v
retrieving revision 1.14
diff -p -u -r1.14 optabs.c
--- optabs.c	1998/09/21 14:23:14	1.14
+++ optabs.c	1998/10/03 01:30:14
@@ -4390,17 +4390,17 @@ init_optabs ()
   fixunstfti_libfunc = gen_rtx_SYMBOL_REF (Pmode, "__fixunstfti");
 
   /* For check-memory-usage.  */
-  chkr_check_addr_libfunc = gen_rtx_SYMBOL_REF (VOIDmode, "chkr_check_addr");
-  chkr_set_right_libfunc = gen_rtx_SYMBOL_REF (VOIDmode, "chkr_set_right");
-  chkr_copy_bitmap_libfunc = gen_rtx_SYMBOL_REF (VOIDmode, "chkr_copy_bitmap");
-  chkr_check_exec_libfunc = gen_rtx_SYMBOL_REF (VOIDmode, "chkr_check_exec");
-  chkr_check_str_libfunc = gen_rtx_SYMBOL_REF (VOIDmode, "chkr_check_str");
+  chkr_check_addr_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_addr");
+  chkr_set_right_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_set_right");
+  chkr_copy_bitmap_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_copy_bitmap");
+  chkr_check_exec_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_exec");
+  chkr_check_str_libfunc = gen_rtx_SYMBOL_REF (Pmode, "chkr_check_str");
 
   /* For function entry/exit instrumentation.  */
   profile_function_entry_libfunc
-    = gen_rtx_SYMBOL_REF (VOIDmode, "__cyg_profile_func_enter");
+    = gen_rtx_SYMBOL_REF (Pmode, "__cyg_profile_func_enter");
   profile_function_exit_libfunc
-    = gen_rtx_SYMBOL_REF (VOIDmode, "__cyg_profile_func_exit");
+    = gen_rtx_SYMBOL_REF (Pmode, "__cyg_profile_func_exit");
 
 #ifdef HAVE_conditional_trap
   init_traps ();
Index: stmt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/stmt.c,v
retrieving revision 1.47
diff -p -u -r1.47 stmt.c
--- stmt.c	1998/08/24 09:27:39	1.47
+++ stmt.c	1998/10/03 01:30:16
@@ -583,7 +583,7 @@ expand_computed_goto (exp)
 
   emit_queue ();
   /* Be sure the function is executable.  */
-  if (flag_check_memory_usage)
+  if (current_function_check_memory_usage)
     emit_library_call (chkr_check_exec_libfunc, 1,
 		       VOIDmode, 1, x, ptr_mode);
 
@@ -1107,7 +1107,7 @@ void
 expand_asm (body)
      tree body;
 {
-  if (flag_check_memory_usage)
+  if (current_function_check_memory_usage)
     {
       error ("`asm' cannot be used with `-fcheck-memory-usage'");
       return;
@@ -1163,7 +1163,7 @@ expand_asm_operands (string, outputs, in
   if (noutputs == 0)
     vol = 1;
 
-  if (flag_check_memory_usage)
+  if (current_function_check_memory_usage)
     {
       error ("`asm' cannot be used with `-fcheck-memory-usage'");
       return;
@@ -3232,7 +3232,7 @@ expand_decl (decl)
 	   && ! TREE_ADDRESSABLE (decl)
 	   && (DECL_REGISTER (decl) || ! obey_regdecls)
 	   /* if -fcheck-memory-usage, check all variables.  */
-	   && ! flag_check_memory_usage)
+	   && ! current_function_check_memory_usage)
     {
       /* Automatic variable that can go in a register.  */
       int unsignedp = TREE_UNSIGNED (type);
Index: tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/tree.h,v
retrieving revision 1.55
diff -p -u -r1.55 tree.h
--- tree.h	1998/09/28 14:23:14	1.55
+++ tree.h	1998/10/03 01:30:17
@@ -1226,6 +1226,10 @@ struct tree_type
    be instrumented with calls to support routines.  */
 #define DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT(NODE) ((NODE)->decl.no_instrument_function_entry_exit)
 
+/* Used in FUNCTION_DECLs to indicate that in this function,
+   check-memory-usage should be disabled.  */
+#define DECL_NO_CHECK_MEMORY_USAGE(NODE) ((NODE)->decl.no_check_memory_usage)
+
 /* Additional flags for language-specific uses.  */
 #define DECL_LANG_FLAG_0(NODE) (DECL_CHECK (NODE)->decl.lang_flag_0)
 #define DECL_LANG_FLAG_1(NODE) (DECL_CHECK (NODE)->decl.lang_flag_1)
@@ -1282,6 +1286,7 @@ struct tree_decl
 
   unsigned non_addr_const_p : 1;
   unsigned no_instrument_function_entry_exit : 1;
+  unsigned no_check_memory_usage : 1;
 
   /* For a FUNCTION_DECL, if inline, this is the size of frame needed.
      If built-in, this is the code for which built-in function.
Index: config/alpha/alpha.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/alpha/alpha.c,v
retrieving revision 1.60
diff -p -u -r1.60 alpha.c
--- alpha.c	1998/09/23 13:28:53	1.60
+++ alpha.c	1998/10/03 01:30:21
@@ -2975,7 +2975,7 @@ alpha_builtin_saveregs (arglist)
       dest = change_address (block, ptr_mode, XEXP (block, 0));
       emit_move_insn (dest, addr);
 
-      if (flag_check_memory_usage)
+      if (current_function_check_memory_usage)
 	emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
 			   dest, ptr_mode,
 			   GEN_INT (GET_MODE_SIZE (ptr_mode)),
@@ -2989,7 +2989,7 @@ alpha_builtin_saveregs (arglist)
 					    POINTER_SIZE/BITS_PER_UNIT));
       emit_move_insn (dest, argsize);
 
-      if (flag_check_memory_usage)
+      if (current_function_check_memory_usage)
 	emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
 			   dest, ptr_mode,
 			   GEN_INT (GET_MODE_SIZE
Index: config/clipper/clipper.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/clipper/clipper.c,v
retrieving revision 1.2
diff -p -u -r1.2 clipper.c
--- clipper.c	1998/04/01 05:19:36	1.2
+++ clipper.c	1998/10/03 01:30:21
@@ -438,7 +438,7 @@ clipper_builtin_saveregs (arglist)
 		  scratch);
 
 
-  if (flag_check_memory_usage)
+  if (current_function_check_memory_usage)
     {
       emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
 			 addr, ptr_mode,
Index: config/m88k/m88k.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/m88k/m88k.c,v
retrieving revision 1.8
diff -p -u -r1.8 m88k.c
--- m88k.c	1998/04/01 05:19:57	1.8
+++ m88k.c	1998/10/03 01:30:21
@@ -2644,7 +2644,7 @@ m88k_builtin_saveregs (arglist)
 			   UNITS_PER_WORD * (8 - fixed));
     }
 
-  if (flag_check_memory_usage)
+  if (current_function_check_memory_usage)
     {
       emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
 			 block, ptr_mode,
Index: config/pa/pa.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/pa/pa.c,v
retrieving revision 1.22
diff -p -u -r1.22 pa.c
--- pa.c	1998/09/15 22:01:08	1.22
+++ pa.c	1998/10/03 01:30:26
@@ -4391,7 +4391,7 @@ hppa_builtin_saveregs (arglist)
      last argument register store.  So we emit a blockage insn here.  */
   emit_insn (gen_blockage ());
 
-  if (flag_check_memory_usage)
+  if (current_function_check_memory_usage)
     emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
 		       dest, ptr_mode,
 		       GEN_INT (4 * UNITS_PER_WORD), TYPE_MODE (sizetype),
Index: config/sparc/sparc.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/sparc/sparc.c,v
retrieving revision 1.59
diff -p -u -r1.59 sparc.c
--- sparc.c	1998/09/24 16:16:58	1.59
+++ sparc.c	1998/10/03 01:30:41
@@ -4279,7 +4279,7 @@ sparc_builtin_saveregs (arglist)
 		     GEN_INT (STACK_POINTER_OFFSET
 			      + UNITS_PER_WORD * first_reg));
 
-  if (flag_check_memory_usage
+  if (current_function_check_memory_usage
       && first_reg < NPARM_REGS (word_mode))
     emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
 		       address, ptr_mode,



diff -r -N -u empty/blkarg.c testsuite/gcc.c-torture/execute/memcheck/blkarg.c
--- empty/blkarg.c	Wed Dec 31 19:00:00 1969
+++ testsuite/gcc.c-torture/execute/memcheck/blkarg.c	Fri Oct  2 20:47:30 1998
@@ -0,0 +1,64 @@
+/* Must define:
+   int expect_error;
+   void test ();
+   void setup () NOCHECK; */
+
+#include "driver.h"
+
+/* Test permissions of BLKmode arguments constructed purely on the
+   stack.
+
+   Maybe we can't guarantee that we'll always wind up with stack args,
+   but if we don't, they're in registers, and permissions should just
+   always yield success.  So while this test may not be effective on
+   all platforms, failure probably does indicate a real bug.
+
+   Note that because of the implementation, we do want to test BLKmode
+   arguments that live purely on the stack and are constructed there.
+   We want to test other situations of function arguments, of course,
+   but don't assume this case would be covered by using one monster
+   argument that is read from memory (including using constructor
+   syntax but constant values), or may live partially in registers.  */
+
+int expect_error = 0;
+
+/* Must be BLKmode.  Using only two fields gets TImode on Alpha.  */
+struct S {
+  unsigned long long ll;
+  long xx, yy;
+};
+
+unsigned long long x = 0x12345689ULL;
+#define I2	42
+
+/* Leading six arguments force X into stack on both Alpha and MIPS.  */
+
+static int first_time = 1;
+int foo (int a1, int a2, int a3, int a4, int a5, int a6, struct S s) {
+  if (a1 != 1 || a2 != 2 || a3 != 3 || a4 != 4 || a5 != 5 || a6 != 6)
+    abort ();
+  if (first_time)
+    {
+      if (s.ll != x || s.xx != I2 || s.yy != 0)
+	abort ();
+      first_time = 0;
+    }
+  else
+    {
+      if (s.ll != 0 || s.xx != 0 || s.yy != 0)
+	abort ();
+    }
+  return 0;
+}
+
+void test ()
+{
+  foo (1, 2, 3, 4, 5, 6, (struct S) { x, I2 });
+  foo (1, 2, 3, 4, 5, 6, (struct S) { 0 });
+}
+
+void setup () /* NOCHECK */
+{
+  mark_region (&x, sizeof (x), ACCESS_RO);
+  mark_region (&first_time, sizeof (first_time), ACCESS_RW);
+}
diff -r -N -u empty/driver.c testsuite/gcc.c-torture/execute/memcheck/driver.c
--- empty/driver.c	Wed Dec 31 19:00:00 1969
+++ testsuite/gcc.c-torture/execute/memcheck/driver.c	Fri Oct  2 20:36:48 1998
@@ -0,0 +1,254 @@
+/* GNU C dependencies:
+   Checker support hooks
+   ISO C 9x array element initialization
+   void-pointer arithmetic */
+
+#include "driver.h"
+
+int verbose = 0;
+int debug = 0;
+int bad_accesses = 0;
+
+const char *const memory_use_strings[] = {
+#define INIT(x)		[x] = #x
+  INIT (MEMORY_USE_BAD),
+  INIT (MEMORY_USE_DONT),
+  INIT (MEMORY_USE_RO),
+  INIT (MEMORY_USE_RW),
+  INIT (MEMORY_USE_TW),
+  INIT (MEMORY_USE_WO),
+#undef INIT
+};
+
+/* This won't be used for any really huge test cases, so a simple
+   linked list is adequate.  We won't even worry about overlapping
+   regions; the matching entry that comes up first wins.  */
+const char *const access_mode_strings[] = {
+  "none", "ro", "wo", "rw",
+};
+struct access_node {
+  struct access_node *next;
+  const void *addr;
+  size_t sz;
+  enum access_mode mode;
+};
+
+static struct access_node *access_list;
+
+void mark_region (const void *addr, size_t sz, enum access_mode mode)
+{
+  struct access_node *a;
+  if (debug)
+    printf ("mark_region (%p, %ld, %s)\n", addr, (long) sz,
+	    access_mode_strings[mode]);
+  a = malloc (sizeof (struct access_node));
+  a->next = access_list;
+  a->addr = addr;
+  a->sz = sz;
+  a->mode = mode;
+  access_list = a;
+}
+
+void report_bad_access (void *, size_t, enum memory_use_mode) NOCHECK;
+void report_bad_access (void *addr, size_t sz, enum memory_use_mode mode)
+{
+  if (++bad_accesses > 100)
+    bad_accesses = 100;
+  if (verbose)
+    {
+      static char x[100];
+      const char *mode_str;
+      if (mode >= 0
+	  && mode < sizeof (memory_use_strings) / sizeof (*memory_use_strings)
+	  && memory_use_strings[mode] != 0)
+	mode_str = memory_use_strings[mode];
+      else
+	{
+	  sprintf (x, "<bad mode %d>", mode);
+	  mode_str = x;
+	}
+      printf ("bad access (%p, %ld, %s)\n", addr, (long) sz, mode_str);
+    }
+}
+
+int verify1 (void *, size_t, enum access_mode, struct access_node *) NOCHECK;
+int verify1 (void *addr, size_t sz, enum access_mode mode,
+	     struct access_node *a)
+{
+  while (a && (addr + sz <= a->addr || addr >= a->addr + a->sz))
+    a = a->next;
+  if (a == 0)
+    return 0;
+
+  if (debug)
+    printf ("verify1 (%p, %ld, %s)\n", addr, (long) sz,
+	    access_mode_strings[mode]);
+
+  if (mode & ~a->mode)
+    return 0;
+
+  if (addr < a->addr)
+    if (verify1 (a, a->addr - addr, mode, a->next) == 0)
+      return 0;
+  if (addr + sz > a->addr + a->sz)
+    if (verify1 (a->addr + a->sz, (addr + sz) - (a->addr + a->sz), mode, a->next) == 0)
+      return 0;
+
+  /* All regions okay.  */
+  return 1;
+}
+
+int verify_range_permission (void *, size_t, enum access_mode) NOCHECK;
+
+int verify_range_permission (void *addr, size_t sz, enum access_mode mode)
+{
+  if (debug)
+    printf ("verify_range_permission (%p, %ld, %s)\n", addr, (long) sz,
+	    access_mode_strings[mode]);
+  return verify1 (addr, sz, mode, access_list);
+}
+
+void chkr_check_addr (void *, size_t, int) NOCHECK;
+
+void chkr_check_addr (void *addr, size_t sz, int mode)
+{
+  switch (mode)
+    {
+    case MEMORY_USE_BAD:
+    case MEMORY_USE_DONT:
+    default:
+      report_bad_access (addr, sz, mode);
+      return;
+    case MEMORY_USE_RO:
+      /* verify range readable */
+      if (!verify_range_permission (addr, sz, ACCESS_RO))
+	report_bad_access (addr, sz, mode);
+      return;
+    case MEMORY_USE_WO:
+      /* verify writeable, set writeable and readable */
+      if (!verify_range_permission (addr, sz, ACCESS_WO))
+	report_bad_access (addr, sz, mode);
+      mark_region (addr, sz, ACCESS_RW);
+      return;
+    case MEMORY_USE_RW:
+      /* verify readable and writeable, no change */
+      if (!verify_range_permission (addr, sz, ACCESS_RW))
+	report_bad_access (addr, sz, mode);
+      return;
+    case MEMORY_USE_TW:
+      /* verify writeable, no change */
+      if (!verify_range_permission (addr, sz, ACCESS_WO))
+	report_bad_access (addr, sz, mode);
+      return;
+    }
+  /* All branches should return.  */
+  abort ();
+}
+
+void copy1 (void *, void *, size_t, struct access_node *) NOCHECK;
+void copy1 (void *dest, void *src, size_t sz, struct access_node *a)
+{
+  while (a && (src + sz <= a->addr || src >= a->addr + a->sz))
+    a = a->next;
+  if (a == 0)
+    {
+      report_bad_access (src, sz, MEMORY_USE_RO);
+      return;
+    }
+
+  if (debug)
+    printf ("copy1 (%p, %p, %ld)\n", dest, src, (long) sz);
+
+  {
+    void *start, *end;
+    start = src;
+    if (start < a->addr)
+      start = a->addr;
+    end = src + sz;
+    if (end > a->addr + a->sz)
+      end = a->addr + a->sz;
+    mark_region (dest + (start - src), end - start, a->mode);
+  }
+
+  if (src < a->addr)
+    copy1 (dest, src, a->addr - src, a->next);
+  if (src + sz > a->addr + a->sz)
+    copy1 (dest + (a->addr + a->sz - src), a->addr + a->sz,
+	   (src + sz) - (a->addr + a->sz), a->next);
+}
+
+void chkr_copy_bitmap (void *, void *, size_t) NOCHECK;
+void chkr_copy_bitmap (void *dest, void *src, size_t sz)
+{
+  if (verify_range_permission (dest, sz, MEMORY_USE_WO) == 0)
+    report_bad_access (dest, sz, MEMORY_USE_WO);
+  copy1 (dest, src, sz, access_list);
+}
+
+void chkr_set_right (void *, size_t, enum access_mode) NOCHECK;
+void chkr_set_right (void *addr, size_t sz, enum access_mode mode)
+{
+  mark_region (addr, sz, mode);
+}
+
+int main () NOCHECK;
+int main ()
+{
+  setup ();
+  test ();
+  bad_accesses = !!bad_accesses; /* get 0 or 1 */
+  /* Return 0 if got expected results, 1 otherwise.  */
+  return !(bad_accesses == expect_error);
+}
+
+struct malloc_node {
+  struct malloc_node *next;
+  void *addr;
+  size_t sz;
+  unsigned is_free : 1;
+};
+static struct malloc_node *malloc_list;
+
+void *c_malloc (size_t sz)
+{
+  void *p;
+  struct malloc_node *m;
+  if (sz == 0)
+    return 0;
+  p = malloc (sz);
+  if (p == 0)
+    {
+      if (verbose)
+	printf ("malloc(%ld) failed\n", (long) sz);
+      exit (1);
+    }
+  m = malloc (sizeof (struct malloc_node));
+  if (m == 0)
+    {
+      if (verbose)
+	printf ("malloc(%ld) failed\n", (long) sizeof (struct malloc_node));
+      exit (1);
+    }
+  mark_region (p, sz, ACCESS_WO);
+  m->addr = p;
+  m->sz = sz;
+  m->is_free = 0;
+  m->next = malloc_list;
+  malloc_list = m;
+  return p;
+}
+
+void c_free (void *p)
+{
+  struct malloc_node *m;
+  if (p == 0)
+    return;
+  for (m = malloc_list; m; m = m->next)
+    if (m->addr == p)
+      break;
+  if (m == 0 || m->is_free)
+    /* Test is broken.  */
+    abort ();
+  m->is_free = 1;
+  free (p);
+}
diff -r -N -u empty/driver.h testsuite/gcc.c-torture/execute/memcheck/driver.h
--- empty/driver.h	Wed Dec 31 19:00:00 1969
+++ testsuite/gcc.c-torture/execute/memcheck/driver.h	Fri Oct  2 20:36:37 1998
@@ -0,0 +1,28 @@
+/* GNU C dependencies:
+   Checker support hooks
+   ISO C 9x array element initialization
+   void-pointer arithmetic */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern void *malloc (size_t);
+extern int printf (const char *, ...);
+
+/* This comes from gcc internals.  Should be exported.  */
+enum memory_use_mode {MEMORY_USE_BAD = 0, MEMORY_USE_RO = 1,
+		      MEMORY_USE_WO = 2, MEMORY_USE_RW = 3,
+		      MEMORY_USE_TW = 6, MEMORY_USE_DONT = 99};
+
+enum access_mode {
+  ACCESS_NONE = 0, ACCESS_RO = 1, ACCESS_WO = 2, ACCESS_RW = 3
+};
+
+#define NOCHECK __attribute__ ((no_check_memory_usage))
+
+void mark_region (const void *, size_t, enum access_mode) NOCHECK;
+void setup () NOCHECK;
+void test ();
+extern int expect_error;
+
+void *c_malloc (size_t) NOCHECK;
+void c_free (void *) NOCHECK;
diff -r -N -u empty/memcheck.exp testsuite/gcc.c-torture/execute/memcheck/memcheck.exp
--- empty/memcheck.exp	Wed Dec 31 19:00:00 1969
+++ testsuite/gcc.c-torture/execute/memcheck/memcheck.exp	Fri Oct  2 20:41:08 1998
@@ -0,0 +1,54 @@
+# Copyright (C) 1991, 92-93, 95, 97, 1998 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gcc@prep.ai.mit.edu
+
+# This file was written by Rob Savoye. (rob@cygnus.com)
+# Modified and maintained by Jeffrey Wheat (cassidy@cygnus.com)
+
+#
+# These tests come from Torbjorn Granlund (tege@cygnus.com)
+# C torture test suite.
+#
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+# load support procs
+load_lib c-torture.exp
+
+#
+# main test loop
+#
+
+set tests [lsort [glob -nocomplain $srcdir/$subdir/*.c]]
+set idx [lsearch $tests */driver.c]
+if $idx>=0 {
+    set tests [lreplace $tests $idx $idx]
+} else {
+    error "list can't find driver.c in $srcdir/$subdir"
+}
+gcc_target_compile $srcdir/$subdir/driver.c driver.o object {additional_flags=-w additional_flags=-g}
+foreach src $tests {
+    # If we're only testing specific files and this isn't one of them, skip it.
+    if ![runtest_file_p $runtests $src] then {
+	continue
+    }
+
+    c-torture-execute $src "-fcheck-memory-usage driver.o"
+}
diff -r -N -u empty/t1.c testsuite/gcc.c-torture/execute/memcheck/t1.c
--- empty/t1.c	Wed Dec 31 19:00:00 1969
+++ testsuite/gcc.c-torture/execute/memcheck/t1.c	Fri Oct  2 19:34:17 1998
@@ -0,0 +1,27 @@
+/* Must define:
+   int expect_error;
+   void test ();
+   void setup ();   -- NOCHECK */
+
+#include "driver.h"
+
+int expect_error = 0;
+
+int *ip;
+
+void test ()
+{
+  ip = c_malloc (sizeof (int));
+  *ip = 42;
+  t2 ();
+}
+
+int t2 ()
+{
+  return *ip;
+}
+
+void setup () /* NOCHECK */
+{
+  mark_region (&ip, sizeof (ip), ACCESS_RW);
+}
diff -r -N -u empty/t2.c testsuite/gcc.c-torture/execute/memcheck/t2.c
--- empty/t2.c	Wed Dec 31 19:00:00 1969
+++ testsuite/gcc.c-torture/execute/memcheck/t2.c	Fri Oct  2 19:34:17 1998
@@ -0,0 +1,26 @@
+/* Must define:
+   int expect_error;
+   void test ();
+   void setup () NOCHECK; */
+
+#include "driver.h"
+
+int expect_error = 1;
+
+int *ip;
+
+void test ()
+{
+  ip = c_malloc (sizeof (int));
+  t2 ();
+}
+
+int t2 ()
+{
+  return *ip;
+}
+
+void setup () /* NOCHECK */
+{
+  mark_region (&ip, sizeof (ip), ACCESS_RW);
+}
diff -r -N -u empty/t3.c testsuite/gcc.c-torture/execute/memcheck/t3.c
--- empty/t3.c	Wed Dec 31 19:00:00 1969
+++ testsuite/gcc.c-torture/execute/memcheck/t3.c	Fri Oct  2 19:34:17 1998
@@ -0,0 +1,25 @@
+/* Must define:
+   int expect_error;
+   void test ();
+   void setup () NOCHECK; */
+
+#include "driver.h"
+
+int expect_error = 0;
+
+int *ip;
+
+void test ()
+{
+  ip = c_malloc (sizeof (int));
+  t2 (ip);
+}
+
+int t2 (int *ip)
+{
+}
+
+void setup () /* NOCHECK */
+{
+  mark_region (&ip, sizeof (ip), ACCESS_RW);
+}
diff -r -N -u empty/t4.c testsuite/gcc.c-torture/execute/memcheck/t4.c
--- empty/t4.c	Wed Dec 31 19:00:00 1969
+++ testsuite/gcc.c-torture/execute/memcheck/t4.c	Fri Oct  2 19:34:17 1998
@@ -0,0 +1,34 @@
+/* Must define:
+   int expect_error;
+   void test ();
+   void setup () NOCHECK; */
+
+#include "driver.h"
+
+int expect_error = 0;
+
+struct s {
+  char c;
+  int a, b;
+};
+
+struct s *sp;
+
+void test ()
+{
+  sp = c_malloc (sizeof (struct s));
+  sp->c = 0;
+  sp->a = 12;
+  sp->b = 47;
+  foo (sp);
+}
+
+int foo (struct s *sp)
+{
+  return sp->c + sp->a + sp->b;
+}
+
+void setup () /* NOCHECK */
+{
+  mark_region (&sp, sizeof (sp), ACCESS_RW);
+}
diff -r -N -u empty/t5.c testsuite/gcc.c-torture/execute/memcheck/t5.c
--- empty/t5.c	Wed Dec 31 19:00:00 1969
+++ testsuite/gcc.c-torture/execute/memcheck/t5.c	Fri Oct  2 19:34:17 1998
@@ -0,0 +1,33 @@
+/* Must define:
+   int expect_error;
+   void test ();
+   void setup () NOCHECK; */
+
+#include "driver.h"
+
+int expect_error = 1;
+
+struct s {
+  char c;
+  int a, b;
+};
+
+struct s *sp;
+
+void test ()
+{
+  sp = c_malloc (sizeof (struct s));
+  sp->c = 0;
+  sp->b = 47;
+  foo (sp);
+}
+
+int foo (struct s *sp)
+{
+  return sp->c + sp->a + sp->b;
+}
+
+void setup () /* NOCHECK */
+{
+  mark_region (&sp, sizeof (sp), ACCESS_RW);
+}
diff -r -N -u empty/t6.c testsuite/gcc.c-torture/execute/memcheck/t6.c
--- empty/t6.c	Wed Dec 31 19:00:00 1969
+++ testsuite/gcc.c-torture/execute/memcheck/t6.c	Fri Oct  2 19:34:17 1998
@@ -0,0 +1,39 @@
+/* Must define:
+   int expect_error;
+   void test ();
+   void setup () NOCHECK; */
+
+#include "driver.h"
+
+int expect_error = 1;
+
+struct s {
+  char c;
+  int a, b;
+};
+
+struct s *sp;
+
+void test ()
+{
+  sp = c_malloc (sizeof (struct s) * 2);
+  sp->c = 0;
+  sp->b = 47;
+  cp (sp);
+  foo (sp);
+}
+
+int foo (struct s *sp)
+{
+  return sp[1].c + sp[1].a + sp[1].b;
+}
+
+int cp (struct s *sp)
+{
+  sp[1] = sp[0];
+}
+
+void setup () /* NOCHECK */
+{
+  mark_region (&sp, sizeof (sp), ACCESS_RW);
+}
diff -r -N -u empty/t7.c testsuite/gcc.c-torture/execute/memcheck/t7.c
--- empty/t7.c	Wed Dec 31 19:00:00 1969
+++ testsuite/gcc.c-torture/execute/memcheck/t7.c	Fri Oct  2 19:34:17 1998
@@ -0,0 +1,40 @@
+/* Must define:
+   int expect_error;
+   void test ();
+   void setup () NOCHECK; */
+
+#include "driver.h"
+
+int expect_error = 0;
+
+struct s {
+  char c;
+  int a, b;
+};
+
+struct s *sp;
+
+void test ()
+{
+  sp = c_malloc (sizeof (struct s) * 2);
+  sp->c = 0;
+  sp->a = 13;
+  sp->b = 47;
+  cp (sp);
+  foo (sp);
+}
+
+int foo (struct s *sp)
+{
+  return sp[1].c + sp[1].a + sp[1].b;
+}
+
+int cp (struct s *sp)
+{
+  sp[1] = sp[0];
+}
+
+void setup () /* NOCHECK */
+{
+  mark_region (&sp, sizeof (sp), ACCESS_RW);
+}
diff -r -N -u empty/t8.c testsuite/gcc.c-torture/execute/memcheck/t8.c
--- empty/t8.c	Wed Dec 31 19:00:00 1969
+++ testsuite/gcc.c-torture/execute/memcheck/t8.c	Fri Oct  2 19:34:17 1998
@@ -0,0 +1,41 @@
+/* Must define:
+   int expect_error;
+   void test ();
+   void setup () NOCHECK; */
+
+#include "driver.h"
+
+int expect_error = 0;
+
+typedef struct {
+  short a;
+  char b;
+} S1;
+typedef struct {
+  struct { int x; S1 *s1p; } *p;
+} S2;
+
+S1 *s1;
+S2 *s2;
+
+void test ()
+{
+  s1 = c_malloc (sizeof (S1));
+  s2 = c_malloc (sizeof (S2));
+  s2->p = c_malloc (sizeof (*s2->p));
+  s2->p->s1p = s1;
+  s1->a = 47;
+  s1->b = 3;
+  foo ();
+}
+
+int foo ()
+{
+  return s2->p->s1p->b;
+}
+
+void setup () /* NOCHECK */
+{
+  mark_region (&s1, sizeof (s1), ACCESS_RW);
+  mark_region (&s2, sizeof (s2), ACCESS_RW);
+}
diff -r -N -u empty/t9.c testsuite/gcc.c-torture/execute/memcheck/t9.c
--- empty/t9.c	Wed Dec 31 19:00:00 1969
+++ testsuite/gcc.c-torture/execute/memcheck/t9.c	Fri Oct  2 19:34:17 1998
@@ -0,0 +1,40 @@
+/* Must define:
+   int expect_error;
+   void test ();
+   void setup () NOCHECK; */
+
+#include "driver.h"
+
+int expect_error = 1;
+
+typedef struct {
+  short a;
+  char b;
+} S1;
+typedef struct {
+  struct { int x; S1 *s1p; } *p;
+} S2;
+
+S1 *s1;
+S2 *s2;
+
+void test ()
+{
+  s1 = c_malloc (sizeof (S1));
+  s2 = c_malloc (sizeof (S2));
+  s2->p = c_malloc (sizeof (*s2->p));
+  s2->p->s1p = s1;
+  s1->a = 47;
+  foo ();
+}
+
+int foo ()
+{
+  return s2->p->s1p->b;
+}
+
+void setup () /* NOCHECK */
+{
+  mark_region (&s1, sizeof (s1), ACCESS_RW);
+  mark_region (&s2, sizeof (s2), ACCESS_RW);
+}
diff -r -N -u empty/template testsuite/gcc.c-torture/execute/memcheck/template
--- empty/template	Wed Dec 31 19:00:00 1969
+++ testsuite/gcc.c-torture/execute/memcheck/template	Fri Oct  2 19:34:17 1998
@@ -0,0 +1,16 @@
+/* Must define:
+   int expect_error;
+   void test ();
+   void setup () NOCHECK; */
+
+#include "driver.h"
+
+int expect_error = ;
+
+void test ()
+{
+}
+
+void setup () /* NOCHECK */
+{
+}



More information about the Gcc-patches mailing list