Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

std::logic_error - Initialization Order Fiasco #229

Merged
merged 2 commits into from Jan 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 22 additions & 2 deletions include/boost/spirit/home/x3/core/parser.hpp
Expand Up @@ -18,6 +18,7 @@
#include <boost/spirit/home/x3/support/context.hpp>
#include <boost/spirit/home/x3/support/traits/has_attribute.hpp>
#include <boost/spirit/home/x3/support/utility/sfinae.hpp>
#include <boost/assert.hpp>
#include <string>

#if !defined(BOOST_SPIRIT_X3_NO_RTTI)
Expand Down Expand Up @@ -63,6 +64,21 @@ namespace boost { namespace spirit { namespace x3
}
};

namespace detail {
template <typename Parser>
static void assert_initialized_rule(Parser const& p) {
// Assert that we are not copying an unitialized static rule. If
// the static is in another TU, it may be initialized after we copy
// it. If so, its name member will be nullptr.
//
// Rather than hardcoding behaviour for rule-type subject parsers,
// we simply allow get_info<> to do the check in debug builds.
#ifndef NDEBUG
what(p); // note: allows get_info<> to diagnose the issue
#endif
}
}

struct unary_category;
struct binary_category;

Expand All @@ -74,7 +90,7 @@ namespace boost { namespace spirit { namespace x3
static bool const has_action = Subject::has_action;

unary_parser(Subject const& subject)
: subject(subject) {}
: subject(subject) { detail::assert_initialized_rule(subject); }

unary_parser const& get_unary() const { return *this; }

Expand All @@ -91,7 +107,11 @@ namespace boost { namespace spirit { namespace x3
left_type::has_action || right_type::has_action;

binary_parser(Left const& left, Right const& right)
: left(left), right(right) {}
: left(left), right(right)
{
detail::assert_initialized_rule(left);
detail::assert_initialized_rule(right);
}

binary_parser const& get_binary() const { return *this; }

Expand Down
3 changes: 2 additions & 1 deletion include/boost/spirit/home/x3/nonterminal/rule.hpp
Expand Up @@ -134,7 +134,8 @@ namespace boost { namespace spirit { namespace x3
typedef std::string result_type;
std::string operator()(T const& r) const
{
return r.name;
BOOST_ASSERT_MSG(r.name, "uninitialized rule"); // static initialization order fiasco
return r.name? r.name : "uninitialized";
}
};

Expand Down