]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
* c-common.c (boolean_increment): New function.
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 13 Nov 2000 14:14:44 +0000 (14:14 +0000)
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 13 Nov 2000 14:14:44 +0000 (14:14 +0000)
* c-common.h (enum c_tree_index): Add CTI_C_BOOL_TYPE,
CTI_C_BOOL_TRUE and CTI_C_BOOL_FALSE.
(c_bool_type_node, c_bool_true_node, c_bool_false_node): Define.
(boolean_increment): Declare.
* c-convert.c (convert): Allow for BOOLEAN_TYPE.
* c-decl.c (init_decl_processing): Create boolean nodes.
(finish_struct): Allow for _Bool bitfields.
* c-parse.in (reswords): Add _Bool.
(rid_to_yy): Allow for RID_BOOL.
* c-typeck.c (default_conversion): Make booleans promote to int.
(convert_arguments, build_unary_op, build_modify_expr,
convert_for_assignment): Allow for booleans.
* ginclude/stdbool.h: Make conforming to C99.

cp:
* typeck.c (build_unary_op): Use boolean_increment from
c-common.c, moving the relevant code there.

testsuite:
* gcc.dg/c99-bool-1.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@37428 138bc75d-0d04-0410-961f-82ee72b054a4

12 files changed:
gcc/ChangeLog
gcc/c-common.c
gcc/c-common.h
gcc/c-convert.c
gcc/c-decl.c
gcc/c-parse.in
gcc/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/ginclude/stdbool.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/c99-bool-1.c [new file with mode: 0644]

index 6d026b153e1ba51af3bfc8946d12d3de6f88eea2..08d2edfb7a64704140529cc789e237219e30a365 100644 (file)
@@ -1,3 +1,20 @@
+2000-11-13  Joseph S. Myers  <jsm28@cam.ac.uk>
+
+       * c-common.c (boolean_increment): New function.
+       * c-common.h (enum c_tree_index): Add CTI_C_BOOL_TYPE,
+       CTI_C_BOOL_TRUE and CTI_C_BOOL_FALSE.
+       (c_bool_type_node, c_bool_true_node, c_bool_false_node): Define.
+       (boolean_increment): Declare.
+       * c-convert.c (convert): Allow for BOOLEAN_TYPE.
+       * c-decl.c (init_decl_processing): Create boolean nodes.
+       (finish_struct): Allow for _Bool bitfields.
+       * c-parse.in (reswords): Add _Bool.
+       (rid_to_yy): Allow for RID_BOOL.
+       * c-typeck.c (default_conversion): Make booleans promote to int.
+       (convert_arguments, build_unary_op, build_modify_expr,
+       convert_for_assignment): Allow for booleans.
+       * ginclude/stdbool.h: Make conforming to C99.
+
 2000-11-13  Joseph S. Myers  <jsm28@cam.ac.uk>
 
        * c-parse.in (c99_block_start, c99_block_end,
index fdc287581cc47316061f35456af4674af80b4b6d..e0d8a45a4a5120dee87a47cca95740a1d9966933 100644 (file)
@@ -6147,3 +6147,44 @@ c_expand_builtin_printf (arglist, target, tmode, modifier, ignore)
                      (ignore ? const0_rtx : target),
                      tmode, modifier);
 }
+\f
+
+/* Given a boolean expression ARG, return a tree representing an increment
+   or decrement (as indicated by CODE) of ARG.  The front end must check for
+   invalid cases (e.g., decrement in C++).  */
+tree
+boolean_increment (code, arg)
+     enum tree_code code;
+     tree arg;
+{
+  tree val;
+  tree true_res = (c_language == clk_cplusplus
+                  ? boolean_true_node
+                  : c_bool_true_node);
+  arg = stabilize_reference (arg);
+  switch (code)
+    {
+    case PREINCREMENT_EXPR:
+      val = build (MODIFY_EXPR, TREE_TYPE (arg), arg, true_res);
+      break;
+    case POSTINCREMENT_EXPR:
+      val = build (MODIFY_EXPR, TREE_TYPE (arg), arg, true_res);
+      arg = save_expr (arg);
+      val = build (COMPOUND_EXPR, TREE_TYPE (arg), val, arg);
+      val = build (COMPOUND_EXPR, TREE_TYPE (arg), arg, val);
+      break;
+    case PREDECREMENT_EXPR:
+      val = build (MODIFY_EXPR, TREE_TYPE (arg), arg, invert_truthvalue (arg));
+      break;
+    case POSTDECREMENT_EXPR:
+      val = build (MODIFY_EXPR, TREE_TYPE (arg), arg, invert_truthvalue (arg));
+      arg = save_expr (arg);
+      val = build (COMPOUND_EXPR, TREE_TYPE (arg), val, arg);
+      val = build (COMPOUND_EXPR, TREE_TYPE (arg), arg, val);
+      break;
+    default:
+      abort ();
+    }
+  TREE_SIDE_EFFECTS (val) = 1;
+  return val;
+}
index 41e771cf7800d47ea43e155a052276510f9a06ca..06c9c61ac12998f54e409664e6f804f564f2bca1 100644 (file)
@@ -130,9 +130,14 @@ enum c_tree_index
     CTI_STRING_TYPE,
     CTI_CONST_STRING_TYPE,
 
+    /* Type for boolean expressions (bool in C++, int in C).  */
     CTI_BOOLEAN_TYPE,
     CTI_BOOLEAN_TRUE,
     CTI_BOOLEAN_FALSE,
+    /* C99's _Bool type.  */
+    CTI_C_BOOL_TYPE,
+    CTI_C_BOOL_TRUE,
+    CTI_C_BOOL_FALSE,
     CTI_DEFAULT_FUNCTION_TYPE,
     CTI_VOID_LIST,
 
@@ -172,6 +177,10 @@ enum c_tree_index
 #define boolean_true_node              c_global_trees[CTI_BOOLEAN_TRUE]
 #define boolean_false_node             c_global_trees[CTI_BOOLEAN_FALSE]
 
+#define c_bool_type_node               c_global_trees[CTI_C_BOOL_TYPE]
+#define c_bool_true_node               c_global_trees[CTI_C_BOOL_TRUE]
+#define c_bool_false_node              c_global_trees[CTI_C_BOOL_FALSE]
+
 #define char_array_type_node           c_global_trees[CTI_CHAR_ARRAY_TYPE]
 #define wchar_array_type_node          c_global_trees[CTI_WCHAR_ARRAY_TYPE]
 #define int_array_type_node            c_global_trees[CTI_INT_ARRAY_TYPE]
@@ -713,6 +722,10 @@ extern tree expand_tree_builtin                 PARAMS ((tree, tree, tree));
 
 extern tree decl_constant_value                PARAMS ((tree));
 
+/* Handle increment and decrement of boolean types.  */
+extern tree boolean_increment                  PARAMS ((enum tree_code,
+                                                        tree));
+
 /* Hook currently used only by the C++ front end to reset internal state
    after entering or leaving a header file.  */
 extern void extract_interface_info             PARAMS ((void));
index 5d7ea00f82bb62cb5f89785e44b8a9b024c2b918..7f57725b7c16039551a911efcc9d1d7f40c87766 100644 (file)
@@ -88,6 +88,8 @@ convert (type, expr)
 #endif
   if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
     return fold (convert_to_integer (type, e));
+  if (code == BOOLEAN_TYPE)
+    return fold (build1 (NOP_EXPR, type, truthvalue_conversion (expr)));
   if (code == POINTER_TYPE || code == REFERENCE_TYPE)
     return fold (convert_to_pointer (type, e));
   if (code == REAL_TYPE)
