* Peter Lupton NCH Swift Sound <[EMAIL PROTECTED]> [051002 05:47]:
> I was hoping was that we could at least have a compile option. So we could 
> turn it on if required. I would definitely mandate it in our organization 
> at least. I am sure others would too.

I'd looked into getting some boolean checking into the C compiler (I am
personally not that interested in C++), but gcc has this "truthvalues are ints" 
quite heavily built in (which is not very suprising, after all the standard says
the are).
Attached is a experimental patch to make the C compiler do boolean checking
by making truthvalues of type bool instead of int and checking for them.
This definitly breaks the standard, as it changed the actual type.
It would be much nicer if there was some kind of "shadow types", that
would be only used for some additional warnings and not for code
generation. That way I think it would still be C standard conform, but
having looked only a very little into the gcc source, I cannot even
guess if it is possible and how much time it would need to implement
that.
While the patch cleary shows my little knowledge of the gcc code, and
switches truthvalue checking on unconditionally (and changes C
semantics, so I really suggest to not use it for anything but type
checking), it found some bugs in code I checked with it. (Which of
course already was written in a way it keeps truthvalues and integers
seperate, such a feature is only sensible if you have such a policy from
the start).
It also has suprisingly few false positives, once one
#define __builtin_expect(a,b) (a)
#define __builtin_constant_p(a) (__builtin_constant_p(a) != 0)
and encapsulates all ctype.h functions...

Hochachtungsvoll,
        Bernhard R. Link
