Path: utzoo!telly!attcan!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!MIZAR.DOCS.UU.SE!ewerlid From: ewerlid@MIZAR.DOCS.UU.SE (Ove Ewerlid) Newsgroups: gnu.gcc Subject: warnings Message-ID: <8907240126.AA23105@mizar.DoCS.UU.SE> Date: 24 Jul 89 01:26:31 GMT Sender: daemon@tut.cis.ohio-state.edu Distribution: gnu Organization: GNUs Not Usenet Lines: 318 > 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; }