index 45dbb2c4d83682075dd6a0b91583431d77cf579f..d9ceac8988ef3f749fcbd60064ea53ff6214c812 100644 (file)
@@ -3113,6 +3113,19 @@ init_decl_processing ()
   boolean_true_node = integer_one_node;
   boolean_false_node = integer_zero_node;
 
+  /* With GCC, C99's _Bool is always of size 1.  */
+  c_bool_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
+  TREE_SET_CODE (c_bool_type_node, BOOLEAN_TYPE);
+  TYPE_MAX_VALUE (c_bool_type_node) = build_int_2 (1, 0);
+  TREE_TYPE (TYPE_MAX_VALUE (c_bool_type_node)) = c_bool_type_node;
+  TYPE_PRECISION (c_bool_type_node) = 1;
+  pushdecl (build_decl (TYPE_DECL, get_identifier ("_Bool"),
+                       c_bool_type_node));
+  c_bool_false_node = build_int_2 (0, 0);
+  TREE_TYPE (c_bool_false_node) = c_bool_type_node;
+  c_bool_true_node = build_int_2 (1, 0);
+  TREE_TYPE (c_bool_true_node) = c_bool_type_node;
+
   string_type_node = build_pointer_type (char_type_node);
   const_string_type_node
     = build_pointer_type (build_type_variant (char_type_node, 1, 0));
@@ -5431,6 +5444,7 @@ finish_struct (t, fieldlist, attributes)
       /* Detect invalid bit-field type.  */
       if (DECL_INITIAL (x)
          && TREE_CODE (TREE_TYPE (x)) != INTEGER_TYPE
+         && TREE_CODE (TREE_TYPE (x)) != BOOLEAN_TYPE
          && TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE)
        {
          error_with_decl (x, "bit-field `%s' has invalid type");
@@ -5440,6 +5454,7 @@ finish_struct (t, fieldlist, attributes)
       if (DECL_INITIAL (x) && pedantic
          && TYPE_MAIN_VARIANT (TREE_TYPE (x)) != integer_type_node
          && TYPE_MAIN_VARIANT (TREE_TYPE (x)) != unsigned_type_node
+         && TYPE_MAIN_VARIANT (TREE_TYPE (x)) != c_bool_type_node
          /* Accept an enum that's equivalent to int or unsigned int.  */
          && !(TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
               && (TYPE_PRECISION (TREE_TYPE (x))
@@ -5450,10 +5465,14 @@ finish_struct (t, fieldlist, attributes)
         field widths.  */
       if (DECL_INITIAL (x))
        {
+         int max_width;
+         if (TYPE_MAIN_VARIANT (TREE_TYPE (x)) == c_bool_type_node)
+           max_width = CHAR_TYPE_SIZE;
+         else
+           max_width = TYPE_PRECISION (TREE_TYPE (x));
          if (tree_int_cst_sgn (DECL_INITIAL (x)) < 0)
            error_with_decl (x, "negative width in bit-field `%s'");
-         else if (0 < compare_tree_int (DECL_INITIAL (x),
-                                        TYPE_PRECISION (TREE_TYPE (x))))
+         else if (0 < compare_tree_int (DECL_INITIAL (x), max_width))
            pedwarn_with_decl (x, "width of `%s' exceeds its type");
          else if (integer_zerop (DECL_INITIAL (x)) && DECL_NAME (x) != 0)
            error_with_decl (x, "zero width for bit-field `%s'");
index bbce2caa199c232580fa0ded300e2521f106acbf..e4daad6d2e0ac20bb607fd8c102e1b63aaa054c1 100644 (file)
@@ -2832,6 +2832,7 @@ struct resword
 
 static const struct resword reswords[] =
 {
+  { "_Bool",           RID_BOOL,       0 },
   { "_Complex",                RID_COMPLEX,    0 },
   { "__alignof",       RID_ALIGNOF,    0 },
   { "__alignof__",     RID_ALIGNOF,    0 },
@@ -3007,7 +3008,7 @@ static const short rid_to_yy[RID_MAX] =
   /* RID_PTRVALUE */   PTR_VALUE,
 
   /* C++ */
-  /* RID_BOOL */       0,
+  /* RID_BOOL */       TYPESPEC,
   /* RID_WCHAR */      0,
   /* RID_CLASS */      0,
   /* RID_PUBLIC */     0,
index 08523b5abf2859ab21eec9ad097cf9993d665623..6705440c3e2d283bc6db8e50fb13b29742d07f28 100644 (file)
@@ -947,6 +947,9 @@ default_conversion (exp)
       return convert (integer_type_node, exp);
     }
 
+  if (code == BOOLEAN_TYPE)
+    return convert (integer_type_node, exp);
+
   if (flag_traditional && !flag_allow_single_precision
       && TYPE_MAIN_VARIANT (type) == float_type_node)
     return convert (double_type_node, exp);
@@ -1733,7 +1736,8 @@ convert_arguments (typelist, values, name, fundecl)
              
              if (PROMOTE_PROTOTYPES
                  && (TREE_CODE (type) == INTEGER_TYPE
-                     || TREE_CODE (type) == ENUMERAL_TYPE)
+                     || TREE_CODE (type) == ENUMERAL_TYPE
+                     || TREE_CODE (type) == BOOLEAN_TYPE)
                  && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
                parmval = default_conversion (parmval);
            }
@@ -2790,7 +2794,7 @@ build_unary_op (code, xarg, noconvert)
 
   if (typecode == ERROR_MARK)
     return error_mark_node;
-  if (typecode == ENUMERAL_TYPE)
+  if (typecode == ENUMERAL_TYPE || typecode == BOOLEAN_TYPE)
     typecode = INTEGER_TYPE;
 
   switch (code)
@@ -2985,18 +2989,23 @@ build_unary_op (code, xarg, noconvert)
              else
                {
                  tree incremented, modify, value;
-                 arg = stabilize_reference (arg);
-                 if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
-                   value = arg;
+                 if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
+                   value = boolean_increment (code, arg);
                  else
-                   value = save_expr (arg);
-                 incremented = build (((code == PREINCREMENT_EXPR
-                                        || code == POSTINCREMENT_EXPR)
-                                       ? PLUS_EXPR : MINUS_EXPR),
-                                      argtype, value, inc);
-                 TREE_SIDE_EFFECTS (incremented) = 1;
-                 modify = build_modify_expr (arg, NOP_EXPR, incremented);
-                 value = build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value);
+                   {
+                     arg = stabilize_reference (arg);
+                     if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
+                       value = arg;
+                     else
+                       value = save_expr (arg);
+                     incremented = build (((code == PREINCREMENT_EXPR
+                                            || code == POSTINCREMENT_EXPR)
+                                           ? PLUS_EXPR : MINUS_EXPR),
+                                          argtype, value, inc);
+                     TREE_SIDE_EFFECTS (incremented) = 1;
+                     modify = build_modify_expr (arg, NOP_EXPR, incremented);
+                     value = build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value);
+                   }
                  TREE_USED (value) = 1;
                  return value;
                }
@@ -3021,7 +3030,10 @@ build_unary_op (code, xarg, noconvert)
                              || code == POSTINCREMENT_EXPR)
                             ? "increment" : "decrement"));
 
-       val = build (code, TREE_TYPE (arg), arg, inc);
+       if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
+         val = boolean_increment (code, arg);
+       else
+         val = build (code, TREE_TYPE (arg), arg, inc);
        TREE_SIDE_EFFECTS (val) = 1;
        val = convert (result_type, val);
        if (TREE_CODE (val) != code)
