From f7fd775f0203c580b35b179976c665db3e4d9e46 Mon Sep 17 00:00:00 2001 From: Joerg Wunsch Date: Tue, 5 Jun 2007 22:25:27 +0000 Subject: [PATCH] re PR preprocessor/23479 (Implement binary constants with a "0b" prefix) 2007-06-05 Joerg Wunsch PR preprocessor/23479 gcc/ * doc/extend.texi: Document the 0b-prefixed binary integer constant extension. libcpp/ * expr.c (cpp_classify_number): Implement 0b-prefixed binary integer constants. (append_digit): Likewise. * include/cpplib.h: Add CPP_N_BINARY, to be used for 0b-prefixed binary integer constants. testsuite/ * testsuite/gcc.dg/binary-constants-1.c: Add test suites for the 0b-prefixed binary integer constants. * testsuite/gcc.dg/binary-constants-2.c: Ditto. * testsuite/gcc.dg/binary-constants-3.c: Ditto. * testsuite/gcc.dg/binary-constants-4.c: Ditto. From-SVN: r125346 --- gcc/ChangeLog | 6 + gcc/doc/extend.texi | 23 ++ gcc/testsuite/ChangeLog | 9 + gcc/testsuite/gcc.dg/binary-constants-1.c | 312 ++++++++++++++++++++++ gcc/testsuite/gcc.dg/binary-constants-2.c | 16 ++ gcc/testsuite/gcc.dg/binary-constants-3.c | 16 ++ gcc/testsuite/gcc.dg/binary-constants-4.c | 18 ++ libcpp/ChangeLog | 9 + libcpp/expr.c | 46 +++- libcpp/include/cpplib.h | 1 + 10 files changed, 453 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/binary-constants-1.c create mode 100644 gcc/testsuite/gcc.dg/binary-constants-2.c create mode 100644 gcc/testsuite/gcc.dg/binary-constants-3.c create mode 100644 gcc/testsuite/gcc.dg/binary-constants-4.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index af639169526..f28d732f851 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2007-06-05 Joerg Wunsch + + PR preprocessor/23479 + * doc/extend.texi: Document the 0b-prefixed binary integer + constant extension. + 2007-06-05 Uros Bizjak PR tree-optimization/32215 diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index b652bff248d..3390bb16437 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -81,6 +81,7 @@ extensions, accepted by GCC in C89 mode and in C++. * Pragmas:: Pragmas accepted by GCC. * Unnamed Fields:: Unnamed struct/union fields within structs/unions. * Thread-Local:: Per-thread variables. +* Binary constants:: Binary constants using the @samp{0b} prefix. @end menu @node Statement Exprs @@ -10860,6 +10861,28 @@ Non-@code{static} members shall not be @code{__thread}. @end quotation @end itemize +@node Binary constants +@section Binary constants using the @samp{0b} prefix +@cindex Binary constants using the @samp{0b} prefix + +Integer constants can be written as binary constants, consisting of a +sequence of @samp{0} and @samp{1} digits, prefixed by @samp{0b} or +@samp{0B}. This is particularly useful in environments that operate a +lot on the bit-level (like microcontrollers). + +The following statements are identical: + +@smallexample +i = 42; +i = 0x2a; +i = 052; +i = 0b101010; +@end smallexample + +The type of these constants follows the same rules as for octal or +hexadecimal integer constants, so suffixes like @samp{L} or @samp{UL} +can be applied. + @node C++ Extensions @chapter Extensions to the C++ Language @cindex extensions, C++ language diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 945521340d9..067322c6a2a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2007-06-05 Joerg Wunsch + + PR preprocessor/23479 + * testsuite/gcc.dg/binary-constants-1.c: Add test suites for + the 0b-prefixed binary integer constants. + * testsuite/gcc.dg/binary-constants-2.c: Ditto. + * testsuite/gcc.dg/binary-constants-3.c: Ditto. + * testsuite/gcc.dg/binary-constants-4.c: Ditto. + 2007-06-05 Ian Lance Taylor * gcc.dg/Wstrict-overflow-19.c: New test. diff --git a/gcc/testsuite/gcc.dg/binary-constants-1.c b/gcc/testsuite/gcc.dg/binary-constants-1.c new file mode 100644 index 00000000000..b7cc5fd0dbe --- /dev/null +++ b/gcc/testsuite/gcc.dg/binary-constants-1.c @@ -0,0 +1,312 @@ +/* Test for binary integer constants. */ + +/* Derived from: c99-intconst-1.c, bye Joseph Myers . */ +/* Origin: Joerg Wunsch . */ +/* { dg-do compile } */ +/* { dg-options "-std=gnu99" } */ + +#include + +/* Assertion that constant C is of type T. */ +#define ASSERT_CONST_TYPE(C, T) \ + do { \ + typedef T type; \ + typedef type **typepp; \ + typedef __typeof__((C)) ctype; \ + typedef ctype **ctypepp; \ + typepp x = 0; \ + ctypepp y = 0; \ + x = y; \ + y = x; \ + } while (0) + +/* (T *) if E is zero, (void *) otherwise. */ +#define type_if_not(T, E) __typeof__(0 ? (T *)0 : (void *)(E)) + +/* (T *) if E is nonzero, (void *) otherwise. */ +#define type_if(T, E) type_if_not(T, !(E)) + +/* Combine pointer types, all but one (void *). */ +#define type_comb2(T1, T2) __typeof__(0 ? (T1)0 : (T2)0) +#define type_comb3(T1, T2, T3) type_comb2(T1, type_comb2(T2, T3)) +#define type_comb4(T1, T2, T3, T4) \ + type_comb2(T1, type_comb2(T2, type_comb2(T3, T4))) +#define type_comb6(T1, T2, T3, T4, T5, T6) \ + type_comb2(T1, \ + type_comb2(T2, \ + type_comb2(T3, \ + type_comb2(T4, \ + type_comb2(T5, T6))))) + +/* (T1 *) if E1, otherwise (T2 *) if E2. */ +#define first_of2p(T1, E1, T2, E2) type_comb2(type_if(T1, (E1)), \ + type_if(T2, (!(E1) && (E2)))) +/* (T1 *) if E1, otherwise (T2 *) if E2, otherwise (T3 *) if E3. */ +#define first_of3p(T1, E1, T2, E2, T3, E3) \ + type_comb3(type_if(T1, (E1)), \ + type_if(T2, (!(E1) && (E2))), \ + type_if(T3, (!(E1) && !(E2) && (E3)))) +/* (T1 *) if E1, otherwise (T2 *) if E2, otherwise (T3 *) if E3, otherwise + (T4 *) if E4. */ +#define first_of4p(T1, E1, T2, E2, T3, E3, T4, E4) \ + type_comb4(type_if(T1, (E1)), \ + type_if(T2, (!(E1) && (E2))), \ + type_if(T3, (!(E1) && !(E2) && (E3))), \ + type_if(T4, (!(E1) && !(E2) && !(E3) && (E4)))) +/* (T1 *) if E1, otherwise (T2 *) if E2, otherwise (T3 *) if E3, otherwise + (T4 *) if E4, otherwise (T5 *) if E5, otherwise (T6 *) if E6. */ +#define first_of6p(T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6) \ + type_comb6(type_if(T1, (E1)), \ + type_if(T2, (!(E1) && (E2))), \ + type_if(T3, (!(E1) && !(E2) && (E3))), \ + type_if(T4, (!(E1) && !(E2) && !(E3) && (E4))), \ + type_if(T5, (!(E1) && !(E2) && !(E3) && !(E4) && (E5))), \ + type_if(T6, (!(E1) && !(E2) && !(E3) \ + && !(E4) && !(E5) && (E6)))) + +/* Likewise, but return the original type rather than a pointer type. */ +#define first_of2(T1, E1, T2, E2) \ + __typeof__(*((first_of2p(T1, (E1), T2, (E2)))0)) +#define first_of3(T1, E1, T2, E2, T3, E3) \ + __typeof__(*((first_of3p(T1, (E1), T2, (E2), T3, (E3)))0)) +#define first_of4(T1, E1, T2, E2, T3, E3, T4, E4) \ + __typeof__(*((first_of4p(T1, (E1), T2, (E2), T3, (E3), T4, (E4)))0)) +#define first_of6(T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6) \ + __typeof__(*((first_of6p(T1, (E1), T2, (E2), T3, (E3), \ + T4, (E4), T5, (E5), T6, (E6)))0)) + +/* Types of constants according to the C99 rules. */ +#define C99_UNSUF_TYPE(C) \ + first_of6(int, (C) <= INT_MAX, \ + unsigned int, (C) <= UINT_MAX, \ + long int, (C) <= LONG_MAX, \ + unsigned long int, (C) <= ULONG_MAX, \ + long long int, (C) <= LLONG_MAX, \ + unsigned long long int, (C) <= ULLONG_MAX) +#define C99_SUFu_TYPE(C) \ + first_of3(unsigned int, (C) <= UINT_MAX, \ + unsigned long int, (C) <= ULONG_MAX, \ + unsigned long long int, (C) <= ULLONG_MAX) +#define C99_SUFl_TYPE(C) \ + first_of4(long int, (C) <= LONG_MAX, \ + unsigned long int, (C) <= ULONG_MAX, \ + long long int, (C) <= LLONG_MAX, \ + unsigned long long int, (C) <= ULLONG_MAX) +#define C99_SUFul_TYPE(C) \ + first_of2(unsigned long int, (C) <= ULONG_MAX, \ + unsigned long long int, (C) <= ULLONG_MAX) +#define C99_SUFll_TYPE(C) \ + first_of2(long long int, (C) <= LLONG_MAX, \ + unsigned long long int, (C) <= ULLONG_MAX) + +/* Checks that constants have correct type. */ +#define CHECK_UNSUF_TYPE(C) \ + ASSERT_CONST_TYPE((C), C99_UNSUF_TYPE((C))) +#define CHECK_SUFu_TYPE(C) ASSERT_CONST_TYPE((C), C99_SUFu_TYPE((C))) +#define CHECK_SUFl_TYPE(C) \ + ASSERT_CONST_TYPE((C), C99_SUFl_TYPE((C))) +#define CHECK_SUFul_TYPE(C) ASSERT_CONST_TYPE((C), C99_SUFul_TYPE((C))) +#define CHECK_SUFll_TYPE(C) \ + ASSERT_CONST_TYPE((C), C99_SUFll_TYPE((C))) +#define CHECK_SUFull_TYPE(C) ASSERT_CONST_TYPE((C), unsigned long long int) + +/* Check an octal or hexadecimal value, with all suffixes. */ +#define CHECK_CONST(C) \ + CHECK_UNSUF_TYPE(C); \ + CHECK_SUFu_TYPE(C##u); \ + CHECK_SUFu_TYPE(C##U); \ + CHECK_SUFl_TYPE(C##l); \ + CHECK_SUFl_TYPE(C##L); \ + CHECK_SUFul_TYPE(C##ul); \ + CHECK_SUFul_TYPE(C##uL); \ + CHECK_SUFul_TYPE(C##Ul); \ + CHECK_SUFul_TYPE(C##UL); \ + CHECK_SUFll_TYPE(C##ll); \ + CHECK_SUFll_TYPE(C##LL); \ + CHECK_SUFull_TYPE(C##ull); \ + CHECK_SUFull_TYPE(C##uLL); \ + CHECK_SUFull_TYPE(C##Ull); \ + CHECK_SUFull_TYPE(C##ULL); + +#define CHECK_BIN_CONST(C) \ + CHECK_CONST(0b##C); \ + CHECK_CONST(0B##C); + +/* True iff "long long" is at least B bits. This presumes that (B-2)/3 is at + most 63. */ +#define LLONG_AT_LEAST(B) \ + (LLONG_MAX >> ((B)-2)/3 >> ((B)-2)/3 \ + >> ((B)-2 - ((B)-2)/3 - ((B)-2)/3)) + +#define LLONG_HAS_BITS(B) (LLONG_AT_LEAST((B)) && !LLONG_AT_LEAST((B) + 1)) + +#define FOO 0b1101 +#if !FOO +# error "preprocessor does not accept binary constants" +#endif + +void +foo (void) +{ + /* Check all 2^n and 2^n - 1 up to 2^72 - 1. */ + CHECK_BIN_CONST(1); + CHECK_BIN_CONST(10); + CHECK_BIN_CONST(11); + CHECK_BIN_CONST(100); + CHECK_BIN_CONST(111); + CHECK_BIN_CONST(1000); + CHECK_BIN_CONST(1111); + CHECK_BIN_CONST(10000); + CHECK_BIN_CONST(11111); + CHECK_BIN_CONST(100000); + CHECK_BIN_CONST(111111); + CHECK_BIN_CONST(1000000); + CHECK_BIN_CONST(1111111); + CHECK_BIN_CONST(10000000); + CHECK_BIN_CONST(11111111); + CHECK_BIN_CONST(100000000); + CHECK_BIN_CONST(111111111); + CHECK_BIN_CONST(1000000000); + CHECK_BIN_CONST(1111111111); + CHECK_BIN_CONST(10000000000); + CHECK_BIN_CONST(11111111111); + CHECK_BIN_CONST(100000000000); + CHECK_BIN_CONST(111111111111); + CHECK_BIN_CONST(1000000000000); + CHECK_BIN_CONST(1111111111111); + CHECK_BIN_CONST(10000000000000); + CHECK_BIN_CONST(11111111111111); + CHECK_BIN_CONST(100000000000000); + CHECK_BIN_CONST(111111111111111); + CHECK_BIN_CONST(1000000000000000); + CHECK_BIN_CONST(1111111111111111); + CHECK_BIN_CONST(10000000000000000); + CHECK_BIN_CONST(11111111111111111); + CHECK_BIN_CONST(100000000000000000); + CHECK_BIN_CONST(111111111111111111); + CHECK_BIN_CONST(1000000000000000000); + CHECK_BIN_CONST(1111111111111111111); + CHECK_BIN_CONST(10000000000000000000); + CHECK_BIN_CONST(11111111111111111111); + CHECK_BIN_CONST(100000000000000000000); + CHECK_BIN_CONST(111111111111111111111); + CHECK_BIN_CONST(1000000000000000000000); + CHECK_BIN_CONST(1111111111111111111111); + CHECK_BIN_CONST(10000000000000000000000); + CHECK_BIN_CONST(11111111111111111111111); + CHECK_BIN_CONST(100000000000000000000000); + CHECK_BIN_CONST(111111111111111111111111); + CHECK_BIN_CONST(1000000000000000000000000); + CHECK_BIN_CONST(1111111111111111111111111); + CHECK_BIN_CONST(10000000000000000000000000); + CHECK_BIN_CONST(11111111111111111111111111); + CHECK_BIN_CONST(100000000000000000000000000); + CHECK_BIN_CONST(111111111111111111111111111); + CHECK_BIN_CONST(1000000000000000000000000000); + CHECK_BIN_CONST(1111111111111111111111111111); + CHECK_BIN_CONST(10000000000000000000000000000); + CHECK_BIN_CONST(11111111111111111111111111111); + CHECK_BIN_CONST(100000000000000000000000000000); + CHECK_BIN_CONST(111111111111111111111111111111); + CHECK_BIN_CONST(1000000000000000000000000000000); + CHECK_BIN_CONST(1111111111111111111111111111111); + CHECK_BIN_CONST(10000000000000000000000000000000); + CHECK_BIN_CONST(11111111111111111111111111111111); + CHECK_BIN_CONST(100000000000000000000000000000000); + CHECK_BIN_CONST(111111111111111111111111111111111); + CHECK_BIN_CONST(1000000000000000000000000000000000); + CHECK_BIN_CONST(1111111111111111111111111111111111); + CHECK_BIN_CONST(10000000000000000000000000000000000); + CHECK_BIN_CONST(11111111111111111111111111111111111); + CHECK_BIN_CONST(100000000000000000000000000000000000); + CHECK_BIN_CONST(111111111111111111111111111111111111); + CHECK_BIN_CONST(1000000000000000000000000000000000000); + CHECK_BIN_CONST(1111111111111111111111111111111111111); + CHECK_BIN_CONST(10000000000000000000000000000000000000); + CHECK_BIN_CONST(11111111111111111111111111111111111111); + CHECK_BIN_CONST(100000000000000000000000000000000000000); + CHECK_BIN_CONST(111111111111111111111111111111111111111); + CHECK_BIN_CONST(1000000000000000000000000000000000000000); + CHECK_BIN_CONST(1111111111111111111111111111111111111111); + CHECK_BIN_CONST(10000000000000000000000000000000000000000); + CHECK_BIN_CONST(11111111111111111111111111111111111111111); + CHECK_BIN_CONST(100000000000000000000000000000000000000000); + CHECK_BIN_CONST(111111111111111111111111111111111111111111); + CHECK_BIN_CONST(1000000000000000000000000000000000000000000); + CHECK_BIN_CONST(1111111111111111111111111111111111111111111); + CHECK_BIN_CONST(10000000000000000000000000000000000000000000); + CHECK_BIN_CONST(11111111111111111111111111111111111111111111); + CHECK_BIN_CONST(100000000000000000000000000000000000000000000); + CHECK_BIN_CONST(111111111111111111111111111111111111111111111); + CHECK_BIN_CONST(1000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(1111111111111111111111111111111111111111111111); + CHECK_BIN_CONST(10000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(11111111111111111111111111111111111111111111111); + CHECK_BIN_CONST(100000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(111111111111111111111111111111111111111111111111); + CHECK_BIN_CONST(1000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(1111111111111111111111111111111111111111111111111); + CHECK_BIN_CONST(10000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(11111111111111111111111111111111111111111111111111); + CHECK_BIN_CONST(100000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(111111111111111111111111111111111111111111111111111); + CHECK_BIN_CONST(1000000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(1111111111111111111111111111111111111111111111111111); + CHECK_BIN_CONST(10000000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(11111111111111111111111111111111111111111111111111111); + CHECK_BIN_CONST(100000000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(111111111111111111111111111111111111111111111111111111); + CHECK_BIN_CONST(1000000000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(1111111111111111111111111111111111111111111111111111111); + CHECK_BIN_CONST(10000000000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(11111111111111111111111111111111111111111111111111111111); + CHECK_BIN_CONST(100000000000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(111111111111111111111111111111111111111111111111111111111); + CHECK_BIN_CONST(1000000000000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(1111111111111111111111111111111111111111111111111111111111); + CHECK_BIN_CONST(10000000000000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(11111111111111111111111111111111111111111111111111111111111); + CHECK_BIN_CONST(100000000000000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(111111111111111111111111111111111111111111111111111111111111); + CHECK_BIN_CONST(1000000000000000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(1111111111111111111111111111111111111111111111111111111111111); + CHECK_BIN_CONST(10000000000000000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(11111111111111111111111111111111111111111111111111111111111111); + CHECK_BIN_CONST(100000000000000000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(111111111111111111111111111111111111111111111111111111111111111); + CHECK_BIN_CONST(1000000000000000000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(1111111111111111111111111111111111111111111111111111111111111111); +#if LLONG_AT_LEAST(65) + CHECK_BIN_CONST(10000000000000000000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(11111111111111111111111111111111111111111111111111111111111111111); +#endif +#if LLONG_AT_LEAST(66) + CHECK_BIN_CONST(100000000000000000000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(111111111111111111111111111111111111111111111111111111111111111111); +#endif +#if LLONG_AT_LEAST(67) + CHECK_BIN_CONST(1000000000000000000000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(1111111111111111111111111111111111111111111111111111111111111111111); +#endif +#if LLONG_AT_LEAST(68) + CHECK_BIN_CONST(10000000000000000000000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(11111111111111111111111111111111111111111111111111111111111111111111); +#endif +#if LLONG_AT_LEAST(69) + CHECK_BIN_CONST(100000000000000000000000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(111111111111111111111111111111111111111111111111111111111111111111111); +#endif +#if LLONG_AT_LEAST(70) + CHECK_BIN_CONST(1000000000000000000000000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(1111111111111111111111111111111111111111111111111111111111111111111111); +#endif +#if LLONG_AT_LEAST(71) + CHECK_BIN_CONST(10000000000000000000000000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(11111111111111111111111111111111111111111111111111111111111111111111111); +#endif +#if LLONG_AT_LEAST(72) + CHECK_BIN_CONST(100000000000000000000000000000000000000000000000000000000000000000000000); + CHECK_BIN_CONST(111111111111111111111111111111111111111111111111111111111111111111111111); +#endif +} + diff --git a/gcc/testsuite/gcc.dg/binary-constants-2.c b/gcc/testsuite/gcc.dg/binary-constants-2.c new file mode 100644 index 00000000000..40d76364656 --- /dev/null +++ b/gcc/testsuite/gcc.dg/binary-constants-2.c @@ -0,0 +1,16 @@ +/* Test for binary integer constants: -pedantic warnings. */ + +/* Origin: Joerg Wunsch . */ +/* { dg-do compile } */ +/* { dg-options "-std=iso9899:1999 -pedantic" } */ + +#define FOO 0b1101 + +int +foo (void) +{ +#if FOO /* { dg-warning "binary constants are a GCC extension" } */ + return 23; +#endif + return 0b1101; /* { dg-warning "binary constants are a GCC extension" } */ +} diff --git a/gcc/testsuite/gcc.dg/binary-constants-3.c b/gcc/testsuite/gcc.dg/binary-constants-3.c new file mode 100644 index 00000000000..984477dca18 --- /dev/null +++ b/gcc/testsuite/gcc.dg/binary-constants-3.c @@ -0,0 +1,16 @@ +/* Test for binary integer constants: -pedantic-errors. */ + +/* Origin: Joerg Wunsch . */ +/* { dg-do compile } */ +/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */ + +#define FOO 0b1101 + +int +foo (void) +{ +#if FOO /* { dg-error "binary constants are a GCC extension" } */ + return 23; +#endif + return 0b1101; /* { dg-error "binary constants are a GCC extension" } */ +} diff --git a/gcc/testsuite/gcc.dg/binary-constants-4.c b/gcc/testsuite/gcc.dg/binary-constants-4.c new file mode 100644 index 00000000000..32c9d65a5ed --- /dev/null +++ b/gcc/testsuite/gcc.dg/binary-constants-4.c @@ -0,0 +1,18 @@ +/* Test for binary integer constants: random errors. */ + +/* Origin: Joerg Wunsch . */ +/* { dg-do compile } */ +/* { dg-options "-std=gnu99" } */ + +void +foo(void) +{ + double d; + int i; + + d = 0b1101; + d = 0b1101p1; /* { dg-error "invalid suffix \"p1\" on integer constant" } */ + d = 0x1101p1; + i = 0b3011; /* { dg-error "invalid suffix \"b3011\" on integer constant" } */ + i = 0b113; /* { dg-error "invalid digit \"3\" in binary constant" } */ +} diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index ef6c39762a8..712bc32784b 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,12 @@ +2007-06-05 Joerg Wunsch + + PR preprocessor/23479 + * expr.c (cpp_classify_number): Implement 0b-prefixed binary + integer constants. + (append_digit): Likewise. + * include/cpplib.h: Add CPP_N_BINARY, to be used for 0b-prefixed + binary integer constants. + 2007-05-31 Dave Korn PR preprocessor/14331 diff --git a/libcpp/expr.c b/libcpp/expr.c index 20090195acc..59de8ef9ec9 100644 --- a/libcpp/expr.c +++ b/libcpp/expr.c @@ -185,6 +185,11 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token) radix = 16; str++; } + else if ((*str == 'b' || *str == 'B') && (str[1] == '0' || str[1] == '1')) + { + radix = 2; + str++; + } } /* Now scan for a well-formed integer or float. */ @@ -223,10 +228,22 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token) radix = 10; if (max_digit >= radix) - SYNTAX_ERROR2 ("invalid digit \"%c\" in octal constant", '0' + max_digit); + { + if (radix == 2) + SYNTAX_ERROR2 ("invalid digit \"%c\" in binary constant", '0' + max_digit); + else + SYNTAX_ERROR2 ("invalid digit \"%c\" in octal constant", '0' + max_digit); + } if (float_flag != NOT_FLOAT) { + if (radix == 2) + { + cpp_error (pfile, CPP_DL_ERROR, + "invalid prefix \"0b\" for floating constant"); + return CPP_N_INVALID; + } + if (radix == 16 && CPP_PEDANTIC (pfile) && !CPP_OPTION (pfile, c99)) cpp_error (pfile, CPP_DL_PEDWARN, "use of C99 hexadecimal floating constant"); @@ -315,11 +332,16 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token) if ((result & CPP_N_IMAGINARY) && CPP_PEDANTIC (pfile)) cpp_error (pfile, CPP_DL_PEDWARN, "imaginary constants are a GCC extension"); + if (radix == 2 && CPP_PEDANTIC (pfile)) + cpp_error (pfile, CPP_DL_PEDWARN, + "binary constants are a GCC extension"); if (radix == 10) result |= CPP_N_DECIMAL; else if (radix == 16) result |= CPP_N_HEX; + else if (radix == 2) + result |= CPP_N_BINARY; else result |= CPP_N_OCTAL; @@ -370,6 +392,11 @@ cpp_interpret_integer (cpp_reader *pfile, const cpp_token *token, base = 16; p += 2; } + else if ((type & CPP_N_RADIX) == CPP_N_BINARY) + { + base = 2; + p += 2; + } /* We can add a digit to numbers strictly less than this without needing the precision and slowness of double integers. */ @@ -425,12 +452,25 @@ static cpp_num append_digit (cpp_num num, int digit, int base, size_t precision) { cpp_num result; - unsigned int shift = 3 + (base == 16); + unsigned int shift; bool overflow; cpp_num_part add_high, add_low; - /* Multiply by 8 or 16. Catching this overflow here means we don't + /* Multiply by 2, 8 or 16. Catching this overflow here means we don't need to worry about add_high overflowing. */ + switch (base) + { + case 2: + shift = 1; + break; + + case 16: + shift = 4; + break; + + default: + shift = 3; + } overflow = !!(num.high >> (PART_PRECISION - shift)); result.high = num.high << shift; result.low = num.low << shift; diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index ff5292ef3c8..0edcf655c92 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -748,6 +748,7 @@ struct cpp_num #define CPP_N_DECIMAL 0x0100 #define CPP_N_HEX 0x0200 #define CPP_N_OCTAL 0x0400 +#define CPP_N_BINARY 0x0800 #define CPP_N_UNSIGNED 0x1000 /* Properties. */ #define CPP_N_IMAGINARY 0x2000