When `min_token_id` is not a valid value for `id_type` and `first_id` is not
provided lexer constructor is triggering UB. To fix this problem, constructor
with ommited `first_id` initializes `next_token_id` directly, so if unique ids
feature is not used there is no UB.
Spirit were assuming that wchar_t is 32-bit and the content is UCS-4.
It is wrong, the actual representation is implementation defined [lex.ccon]/6.
However, on most Unix platforms this assumption is valid and gives the
expected outcome, but on Windows wchar_t is 16-bit and the content is UTF-16.
With `BOOST_SPIRIT_UNICODE` defined Clang, MinGW and Cygwin were using `wchar_t`.
I have switched to OS detection with `_WIN32`, it will give the right results for
most compilers except Cygwin.
Domain-agnostic class template partial specializations and
type agnostic domain partial specializations are ambious.
To resolve the ambiguity type agnostic domain partial
specializations are dispatched via intermediate type.
This applies the fix in 6d6f40c3e5 to all BOOST_NOEXCEPT_IF statements in
variant.cpp. I have trouple compiling a toy project with VS2015, as these
noexcept if statements fails to compile.
The `extract_from_attribute` returns a reference to a temporary
value produced by calling Fusion ADT adapted sequence getter that
returns by value.
Was reported 6 years ago https://svn.boost.org/trac10/ticket/6126
Boost's iterator.hpp is deprecated, too. It does nothing but pulling std::iterator into namespace boost and including standard headers 'iterator' and 'cstddef'. Therefore get rid of all of that and replace inheritance by lifting std::iterator's members into the derived class.
.\boost/spirit/home/x3/core/detail/parse_into_container.hpp(299): error C2752: 'boost::spirit::x3::detail::parse_into_container_impl<Parser,Context,RContext,void>': more than one partial specialization matches the template argument list
A single item sequences like `fusion::vector<T>` will be passed through,
while fusion iterators, fusion iterator range or view of size one will
be dereferenced before passing to underlying parsers of sequence parser.
Actually the warning here is a sign of bad design. Attribute should go directly
to sink, and there will be no truncation warning except a situation when sink
is not wide enough for attribute or binded value.
Closes https://svn.boost.org/trac10/ticket/11540.
Actually this should have been caught by `regression_matlib_generate_switch`
test, but it is not complex enough to cover all cases. We do not have the
coverage reports yet, but the fix is trivial so I think it is ok.
The concept of ForwardIterator is flawed because it mixed 2 sets of concepts (value access and traversal) into 1 package.
http://www.boost.org/doc/libs/1_65_1/libs/iterator/doc/new-iter-concepts.html
It requires value_type (const)& as return type when dereference is applied, which is not mandatory in spirit parsing. A return type which is convertible to value_type is good enough. ReadableIteratorConcept and ForwardTraversalConcept should be what we need for the iterator check.
For example, the iterator of the range returned by boost::adaptors::transform(std::string, func) is normally not a ForwardIterator. But it fulfills ReadableIteratorConcept and ForwardTraversalConcept and should be able to be parsed by spirit.
Closes https://svn.boost.org/trac10/ticket/12473
Optional parser never fails so `attr = val;` always triggers and initializes
the `attr` value. The special case for optional attributes could be safely
removed as any underlying parser must already correctly handle optionals.
After two hours of fighting with the optimizer, I happily drew attention to
this little nifty bitwise operator in `any_if_ns` function.
Explanation of the bug: bitwise inclusive OR operator is not a sequence point
(per chapter §5.13 of C++14 standard), that's why at compiling the expression
`a() | b() | ... | z()` optimizer is allowed to rearrange the execution order
of the functions `a`, `b` ... `z`.
There is high chance that a lot of people were misguided by the bug and chose
not to use `sequential_or`.
I vaguely remember how about three years ago I thought that I am dumb and/or
the documentation is wrong when I tried to use the `sequential_or` but ended
with some workaround.
There are three possible fixes:
- This one
- Make the original `any_ns` and `any_if_ns` strict ordered
(could potentially make permutations operator slower)
- Break the `any_ns` and `any_if_ns` API and somehow generalize the code
According to spirit document,
"All numeric parsers check for overflow conditions based on the type T the corresponding uint_parser<> has been instantiated with. If the parsed number overflows this type the parsing fails. Please be aware that the overflow check is not based on the type of the supplied attribute but solely depends on the template parameter T."
the valid input range of x3::uint_parser<T> should be 0 - std::numeric_limits<T>::max(). However, the current implementation takes values from std::numeric_limits<T>::max()+1 - std::numeric_limits<std::make_unsigned_t<T>>::max() also as valid input.
It took me 3 days of pulling my hair to debug and fix the bug. The subrule's
author put a big bomb under it and I caught the exposition only in a single
test, with modern versions of Clang/GCC and enabled optimizations (most of
boost regression test runners does not use `variant=release`). Valgrind did
not catch any problems. Enabling address sanitizer causes the bug to disappear
(now I understand why, it places big gaps between stack pointers).
`-fsanitize-address-use-after-scope` catches the bug, but I have discovered
that it is turned off in Clang by default after already having a repro.
The bug could be easily reproduced if you use any parser that invalidates
it's state in the destructor.
I used `literal_char` with added `~literal_char() { ch = char_type(0); }`.
Reproduction code:
```cpp
rule<char const*> r;
subrule<0> entry;
r = (entry = 'a');
BOOST_TEST(test("a", r));
```
It will fail because after assignment to `r` a temporary `subrule_group` is
destroyed and rule is binded to the already destroyed object.
The cause is in usage of `reference` parser. I am 100% sure the code was
copy-pasted from `rule`/`grammar`. They store an expression within their
body, while `subrule` actually used only as a placeholder.
I have split `subrule_group` into an actual parser/generator that stores the
expression and a Proto terminal that contains the parser/generator.
Tested on:
- VS 2008, 2010, 2015, 2017
- Clang 3.8, 3.9, 4.0, 5.0
- GCC 4.8, 7
While I do not see usages for `bool` scanner and consider it is a dumb idea
I have not removed the test. Adding the `isblank(bool)` overload seems to me
as a reasonable compromise because it cannot break anything.
`boost::optional<T &>` has member named `argument_type`
I do not know when it did break because defining
`BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL`
does not solve the problem.
Replaces #201, fixes#249.
New `boost:optional` implementation does not contain `types` what caused
a compilation error for Qi and wrong results for Karma.
Other problem is that `not_is_variant<optional<variant<T...>>>` results in
`mpl::false_` what is unclear from it's name. While Karma relays on exactly
this behavior, Qi wrongly considers that it `mpl::true_`. I have fixed this
name ambiguity and updated Karma for the new `not_is_variant` behavior.
/usr/include/boost/spirit/home/qi/numeric/detail/real_impl.hpp:86:48: runtime error: negation of -2147483648 cannot be represented in type 'int'; cast to an unsigned type to negate this value to itself
With -Wlogical-op, gcc warns in radix_traits::is_valid with Radix <= 10:
```
boost/spirit/home/qi/numeric/detail/numeric_utils.hpp: In instantiation of ‘static bool boost::spirit::qi::detail::radix_traits<10u>::is_valid<char>(char)’:
[...]
boost/spirit/home/qi/numeric/detail/numeric_utils.hpp:107:31: warning: logical ‘and’ of mutually exclusive tests is always false [-Wlogical-op]
|| (ch >= 'a' && ch <= static_cast<Char>('a' + Radix -10 -1))
^
boost/spirit/home/qi/numeric/detail/numeric_utils.hpp:108:31: warning: logical ‘and’ of mutually exclusive tests is always false [-Wlogical-op]
|| (ch >= 'A' && ch <= static_cast<Char>('A' + Radix -10 -1));
^
```
Rather than suppressing the warning (https://github.com/boostorg/spirit/pull/77), refactor the test so that the warning is not triggered.
1. when used as x3::with<ID>(x), where x is an lvalue, we inject an lvalue reference of x to the context.
2. when used as x3::with<ID>(x), where x is a const lvalue, we inject a const lvalue reference of x to the context.
3. when used as x3::with<ID>(x), where x is an rvalue, we move the rvalue to the member of with_directive and inject an lvalue reference of that member to the context.
4. No copy is applied; std::ref is not needed
5. remove unused with_context