@@ -3969,6 +3981,7 @@ build_modify_expr (lhs, modifycode, rhs)
 
   if (TREE_CODE (lhs) == COMPONENT_REF
       && (TREE_CODE (lhstype) == INTEGER_TYPE
+         || TREE_CODE (lhstype) == BOOLEAN_TYPE
          || TREE_CODE (lhstype) == REAL_TYPE
          || TREE_CODE (lhstype) == ENUMERAL_TYPE))
     lhstype = TREE_TYPE (get_unwidened (lhs, 0));
@@ -4084,9 +4097,11 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
     }
   /* Arithmetic types all interconvert, and enum is treated like int.  */
   else if ((codel == INTEGER_TYPE || codel == REAL_TYPE 
-           || codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE)
+           || codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE
+           || codel == BOOLEAN_TYPE)
           && (coder == INTEGER_TYPE || coder == REAL_TYPE 
-              || coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE))
+              || coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE
+              || coder == BOOLEAN_TYPE))
     return convert_and_check (type, rhs);
 
   /* Conversion to a transparent union from its member types.
@@ -4266,6 +4281,8 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
                           errtype, funname, parmnum);
       return convert (type, rhs);
     }
+  else if (codel == BOOLEAN_TYPE && coder == POINTER_TYPE)
+    return convert (type, rhs);
 
   if (!errtype)
     {
index 1dfd37aa362032eeddc813e1bbf28aaac2923b28..7e6d6f7e105a6dc935a3dba6d8e321f98ed602ca 100644 (file)
@@ -1,3 +1,8 @@
+2000-11-13  Joseph S. Myers  <jsm28@cam.ac.uk>
+
+       * typeck.c (build_unary_op): Use boolean_increment from
+       c-common.c, moving the relevant code there.
+
 2000-11-11  Jason Merrill  <jason@redhat.com>
 
        * typeck.c (mark_addressable): Don't call put_var_into_stack.
index 06e6deee178e3db80e93ddc4f4f0dc4fa1986e3e..0c628bb4cd10946cbb918e36534edd8bf75bea1b 100644 (file)
@@ -4580,18 +4580,7 @@ build_unary_op (code, xarg, noconvert)
               my patch to expand_increment. (jason)  */
            val = build (code, TREE_TYPE (arg), arg, inc);
 #else
-           if (code == POSTINCREMENT_EXPR)
-             {
-               arg = stabilize_reference (arg);
-               val = build (MODIFY_EXPR, TREE_TYPE (arg), arg,
-                            boolean_true_node);
-               arg = save_expr (arg);
-               val = build (COMPOUND_EXPR, TREE_TYPE (arg), val, arg);
-               val = build (COMPOUND_EXPR, TREE_TYPE (arg), arg, val);
-             }
-           else
-             val = build (MODIFY_EXPR, TREE_TYPE (arg), arg,
-                          boolean_true_node);
+           val = boolean_increment (code, arg);
 #endif
          }
        else
index 1e49dc0fe7435bcd9c37ee553d0864443766102d..33f7d3d4110b843db57318b478db8a76b4f4c932 100644 (file)
@@ -32,20 +32,10 @@ Boston, MA 02111-1307, USA.  */
 #define _STDBOOL_H
 
 #ifndef __cplusplus
-/* The type `_Bool' must promote to `int' or `unsigned int'.  The constants
-   `true' and `false' must have the value 0 and 1 respectively.  */
-typedef enum
-  {
-    false = 0,
-    true = 1
-  } _Bool;
-
-/* The names `true' and `false' must also be made available as macros.  */
-#define false  false
-#define true   true
 
-/* The macro `bool', which may be undefined, expands to _Bool.  */
-#define bool _Bool
+#define bool   _Bool
+#define true   1
+#define false  0
 
 #else /* __cplusplus */
 
