Commit 19552aa5 by Joseph Myers Committed by Joseph Myers

c-common.c (boolean_increment): New function.

	* 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.

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.

From-SVN: r37428
parent 444ca59f
2000-11-13 Joseph S. Myers <jsm28@cam.ac.uk> 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, * c-parse.in (c99_block_start, c99_block_end,
c99_block_lineno_labeled_stmt): New. c99_block_lineno_labeled_stmt): New.
(simple_if, do_stmt_start): Use c99_block_lineno_labeled_stmt. (simple_if, do_stmt_start): Use c99_block_lineno_labeled_stmt.
......
...@@ -6147,3 +6147,44 @@ c_expand_builtin_printf (arglist, target, tmode, modifier, ignore) ...@@ -6147,3 +6147,44 @@ c_expand_builtin_printf (arglist, target, tmode, modifier, ignore)
(ignore ? const0_rtx : target), (ignore ? const0_rtx : target),
tmode, modifier); 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;
}
...@@ -130,9 +130,14 @@ enum c_tree_index ...@@ -130,9 +130,14 @@ enum c_tree_index
CTI_STRING_TYPE, CTI_STRING_TYPE,
CTI_CONST_STRING_TYPE, CTI_CONST_STRING_TYPE,
/* Type for boolean expressions (bool in C++, int in C). */
CTI_BOOLEAN_TYPE, CTI_BOOLEAN_TYPE,
CTI_BOOLEAN_TRUE, CTI_BOOLEAN_TRUE,
CTI_BOOLEAN_FALSE, CTI_BOOLEAN_FALSE,
/* C99's _Bool type. */
CTI_C_BOOL_TYPE,
CTI_C_BOOL_TRUE,
CTI_C_BOOL_FALSE,
CTI_DEFAULT_FUNCTION_TYPE, CTI_DEFAULT_FUNCTION_TYPE,
CTI_VOID_LIST, CTI_VOID_LIST,
...@@ -172,6 +177,10 @@ enum c_tree_index ...@@ -172,6 +177,10 @@ enum c_tree_index
#define boolean_true_node c_global_trees[CTI_BOOLEAN_TRUE] #define boolean_true_node c_global_trees[CTI_BOOLEAN_TRUE]
#define boolean_false_node c_global_trees[CTI_BOOLEAN_FALSE] #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 char_array_type_node c_global_trees[CTI_CHAR_ARRAY_TYPE]
#define wchar_array_type_node c_global_trees[CTI_WCHAR_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] #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)); ...@@ -713,6 +722,10 @@ extern tree expand_tree_builtin PARAMS ((tree, tree, tree));
extern tree decl_constant_value PARAMS ((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 /* Hook currently used only by the C++ front end to reset internal state
after entering or leaving a header file. */ after entering or leaving a header file. */
extern void extract_interface_info PARAMS ((void)); extern void extract_interface_info PARAMS ((void));
......
...@@ -88,6 +88,8 @@ convert (type, expr) ...@@ -88,6 +88,8 @@ convert (type, expr)
#endif #endif
if (code == INTEGER_TYPE || code == ENUMERAL_TYPE) if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
return fold (convert_to_integer (type, e)); 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) if (code == POINTER_TYPE || code == REFERENCE_TYPE)
return fold (convert_to_pointer (type, e)); return fold (convert_to_pointer (type, e));
if (code == REAL_TYPE) if (code == REAL_TYPE)
......
...@@ -3113,6 +3113,19 @@ init_decl_processing () ...@@ -3113,6 +3113,19 @@ init_decl_processing ()
boolean_true_node = integer_one_node; boolean_true_node = integer_one_node;
boolean_false_node = integer_zero_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); string_type_node = build_pointer_type (char_type_node);
const_string_type_node const_string_type_node
= build_pointer_type (build_type_variant (char_type_node, 1, 0)); = build_pointer_type (build_type_variant (char_type_node, 1, 0));
...@@ -5431,6 +5444,7 @@ finish_struct (t, fieldlist, attributes) ...@@ -5431,6 +5444,7 @@ finish_struct (t, fieldlist, attributes)
/* Detect invalid bit-field type. */ /* Detect invalid bit-field type. */
if (DECL_INITIAL (x) if (DECL_INITIAL (x)
&& TREE_CODE (TREE_TYPE (x)) != INTEGER_TYPE && TREE_CODE (TREE_TYPE (x)) != INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (x)) != BOOLEAN_TYPE
&& TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE) && TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE)
{ {
error_with_decl (x, "bit-field `%s' has invalid type"); error_with_decl (x, "bit-field `%s' has invalid type");
...@@ -5440,6 +5454,7 @@ finish_struct (t, fieldlist, attributes) ...@@ -5440,6 +5454,7 @@ finish_struct (t, fieldlist, attributes)
if (DECL_INITIAL (x) && pedantic if (DECL_INITIAL (x) && pedantic
&& TYPE_MAIN_VARIANT (TREE_TYPE (x)) != integer_type_node && TYPE_MAIN_VARIANT (TREE_TYPE (x)) != integer_type_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (x)) != unsigned_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. */ /* Accept an enum that's equivalent to int or unsigned int. */
&& !(TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE && !(TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
&& (TYPE_PRECISION (TREE_TYPE (x)) && (TYPE_PRECISION (TREE_TYPE (x))
...@@ -5450,10 +5465,14 @@ finish_struct (t, fieldlist, attributes) ...@@ -5450,10 +5465,14 @@ finish_struct (t, fieldlist, attributes)
field widths. */ field widths. */
if (DECL_INITIAL (x)) 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) if (tree_int_cst_sgn (DECL_INITIAL (x)) < 0)
error_with_decl (x, "negative width in bit-field `%s'"); error_with_decl (x, "negative width in bit-field `%s'");
else if (0 < compare_tree_int (DECL_INITIAL (x), else if (0 < compare_tree_int (DECL_INITIAL (x), max_width))
TYPE_PRECISION (TREE_TYPE (x))))
pedwarn_with_decl (x, "width of `%s' exceeds its type"); pedwarn_with_decl (x, "width of `%s' exceeds its type");
else if (integer_zerop (DECL_INITIAL (x)) && DECL_NAME (x) != 0) else if (integer_zerop (DECL_INITIAL (x)) && DECL_NAME (x) != 0)
error_with_decl (x, "zero width for bit-field `%s'"); error_with_decl (x, "zero width for bit-field `%s'");
......
...@@ -2832,6 +2832,7 @@ struct resword ...@@ -2832,6 +2832,7 @@ struct resword
static const struct resword reswords[] = static const struct resword reswords[] =
{ {
{ "_Bool", RID_BOOL, 0 },
{ "_Complex", RID_COMPLEX, 0 }, { "_Complex", RID_COMPLEX, 0 },
{ "__alignof", RID_ALIGNOF, 0 }, { "__alignof", RID_ALIGNOF, 0 },
{ "__alignof__", RID_ALIGNOF, 0 }, { "__alignof__", RID_ALIGNOF, 0 },
...@@ -3007,7 +3008,7 @@ static const short rid_to_yy[RID_MAX] = ...@@ -3007,7 +3008,7 @@ static const short rid_to_yy[RID_MAX] =
/* RID_PTRVALUE */ PTR_VALUE, /* RID_PTRVALUE */ PTR_VALUE,
/* C++ */ /* C++ */
/* RID_BOOL */ 0, /* RID_BOOL */ TYPESPEC,
/* RID_WCHAR */ 0, /* RID_WCHAR */ 0,
/* RID_CLASS */ 0, /* RID_CLASS */ 0,
/* RID_PUBLIC */ 0, /* RID_PUBLIC */ 0,
......
...@@ -947,6 +947,9 @@ default_conversion (exp) ...@@ -947,6 +947,9 @@ default_conversion (exp)
return convert (integer_type_node, exp); return convert (integer_type_node, exp);
} }
if (code == BOOLEAN_TYPE)
return convert (integer_type_node, exp);
if (flag_traditional && !flag_allow_single_precision if (flag_traditional && !flag_allow_single_precision
&& TYPE_MAIN_VARIANT (type) == float_type_node) && TYPE_MAIN_VARIANT (type) == float_type_node)
return convert (double_type_node, exp); return convert (double_type_node, exp);
...@@ -1733,7 +1736,8 @@ convert_arguments (typelist, values, name, fundecl) ...@@ -1733,7 +1736,8 @@ convert_arguments (typelist, values, name, fundecl)
if (PROMOTE_PROTOTYPES if (PROMOTE_PROTOTYPES
&& (TREE_CODE (type) == INTEGER_TYPE && (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))) && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
parmval = default_conversion (parmval); parmval = default_conversion (parmval);
} }
...@@ -2790,7 +2794,7 @@ build_unary_op (code, xarg, noconvert) ...@@ -2790,7 +2794,7 @@ build_unary_op (code, xarg, noconvert)
if (typecode == ERROR_MARK) if (typecode == ERROR_MARK)
return error_mark_node; return error_mark_node;
if (typecode == ENUMERAL_TYPE) if (typecode == ENUMERAL_TYPE || typecode == BOOLEAN_TYPE)
typecode = INTEGER_TYPE; typecode = INTEGER_TYPE;
switch (code) switch (code)
...@@ -2985,18 +2989,23 @@ build_unary_op (code, xarg, noconvert) ...@@ -2985,18 +2989,23 @@ build_unary_op (code, xarg, noconvert)
else else
{ {
tree incremented, modify, value; tree incremented, modify, value;
arg = stabilize_reference (arg); if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR) value = boolean_increment (code, arg);
value = arg;
else else
value = save_expr (arg); {
incremented = build (((code == PREINCREMENT_EXPR arg = stabilize_reference (arg);
|| code == POSTINCREMENT_EXPR) if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
? PLUS_EXPR : MINUS_EXPR), value = arg;
argtype, value, inc); else
TREE_SIDE_EFFECTS (incremented) = 1; value = save_expr (arg);
modify = build_modify_expr (arg, NOP_EXPR, incremented); incremented = build (((code == PREINCREMENT_EXPR
value = build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value); || 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; TREE_USED (value) = 1;
return value; return value;
} }
...@@ -3021,7 +3030,10 @@ build_unary_op (code, xarg, noconvert) ...@@ -3021,7 +3030,10 @@ build_unary_op (code, xarg, noconvert)
|| code == POSTINCREMENT_EXPR) || code == POSTINCREMENT_EXPR)
? "increment" : "decrement")); ? "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; TREE_SIDE_EFFECTS (val) = 1;
val = convert (result_type, val); val = convert (result_type, val);
if (TREE_CODE (val) != code) if (TREE_CODE (val) != code)
...@@ -3969,6 +3981,7 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -3969,6 +3981,7 @@ build_modify_expr (lhs, modifycode, rhs)
if (TREE_CODE (lhs) == COMPONENT_REF if (TREE_CODE (lhs) == COMPONENT_REF
&& (TREE_CODE (lhstype) == INTEGER_TYPE && (TREE_CODE (lhstype) == INTEGER_TYPE
|| TREE_CODE (lhstype) == BOOLEAN_TYPE
|| TREE_CODE (lhstype) == REAL_TYPE || TREE_CODE (lhstype) == REAL_TYPE
|| TREE_CODE (lhstype) == ENUMERAL_TYPE)) || TREE_CODE (lhstype) == ENUMERAL_TYPE))
lhstype = TREE_TYPE (get_unwidened (lhs, 0)); lhstype = TREE_TYPE (get_unwidened (lhs, 0));
...@@ -4084,9 +4097,11 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum) ...@@ -4084,9 +4097,11 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
} }
/* Arithmetic types all interconvert, and enum is treated like int. */ /* Arithmetic types all interconvert, and enum is treated like int. */
else if ((codel == INTEGER_TYPE || codel == REAL_TYPE 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 == 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); return convert_and_check (type, rhs);
/* Conversion to a transparent union from its member types. /* Conversion to a transparent union from its member types.
...@@ -4266,6 +4281,8 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum) ...@@ -4266,6 +4281,8 @@ convert_for_assignment (type, rhs, errtype, fundecl, funname, parmnum)
errtype, funname, parmnum); errtype, funname, parmnum);
return convert (type, rhs); return convert (type, rhs);
} }
else if (codel == BOOLEAN_TYPE && coder == POINTER_TYPE)
return convert (type, rhs);
if (!errtype) if (!errtype)
{ {
......
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> 2000-11-11 Jason Merrill <jason@redhat.com>
* typeck.c (mark_addressable): Don't call put_var_into_stack. * typeck.c (mark_addressable): Don't call put_var_into_stack.
......
...@@ -4580,18 +4580,7 @@ build_unary_op (code, xarg, noconvert) ...@@ -4580,18 +4580,7 @@ build_unary_op (code, xarg, noconvert)
my patch to expand_increment. (jason) */ my patch to expand_increment. (jason) */
val = build (code, TREE_TYPE (arg), arg, inc); val = build (code, TREE_TYPE (arg), arg, inc);
#else #else
if (code == POSTINCREMENT_EXPR) val = boolean_increment (code, arg);
{
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);
#endif #endif
} }
else else
......
...@@ -32,20 +32,10 @@ Boston, MA 02111-1307, USA. */ ...@@ -32,20 +32,10 @@ Boston, MA 02111-1307, USA. */
#define _STDBOOL_H #define _STDBOOL_H
#ifndef __cplusplus #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 */ #else /* __cplusplus */
......
2000-11-13 Joseph S. Myers <jsm28@cam.ac.uk> 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-1.c: Remove xfail.
* gcc.dg/c99-scope-2.c: New test. * gcc.dg/c99-scope-2.c: New test.
......
/* 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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment