From:	CRDGW2::CRDGW2::MRGATE::"SMTP::PREP.AI.MIT.EDU::INFO-GCC-REQUEST" 24-JUL-1989 19:17
To:	MRGATE::"ARISIA::EVERHART"
Subj:	warnings

Received: by life.ai.mit.edu (4.1/AI-4.10) id AA27401; Mon, 24 Jul 89 07:19:18 EDT
Return-Path: <ewerlid@mizar.docs.uu.se>
Received: from mizar.DoCS.UU.SE by life.ai.mit.edu (4.1/AI-4.10) id AA27370; Mon, 24 Jul 89 07:12:31 EDT
Received: by mizar.DoCS.UU.SE (Sun-4/260, SunOS 4.0)
 with sendmail 5.59++/IDA 1.2.5 id AA23105; Mon, 24 Jul 89 03:26:31 +0200
Date: Mon, 24 Jul 89 03:26:31 +0200
From: Ove Ewerlid  <ewerlid@mizar.docs.uu.se>
Message-Id: <8907240126.AA23105@mizar.DoCS.UU.SE>
To: info-gcc@prep.ai.mit.edu
Subject: warnings


> From: schmidt@CRIMEE.ICS.UCI.EDU ("Douglas C. Schmidt")
> Subject: Warning messages for out-of-range values?
> Date: 17 Jul 89 04:58:40 GMT


> It would be nice if g++ and gcc gave warning message
> about the following compile-time range errors:

>  char c = 101023092.0938;
>  b.p = 500;				{ bitfield 2 bits }
>  b.c = 10101910;			{ char }


	------ + ------

> From: sequent!phil@DECWRL.DEC.COM (Phil Hochstetler)
> Newsgroups: gnu.gcc.bug
> Subject: GNU C bug
> Date: 17 Jul 89 21:30:35 GMT

> /* GNU C compiler fails to flag the type mismatch between enums */
>	enum option try2;
>	enum again try3;
>	if (try2 == try3)		/* compiler should complain */


	------ + -------

If everybody adjusted gcc so it gave a warning whenever they was bitten by
a bug, gcc might become an alarmingly verbose compiler.

 - 'Real men don't need warnings' :-)

Nevertheless, warnings may save someone somewhere some trouble.

(The patches below works fine for me, but since the below isn't part of
 the official gcc-distribution anyone that don't know whats going on below
 shouldn't really proceed :-)

To get -Wconst-accuracy-loss and -Wenum apply the following patches to gcc-1.35


enjoy	ove


		------- + -------


*** gcc-dist-1.35/c-decl.c	Wed Apr 26 08:44:58 1989
--- gcc/c-decl.c	Mon Jul 24 02:22:25 1989
***************
*** 227,232 ****
--- 227,241 ----
  
  int warn_strict_prototypes;
  
+ /* Nonzero means warn if precision in bits of lhs can't hold the number
+    of bits required by the constant rhs without a lossage of information */
+ 
+ int warn_prec_loss = 0;
+ 
+ /* Nonzero means warn when some inconsistency with enums is detected */
+ 
+ int warn_enum = 0;
+ 
  /* Nonzero means `$' can be in an identifier.
     See cccp.c for reasons why this breaks some obscure ANSI C programs.  */
  
***************
*** 278,283 ****
--- 287,296 ----
      warn_pointer_arith = 1;
    else if (!strcmp (p, "-Wstrict-prototypes"))
      warn_strict_prototypes = 1;
+   else if (!strcmp (p, "-Wconst-accuracy-loss"))
+     warn_prec_loss = 1;
+   else if (!strcmp (p, "-Wenum"))
+     warn_enum = 1;
    else if (!strcmp (p, "-Wcomment"))
      ; /* cpp handles this one.  */
    else if (!strcmp (p, "-Wcomments"))
***************
*** 291,296 ****
--- 304,311 ----
        warn_return_type = 1;
        warn_unused = 1;
        warn_switch = 1;
+       warn_prec_loss = 1;
+       warn_enum = 1;
      }
    else
      return 0;