index cf20ec6adbd782db0357cb3d657d8310fa4c2af3..30345b6c9ed569299d27a1f99b7953609c4a178e 100644 (file)
@@ -1,3 +1,7 @@
+2000-11-13  Joseph S. Myers  <jsm28@cam.ac.uk>
+
+       * gcc.dg/c99-bool-1.c: New test.
+
 2000-11-13  Joseph S. Myers  <jsm28@cam.ac.uk>
 
        * gcc.dg/c99-scope-1.c: Remove xfail.
diff --git a/gcc/testsuite/gcc.dg/c99-bool-1.c b/gcc/testsuite/gcc.dg/c99-bool-1.c
new file mode 100644 (file)
index 0000000..632c486
--- /dev/null
@@ -0,0 +1,262 @@
+/* Test for _Bool and <stdbool.h> in C99.  */
+/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
+/* { dg-do run } */
+/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
+
+/* _Bool must be a builtin type.  */
+
+_Bool foo;
+
+#include <stdbool.h>
+
+/* Three macros must be integer constant expressions suitable for use
+   in #if.
+*/
+
+#if !defined(true) || (true != 1)
+#error "bad stdbool true" /* { dg-bogus "#error" "bad stdbool.h" } */
+#endif
+
+#if !defined(false) || (false != 0)
+#error "bad stdbool false" /* { dg-bogus "#error" "bad stdbool.h" } */
+#endif
+
+#if !defined(__bool_true_false_are_defined) || (__bool_true_false_are_defined != 1)
+#error "bad stdbool __bool_true_false_are_defined" /* { dg-bogus "#error" "bad stdbool.h" } */
+#endif
+
+int a = true;
+int b = false;
+int c = __bool_true_false_are_defined;
+
+struct foo
+{
+  _Bool a : 1;
+  _Bool b : 2;
+  _Bool c : 7;
+} sf;
+
+#define str(x) xstr(x)
+#define xstr(x) #x
+
+
+extern void abort (void);
+extern void exit (int);
+extern int strcmp (const char *, const char *);
+
+int
+main (void)
+{
+  /* The macro `bool' must expand to _Bool.  */
+  const char *t = str (bool);
+  _Bool u, v;
+  if (strcmp (t, "_Bool"))
+    abort ();
+  if (a != 1 || b != 0 || c != 1)
+    abort ();
+  /* Casts to _Bool have a specified behaviour.  */
+  if ((int)(_Bool)2 != 1)
+    abort ();
+  if ((int)(_Bool)0.2 != 1)
+    abort ();
+  /* Pointers may be assigned to _Bool.  */
+  if ((u = t) != 1)
+    abort ();
+  /* _Bool may be used to subscript arrays.  */
+  u = 0;
+  if (t[u] != '_')
+    abort ();
+  if (u[t] != '_')
+    abort ();
+  u = 1;
+  if (t[u] != 'B')
+    abort ();
+  if (u[t] != 'B')
+    abort ();
+  /* Test increment and decrement operators.  */
+  u = 0;
+  if (u++ != 0)
+    abort ();
+  if (u != 1)
+    abort ();
+  if (u++ != 1)
+    abort ();
+  if (u != 1)
+    abort ();
+  u = 0;
+  if (++u != 1)
+    abort ();
+  if (u != 1)
+    abort ();
+  if (++u != 1)
+    abort ();
+  if (u != 1)
+    abort ();
+  u = 0;
+  if (u-- != 0)
+    abort ();
+  if (u != 1)
+    abort ();
+  if (u-- != 1)
+    abort ();
+  if (u != 0)
+    abort ();
+  u = 0;
+  if (--u != 1)
+    abort ();
+  if (u != 1)
+    abort ();
+  if (--u != 0)
+    abort ();
+  if (u != 0)
+    abort ();
+  /* Test unary + - ~ !.  */
+  u = 0;
+  if (+u != 0)
+    abort ();
+  if (-u != 0)
+    abort ();
+  u = 1;
+  if (+u != 1)
+    abort ();
+  if (-u != -1)
+    abort ();
+  u = 2;
+  if (+u != 1)
+    abort ();
+  if (-u != -1)
+    abort ();
+  u = 0;
+  if (~u != ~(int)0)
+    abort ();
+  u = 1;
+  if (~u != ~(int)1)
+    abort ();
+  u = 0;
+  if (!u != 1)
+    abort ();
+  u = 1;
+  if (!u != 0)
+    abort ();
+  /* Test arithmetic * / % + - (which all apply promotions).  */
+  u = 0;
+  if (u + 2 != 2)
+    abort ();
+  u = 1;
+  if (u * 4 != 4)
+    abort ();
+  if (u % 3 != 1)
+    abort ();
+  if (u / 1 != 1)
+    abort ();
+  if (4 / u != 4)
+    abort ();
+  if (u - 7 != -6)
+    abort ();
+  /* Test bitwise shift << >>.  */
+  u = 1;
+  if (u << 1 != 2)
+    abort ();
+  if (u >> 1 != 0)
+    abort ();
+  /* Test relational and equality operators < > <= >= == !=.  */
+  u = 0;
+  v = 0;
+  if (u < v || u > v || !(u <= v) || !(u >= v) || !(u == v) || u != v)
+    abort ();
+  u = 0;
+  v = 1;
+  if (!(u < v) || u > v || !(u <= v) || u >= v || u == v || !(u != v))
+    abort ();
+  /* Test bitwise operators & ^ |.  */
+  u = 1;
+  if ((u | 2) != 3)
+    abort ();
+  if ((u ^ 3) != 2)
+    abort ();
+  if ((u & 1) != 1)
+    abort ();
+  if ((u & 0) != 0)
+    abort ();
+  /* Test logical && ||.  */
+  u = 0;
+  v = 1;
+  if (!(u || v))
+    abort ();
+  if (!(v || u))
+    abort ();
+  if (u && v)
+    abort ();
+  if (v && u)
+    abort ();
+  u = 1;
+  v = 1;
+  if (!(u && v))
+    abort ();
+  /* Test conditional ? :.  */
+  u = 0;
+  if ((u ? 4 : 7) != 7)
+    abort ();
+  u = 1;
+  v = 0;
+  if ((1 ? u : v) != 1)
+    abort ();
+  if ((1 ? 4 : u) != 4)
+    abort ();
+  /* Test assignment operators = *= /= %= += -= <<= >>= &= ^= |=.  */
+  if ((u = 2) != 1)
+    abort ();
+  if (u != 1)
+    abort ();
+  if ((u *= -1) != 1)
+    abort ();
+  if (u != 1)
+    abort ();
+  if ((u /= 2) != 0)
+    abort ();
+  if ((u += 3) != 1)
+    abort ();
+  if ((u -= 1) != 0)
+    abort ();
+  u = 1;
+  if ((u <<= 4) != 1)
+    abort ();
+  if ((u >>= 1) != 0)
+    abort ();
+  u = 1;
+  if ((u &= 0) != 0)
+    abort ();
+  if ((u |= 2) != 1)
+    abort ();
+  if ((u ^= 3) != 1)
+    abort ();
+  /* Test comma expressions.  */
+  u = 1;
+  if ((4, u) != 1)
+    abort ();
+  /* Test bitfields.  */
+  {
+    int i;
+    for (i = 0; i < sizeof (struct foo); i++)
+      *((unsigned char *)&sf + i) = (unsigned char) -1;
+    sf.a = 1;
+    if (sf.a != 1)
+      abort ();
+    sf.b = 1;
+    if (sf.b != 1)
+      abort ();
+    sf.c = 1;
+    if (sf.c != 1)
+      abort ();
+    sf.a = 0;
+    if (sf.a != 0)
+      abort ();
+    sf.b = 0;
+    if (sf.b != 0)
+      abort ();
+    sf.c = 0;
+    if (sf.c != 0)
+      abort ();
+  }
+  exit (0);
+}