[Spirit] Qi int_parser rejecting a negative signed std::intmax_t
Hello, qi::int_parser works fine for a positive signed hex radix integer, but is failing for a negative signed hex radix integer. My integer type is std::intmax_t, which on this platform I think is long long. Is there an integer width constraint? And/or a signage problem? Do I need to enable BOOST_HAS_LONG_LONG? Or is that enabled by default? Cheers, thanks! Michael Powell
On Mon, Nov 12, 2018 at 10:34 AM Michael Powell <mwpowellhtx@gmail.com> wrote:
Hello,
qi::int_parser works fine for a positive signed hex radix integer, but is failing for a negative signed hex radix integer.
I've got some sample code, it builds, but I am receiving a seg fault. http://coliru.stacked-crooked.com/a/ed4608c077bb3d69
My integer type is std::intmax_t, which on this platform I think is long long.
Is there an integer width constraint? And/or a signage problem?
Do I need to enable BOOST_HAS_LONG_LONG? Or is that enabled by default?
Cheers, thanks!
Michael Powell
On Mon, Nov 12, 2018 at 11:17 AM Michael Powell <mwpowellhtx@gmail.com> wrote:
On Mon, Nov 12, 2018 at 10:34 AM Michael Powell <mwpowellhtx@gmail.com> wrote:
Hello,
qi::int_parser works fine for a positive signed hex radix integer, but is failing for a negative signed hex radix integer.
I've got some sample code, it builds, but I am receiving a seg fault.
Oops, my mistake. An error in one of the rules. Fixed it, and can demonstrate that negative values do not seem to parse correctly: http://coliru.stacked-crooked.com/a/370b6aa5c167434b
My integer type is std::intmax_t, which on this platform I think is long long.
Is there an integer width constraint? And/or a signage problem?
Do I need to enable BOOST_HAS_LONG_LONG? Or is that enabled by default?
Cheers, thanks!
Michael Powell
On 13/11/2018 05:27, Michael Powell wrote:
Oops, my mistake. An error in one of the rules. Fixed it, and can demonstrate that negative values do not seem to parse correctly:
Hex and octal literals produce unsigned values. You need to put those into a uintmax_t, not an intmax_t. FWIW, you can still use an intmax_t in your AST if you want, as the automatic attribute conversion will permit the twos-complement conversion (though it might annoy some sanitisers). hex_val %= no_case["0x"] >> uint_parser<std::uintmax_t, 16>{}; oct_val %= "0" >> uint_parser<std::uintmax_t, 8>{}; dec_val %= int_parser<ast::int_t, 10>{}; If you feel especially enthused, you can use std::make_unsigned_t<ast::int_t> instead.
On Mon, Nov 12, 2018 at 5:43 PM Gavin Lambert via Boost-users <boost-users@lists.boost.org> wrote:
On 13/11/2018 05:27, Michael Powell wrote:
Oops, my mistake. An error in one of the rules. Fixed it, and can demonstrate that negative values do not seem to parse correctly:
Hex and octal literals produce unsigned values. You need to put those into a uintmax_t, not an intmax_t.
FWIW, you can still use an intmax_t in your AST if you want, as the automatic attribute conversion will permit the twos-complement conversion (though it might annoy some sanitisers).
hex_val %= no_case["0x"] >> uint_parser<std::uintmax_t, 16>{}; oct_val %= "0" >> uint_parser<std::uintmax_t, 8>{}; dec_val %= int_parser<ast::int_t, 10>{};
Hmm, I see... Maybe this is rinsing out in the conversion wash, then, because the decimal phrase seems to handle negative values just fine, whereas the hex and octal parsers fall flag on their face. Anyway, it makes dealing with signage kind of tricky in the face of those nuances.
If you feel especially enthused, you can use std::make_unsigned_t<ast::int_t> instead. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org https://lists.boost.org/mailman/listinfo.cgi/boost-users
On 13/11/2018 11:47, Michael Powell wrote:
Hex and octal literals produce unsigned values. You need to put those into a uintmax_t, not an intmax_t.
FWIW, you can still use an intmax_t in your AST if you want, as the automatic attribute conversion will permit the twos-complement conversion (though it might annoy some sanitisers).
hex_val %= no_case["0x"] >> uint_parser<std::uintmax_t, 16>{}; oct_val %= "0" >> uint_parser<std::uintmax_t, 8>{}; dec_val %= int_parser<ast::int_t, 10>{};
Hmm, I see... Maybe this is rinsing out in the conversion wash, then, because the decimal phrase seems to handle negative values just fine, whereas the hex and octal parsers fall flag on their face.
Decimal values can be negative. Octal and hex values can't.
On Mon, Nov 12, 2018 at 5:54 PM Gavin Lambert via Boost-users <boost-users@lists.boost.org> wrote:
On 13/11/2018 11:47, Michael Powell wrote:
Hex and octal literals produce unsigned values. You need to put those into a uintmax_t, not an intmax_t.
FWIW, you can still use an intmax_t in your AST if you want, as the automatic attribute conversion will permit the twos-complement conversion (though it might annoy some sanitisers).
hex_val %= no_case["0x"] >> uint_parser<std::uintmax_t, 16>{}; oct_val %= "0" >> uint_parser<std::uintmax_t, 8>{}; dec_val %= int_parser<ast::int_t, 10>{};
Hmm, I see... Maybe this is rinsing out in the conversion wash, then, because the decimal phrase seems to handle negative values just fine, whereas the hex and octal parsers fall flag on their face.
Decimal values can be negative. Octal and hex values can't.
Right, I understand that. However, ultimately when the AST is synthesized, I do not care whether numeric literals were hex, octal, decimal, or some other indeterminate radix. The sign applies to whatever that result is, at least according to the language spec I am working with.
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org https://lists.boost.org/mailman/listinfo.cgi/boost-users
On 13/11/2018 11:57, Michael Powell wrote:
Decimal values can be negative. Octal and hex values can't.
Right, I understand that. However, ultimately when the AST is synthesized, I do not care whether numeric literals were hex, octal, decimal, or some other indeterminate radix. The sign applies to whatever that result is, at least according to the language spec I am working with.
That's fine though -- as I said you can still just use intptr_t in the AST and it will store the signed two's complement equivalent of whatever literal was specified, regardless of radix. You just need to specify the signedness correctly in the actual parse step. I'm not sure exactly what was making it fail with intmax_t, but it's not entirely surprising, and using uintmax_t to parse makes it work as expected.
participants (2)
-
Gavin Lambert
-
Michael Powell