2
0
mirror of https://github.com/boostorg/wave.git synced 2026-01-19 04:42:16 +00:00

Implement support for digit separators in preprocessor expressions

Integers with digit separators are already recognized as literal
tokens. This commit adds proper interpretation of them as integers for
use in expressions e.g. with #if
This commit is contained in:
Jeff Trull
2025-11-13 14:29:08 -08:00
committed by Jeff Trull
parent 7a8e9d3884
commit ac31d13c6a
6 changed files with 922 additions and 804 deletions

View File

@@ -468,7 +468,7 @@ pp_number:
if (s->detect_pp_numbers) {
/*!re2c
"."? Digit (Digit | NonDigit | ExponentStart | ".")*
"."? Digit (("'"? (Digit | NonDigit | ExponentStart)) | ".")*
{ BOOST_WAVE_RET(T_PP_NUMBER); }
// because we reached this point, then reset the cursor,

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
/* Generated by re2c 1.0.2 on Sun Oct 26 21:28:07 2025 */
/* Generated by re2c 1.0.2 on Thu Nov 13 14:28:22 2025 */
#line 1 "strict_cpp.re"
/*=============================================================================
Boost.Wave: A Standard compliant C++ preprocessor library

View File

@@ -13,6 +13,8 @@
#include <boost/wave/wave_config.hpp>
#include <boost/iterator/filter_iterator.hpp>
#include <boost/spirit/include/classic_core.hpp>
#include <boost/spirit/include/classic_closure.hpp>
#include <boost/spirit/include/classic_assign_actor.hpp>
@@ -171,13 +173,20 @@ intlit_grammar_gen<TokenT>::evaluate(TokenT const &token,
intlit_grammar g(is_unsigned);
uint_literal_type result = 0;
typename TokenT::string_type const &token_val = token.get_value();
// filter out digit separators
auto not_digit_separator = [](char c){ return c != '\''; };
auto digits_begin = boost::make_filter_iterator(not_digit_separator, token_val.begin(), token_val.end());
auto digits_end = boost::make_filter_iterator(not_digit_separator, token_val.end(), token_val.end());
typename TokenT::string_type token_digits(digits_begin, digits_end);
using boost::spirit::classic::parse_info;
parse_info<typename TokenT::string_type::const_iterator> hit =
parse(token_val.begin(), token_val.end(), g[spirit_assign_actor(result)]);
parse(token_digits.begin(), token_digits.end(), g[spirit_assign_actor(result)]);
if (!hit.hit) {
BOOST_WAVE_THROW(preprocess_exception, ill_formed_integer_literal,
token_val.c_str(), token.get_position());
token_digits.c_str(), token.get_position());
}
return result;
}

View File

@@ -16,9 +16,10 @@
// Tests integer preprocessing number token and type of #if expression.
//O --long_long
//O --c++17
// 12.1:
//R #line 26 "t_5_014.cpp"
//R #line 27 "t_5_014.cpp"
//R true
#if __TESTWAVE_LONG_MAX__ <= __TESTWAVE_LONG_MIN__
"Bad evaluation of long."
@@ -26,7 +27,7 @@
true
#endif
//R #line 34 "t_5_014.cpp"
//R #line 35 "t_5_014.cpp"
//R true
#if __TESTWAVE_LONG_MAX__ <= (__TESTWAVE_LONG_MAX__ / 2) /* 0x3FFFFFFF */
"Bad evaluation of long."
@@ -35,7 +36,7 @@ true
#endif
// 12.2:
//R #line 43 "t_5_014.cpp"
//R #line 44 "t_5_014.cpp"
//R true
#if __TESTWAVE_ULONG_MAX__ / 2 < __TESTWAVE_LONG_MAX__
"Bad evaluation of unsigned long."
@@ -44,7 +45,7 @@ true
#endif
// 12.3: Octal number.
//R #line 52 "t_5_014.cpp"
//R #line 53 "t_5_014.cpp"
//R true
#if 0177777 != 65535
"Bad evaluation of octal number."
@@ -53,7 +54,7 @@ true
#endif
// 12.4: Hexadecimal number.
//R #line 61 "t_5_014.cpp"
//R #line 62 "t_5_014.cpp"
//R true
#if 0Xffff != 65535 || 0xFfFf != 65535
"Bad evaluation of hexadecimal number."
@@ -62,7 +63,7 @@ true
#endif
// 12.5: Suffix 'L' or 'l'.
//R #line 70 "t_5_014.cpp"
//R #line 71 "t_5_014.cpp"
//R true
#if 0L != 0 || 0l != 0
"Bad evaluation of 'L' suffix."
@@ -71,7 +72,7 @@ true
#endif
// 12.6: Suffix 'U' or 'u'.
//R #line 79 "t_5_014.cpp"
//R #line 80 "t_5_014.cpp"
//R true
#if 1U != 1 || 1u != 1
"Bad evaluation of 'U' suffix."
@@ -80,7 +81,7 @@ true
#endif
// 12.7: Negative integer.
//R #line 88 "t_5_014.cpp"
//R #line 89 "t_5_014.cpp"
//R true
#if 0 <= -1
"Bad evaluation of negative number."
@@ -89,7 +90,7 @@ true
#endif
// 12.8: Long Long integers
//R #line 97 "t_5_014.cpp"
//R #line 98 "t_5_014.cpp"
//R true
#if 0LL != 0 || 0ll != 0
"Bad evaluation of 'LL' suffix."
@@ -98,7 +99,7 @@ true
#endif
// 12.8: Unsigned Long Long integers
//R #line 106 "t_5_014.cpp"
//R #line 107 "t_5_014.cpp"
//R true
#if 1ull != 1 || 1uLL != 1 || 1Ull != 1 || 1ULL != 1 || 1llu != 1 || 1llU != 1 || 1LLu != 1 || 1LLU != 1
"Bad evaluation of 'ULL' or 'LLU' suffix."
@@ -107,7 +108,7 @@ true
#endif
// 12.9: invalid (mixed case) long long integers
//R #line 115 "t_5_014.cpp"
//R #line 116 "t_5_014.cpp"
//R long long foo = 1234l L;
//R long long bar = 5678L l;
//R unsigned long long baz = 1234uL l;
@@ -117,6 +118,81 @@ long long bar = 5678Ll;
unsigned long long baz = 1234uLl;
unsigned long long quux = 5678uLl;
// Evaluating numbers containing digit separators
//R #line 128 "t_5_014.cpp"
//R true
#if 120'3 < 120'2
"Bad comparison of signed integers with digit separators"
#else
true
#endif
//R #line 136 "t_5_014.cpp"
//R true
#if 1'202 != 120'2l
"Bad equality comparison of signed integers with digit separators"
#else
true
#endif
//R #line 144 "t_5_014.cpp"
//R true
#if 120'3ul < 120'2u
"Bad comparison of unsigned integers with digit separators"
#else
true
#endif
//R #line 152 "t_5_014.cpp"
//R true
#if 1'202U != 120'2UL
"Bad equality comparison of unsigned integers with digit separators"
#else
true
#endif
//R #line 160 "t_5_014.cpp"
//R true
#if 0x13'37c0de != 0x13'37c0'de
"Bad equality comparison of hex integers with digit separators"
#else
true
#endif
//R #line 168 "t_5_014.cpp"
//R true
#if 0x13'37c0de < 0x13'27c0'de
"Bad comparison of hex integers with digit separators"
#else
true
#endif
//R #line 176 "t_5_014.cpp"
//R true
#if 0b10'0101 != 0b1'00101
"Bad equality comparison of binary integers with digit separators"
#else
true
#endif
//R #line 184 "t_5_014.cpp"
//R true
#if 0b10'0101 > 0b11'0101
"Bad comparison of binary integers with digit separators"
#else
true
#endif
// Now one comparison the other way, just in case
//R #line 191 "t_5_014.cpp"
//R true
#if 0x13'37c0d'e == 0x1'3'3'7'c0de
true
#else
"Bad equality comparison for many hex digits with separator"
#endif
/*-
* Copyright (c) 1998, 2002-2005 Kiyoshi Matsui <kmatsui@t3.rim.or.jp>

View File

@@ -11,12 +11,12 @@
// Verify that long integer literals from a macro expansion parse correctly
// This test covers #162
//O --c++11
//O --c++17
//O -DFOO=0x1234567ULL
#define BAZ (FOO*2UL+1UL)
#define BAR (BAZ + 1ULL)
#if defined(BAR) && (BAR == 0x2468AD0)
#if defined(BAR) && (BAR == 0x246'8AD0)
struct Bar {};
#else
#endif