Commit a0059d78 authored by Dominik Charousset's avatar Dominik Charousset

fixed handling of 'const' in `to_uniform_name`

parent 40b92b4c
...@@ -94,7 +94,13 @@ constexpr const char* mapped_name() { ...@@ -94,7 +94,13 @@ constexpr const char* mapped_name() {
return mapped_type_names[util::tl_index_of<zipped_type_list, T>::value][1]; return mapped_type_names[util::tl_index_of<zipped_type_list, T>::value][1];
} }
const char* mapped_name_by_decorated_name(const char* decorated_type_name); const char* mapped_name_by_decorated_name(const char* decorated_name);
std::string mapped_name_by_decorated_name(std::string&& decorated_name);
inline const char* mapped_name_by_decorated_name(const std::string& decorated_name) {
return mapped_name_by_decorated_name(decorated_name.c_str());
}
// lookup table for integer types // lookup table for integer types
extern const char* mapped_int_names[][2]; extern const char* mapped_int_names[][2];
......
...@@ -45,11 +45,33 @@ ...@@ -45,11 +45,33 @@
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/message_header.hpp" #include "cppa/message_header.hpp"
#include "cppa/util/algorithm.hpp"
#include "cppa/util/scope_guard.hpp"
#include "cppa/detail/demangle.hpp" #include "cppa/detail/demangle.hpp"
#include "cppa/detail/to_uniform_name.hpp" #include "cppa/detail/to_uniform_name.hpp"
#include "cppa/detail/singleton_manager.hpp" #include "cppa/detail/singleton_manager.hpp"
#include "cppa/detail/uniform_type_info_map.hpp" #include "cppa/detail/uniform_type_info_map.hpp"
//#define DEBUG_PARSER
#ifdef DEBUG_PARSER
namespace { size_t s_indentation = 0; }
# define PARSER_INIT(message) \
std::cout << std::string(s_indentation, ' ') << ">>> " << message \
<< std::endl; \
s_indentation += 2; \
auto ____sg = cppa::util::make_scope_guard([] { s_indentation -= 2; })
# define PARSER_OUT(condition, message) \
if (condition) { \
std::cout << std::string(s_indentation, ' ') << "### " << message \
<< std::endl; \
} static_cast<void>(0)
#else
# define PARSER_INIT(unused) static_cast<void>(0)
# define PARSER_OUT(unused1, unused2) static_cast<void>(0)
#endif
namespace { namespace {
using namespace std; using namespace std;
...@@ -86,6 +108,7 @@ platform_int_mapping platform_dependent_sizes[] = { ...@@ -86,6 +108,7 @@ platform_int_mapping platform_dependent_sizes[] = {
{"unsigned short int", sizeof(unsigned short int), false} {"unsigned short int", sizeof(unsigned short int), false}
}; };
/*
string map2decorated(const char* name) { string map2decorated(const char* name) {
auto cmp = [](const platform_int_mapping& pim, const char* name) { auto cmp = [](const platform_int_mapping& pim, const char* name) {
return strcmp(pim.name, name) < 0; return strcmp(pim.name, name) < 0;
...@@ -97,42 +120,66 @@ string map2decorated(const char* name) { ...@@ -97,42 +120,66 @@ string map2decorated(const char* name) {
} }
return mapped_name_by_decorated_name(name); return mapped_name_by_decorated_name(name);
} }
*/
string map2decorated(string&& name) {
auto cmp = [](const platform_int_mapping& pim, const string& str) {
return strcmp(pim.name, str.c_str()) < 0;
};
auto e = end(platform_dependent_sizes);
auto i = lower_bound(begin(platform_dependent_sizes), e, name, cmp);
if (i != e && i->name == name) {
PARSER_OUT(true, name << " => " << mapped_int_names[i->size][i->is_signed ? 1 : 0]);
return mapped_int_names[i->size][i->is_signed ? 1 : 0];
}
# ifdef DEBUG_PARSER
auto mapped = mapped_name_by_decorated_name(name.c_str());
PARSER_OUT(mapped != name, name << " => " << string{mapped});
return mapped;
# else
return mapped_name_by_decorated_name(std::move(name));
# endif
}
class parse_tree { class parse_tree {
public: public:
string compile() const { string compile(bool parent_invoked = false) {
string result; string result;
if (has_children()) { propagate_flags();
for (auto& c : m_children) { if (!parent_invoked) {
if (!result.empty()) result += "::";
result += map2decorated(c.compile().c_str());
}
}
else {
if (m_volatile) result += "volatile "; if (m_volatile) result += "volatile ";
if (m_const) result += "const "; if (m_const) result += "const ";
if (!is_template()) { }
result += map2decorated(m_name.c_str()); if (has_children()) {
string sub_result = m_children.front().compile(true);
for (auto i = m_children.begin() + 1; i != m_children.end(); ++i) {
sub_result += "::";
sub_result += i->compile(true);
}
result += map2decorated(std::move(sub_result));
} }
else { else {
string full_name = m_name; string full_name = map2decorated(std::move(m_name));
if (is_template()) {
full_name += "<"; full_name += "<";
for (auto& tparam : m_template_parameters) { for (auto& tparam : m_template_parameters) {
// decorate each single template parameter // decorate each single template parameter
if (full_name.back() != '<') full_name += ","; if (full_name.back() != '<') full_name += ",";
full_name += map2decorated(tparam.compile().c_str()); full_name += tparam.compile();
} }
full_name += ">"; full_name += ">";
// decorate full name // decorate full name
result += map2decorated(full_name.c_str());
} }
result += map2decorated(std::move(full_name));
}
if (!parent_invoked) {
if (m_pointer) result += "*"; if (m_pointer) result += "*";
if (m_lvalue_ref) result += "&"; if (m_lvalue_ref) result += "&";
if (m_rvalue_ref) result += "&&"; if (m_rvalue_ref) result += "&&";
} }
return result; return map2decorated(std::move(result));
} }
template<typename Iterator> template<typename Iterator>
...@@ -140,6 +187,7 @@ class parse_tree { ...@@ -140,6 +187,7 @@ class parse_tree {
template<typename Iterator> template<typename Iterator>
static parse_tree parse(Iterator first, Iterator last) { static parse_tree parse(Iterator first, Iterator last) {
PARSER_INIT((std::string{first, last}));
parse_tree result; parse_tree result;
typedef std::pair<Iterator, Iterator> range; typedef std::pair<Iterator, Iterator> range;
std::vector<range> subranges; std::vector<range> subranges;
...@@ -157,8 +205,9 @@ class parse_tree { ...@@ -157,8 +205,9 @@ class parse_tree {
}; };
auto sub_first = find(first, last, '<'); auto sub_first = find(first, last, '<');
while (sub_first != last) { while (sub_first != last) {
subranges.emplace_back(sub_first, find_end(sub_first)); auto sub_last = find_end(sub_first);
sub_first = find(sub_first + 1, last, '<'); subranges.emplace_back(sub_first, sub_last);
sub_first = find(sub_last + 1, last, '<');
} }
} }
auto islegal = [](char c) { return isalnum(c) || c == ':' || c == '_'; }; auto islegal = [](char c) { return isalnum(c) || c == ':' || c == '_'; };
...@@ -172,6 +221,8 @@ class parse_tree { ...@@ -172,6 +221,8 @@ class parse_tree {
return false; return false;
}; };
auto add_child = [&](Iterator ch_first, Iterator ch_last) { auto add_child = [&](Iterator ch_first, Iterator ch_last) {
PARSER_OUT(true, "new child: [" << distance(first, ch_first) << ", "
<< ", " << distance(first, ch_last) << ")");
result.m_children.push_back(parse(ch_first, ch_last)); result.m_children.push_back(parse(ch_first, ch_last));
}; };
// scan string for "::" separators // scan string for "::" separators
...@@ -180,13 +231,13 @@ class parse_tree { ...@@ -180,13 +231,13 @@ class parse_tree {
auto sr_last = sr_first + 2; auto sr_last = sr_first + 2;
auto scope_iter = search(first, last, sr_first, sr_last); auto scope_iter = search(first, last, sr_first, sr_last);
if (scope_iter != last) { if (scope_iter != last) {
Iterator itermediate = first; auto itermediate = first;
if (!is_in_subrange(scope_iter)) { if (!is_in_subrange(scope_iter)) {
add_child(first, scope_iter); add_child(first, scope_iter);
itermediate = scope_iter + 2; itermediate = scope_iter + 2;
} }
while (scope_iter != last) { while (scope_iter != last) {
scope_iter = find_first_of(scope_iter + 2, last, sr_first, sr_last); scope_iter = search(scope_iter + 2, last, sr_first, sr_last);
if (scope_iter != last && !is_in_subrange(scope_iter)) { if (scope_iter != last && !is_in_subrange(scope_iter)) {
add_child(itermediate, scope_iter); add_child(itermediate, scope_iter);
itermediate = scope_iter + 2; itermediate = scope_iter + 2;
...@@ -199,9 +250,20 @@ class parse_tree { ...@@ -199,9 +250,20 @@ class parse_tree {
if (result.m_children.empty()) { if (result.m_children.empty()) {
// no children -> leaf node; parse non-template part now // no children -> leaf node; parse non-template part now
CPPA_REQUIRE(subranges.size() < 2); CPPA_REQUIRE(subranges.size() < 2);
auto non_template_last = subranges.empty() ? last vector<range> non_template_ranges;
: subranges[0].first; if (subranges.empty()) {
for (auto i = first; i != non_template_last; ++i) { non_template_ranges.emplace_back(first, last);
}
else {
non_template_ranges.emplace_back(first, subranges[0].first);
for (size_t i = 1; i < subranges.size(); ++i) {
non_template_ranges.emplace_back(subranges[i-1].second + 1,
subranges[i].first);
}
non_template_ranges.emplace_back(subranges.back().second + 1, last);
}
for (auto& ntr : non_template_ranges) {
for (auto i = ntr.first; i != ntr.second; ++i) {
char c = *i; char c = *i;
if (islegal(c)) { if (islegal(c)) {
if (!tokens.back().empty() && !islegal(tokens.back().back())) { if (!tokens.back().empty() && !islegal(tokens.back().back())) {
...@@ -224,8 +286,12 @@ class parse_tree { ...@@ -224,8 +286,12 @@ class parse_tree {
tokens.push_back("*"); tokens.push_back("*");
} }
} }
tokens.push_back("");
}
if (!subranges.empty()) { if (!subranges.empty()) {
auto& range0 = subranges.front(); auto& range0 = subranges.front();
PARSER_OUT(true, "subrange: [" << distance(first, range0.first + 1)
<< "," << distance(first, range0.second) << ")");
result.m_template_parameters = parse_tpl_args(range0.first + 1, result.m_template_parameters = parse_tpl_args(range0.first + 1,
range0.second); range0.second);
} }
...@@ -254,6 +320,8 @@ class parse_tree { ...@@ -254,6 +320,8 @@ class parse_tree {
} }
} }
} }
PARSER_OUT(!subranges.empty(), subranges.size() << " subranges");
PARSER_OUT(!result.m_children.empty(), result.m_children.size() << " children");
return result; return result;
} }
...@@ -267,6 +335,17 @@ class parse_tree { ...@@ -267,6 +335,17 @@ class parse_tree {
private: private:
void propagate_flags() {
for (auto& c : m_children) {
c.propagate_flags();
if (c.m_volatile) m_volatile = true;
if (c.m_const) m_const = true;
if (c.m_pointer) m_pointer = true;
if (c.m_lvalue_ref) m_lvalue_ref = true;
if (c.m_rvalue_ref) m_rvalue_ref = true;
}
}
parse_tree() parse_tree()
: m_const(false), m_pointer(false), m_volatile(false) : m_const(false), m_pointer(false), m_volatile(false)
, m_lvalue_ref(false), m_rvalue_ref(false) { } , m_lvalue_ref(false), m_rvalue_ref(false) { }
...@@ -333,7 +412,7 @@ std::string to_uniform_name(const std::string& dname) { ...@@ -333,7 +412,7 @@ std::string to_uniform_name(const std::string& dname) {
auto r = parse_tree::parse(begin(dname), end(dname)).compile(); auto r = parse_tree::parse(begin(dname), end(dname)).compile();
// replace compiler-dependent "anonmyous namespace" with "@_" // replace compiler-dependent "anonmyous namespace" with "@_"
replace_all(r, s_rawan, s_an); replace_all(r, s_rawan, s_an);
return r; return r.c_str();
} }
std::string to_uniform_name(const std::type_info& tinfo) { std::string to_uniform_name(const std::type_info& tinfo) {
......
...@@ -123,6 +123,11 @@ const char* mapped_name_by_decorated_name(const char* cstr) { ...@@ -123,6 +123,11 @@ const char* mapped_name_by_decorated_name(const char* cstr) {
return cstr; return cstr;
} }
std::string mapped_name_by_decorated_name(std::string&& str) {
auto res = mapped_name_by_decorated_name(str.c_str());
if (res == str.c_str()) return std::move(str);
return res;
}
namespace { namespace {
......
...@@ -64,6 +64,11 @@ int main() { ...@@ -64,6 +64,11 @@ int main() {
CPPA_CHECK_EQUAL(get<foo>(obj1).value, 42); CPPA_CHECK_EQUAL(get<foo>(obj1).value, 42);
CPPA_CHECK_EQUAL(get<foo>(obj2).value, 0); CPPA_CHECK_EQUAL(get<foo>(obj2).value, 0);
} }
{
auto uti = uniform_typeid<atom_value>();
CPPA_CHECK(uti != nullptr);
CPPA_CHECK_EQUAL(uti->name(), "@atom");
}
// these types (and only those) are present if // these types (and only those) are present if
// the uniform_type_info implementation is correct // the uniform_type_info implementation is correct
std::set<std::string> expected = { std::set<std::string> expected = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment