This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Patch to implement C99 _Bool


This patch implements C99's _Bool type in GCC.

Some notes:

(a) It seems to work, judging by the testcase included, but there may
well be some bugs.

(b) Hopefully debug information output will "just work" (using
existing support for output of information for boolean types).

(c) _Bool is always the same size as char, though it can never (except
through reading uninitialized memory or memory initialized with
another type, which is undefined behavior anyway) have any value other
than 0 or 1.  This is binary incompatible with the existing (broken -
based on an old draft) stdbool.h, but hopefully no-one was using that,
and should be compatible with the new C++ ABI.

(d) The code for handling ++ on boolean types can be shared with C++,
so that in the C++ front end is moved by this patch to a function in
c-common.c.

Bootstrapped with no regressions on i686-pc-linux-gnu.  OK to commit?

gcc/ChangeLog:
2000-11-01  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.

gcc/cp/ChangeLog:
2000-11-01  Joseph S. Myers  <jsm28@cam.ac.uk>

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

gcc/testsuite/ChangeLog:
2000-11-01  Joseph S. Myers  <jsm28@cam.ac.uk>

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

--- c-common.c.orig	Tue Oct 24 19:38:02 2000
+++ c-common.c	Tue Oct 31 21:28:54 2000
@@ -6084,3 +6084,44 @@ c_expand_builtin_printf (arglist, target
 		      (ignore ? const0_rtx : target),
 		      tmode, modifier);
 }
+
+
+/* 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;
+}
--- c-common.h.orig	Wed Oct 18 21:27:38 2000
+++ c-common.h	Tue Oct 31 21:12:53 2000
@@ -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]
@@ -690,6 +699,10 @@ extern tree common_type
 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.  */
--- c-convert.c.orig	Sat Jun 24 19:26:42 2000
+++ c-convert.c	Tue Oct 31 21:34:56 2000
@@ -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)
--- c-decl.c.orig	Sun Oct 29 10:45:46 2000
+++ c-decl.c	Tue Oct 31 23:55:08 2000
@@ -3104,6 +3104,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));
@@ -5422,6 +5435,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");
@@ -5431,6 +5445,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))
@@ -5441,10 +5456,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'");
--- c-parse.in.orig	Sun Sep 17 15:40:10 2000
+++ c-parse.in	Tue Oct 31 23:08:57 2000
@@ -2776,6 +2776,7 @@ struct resword

 static const struct resword reswords[] =
 {
+  { "_Bool",		RID_BOOL,	0 },
   { "_Complex",		RID_COMPLEX,	0 },
   { "__alignof",	RID_ALIGNOF,	0 },
   { "__alignof__",	RID_ALIGNOF,	0 },
@@ -2951,7 +2952,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,
--- c-typeck.c.orig	Tue Oct 31 20:35:11 2000
+++ c-typeck.c	Tue Oct 31 22:06:06 2000
@@ -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);
@@ -1732,7 +1735,8 @@ convert_arguments (typelist, values, nam

 	      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);
 	    }
@@ -2789,7 +2793,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)
@@ -2984,18 +2988,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;
 		}
@@ -3020,7 +3029,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)
@@ -3968,6 +3980,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));
@@ -4083,9 +4096,11 @@ convert_for_assignment (type, rhs, errty
     }
   /* 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.
@@ -4265,6 +4280,8 @@ convert_for_assignment (type, rhs, errty
 			   errtype, funname, parmnum);
       return convert (type, rhs);
     }
+  else if (codel == BOOLEAN_TYPE && coder == POINTER_TYPE)
+    return convert (type, rhs);

   if (!errtype)
     {
--- ginclude/stdbool.h.orig	Tue Jan  4 10:12:22 2000
+++ ginclude/stdbool.h	Tue Oct 31 22:49:53 2000
@@ -32,20 +32,10 @@
 #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 */

--- cp/typeck.c.orig	Sun Oct 22 22:34:59 2000
+++ cp/typeck.c	Tue Oct 31 22:07:11 2000
@@ -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
--- testsuite/gcc.dg/c99-bool-1.c.orig	Fri Sep 11 11:31:59 1998
+++ testsuite/gcc.dg/c99-bool-1.c	Wed Nov  1 01:39:00 2000
@@ -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);
+}

-- 
Joseph S. Myers
jsm28@cam.ac.uk


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]