Index: gcc/c-common.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.653
diff -u -r1.653 c-common.c
--- gcc/c-common.c      27 Sep 2005 16:04:06 -0000      1.653
+++ gcc/c-common.c      2 Oct 2005 12:30:10 -0000
@@ -2323,6 +2323,10 @@
 tree
 c_common_truthvalue_conversion (tree expr)
 {
+  if (TREE_TYPE (expr) != truthvalue_type_node)
+    {
+      warning (0, "Implicit truth value");
+    }
   switch (TREE_CODE (expr))
     {
     case EQ_EXPR:   case NE_EXPR:   case UNEQ_EXPR: case LTGT_EXPR:
Index: gcc/c-decl.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.685
diff -u -r1.685 c-decl.c
--- gcc/c-decl.c        29 Sep 2005 21:34:24 -0000      1.685
+++ gcc/c-decl.c        2 Oct 2005 12:30:10 -0000
@@ -2714,10 +2714,11 @@
 
   c_common_nodes_and_builtins ();
 
-  /* In C, comparisons and TRUTH_* expressions have type int.  */
-  truthvalue_type_node = integer_type_node;
-  truthvalue_true_node = integer_one_node;
-  truthvalue_false_node = integer_zero_node;
+  truthvalue_type_node = boolean_type_node;
+  /* For this to work, it has to be 0 and 1, which theese are,
+   * but it is a bit ugly that truthvalue is a C frontend speciality */
+  truthvalue_true_node = boolean_true_node;
+  truthvalue_false_node = boolean_false_node;
 
   /* Even in C99, which has a real boolean type.  */
   pushdecl (build_decl (TYPE_DECL, get_identifier ("_Bool"),
Index: gcc/c-parser.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/c-parser.c,v
retrieving revision 2.22
diff -u -r2.22 c-parser.c
--- gcc/c-parser.c      8 Sep 2005 13:09:28 -0000       2.22
+++ gcc/c-parser.c      2 Oct 2005 12:30:11 -0000
@@ -4172,7 +4172,7 @@
       if (pedantic)
        pedwarn ("ISO C forbids omitting the middle term of a ?: expression");
       /* Make sure first operand is calculated only once.  */
-      exp1.value = save_expr (default_conversion (cond.value));
+      exp1.value = save_expr (default_truth_conversion (cond.value));
       cond.value = c_objc_common_truthvalue_conversion (exp1.value);
       skip_evaluation += cond.value == truthvalue_true_node;
     }
@@ -4180,7 +4180,7 @@
     {
       cond.value
        = c_objc_common_truthvalue_conversion
-       (default_conversion (cond.value));
+       (default_truth_conversion (cond.value));
       skip_evaluation += cond.value == truthvalue_false_node;
       exp1 = c_parser_expression_conv (parser);
       skip_evaluation += ((cond.value == truthvalue_true_node)
@@ -4425,14 +4425,14 @@
          stack[sp].expr
            = default_function_array_conversion (stack[sp].expr);
          stack[sp].expr.value = c_objc_common_truthvalue_conversion
-           (default_conversion (stack[sp].expr.value));
+           (default_truth_conversion (stack[sp].expr.value));
          skip_evaluation += stack[sp].expr.value == truthvalue_false_node;
          break;
        case TRUTH_ORIF_EXPR:
          stack[sp].expr
            = default_function_array_conversion (stack[sp].expr);
          stack[sp].expr.value = c_objc_common_truthvalue_conversion
-           (default_conversion (stack[sp].expr.value));
+           (default_truth_conversion (stack[sp].expr.value));
          skip_evaluation += stack[sp].expr.value == truthvalue_true_node;
          break;
        default:
Index: gcc/c-tree.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/c-tree.h,v
retrieving revision 1.209
diff -u -r1.209 c-tree.h
--- gcc/c-tree.h        23 Jul 2005 15:22:45 -0000      1.209
+++ gcc/c-tree.h        2 Oct 2005 12:30:11 -0000
@@ -524,6 +524,7 @@
 extern void c_incomplete_type_error (tree, tree);
 extern tree c_type_promotes_to (tree);
 extern tree default_conversion (tree);
+extern tree default_truth_conversion (tree);
 extern struct c_expr default_function_array_conversion (struct c_expr);
 extern tree composite_type (tree, tree);
 extern tree build_component_ref (tree, tree);
Index: gcc/c-typeck.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.479
diff -u -r1.479 c-typeck.c
--- gcc/c-typeck.c      6 Sep 2005 20:06:52 -0000       1.479
+++ gcc/c-typeck.c      2 Oct 2005 12:30:11 -0000
@@ -1489,6 +1489,48 @@
     }
   return exp;
 }
+tree
+default_truth_conversion (tree exp)
+{
+  tree orig_exp;
+  tree type = TREE_TYPE (exp);
+  enum tree_code code = TREE_CODE (type);
+
+  /* Functions and arrays have been converted during parsing.  */
+  gcc_assert (code != FUNCTION_TYPE);
+  if (code == ARRAY_TYPE)
+    return exp;
+
+  /* Constants can be used directly unless they're not loadable.  */
+  if (TREE_CODE (exp) == CONST_DECL)
+    exp = DECL_INITIAL (exp);
+
+  /* Replace a nonvolatile const static variable with its value unless
+     it is an array, in which case we must be sure that taking the
+     address of the array produces consistent results.  */
+  else if (optimize && TREE_CODE (exp) == VAR_DECL && code != ARRAY_TYPE)
+    {
+      exp = decl_constant_value_for_broken_optimization (exp);
+      type = TREE_TYPE (exp);
+    }
+
+  /* Strip no-op conversions.  */
+  orig_exp = exp;
+  STRIP_TYPE_NOPS (exp);
+
+  if (TREE_NO_WARNING (orig_exp))
+    TREE_NO_WARNING (exp) = 1;
+
+  if (INTEGRAL_TYPE_P (type) && type != truthvalue_type_node )
+    return perform_integral_promotions (exp);
+
+  if (code == VOID_TYPE)
+    {
+      error ("void value not ignored as it ought to be");
+      return error_mark_node;
+    }
+  return exp;
+}
 
 /* Look up COMPONENT in a structure or union DECL.
 
@@ -7566,8 +7608,20 @@
 
   if (convert_p)
     {
-      op0 = default_conversion (orig_op0);
-      op1 = default_conversion (orig_op1);
+        switch( code )
+           {
+           case TRUTH_ANDIF_EXPR:
+           case TRUTH_ORIF_EXPR:
+           case TRUTH_AND_EXPR:
+           case TRUTH_OR_EXPR:
+           case TRUTH_XOR_EXPR:
+               op0 = default_truth_conversion (orig_op0);
+               op1 = default_truth_conversion (orig_op1);
+               break;
+           default:
+               op0 = default_conversion (orig_op0);
+               op1 = default_conversion (orig_op1);
+           }
     }
   else
     {
@@ -7701,18 +7755,21 @@
     case TRUTH_OR_EXPR:
     case TRUTH_XOR_EXPR:
       if ((code0 == INTEGER_TYPE || code0 == POINTER_TYPE
-          || code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
+          || code0 == REAL_TYPE || code0 == COMPLEX_TYPE || code0 == 
BOOLEAN_TYPE)
          && (code1 == INTEGER_TYPE || code1 == POINTER_TYPE
-             || code1 == REAL_TYPE || code1 == COMPLEX_TYPE))
+             || code1 == REAL_TYPE || code1 == COMPLEX_TYPE || code1 == 
BOOLEAN_TYPE))
        {
          /* Result of these operations is always an int,
             but that does not mean the operands should be
             converted to ints!  */
-         result_type = integer_type_node;
+         result_type = truthvalue_type_node;
          op0 = c_common_truthvalue_conversion (op0);
          op1 = c_common_truthvalue_conversion (op1);
          converted = 1;
        }
+      else {
+             warning (0, "bla %d %d : %d %d %d %d 
%d",code0,code1,INTEGER_TYPE,POINTER_TYPE,REAL_TYPE,COMPLEX_TYPE,BOOLEAN_TYPE);
+      }
       break;
 
       /* Shift operations: result has same type as first operand;
@@ -7777,7 +7834,7 @@
                 "comparing floating point with == or != is unsafe");
       /* Result of comparison is always int,
         but don't convert the args to int!  */
-      build_type = integer_type_node;
+      build_type = truthvalue_type_node;
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
           || code0 == COMPLEX_TYPE)
          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
@@ -7838,7 +7895,7 @@
     case GE_EXPR:
     case LT_EXPR:
     case GT_EXPR:
-      build_type = integer_type_node;
+      build_type = truthvalue_type_node;
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
        short_compare = 1;

Reply via email to