summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/c-common.c41
-rw-r--r--gcc/c-common.h13
-rw-r--r--gcc/c-convert.c2
-rw-r--r--gcc/c-decl.c23
-rw-r--r--gcc/c-parse.in3
-rw-r--r--gcc/c-typeck.c49
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/typeck.c13
-rw-r--r--gcc/ginclude/stdbool.h16
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/c99-bool-1.c262
12 files changed, 404 insertions, 44 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6d026b153e1..08d2edfb7a6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,22 @@
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,
c99_block_lineno_labeled_stmt): New.
(simple_if, do_stmt_start): Use c99_block_lineno_labeled_stmt.
diff --git a/gcc/c-common.c b/gcc/c-common.c
index fdc287581cc..e0d8a45a4a5 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -6147,3 +6147,44 @@ c_expand_builtin_printf (arglist, target, tmode, modifier, ignore)
(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;
+}
diff --git a/gcc/c-common.h b/gcc/c-common.h
index 41e771cf780..06c9c61ac12 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -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));
diff --git a/gcc/c-convert.c b/gcc/c-convert.c
index 5d7ea00f82b..7f57725b7c1 100644
--- a/gcc/c-convert.c
+++ b/gcc/c-convert.c
@@ -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)
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 45dbb2c4d83..d9ceac8988e 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -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'");
diff --git a/gcc/c-parse.in b/gcc/c-parse.in
index bbce2caa199..e4daad6d2e0 100644
--- a/gcc/c-parse.in
+++ b/gcc/c-parse.in
@@ -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,
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 08523b5abf2..6705440c3e2 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -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)
{
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1dfd37aa362..7e6d6f7e105 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 06e6deee178..0c628bb4cd1 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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
diff --git a/gcc/ginclude/stdbool.h b/gcc/ginclude/stdbool.h
index 1e49dc0fe74..33f7d3d4110 100644
--- a/gcc/ginclude/stdbool.h
+++ b/gcc/ginclude/stdbool.h
@@ -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 */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index cf20ec6adbd..30345b6c9ed 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
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.
* gcc.dg/c99-scope-2.c: New test.
diff --git a/gcc/testsuite/gcc.dg/c99-bool-1.c b/gcc/testsuite/gcc.dg/c99-bool-1.c
new file mode 100644
index 00000000000..632c486c865
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c99-bool-1.c
@@ -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);
+}