[gnu.gcc.bug] -Wall and assert

eggert@twinsun.com (Paul Eggert) (03/02/90)

GCC 1.37's -Wall option doesn't mix well with assert().  For example, given

	#include <assert.h>
	int main(int argc) { assert(argc); return 1; }

gcc -Wall reports

	t.c: In function main:
	t.c:2: warning: implicit declaration of function `abort'
	t.c:2: warning: value computed is not used

Furthermore, gcc -Wall -DNDEBUG reports

	t.c: In function main:
	t.c:2: warning: statement with no effect

In the following fix, to suppress the first message, the call to abort() is
moved to inside __eprintf().  (It's not clear to me whether declaring abort()
inside <assert.h> is allowed by the ANSI standard, and this fix finesses the
issue.)

To suppress the second message, this fix changes assert() to yield void rather
than 0.  To simplify the code and avoid duplicate copies of the "Failed
assertion ..." message, the near-duplicate definitions of __assert() are
collapsed into and moved into gnulib.c.  __eprintf should probably be renamed
__assert, but this would also require changes to Makefile.

Suppressing the third message requires a fix in expand_expr_stmt() to avoid
complaining about the statement ``((void)0);''.

===================================================================
RCS file: RCS/assert.h,v
retrieving revision 1.37
diff -c -r1.37 assert.h
*** /tmp/,RCSt1a06022	Thu Mar  1 14:36:31 1990
--- assert.h	Thu Mar  1 14:16:24 1990
***************
*** 12,33 ****
  #ifdef __STDC__
  
  #define assert(expression)  \
!   ((expression) ? 0 : (__assert (#expression, __FILE__, __LINE__), 0))
  
- #define __assert(expression, file, line)  \
-   (__eprintf ("Failed assertion `%s' at line %d of `%s'.\n",	\
- 	      expression, line, file),				\
-    abort ())
- 
  #else /* no __STDC__; i.e. -traditional.  */
  
  #define assert(expression)  \
!   ((expression) ? 0 : __assert (expression, __FILE__, __LINE__))
! 
! #define __assert(expression, file, lineno)  \
!   (__eprintf ("Failed assertion `%s' at line %d of `%s'.\n",	\
! 	      "expression", lineno, file),			\
!    abort ())
  
  #endif /* no __STDC__; i.e. -traditional.  */
  
--- 12,23 ----
  #ifdef __STDC__
  
  #define assert(expression)  \
!   ((expression) ? (void)0 : __eprintf (#expression, __LINE__, __FILE__))
  
  #else /* no __STDC__; i.e. -traditional.  */
  
  #define assert(expression)  \
!   ((expression) ? (void)0 : __eprintf ("expression", __LINE__, __FILE__))
  
  #endif /* no __STDC__; i.e. -traditional.  */
  
===================================================================
RCS file: RCS/gnulib.c,v
retrieving revision 1.37
diff -c -r1.37 gnulib.c
*** /tmp/,RCSt1a06022	Thu Mar  1 14:36:32 1990
--- gnulib.c	Thu Mar  1 14:07:12 1990
***************
*** 29,41 ****
  #include <stdio.h>
  /* This is used by the `assert' macro.  */
  void
! __eprintf (string, expression, line, filename)
!      char *string;
       char *expression;
       int line;
       char *filename;
  {
!   fprintf (stderr, string, expression, line, filename);
  }
  #endif
  
--- 29,41 ----
  #include <stdio.h>
  /* This is used by the `assert' macro.  */
  void
! __eprintf (expression, line, filename)
       char *expression;
       int line;
       char *filename;
  {
!   fprintf (stderr, "Failed assertion `%s' at line %d of `%s'.\n", expression, line, filename);
!   abort();
  }
  #endif
  
===================================================================
RCS file: RCS/stmt.c,v
retrieving revision 1.37
diff -c -r1.37 stmt.c
*** /tmp/,RCSt1a06022	Thu Mar  1 14:36:33 1990
--- stmt.c	Thu Mar  1 13:37:43 1990
***************
*** 976,985 ****
       tree exp;
  {
    /* If -W, warn about statements with no side effects,
       except inside a ({...}) where they may be useful.  */
    if (expr_stmts_for_value == 0 && exp != error_mark_node)
      {
!       if (! TREE_VOLATILE (exp) && (extra_warnings || warn_unused))
  	warning_with_file_and_line (emit_filename, emit_lineno,
  				    "statement with no effect");
        else if (warn_unused)
--- 976,989 ----
       tree exp;
  {
    /* If -W, warn about statements with no side effects,
+      except for statements explicitly casted to void (e.g. for assert()), and
       except inside a ({...}) where they may be useful.  */
    if (expr_stmts_for_value == 0 && exp != error_mark_node)
      {
!       if (! TREE_VOLATILE (exp)
! 	  && !(TREE_CODE (exp) == CONVERT_EXPR
! 	       && TREE_TYPE (exp) == void_type_node)
! 	  && (extra_warnings || warn_unused))
  	warning_with_file_and_line (emit_filename, emit_lineno,
  				    "statement with no effect");
        else if (warn_unused)