***************
*** 1751,1766 ****
    int was_incomplete = (DECL_SIZE (decl) == 0);
    int temporary = allocation_temporary_p ();
  
-   /* If `start_decl' didn't like having an initialization, ignore it now.  */
  
-   if (init != 0 && DECL_INITIAL (decl) == 0)
-     init = 0;
- 
    if (init)
      {
!       if (TREE_CODE (decl) != TYPE_DECL)
! 	store_init_value (decl, init);
!       else
  	{
  	  /* typedef foo = bar; store the type of bar as the type of foo.  */
  	  TREE_TYPE (decl) = TREE_TYPE (init);
--- 1766,1784 ----
    int was_incomplete = (DECL_SIZE (decl) == 0);
    int temporary = allocation_temporary_p ();
  
  
    if (init)
      {
!       if (warn_prec_loss && actual_prec(decl) < const_actual_prec(init))
! 	warning("Accuracy loss: %d bits can't hold %d bits",
! 		actual_prec(decl), const_actual_prec(init));
!     /* If `start_decl' didn't like having an initialization, ignore it now.  */
!       if (DECL_INITIAL (decl) == 0)
! 	init = 0;
!       else 
! 	if (TREE_CODE (decl) != TYPE_DECL)
! 	  store_init_value (decl, init);
! 	else
  	{
  	  /* typedef foo = bar; store the type of bar as the type of foo.  */
  	  TREE_TYPE (decl) = TREE_TYPE (init);
*** gcc-dist-1.35/c-tree.h	Thu Mar 30 01:58:39 1989
--- gcc/c-tree.h	Mon Jul 24 02:11:56 1989
***************
*** 134,136 ****
--- 134,150 ----
  /* Nonzero means do some things the same way PCC does.  */
  
  extern int flag_traditional;
+ 
+ /* Nonzero means warn if precision in bits of lhs can't hold the number
+    of bits required by the constant rhs */
+ 
+ extern int warn_prec_loss;
+ 
+ /* Nonzero means warn when some inconsistency with enums is detected */
+ 
+ extern int warn_enum;
+ 
+ /* return precision of tree if appropriate, zero otherwise */
+ 
+ extern int const_actual_prec();
+ extern int actual_prec();
diff -c gcc-dist-1.35/c-typeck.c gcc/c-typeck.c
*** gcc-dist-1.35/c-typeck.c	Mon Apr 24 21:30:27 1989
--- gcc/c-typeck.c	Mon Jul 24 02:14:31 1989
***************
*** 1080,1085 ****
--- 1080,1093 ----
       enum tree_code code;
       tree arg1, arg2;
  {
+   /* do some type checking on enums, ie barf on 'enum foo == enum bar' */
+   if (code == EQ_EXPR && warn_enum)
+     if (TREE_CODE (TREE_TYPE (arg1)) == ENUMERAL_TYPE &&
+ 	TREE_CODE (TREE_TYPE (arg2)) == ENUMERAL_TYPE)
+       if ( &TYPE_NAME (TREE_TYPE (arg1))->identifier !=
+ 	  &TYPE_NAME (TREE_TYPE (arg2))->identifier)
+ 	warning("binary operation on incompatible enumerations");
+ 
    return build_binary_op_nodefault (code, default_conversion (arg1),
  				    default_conversion (arg2), code);
  }
***************
*** 2874,2879 ****
--- 2882,2894 ----
    if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
      return error_mark_node;
  
+   /* Warn if lhs does't have enough bits to hold the *constant* rhs */
+   if ( modifycode == NOP_EXPR )
+   {
+     if (warn_prec_loss && actual_prec(lhs) < const_actual_prec(rhs))
+       warning("accuracy loss: %d bits can't hold %d bits",
+ 	      actual_prec(lhs), const_actual_prec(rhs));
+   }
    /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
       Strip such NOP_EXPRs, since RHS is being used in non-lvalue context.  */
    if (TREE_CODE (rhs) == NOP_EXPR
***************
*** 3673,3676 ****
--- 3688,3813 ----
    expand_start_case (1, exp, type);
  
    return exp;
+ }
+ 
+ 
+ /* Return number of bits neded to hold the tree 'init' (>0).
+    If not constant the value 0 is returned.
+    Note that the below is based on the low part of data only and that
+    there are other more efficient but maybe less general methods to do it */
+ int const_actual_prec (init)
+      tree init;
+ {
+   register int cst, i;
+ 
+   if (TREE_CODE (init) == REAL_CST)
+     return 32; /* need at least 32 bits */
+   else if (TREE_CODE (init) == INTEGER_CST)
+   {
+     cst = TREE_INT_CST_LOW (init);
+     if (TREE_INT_CST_HIGH (init) && TREE_INT_CST_HIGH (init) != -1)
+       return 33; /* we need from 33 to 64 bits */
+   }
+   else return 0;
+   if (cst < 0)  cst = -cst << 1; /* need a sign bit */
+ 
+ #if 1  
+   /* derive actual precision of number using linear scan
+      TIMECOMPLEXITY is proportional to max_precision = 32.
+      This is a winner if small constants are the usual case */
+   for (i = 1; i < 32 && (cst & 0xfffffffe) ; i++, cst >>= 1);
+   return i;
+ #else
+   /* derive actual precision of number using binary scan
+      TIMECOMPLEXITY is proportional to log2(max_precision = 32) */
+   if (cst & 0xffff0000)
+   {
+     if (cst & 0xff000000)
+     {
+       if (cst & 0xf0000000)
+       {
+ 	if (cst & 0xc0000000)
+ 	{
+ 	  if (cst & 0x80000000) return 32; else return 31;
+ 	} else {
+ 	  if (cst & 0x20000000) return 30; else return 29;
+ 	}
+       } else {
+ 	if (cst & 0xc000000)
+ 	{
+ 	  if (cst & 0x8000000) return 28; else return 27;
+ 	} else {
+ 	  if (cst & 0x2000000) return 26; else return 25;
+ 	}
+       }
+     } else {
+       if (cst & 0xf00000)
+       {
+ 	if (cst & 0xc00000)
+ 	{
+ 	  if (cst & 0x800000) return 24; else return 23;
+ 	} else {
+ 	  if (cst & 0x200000) return 22; else return 21;
+ 	}
+       } else {
+ 	if (cst & 0xc0000)
+ 	{
+ 	  if (cst & 0x80000) return 20; else return 19;
+ 	} else {
+ 	  if (cst & 0x20000) return 18; else return 17;
+ 	}
+       }
+     }
+   } else {
+     if (cst & 0xff00)
+     {
+       if (cst & 0xf000)
+       {
+ 	if (cst & 0xc000)
+ 	{
+ 	  if (cst & 0x8000) return 16; else return 15;
+ 	} else {
+ 	  if (cst & 0x2000) return 14; else return 13;
+ 	}
+       } else {
+ 	if (cst & 0xc00)
+ 	{
+ 	  if (cst & 0x800) return 12; else return 11;
+ 	} else {
+ 	  if (cst & 0x200) return 10; else return 9;
+ 	}
+       }
+     } else {
+       if (cst & 0xf0)
+       {
+ 	if (cst & 0xc0)
+ 	{
+ 	  if (cst & 0x80) return 8; else return 7;
+ 	} else {
+ 	  if (cst & 0x20) return 6; else return 5;
+ 	}
+       } else {
+ 	if (cst & 0xc)
+ 	{
+ 	  if (cst & 0x8) return 4; else return 3;
+ 	} else {
+ 	  if (cst & 0x2) return 2; else return 1;
+ 	}
+       }
+     }
+   }
+ #endif
+ }
+ /* return actual precision available in a tree for storage */
+ int actual_prec (decl)
+      tree decl;
+ {
+   if (TREE_CODE (decl) == VAR_DECL)
+   {
+     if (DECL_SIZE(decl))
+       return DECL_SIZE_UNIT (decl) * TREE_INT_CST_LOW (DECL_SIZE(decl));
+   }
+   else if (TREE_CODE (decl) == COMPONENT_REF)
+     return DECL_SIZE_UNIT (IDENTIFIER_GLOBAL_VALUE(decl));
+   else return 64;
  }
