diff options
author | Kate Stone <katherine.stone@apple.com> | 2016-09-06 20:57:50 +0000 |
---|---|---|
committer | Kate Stone <katherine.stone@apple.com> | 2016-09-06 20:57:50 +0000 |
commit | b9c1b51e45b845debb76d8658edabca70ca56079 (patch) | |
tree | dfcb5a13ef2b014202340f47036da383eaee74aa /lldb/source/Core/CxaDemangle.cpp | |
parent | d5aa73376966339caad04013510626ec2e42c760 (diff) | |
download | bcm5719-llvm-b9c1b51e45b845debb76d8658edabca70ca56079.tar.gz bcm5719-llvm-b9c1b51e45b845debb76d8658edabca70ca56079.zip |
*** This commit represents a complete reformatting of the LLDB source code
*** to conform to clang-format’s LLVM style. This kind of mass change has
*** two obvious implications:
Firstly, merging this particular commit into a downstream fork may be a huge
effort. Alternatively, it may be worth merging all changes up to this commit,
performing the same reformatting operation locally, and then discarding the
merge for this particular commit. The commands used to accomplish this
reformatting were as follows (with current working directory as the root of
the repository):
find . \( -iname "*.c" -or -iname "*.cpp" -or -iname "*.h" -or -iname "*.mm" \) -exec clang-format -i {} +
find . -iname "*.py" -exec autopep8 --in-place --aggressive --aggressive {} + ;
The version of clang-format used was 3.9.0, and autopep8 was 1.2.4.
Secondly, “blame” style tools will generally point to this commit instead of
a meaningful prior commit. There are alternatives available that will attempt
to look through this change and find the appropriate prior commit. YMMV.
llvm-svn: 280751
Diffstat (limited to 'lldb/source/Core/CxaDemangle.cpp')
-rw-r--r-- | lldb/source/Core/CxaDemangle.cpp | 8093 |
1 files changed, 3741 insertions, 4352 deletions
diff --git a/lldb/source/Core/CxaDemangle.cpp b/lldb/source/Core/CxaDemangle.cpp index 4bb0af52e20..5c1c2683418 100644 --- a/lldb/source/Core/CxaDemangle.cpp +++ b/lldb/source/Core/CxaDemangle.cpp @@ -16,11 +16,11 @@ // - Include <cstdio> for fprintf, stderr like entities. //---------------------------------------------------------------------- -#include "llvm/Support/Compiler.h" // LLVM_{NOEXCEPT, CONSTEXPR, ALIGNAS} +#include "llvm/Support/Compiler.h" // LLVM_{NOEXCEPT, CONSTEXPR, ALIGNAS} #include "lldb/Host/PosixApi.h" #include "lldb/lldb-private.h" -#undef _LIBCPP_EXTERN_TEMPLATE // Avoid warning below +#undef _LIBCPP_EXTERN_TEMPLATE // Avoid warning below //===-------------------------- cxa_demangle.cpp --------------------------===// // @@ -34,237 +34,202 @@ #define _LIBCPP_EXTERN_TEMPLATE(...) #define _LIBCPP_NO_EXCEPTIONS -#include <vector> #include <algorithm> -#include <string> -#include <numeric> -#include <cstdlib> -#include <cstring> #include <cctype> #include <cstdio> +#include <cstdlib> +#include <cstring> +#include <numeric> +#include <string> +#include <vector> -namespace lldb_private -{ +namespace lldb_private { -namespace -{ +namespace { -enum -{ - unknown_error = -4, - invalid_args = -3, - invalid_mangled_name, - memory_alloc_failure, - success +enum { + unknown_error = -4, + invalid_args = -3, + invalid_mangled_name, + memory_alloc_failure, + success }; template <class C> - const char* parse_type(const char* first, const char* last, C& db); +const char *parse_type(const char *first, const char *last, C &db); template <class C> - const char* parse_encoding(const char* first, const char* last, C& db); +const char *parse_encoding(const char *first, const char *last, C &db); template <class C> - const char* parse_name(const char* first, const char* last, C& db, - bool* ends_with_template_args = 0); +const char *parse_name(const char *first, const char *last, C &db, + bool *ends_with_template_args = 0); template <class C> - const char* parse_expression(const char* first, const char* last, C& db); +const char *parse_expression(const char *first, const char *last, C &db); template <class C> - const char* parse_template_args(const char* first, const char* last, C& db); +const char *parse_template_args(const char *first, const char *last, C &db); template <class C> - const char* parse_operator_name(const char* first, const char* last, C& db); +const char *parse_operator_name(const char *first, const char *last, C &db); template <class C> - const char* parse_unqualified_name(const char* first, const char* last, C& db); +const char *parse_unqualified_name(const char *first, const char *last, C &db); template <class C> - const char* parse_decltype(const char* first, const char* last, C& db); - -template <class C> -void -print_stack(const C& db) -{ - fprintf(stderr, "---------\n"); - fprintf(stderr, "names:\n"); - for (auto& s : db.names) - fprintf(stderr, "{%s#%s}\n", s.first.c_str(), s.second.c_str()); - int i = -1; - fprintf(stderr, "subs:\n"); - for (auto& v : db.subs) - { - if (i >= 0) - fprintf(stderr, "S%i_ = {", i); - else - fprintf(stderr, "S_ = {"); - for (auto& s : v) - fprintf(stderr, "{%s#%s}", s.first.c_str(), s.second.c_str()); - fprintf(stderr, "}\n"); - ++i; - } - fprintf(stderr, "template_param:\n"); - for (auto& t : db.template_param) - { - fprintf(stderr, "--\n"); - i = -1; - for (auto& v : t) - { - if (i >= 0) - fprintf(stderr, "T%i_ = {", i); - else - fprintf(stderr, "T_ = {"); - for (auto& s : v) - fprintf(stderr, "{%s#%s}", s.first.c_str(), s.second.c_str()); - fprintf(stderr, "}\n"); - ++i; - } +const char *parse_decltype(const char *first, const char *last, C &db); + +template <class C> void print_stack(const C &db) { + fprintf(stderr, "---------\n"); + fprintf(stderr, "names:\n"); + for (auto &s : db.names) + fprintf(stderr, "{%s#%s}\n", s.first.c_str(), s.second.c_str()); + int i = -1; + fprintf(stderr, "subs:\n"); + for (auto &v : db.subs) { + if (i >= 0) + fprintf(stderr, "S%i_ = {", i); + else + fprintf(stderr, "S_ = {"); + for (auto &s : v) + fprintf(stderr, "{%s#%s}", s.first.c_str(), s.second.c_str()); + fprintf(stderr, "}\n"); + ++i; + } + fprintf(stderr, "template_param:\n"); + for (auto &t : db.template_param) { + fprintf(stderr, "--\n"); + i = -1; + for (auto &v : t) { + if (i >= 0) + fprintf(stderr, "T%i_ = {", i); + else + fprintf(stderr, "T_ = {"); + for (auto &s : v) + fprintf(stderr, "{%s#%s}", s.first.c_str(), s.second.c_str()); + fprintf(stderr, "}\n"); + ++i; } - fprintf(stderr, "---------\n\n"); + } + fprintf(stderr, "---------\n\n"); } template <class C> -void -print_state(const char* msg, const char* first, const char* last, const C& db) -{ - fprintf(stderr, "%s: ", msg); - for (; first != last; ++first) - fprintf(stderr, "%c", *first); - fprintf(stderr, "\n"); - print_stack(db); +void print_state(const char *msg, const char *first, const char *last, + const C &db) { + fprintf(stderr, "%s: ", msg); + for (; first != last; ++first) + fprintf(stderr, "%c", *first); + fprintf(stderr, "\n"); + print_stack(db); } // <number> ::= [n] <non-negative decimal integer> -const char* -parse_number(const char* first, const char* last) -{ - if (first != last) - { - const char* t = first; - if (*t == 'n') - ++t; - if (t != last) - { - if (*t == '0') - { - first = t+1; - } - else if ('1' <= *t && *t <= '9') - { - first = t+1; - while (first != last && std::isdigit(*first)) - ++first; - } - } +const char *parse_number(const char *first, const char *last) { + if (first != last) { + const char *t = first; + if (*t == 'n') + ++t; + if (t != last) { + if (*t == '0') { + first = t + 1; + } else if ('1' <= *t && *t <= '9') { + first = t + 1; + while (first != last && std::isdigit(*first)) + ++first; + } } - return first; + } + return first; } -template <class Float> -struct float_data; +template <class Float> struct float_data; -template <> -struct float_data<float> -{ - static const size_t mangled_size = 8; - static const size_t max_demangled_size = 24; - static const char* spec; +template <> struct float_data<float> { + static const size_t mangled_size = 8; + static const size_t max_demangled_size = 24; + static const char *spec; }; -const char* float_data<float>::spec = "%af"; +const char *float_data<float>::spec = "%af"; -template <> -struct float_data<double> -{ - static const size_t mangled_size = 16; - static const size_t max_demangled_size = 32; - static const char* spec; +template <> struct float_data<double> { + static const size_t mangled_size = 16; + static const size_t max_demangled_size = 32; + static const char *spec; }; -const char* float_data<double>::spec = "%a"; +const char *float_data<double>::spec = "%a"; -template <> -struct float_data<long double> -{ +template <> struct float_data<long double> { #if defined(__arm__) - static const size_t mangled_size = 16; + static const size_t mangled_size = 16; #else - static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms + static const size_t mangled_size = + 20; // May need to be adjusted to 16 or 24 on other platforms #endif - static const size_t max_demangled_size = 40; - static const char* spec; + static const size_t max_demangled_size = 40; + static const char *spec; }; -const char* float_data<long double>::spec = "%LaL"; +const char *float_data<long double>::spec = "%LaL"; template <class Float, class C> -const char* -parse_floating_number(const char* first, const char* last, C& db) -{ - const size_t N = float_data<Float>::mangled_size; - if (static_cast<std::size_t>(last - first) > N) - { - last = first + N; - union - { - Float value; - char buf[sizeof(Float)]; - }; - const char* t = first; - char* e = buf; - for (; t != last; ++t, ++e) - { - if (!isxdigit(*t)) - return first; - unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0') : - static_cast<unsigned>(*t - 'a' + 10); - ++t; - unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0') : - static_cast<unsigned>(*t - 'a' + 10); - *e = static_cast<char>((d1 << 4) + d0); - } - if (*t == 'E') - { +const char *parse_floating_number(const char *first, const char *last, C &db) { + const size_t N = float_data<Float>::mangled_size; + if (static_cast<std::size_t>(last - first) > N) { + last = first + N; + union { + Float value; + char buf[sizeof(Float)]; + }; + const char *t = first; + char *e = buf; + for (; t != last; ++t, ++e) { + if (!isxdigit(*t)) + return first; + unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0') + : static_cast<unsigned>(*t - 'a' + 10); + ++t; + unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0') + : static_cast<unsigned>(*t - 'a' + 10); + *e = static_cast<char>((d1 << 4) + d0); + } + if (*t == 'E') { #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - std::reverse(buf, e); + std::reverse(buf, e); #endif - char num[float_data<Float>::max_demangled_size] = {0}; - int n = snprintf(num, sizeof(num), float_data<Float>::spec, value); - if (static_cast<std::size_t>(n) >= sizeof(num)) - return first; - db.names.push_back(typename C::String(num, static_cast<std::size_t>(n))); - first = t+1; - } + char num[float_data<Float>::max_demangled_size] = {0}; + int n = snprintf(num, sizeof(num), float_data<Float>::spec, value); + if (static_cast<std::size_t>(n) >= sizeof(num)) + return first; + db.names.push_back(typename C::String(num, static_cast<std::size_t>(n))); + first = t + 1; } - return first; + } + return first; } // <source-name> ::= <positive length number> <identifier> template <class C> -const char* -parse_source_name(const char* first, const char* last, C& db) -{ - if (first != last) - { - char c = *first; - if (isdigit(c) && first+1 != last) - { - const char* t = first+1; - size_t n = static_cast<size_t>(c - '0'); - for (c = *t; isdigit(c); c = *t) - { - n = n * 10 + static_cast<size_t>(c - '0'); - if (++t == last) - return first; - } - if (static_cast<size_t>(last - t) >= n) - { - typename C::String r(t, n); - if (r.substr(0, 10) == "_GLOBAL__N") - db.names.push_back("(anonymous namespace)"); - else - db.names.push_back(std::move(r)); - first = t + n; - } - } +const char *parse_source_name(const char *first, const char *last, C &db) { + if (first != last) { + char c = *first; + if (isdigit(c) && first + 1 != last) { + const char *t = first + 1; + size_t n = static_cast<size_t>(c - '0'); + for (c = *t; isdigit(c); c = *t) { + n = n * 10 + static_cast<size_t>(c - '0'); + if (++t == last) + return first; + } + if (static_cast<size_t>(last - t) >= n) { + typename C::String r(t, n); + if (r.substr(0, 10) == "_GLOBAL__N") + db.names.push_back("(anonymous namespace)"); + else + db.names.push_back(std::move(r)); + first = t + n; + } } - return first; + } + return first; } // <substitution> ::= S <seq-id> _ @@ -279,79 +244,70 @@ parse_source_name(const char* first, const char* last, C& db) // <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> > template <class C> -const char* -parse_substitution(const char* first, const char* last, C& db) -{ - if (last - first >= 2) - { - if (*first == 'S') - { - switch (first[1]) - { - case 'a': - db.names.push_back("std::allocator"); - first += 2; - break; - case 'b': - db.names.push_back("std::basic_string"); - first += 2; - break; - case 's': - db.names.push_back("std::string"); - first += 2; - break; - case 'i': - db.names.push_back("std::istream"); - first += 2; - break; - case 'o': - db.names.push_back("std::ostream"); - first += 2; - break; - case 'd': - db.names.push_back("std::iostream"); - first += 2; - break; - case '_': - if (!db.subs.empty()) - { - for (const auto& n : db.subs.front()) - db.names.push_back(n); - first += 2; - } - break; - default: - if (std::isdigit(first[1]) || std::isupper(first[1])) - { - size_t sub = 0; - const char* t = first+1; - if (std::isdigit(*t)) - sub = static_cast<size_t>(*t - '0'); - else - sub = static_cast<size_t>(*t - 'A') + 10; - for (++t; t != last && (std::isdigit(*t) || std::isupper(*t)); ++t) - { - sub *= 36; - if (std::isdigit(*t)) - sub += static_cast<size_t>(*t - '0'); - else - sub += static_cast<size_t>(*t - 'A') + 10; - } - if (t == last || *t != '_') - return first; - ++sub; - if (sub < db.subs.size()) - { - for (const auto& n : db.subs[sub]) - db.names.push_back(n); - first = t+1; - } - } - break; - } +const char *parse_substitution(const char *first, const char *last, C &db) { + if (last - first >= 2) { + if (*first == 'S') { + switch (first[1]) { + case 'a': + db.names.push_back("std::allocator"); + first += 2; + break; + case 'b': + db.names.push_back("std::basic_string"); + first += 2; + break; + case 's': + db.names.push_back("std::string"); + first += 2; + break; + case 'i': + db.names.push_back("std::istream"); + first += 2; + break; + case 'o': + db.names.push_back("std::ostream"); + first += 2; + break; + case 'd': + db.names.push_back("std::iostream"); + first += 2; + break; + case '_': + if (!db.subs.empty()) { + for (const auto &n : db.subs.front()) + db.names.push_back(n); + first += 2; + } + break; + default: + if (std::isdigit(first[1]) || std::isupper(first[1])) { + size_t sub = 0; + const char *t = first + 1; + if (std::isdigit(*t)) + sub = static_cast<size_t>(*t - '0'); + else + sub = static_cast<size_t>(*t - 'A') + 10; + for (++t; t != last && (std::isdigit(*t) || std::isupper(*t)); ++t) { + sub *= 36; + if (std::isdigit(*t)) + sub += static_cast<size_t>(*t - '0'); + else + sub += static_cast<size_t>(*t - 'A') + 10; + } + if (t == last || *t != '_') + return first; + ++sub; + if (sub < db.subs.size()) { + for (const auto &n : db.subs[sub]) + db.names.push_back(n); + first = t + 1; + } } + break; + } } - return first; + } + return first; } // <builtin-type> ::= v # void @@ -387,587 +343,513 @@ parse_substitution(const char* first, const char* last, C& db) // ::= u <source-name> # vendor extended type template <class C> -const char* -parse_builtin_type(const char* first, const char* last, C& db) -{ - if (first != last) - { - switch (*first) - { - case 'v': - db.names.push_back("void"); - ++first; - break; - case 'w': - db.names.push_back("wchar_t"); - ++first; - break; - case 'b': - db.names.push_back("bool"); - ++first; - break; - case 'c': - db.names.push_back("char"); - ++first; - break; - case 'a': - db.names.push_back("signed char"); - ++first; - break; +const char *parse_builtin_type(const char *first, const char *last, C &db) { + if (first != last) { + switch (*first) { + case 'v': + db.names.push_back("void"); + ++first; + break; + case 'w': + db.names.push_back("wchar_t"); + ++first; + break; + case 'b': + db.names.push_back("bool"); + ++first; + break; + case 'c': + db.names.push_back("char"); + ++first; + break; + case 'a': + db.names.push_back("signed char"); + ++first; + break; + case 'h': + db.names.push_back("unsigned char"); + ++first; + break; + case 's': + db.names.push_back("short"); + ++first; + break; + case 't': + db.names.push_back("unsigned short"); + ++first; + break; + case 'i': + db.names.push_back("int"); + ++first; + break; + case 'j': + db.names.push_back("unsigned int"); + ++first; + break; + case 'l': + db.names.push_back("long"); + ++first; + break; + case 'm': + db.names.push_back("unsigned long"); + ++first; + break; + case 'x': + db.names.push_back("long long"); + ++first; + break; + case 'y': + db.names.push_back("unsigned long long"); + ++first; + break; + case 'n': + db.names.push_back("__int128"); + ++first; + break; + case 'o': + db.names.push_back("unsigned __int128"); + ++first; + break; + case 'f': + db.names.push_back("float"); + ++first; + break; + case 'd': + db.names.push_back("double"); + ++first; + break; + case 'e': + db.names.push_back("long double"); + ++first; + break; + case 'g': + db.names.push_back("__float128"); + ++first; + break; + case 'z': + db.names.push_back("..."); + ++first; + break; + case 'u': { + const char *t = parse_source_name(first + 1, last, db); + if (t != first + 1) + first = t; + } break; + case 'D': + if (first + 1 != last) { + switch (first[1]) { + case 'd': + db.names.push_back("decimal64"); + first += 2; + break; + case 'e': + db.names.push_back("decimal128"); + first += 2; + break; + case 'f': + db.names.push_back("decimal32"); + first += 2; + break; case 'h': - db.names.push_back("unsigned char"); - ++first; - break; - case 's': - db.names.push_back("short"); - ++first; - break; - case 't': - db.names.push_back("unsigned short"); - ++first; - break; + db.names.push_back("decimal16"); + first += 2; + break; case 'i': - db.names.push_back("int"); - ++first; - break; - case 'j': - db.names.push_back("unsigned int"); - ++first; - break; - case 'l': - db.names.push_back("long"); - ++first; - break; - case 'm': - db.names.push_back("unsigned long"); - ++first; - break; - case 'x': - db.names.push_back("long long"); - ++first; - break; - case 'y': - db.names.push_back("unsigned long long"); - ++first; - break; + db.names.push_back("char32_t"); + first += 2; + break; + case 's': + db.names.push_back("char16_t"); + first += 2; + break; + case 'a': + db.names.push_back("auto"); + first += 2; + break; + case 'c': + db.names.push_back("decltype(auto)"); + first += 2; + break; case 'n': - db.names.push_back("__int128"); - ++first; - break; - case 'o': - db.names.push_back("unsigned __int128"); - ++first; - break; - case 'f': - db.names.push_back("float"); - ++first; - break; - case 'd': - db.names.push_back("double"); - ++first; - break; - case 'e': - db.names.push_back("long double"); - ++first; - break; - case 'g': - db.names.push_back("__float128"); - ++first; - break; - case 'z': - db.names.push_back("..."); - ++first; - break; - case 'u': - { - const char*t = parse_source_name(first+1, last, db); - if (t != first+1) - first = t; - } - break; - case 'D': - if (first+1 != last) - { - switch (first[1]) - { - case 'd': - db.names.push_back("decimal64"); - first += 2; - break; - case 'e': - db.names.push_back("decimal128"); - first += 2; - break; - case 'f': - db.names.push_back("decimal32"); - first += 2; - break; - case 'h': - db.names.push_back("decimal16"); - first += 2; - break; - case 'i': - db.names.push_back("char32_t"); - first += 2; - break; - case 's': - db.names.push_back("char16_t"); - first += 2; - break; - case 'a': - db.names.push_back("auto"); - first += 2; - break; - case 'c': - db.names.push_back("decltype(auto)"); - first += 2; - break; - case 'n': - db.names.push_back("std::nullptr_t"); - first += 2; - break; - } - } - break; + db.names.push_back("std::nullptr_t"); + first += 2; + break; } + } + break; } - return first; + } + return first; } // <CV-qualifiers> ::= [r] [V] [K] -const char* -parse_cv_qualifiers(const char* first, const char* last, unsigned& cv) -{ - cv = 0; - if (first != last) - { - if (*first == 'r') - { - cv |= 4; - ++first; - } - if (*first == 'V') - { - cv |= 2; - ++first; - } - if (*first == 'K') - { - cv |= 1; - ++first; - } +const char *parse_cv_qualifiers(const char *first, const char *last, + unsigned &cv) { + cv = 0; + if (first != last) { + if (*first == 'r') { + cv |= 4; + ++first; + } + if (*first == 'V') { + cv |= 2; + ++first; } - return first; + if (*first == 'K') { + cv |= 1; + ++first; + } + } + return first; } // <template-param> ::= T_ # first template parameter // ::= T <parameter-2 non-negative number> _ template <class C> -const char* -parse_template_param(const char* first, const char* last, C& db) -{ - if (last - first >= 2) - { - if (*first == 'T') - { - if (first[1] == '_') - { - if (db.template_param.empty()) - return first; - if (!db.template_param.back().empty()) - { - for (auto& t : db.template_param.back().front()) - db.names.push_back(t); - first += 2; - } - else - { - db.names.push_back("T_"); - first += 2; - db.fix_forward_references = true; - } - } - else if (isdigit(first[1])) - { - const char* t = first+1; - size_t sub = static_cast<size_t>(*t - '0'); - for (++t; t != last && isdigit(*t); ++t) - { - sub *= 10; - sub += static_cast<size_t>(*t - '0'); - } - if (t == last || *t != '_' || db.template_param.empty()) - return first; - ++sub; - if (sub < db.template_param.back().size()) - { - for (auto& temp : db.template_param.back()[sub]) - db.names.push_back(temp); - first = t+1; - } - else - { - db.names.push_back(typename C::String(first, t+1)); - first = t+1; - db.fix_forward_references = true; - } - } +const char *parse_template_param(const char *first, const char *last, C &db) { + if (last - first >= 2) { + if (*first == 'T') { + if (first[1] == '_') { + if (db.template_param.empty()) + return first; + if (!db.template_param.back().empty()) { + for (auto &t : db.template_param.back().front()) + db.names.push_back(t); + first += 2; + } else { + db.names.push_back("T_"); + first += 2; + db.fix_forward_references = true; + } + } else if (isdigit(first[1])) { + const char *t = first + 1; + size_t sub = static_cast<size_t>(*t - '0'); + for (++t; t != last && isdigit(*t); ++t) { + sub *= 10; + sub += static_cast<size_t>(*t - '0'); } + if (t == last || *t != '_' || db.template_param.empty()) + return first; + ++sub; + if (sub < db.template_param.back().size()) { + for (auto &temp : db.template_param.back()[sub]) + db.names.push_back(temp); + first = t + 1; + } else { + db.names.push_back(typename C::String(first, t + 1)); + first = t + 1; + db.fix_forward_references = true; + } + } } - return first; + } + return first; } -// cc <type> <expression> # const_cast<type> (expression) +// cc <type> <expression> # const_cast<type> +// (expression) template <class C> -const char* -parse_const_cast_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 'c' && first[1] == 'c') - { - const char* t = parse_type(first+2, last, db); - if (t != first+2) - { - const char* t1 = parse_expression(t, last, db); - if (t1 != t) - { - if (db.names.size() < 2) - return first; - auto expr = db.names.back().move_full(); - db.names.pop_back(); - db.names.back() = "const_cast<" + db.names.back().move_full() + ">(" + expr + ")"; - first = t1; - } - } +const char *parse_const_cast_expr(const char *first, const char *last, C &db) { + if (last - first >= 3 && first[0] == 'c' && first[1] == 'c') { + const char *t = parse_type(first + 2, last, db); + if (t != first + 2) { + const char *t1 = parse_expression(t, last, db); + if (t1 != t) { + if (db.names.size() < 2) + return first; + auto expr = db.names.back().move_full(); + db.names.pop_back(); + db.names.back() = + "const_cast<" + db.names.back().move_full() + ">(" + expr + ")"; + first = t1; + } } - return first; + } + return first; } -// dc <type> <expression> # dynamic_cast<type> (expression) +// dc <type> <expression> # dynamic_cast<type> +// (expression) template <class C> -const char* -parse_dynamic_cast_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 'd' && first[1] == 'c') - { - const char* t = parse_type(first+2, last, db); - if (t != first+2) - { - const char* t1 = parse_expression(t, last, db); - if (t1 != t) - { - if (db.names.size() < 2) - return first; - auto expr = db.names.back().move_full(); - db.names.pop_back(); - db.names.back() = "dynamic_cast<" + db.names.back().move_full() + ">(" + expr + ")"; - first = t1; - } - } +const char *parse_dynamic_cast_expr(const char *first, const char *last, + C &db) { + if (last - first >= 3 && first[0] == 'd' && first[1] == 'c') { + const char *t = parse_type(first + 2, last, db); + if (t != first + 2) { + const char *t1 = parse_expression(t, last, db); + if (t1 != t) { + if (db.names.size() < 2) + return first; + auto expr = db.names.back().move_full(); + db.names.pop_back(); + db.names.back() = + "dynamic_cast<" + db.names.back().move_full() + ">(" + expr + ")"; + first = t1; + } } - return first; + } + return first; } -// rc <type> <expression> # reinterpret_cast<type> (expression) +// rc <type> <expression> # reinterpret_cast<type> +// (expression) template <class C> -const char* -parse_reinterpret_cast_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 'r' && first[1] == 'c') - { - const char* t = parse_type(first+2, last, db); - if (t != first+2) - { - const char* t1 = parse_expression(t, last, db); - if (t1 != t) - { - if (db.names.size() < 2) - return first; - auto expr = db.names.back().move_full(); - db.names.pop_back(); - db.names.back() = "reinterpret_cast<" + db.names.back().move_full() + ">(" + expr + ")"; - first = t1; - } - } +const char *parse_reinterpret_cast_expr(const char *first, const char *last, + C &db) { + if (last - first >= 3 && first[0] == 'r' && first[1] == 'c') { + const char *t = parse_type(first + 2, last, db); + if (t != first + 2) { + const char *t1 = parse_expression(t, last, db); + if (t1 != t) { + if (db.names.size() < 2) + return first; + auto expr = db.names.back().move_full(); + db.names.pop_back(); + db.names.back() = "reinterpret_cast<" + db.names.back().move_full() + + ">(" + expr + ")"; + first = t1; + } } - return first; + } + return first; } -// sc <type> <expression> # static_cast<type> (expression) +// sc <type> <expression> # static_cast<type> +// (expression) template <class C> -const char* -parse_static_cast_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 's' && first[1] == 'c') - { - const char* t = parse_type(first+2, last, db); - if (t != first+2) - { - const char* t1 = parse_expression(t, last, db); - if (t1 != t) - { - if (db.names.size() < 2) - return first; - auto expr = db.names.back().move_full(); - db.names.pop_back(); - db.names.back() = "static_cast<" + db.names.back().move_full() + ">(" + expr + ")"; - first = t1; - } - } +const char *parse_static_cast_expr(const char *first, const char *last, C &db) { + if (last - first >= 3 && first[0] == 's' && first[1] == 'c') { + const char *t = parse_type(first + 2, last, db); + if (t != first + 2) { + const char *t1 = parse_expression(t, last, db); + if (t1 != t) { + if (db.names.size() < 2) + return first; + auto expr = db.names.back().move_full(); + db.names.pop_back(); + db.names.back() = + "static_cast<" + db.names.back().move_full() + ">(" + expr + ")"; + first = t1; + } } - return first; + } + return first; } // sp <expression> # pack expansion template <class C> -const char* -parse_pack_expansion(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 's' && first[1] == 'p') - { - const char* t = parse_expression(first+2, last, db); - if (t != first+2) - first = t; - } - return first; +const char *parse_pack_expansion(const char *first, const char *last, C &db) { + if (last - first >= 3 && first[0] == 's' && first[1] == 'p') { + const char *t = parse_expression(first + 2, last, db); + if (t != first + 2) + first = t; + } + return first; } // st <type> # sizeof (a type) template <class C> -const char* -parse_sizeof_type_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 's' && first[1] == 't') - { - const char* t = parse_type(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back() = "sizeof (" + db.names.back().move_full() + ")"; - first = t; - } +const char *parse_sizeof_type_expr(const char *first, const char *last, C &db) { + if (last - first >= 3 && first[0] == 's' && first[1] == 't') { + const char *t = parse_type(first + 2, last, db); + if (t != first + 2) { + if (db.names.empty()) + return first; + db.names.back() = "sizeof (" + db.names.back().move_full() + ")"; + first = t; } - return first; + } + return first; } // sz <expr> # sizeof (a expression) template <class C> -const char* -parse_sizeof_expr_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 's' && first[1] == 'z') - { - const char* t = parse_expression(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back() = "sizeof (" + db.names.back().move_full() + ")"; - first = t; - } +const char *parse_sizeof_expr_expr(const char *first, const char *last, C &db) { + if (last - first >= 3 && first[0] == 's' && first[1] == 'z') { + const char *t = parse_expression(first + 2, last, db); + if (t != first + 2) { + if (db.names.empty()) + return first; + db.names.back() = "sizeof (" + db.names.back().move_full() + ")"; + first = t; } - return first; + } + return first; } -// sZ <template-param> # size of a parameter pack +// sZ <template-param> # size of a parameter +// pack template <class C> -const char* -parse_sizeof_param_pack_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 's' && first[1] == 'Z' && first[2] == 'T') - { - size_t k0 = db.names.size(); - const char* t = parse_template_param(first+2, last, db); - size_t k1 = db.names.size(); - if (t != first+2) - { - typename C::String tmp("sizeof...("); - size_t k = k0; - if (k != k1) - { - tmp += db.names[k].move_full(); - for (++k; k != k1; ++k) - tmp += ", " + db.names[k].move_full(); - } - tmp += ")"; - for (; k1 != k0; --k1) - db.names.pop_back(); - db.names.push_back(std::move(tmp)); - first = t; - } +const char *parse_sizeof_param_pack_expr(const char *first, const char *last, + C &db) { + if (last - first >= 3 && first[0] == 's' && first[1] == 'Z' && + first[2] == 'T') { + size_t k0 = db.names.size(); + const char *t = parse_template_param(first + 2, last, db); + size_t k1 = db.names.size(); + if (t != first + 2) { + typename C::String tmp("sizeof...("); + size_t k = k0; + if (k != k1) { + tmp += db.names[k].move_full(); + for (++k; k != k1; ++k) + tmp += ", " + db.names[k].move_full(); + } + tmp += ")"; + for (; k1 != k0; --k1) + db.names.pop_back(); + db.names.push_back(std::move(tmp)); + first = t; } - return first; + } + return first; } -// <function-param> ::= fp <top-level CV-qualifiers> _ # L == 0, first parameter -// ::= fp <top-level CV-qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters -// ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> _ # L > 0, first parameter -// ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters +// <function-param> ::= fp <top-level CV-qualifiers> _ # L == 0, first parameter +// ::= fp <top-level CV-qualifiers> <parameter-2 non-negative +// number> _ # L == 0, second and later parameters +// ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> +// _ # L > 0, first parameter +// ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> +// <parameter-2 non-negative number> _ # L > 0, second and +// later parameters template <class C> -const char* -parse_function_param(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && *first == 'f') - { - if (first[1] == 'p') - { - unsigned cv; - const char* t = parse_cv_qualifiers(first+2, last, cv); - const char* t1 = parse_number(t, last); - if (t1 != last && *t1 == '_') - { - db.names.push_back("fp" + typename C::String(t, t1)); - first = t1+1; - } - } - else if (first[1] == 'L') - { - unsigned cv; - const char* t0 = parse_number(first+2, last); - if (t0 != last && *t0 == 'p') - { - ++t0; - const char* t = parse_cv_qualifiers(t0, last, cv); - const char* t1 = parse_number(t, last); - if (t1 != last && *t1 == '_') - { - db.names.push_back("fp" + typename C::String(t, t1)); - first = t1+1; - } - } +const char *parse_function_param(const char *first, const char *last, C &db) { + if (last - first >= 3 && *first == 'f') { + if (first[1] == 'p') { + unsigned cv; + const char *t = parse_cv_qualifiers(first + 2, last, cv); + const char *t1 = parse_number(t, last); + if (t1 != last && *t1 == '_') { + db.names.push_back("fp" + typename C::String(t, t1)); + first = t1 + 1; + } + } else if (first[1] == 'L') { + unsigned cv; + const char *t0 = parse_number(first + 2, last); + if (t0 != last && *t0 == 'p') { + ++t0; + const char *t = parse_cv_qualifiers(t0, last, cv); + const char *t1 = parse_number(t, last); + if (t1 != last && *t1 == '_') { + db.names.push_back("fp" + typename C::String(t, t1)); + first = t1 + 1; } + } } - return first; + } + return first; } -// sZ <function-param> # size of a function parameter pack +// sZ <function-param> # size of a function +// parameter pack template <class C> -const char* -parse_sizeof_function_param_pack_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 's' && first[1] == 'Z' && first[2] == 'f') - { - const char* t = parse_function_param(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back() = "sizeof...(" + db.names.back().move_full() + ")"; - first = t; - } +const char *parse_sizeof_function_param_pack_expr(const char *first, + const char *last, C &db) { + if (last - first >= 3 && first[0] == 's' && first[1] == 'Z' && + first[2] == 'f') { + const char *t = parse_function_param(first + 2, last, db); + if (t != first + 2) { + if (db.names.empty()) + return first; + db.names.back() = "sizeof...(" + db.names.back().move_full() + ")"; + first = t; } - return first; + } + return first; } // te <expression> # typeid (expression) // ti <type> # typeid (type) template <class C> -const char* -parse_typeid_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 't' && (first[1] == 'e' || first[1] == 'i')) - { - const char* t; - if (first[1] == 'e') - t = parse_expression(first+2, last, db); - else - t = parse_type(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back() = "typeid(" + db.names.back().move_full() + ")"; - first = t; - } +const char *parse_typeid_expr(const char *first, const char *last, C &db) { + if (last - first >= 3 && first[0] == 't' && + (first[1] == 'e' || first[1] == 'i')) { + const char *t; + if (first[1] == 'e') + t = parse_expression(first + 2, last, db); + else + t = parse_type(first + 2, last, db); + if (t != first + 2) { + if (db.names.empty()) + return first; + db.names.back() = "typeid(" + db.names.back().move_full() + ")"; + first = t; } - return first; + } + return first; } // tw <expression> # throw expression template <class C> -const char* -parse_throw_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 't' && first[1] == 'w') - { - const char* t = parse_expression(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back() = "throw " + db.names.back().move_full(); - first = t; - } +const char *parse_throw_expr(const char *first, const char *last, C &db) { + if (last - first >= 3 && first[0] == 't' && first[1] == 'w') { + const char *t = parse_expression(first + 2, last, db); + if (t != first + 2) { + if (db.names.empty()) + return first; + db.names.back() = "throw " + db.names.back().move_full(); + first = t; } - return first; + } + return first; } // ds <expression> <expression> # expr.*expr template <class C> -const char* -parse_dot_star_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 'd' && first[1] == 's') - { - const char* t = parse_expression(first+2, last, db); - if (t != first+2) - { - const char* t1 = parse_expression(t, last, db); - if (t1 != t) - { - if (db.names.size() < 2) - return first; - auto expr = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += ".*" + expr; - first = t1; - } - } +const char *parse_dot_star_expr(const char *first, const char *last, C &db) { + if (last - first >= 3 && first[0] == 'd' && first[1] == 's') { + const char *t = parse_expression(first + 2, last, db); + if (t != first + 2) { + const char *t1 = parse_expression(t, last, db); + if (t1 != t) { + if (db.names.size() < 2) + return first; + auto expr = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += ".*" + expr; + first = t1; + } } - return first; + } + return first; } // <simple-id> ::= <source-name> [ <template-args> ] template <class C> -const char* -parse_simple_id(const char* first, const char* last, C& db) -{ - if (first != last) - { - const char* t = parse_source_name(first, last, db); - if (t != first) - { - const char* t1 = parse_template_args(t, last, db); - if (t1 != t) - { - if (db.names.size() < 2) - return first; - auto args = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += std::move(args); - } - first = t1; - } - else - first = t; - } - return first; +const char *parse_simple_id(const char *first, const char *last, C &db) { + if (first != last) { + const char *t = parse_source_name(first, last, db); + if (t != first) { + const char *t1 = parse_template_args(t, last, db); + if (t1 != t) { + if (db.names.size() < 2) + return first; + auto args = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += std::move(args); + } + first = t1; + } else + first = t; + } + return first; } // <unresolved-type> ::= <template-param> @@ -975,615 +857,552 @@ parse_simple_id(const char* first, const char* last, C& db) // ::= <substitution> template <class C> -const char* -parse_unresolved_type(const char* first, const char* last, C& db) -{ - if (first != last) - { - const char* t = first; - switch (*first) - { - case 'T': - { - size_t k0 = db.names.size(); - t = parse_template_param(first, last, db); - size_t k1 = db.names.size(); - if (t != first && k1 == k0 + 1) - { - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - first = t; - } - else - { - for (; k1 != k0; --k1) - db.names.pop_back(); - } - break; +const char *parse_unresolved_type(const char *first, const char *last, C &db) { + if (first != last) { + const char *t = first; + switch (*first) { + case 'T': { + size_t k0 = db.names.size(); + t = parse_template_param(first, last, db); + size_t k1 = db.names.size(); + if (t != first && k1 == k0 + 1) { + db.subs.push_back( + typename C::sub_type(1, db.names.back(), db.names.get_allocator())); + first = t; + } else { + for (; k1 != k0; --k1) + db.names.pop_back(); + } + break; + } + case 'D': + t = parse_decltype(first, last, db); + if (t != first) { + if (db.names.empty()) + return first; + db.subs.push_back( + typename C::sub_type(1, db.names.back(), db.names.get_allocator())); + first = t; + } + break; + case 'S': + t = parse_substitution(first, last, db); + if (t != first) + first = t; + else { + if (last - first > 2 && first[1] == 't') { + t = parse_unqualified_name(first + 2, last, db); + if (t != first + 2) { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "std::"); + db.subs.push_back(typename C::sub_type(1, db.names.back(), + db.names.get_allocator())); + first = t; } - case 'D': - t = parse_decltype(first, last, db); - if (t != first) - { - if (db.names.empty()) - return first; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - first = t; - } - break; - case 'S': - t = parse_substitution(first, last, db); - if (t != first) - first = t; - else - { - if (last - first > 2 && first[1] == 't') - { - t = parse_unqualified_name(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "std::"); - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - first = t; - } - } - } - break; - } + } + } + break; } - return first; + } + return first; } -// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f()) -// ::= <simple-id> # e.g., ~A<2*N> +// <destructor-name> ::= <unresolved-type> # e.g., +// ~T or ~decltype(f()) +// ::= <simple-id> # e.g., +// ~A<2*N> template <class C> -const char* -parse_destructor_name(const char* first, const char* last, C& db) -{ - if (first != last) - { - const char* t = parse_unresolved_type(first, last, db); - if (t == first) - t = parse_simple_id(first, last, db); - if (t != first) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "~"); - first = t; - } +const char *parse_destructor_name(const char *first, const char *last, C &db) { + if (first != last) { + const char *t = parse_unresolved_type(first, last, db); + if (t == first) + t = parse_simple_id(first, last, db); + if (t != first) { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "~"); + first = t; } - return first; + } + return first; } -// <base-unresolved-name> ::= <simple-id> # unresolved name -// extension ::= <operator-name> # unresolved operator-function-id -// extension ::= <operator-name> <template-args> # unresolved operator template-id -// ::= on <operator-name> # unresolved operator-function-id -// ::= on <operator-name> <template-args> # unresolved operator template-id -// ::= dn <destructor-name> # destructor or pseudo-destructor; -// # e.g. ~X or ~X<N-1> +// <base-unresolved-name> ::= <simple-id> # +// unresolved name +// extension ::= <operator-name> # +// unresolved operator-function-id +// extension ::= <operator-name> <template-args> # +// unresolved operator template-id +// ::= on <operator-name> # +// unresolved operator-function-id +// ::= on <operator-name> <template-args> # +// unresolved operator template-id +// ::= dn <destructor-name> # +// destructor or pseudo-destructor; +// # +// e.g. +// ~X or +// ~X<N-1> template <class C> -const char* -parse_base_unresolved_name(const char* first, const char* last, C& db) -{ - if (last - first >= 2) - { - if ((first[0] == 'o' || first[0] == 'd') && first[1] == 'n') - { - if (first[0] == 'o') - { - const char* t = parse_operator_name(first+2, last, db); - if (t != first+2) - { - first = parse_template_args(t, last, db); - if (first != t) - { - if (db.names.size() < 2) - return first; - auto args = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += std::move(args); - } - } - } - else - { - const char* t = parse_destructor_name(first+2, last, db); - if (t != first+2) - first = t; - } +const char *parse_base_unresolved_name(const char *first, const char *last, + C &db) { + if (last - first >= 2) { + if ((first[0] == 'o' || first[0] == 'd') && first[1] == 'n') { + if (first[0] == 'o') { + const char *t = parse_operator_name(first + 2, last, db); + if (t != first + 2) { + first = parse_template_args(t, last, db); + if (first != t) { + if (db.names.size() < 2) + return first; + auto args = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += std::move(args); + } } - else - { - const char* t = parse_simple_id(first, last, db); - if (t == first) - { - t = parse_operator_name(first, last, db); - if (t != first) - { - first = parse_template_args(t, last, db); - if (first != t) - { - if (db.names.size() < 2) - return first; - auto args = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += std::move(args); - } - } - } - else - first = t; + } else { + const char *t = parse_destructor_name(first + 2, last, db); + if (t != first + 2) + first = t; + } + } else { + const char *t = parse_simple_id(first, last, db); + if (t == first) { + t = parse_operator_name(first, last, db); + if (t != first) { + first = parse_template_args(t, last, db); + if (first != t) { + if (db.names.size() < 2) + return first; + auto args = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += std::move(args); + } } + } else + first = t; } - return first; + } + return first; } // <unresolved-qualifier-level> ::= <simple-id> template <class C> -const char* -parse_unresolved_qualifier_level(const char* first, const char* last, C& db) -{ - return parse_simple_id(first, last, db); +const char *parse_unresolved_qualifier_level(const char *first, + const char *last, C &db) { + return parse_simple_id(first, last, db); } // <unresolved-name> -// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name> -// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x -// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name> -// # A::x, N::y, A<T>::z; "gs" means leading "::" -// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x -// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name> -// # T::N::x /decltype(p)::N::x -// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name> +// extension ::= srN <unresolved-type> [<template-args>] +// <unresolved-qualifier-level>* E <base-unresolved-name> +// ::= [gs] <base-unresolved-name> # x or +// (with "gs") ::x +// ::= [gs] sr <unresolved-qualifier-level>+ E +// <base-unresolved-name> +// # A::x, +// N::y, +// A<T>::z; +// "gs" +// means +// leading +// "::" +// ::= sr <unresolved-type> <base-unresolved-name> # T::x +// / decltype(p)::x +// extension ::= sr <unresolved-type> <template-args> +// <base-unresolved-name> +// # +// T::N::x +// /decltype(p)::N::x +// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E +// <base-unresolved-name> template <class C> -const char* -parse_unresolved_name(const char* first, const char* last, C& db) -{ - if (last - first > 2) - { - const char* t = first; - bool global = false; - if (t[0] == 'g' && t[1] == 's') - { - global = true; - t += 2; +const char *parse_unresolved_name(const char *first, const char *last, C &db) { + if (last - first > 2) { + const char *t = first; + bool global = false; + if (t[0] == 'g' && t[1] == 's') { + global = true; + t += 2; + } + const char *t2 = parse_base_unresolved_name(t, last, db); + if (t2 != t) { + if (global) { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "::"); + } + first = t2; + } else if (last - t > 2 && t[0] == 's' && t[1] == 'r') { + if (t[2] == 'N') { + t += 3; + const char *t1 = parse_unresolved_type(t, last, db); + if (t1 == t || t1 == last) + return first; + t = t1; + t1 = parse_template_args(t, last, db); + if (t1 != t) { + if (db.names.size() < 2) + return first; + auto args = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += std::move(args); + t = t1; + if (t == last) { + db.names.pop_back(); + return first; + } } - const char* t2 = parse_base_unresolved_name(t, last, db); - if (t2 != t) - { - if (global) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "::"); - } - first = t2; + while (*t != 'E') { + t1 = parse_unresolved_qualifier_level(t, last, db); + if (t1 == t || t1 == last || db.names.size() < 2) + return first; + auto s = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += "::" + std::move(s); + t = t1; } - else if (last - t > 2 && t[0] == 's' && t[1] == 'r') - { - if (t[2] == 'N') - { - t += 3; - const char* t1 = parse_unresolved_type(t, last, db); - if (t1 == t || t1 == last) - return first; - t = t1; - t1 = parse_template_args(t, last, db); - if (t1 != t) - { - if (db.names.size() < 2) - return first; - auto args = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += std::move(args); - t = t1; - if (t == last) - { - db.names.pop_back(); - return first; - } - } - while (*t != 'E') - { - t1 = parse_unresolved_qualifier_level(t, last, db); - if (t1 == t || t1 == last || db.names.size() < 2) - return first; - auto s = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += "::" + std::move(s); - t = t1; - } - ++t; - t1 = parse_base_unresolved_name(t, last, db); - if (t1 == t) - { - if (!db.names.empty()) - db.names.pop_back(); - return first; - } - if (db.names.size() < 2) - return first; - auto s = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += "::" + std::move(s); - first = t1; - } - else - { - t += 2; - const char* t1 = parse_unresolved_type(t, last, db); - if (t1 != t) - { - t = t1; - t1 = parse_template_args(t, last, db); - if (t1 != t) - { - if (db.names.size() < 2) - return first; - auto args = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += std::move(args); - t = t1; - } - t1 = parse_base_unresolved_name(t, last, db); - if (t1 == t) - { - if (!db.names.empty()) - db.names.pop_back(); - return first; - } - if (db.names.size() < 2) - return first; - auto s = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += "::" + std::move(s); - first = t1; - } - else - { - t1 = parse_unresolved_qualifier_level(t, last, db); - if (t1 == t || t1 == last) - return first; - t = t1; - if (global) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "::"); - } - while (*t != 'E') - { - t1 = parse_unresolved_qualifier_level(t, last, db); - if (t1 == t || t1 == last || db.names.size() < 2) - return first; - auto s = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += "::" + std::move(s); - t = t1; - } - ++t; - t1 = parse_base_unresolved_name(t, last, db); - if (t1 == t) - { - if (!db.names.empty()) - db.names.pop_back(); - return first; - } - if (db.names.size() < 2) - return first; - auto s = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += "::" + std::move(s); - first = t1; - } - } + ++t; + t1 = parse_base_unresolved_name(t, last, db); + if (t1 == t) { + if (!db.names.empty()) + db.names.pop_back(); + return first; } + if (db.names.size() < 2) + return first; + auto s = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += "::" + std::move(s); + first = t1; + } else { + t += 2; + const char *t1 = parse_unresolved_type(t, last, db); + if (t1 != t) { + t = t1; + t1 = parse_template_args(t, last, db); + if (t1 != t) { + if (db.names.size() < 2) + return first; + auto args = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += std::move(args); + t = t1; + } + t1 = parse_base_unresolved_name(t, last, db); + if (t1 == t) { + if (!db.names.empty()) + db.names.pop_back(); + return first; + } + if (db.names.size() < 2) + return first; + auto s = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += "::" + std::move(s); + first = t1; + } else { + t1 = parse_unresolved_qualifier_level(t, last, db); + if (t1 == t || t1 == last) + return first; + t = t1; + if (global) { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "::"); + } + while (*t != 'E') { + t1 = parse_unresolved_qualifier_level(t, last, db); + if (t1 == t || t1 == last || db.names.size() < 2) + return first; + auto s = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += "::" + std::move(s); + t = t1; + } + ++t; + t1 = parse_base_unresolved_name(t, last, db); + if (t1 == t) { + if (!db.names.empty()) + db.names.pop_back(); + return first; + } + if (db.names.size() < 2) + return first; + auto s = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += "::" + std::move(s); + first = t1; + } + } } - return first; + } + return first; } // dt <expression> <unresolved-name> # expr.name template <class C> -const char* -parse_dot_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 'd' && first[1] == 't') - { - const char* t = parse_expression(first+2, last, db); - if (t != first+2) - { - const char* t1 = parse_unresolved_name(t, last, db); - if (t1 != t) - { - if (db.names.size() < 2) - return first; - auto name = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += "." + name; - first = t1; - } - } +const char *parse_dot_expr(const char *first, const char *last, C &db) { + if (last - first >= 3 && first[0] == 'd' && first[1] == 't') { + const char *t = parse_expression(first + 2, last, db); + if (t != first + 2) { + const char *t1 = parse_unresolved_name(t, last, db); + if (t1 != t) { + if (db.names.size() < 2) + return first; + auto name = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += "." + name; + first = t1; + } } - return first; + } + return first; } // cl <expression>+ E # call template <class C> -const char* -parse_call_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 4 && first[0] == 'c' && first[1] == 'l') - { - const char* t = parse_expression(first+2, last, db); - if (t != first+2) - { - if (t == last) - return first; - if (db.names.empty()) - return first; - db.names.back().first += db.names.back().second; - db.names.back().second = typename C::String(); - db.names.back().first.append("("); - bool first_expr = true; - while (*t != 'E') - { - const char* t1 = parse_expression(t, last, db); - if (t1 == t || t1 == last) - return first; - if (db.names.empty()) - return first; - auto tmp = db.names.back().move_full(); - db.names.pop_back(); - if (!tmp.empty()) - { - if (db.names.empty()) - return first; - if (!first_expr) - { - db.names.back().first.append(", "); - first_expr = false; - } - db.names.back().first.append(tmp); - } - t = t1; - } - ++t; - if (db.names.empty()) - return first; - db.names.back().first.append(")"); - first = t; +const char *parse_call_expr(const char *first, const char *last, C &db) { + if (last - first >= 4 && first[0] == 'c' && first[1] == 'l') { + const char *t = parse_expression(first + 2, last, db); + if (t != first + 2) { + if (t == last) + return first; + if (db.names.empty()) + return first; + db.names.back().first += db.names.back().second; + db.names.back().second = typename C::String(); + db.names.back().first.append("("); + bool first_expr = true; + while (*t != 'E') { + const char *t1 = parse_expression(t, last, db); + if (t1 == t || t1 == last) + return first; + if (db.names.empty()) + return first; + auto tmp = db.names.back().move_full(); + db.names.pop_back(); + if (!tmp.empty()) { + if (db.names.empty()) + return first; + if (!first_expr) { + db.names.back().first.append(", "); + first_expr = false; + } + db.names.back().first.append(tmp); } + t = t1; + } + ++t; + if (db.names.empty()) + return first; + db.names.back().first.append(")"); + first = t; } - return first; + } + return first; } // [gs] nw <expression>* _ <type> E # new (expr-list) type -// [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init) +// [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type +// (init) // [gs] na <expression>* _ <type> E # new[] (expr-list) type -// [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init) -// <initializer> ::= pi <expression>* E # parenthesized initialization +// [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type +// (init) +// <initializer> ::= pi <expression>* E # parenthesized +// initialization template <class C> -const char* -parse_new_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 4) - { - const char* t = first; - bool parsed_gs = false; - if (t[0] == 'g' && t[1] == 's') - { - t += 2; - parsed_gs = true; +const char *parse_new_expr(const char *first, const char *last, C &db) { + if (last - first >= 4) { + const char *t = first; + bool parsed_gs = false; + if (t[0] == 'g' && t[1] == 's') { + t += 2; + parsed_gs = true; + } + if (t[0] == 'n' && (t[1] == 'w' || t[1] == 'a')) { + bool is_array = t[1] == 'a'; + t += 2; + if (t == last) + return first; + bool has_expr_list = false; + bool first_expr = true; + while (*t != '_') { + const char *t1 = parse_expression(t, last, db); + if (t1 == t || t1 == last) + return first; + has_expr_list = true; + if (!first_expr) { + if (db.names.empty()) + return first; + auto tmp = db.names.back().move_full(); + db.names.pop_back(); + if (!tmp.empty()) { + if (db.names.empty()) + return first; + db.names.back().first.append(", "); + db.names.back().first.append(tmp); + first_expr = false; + } } - if (t[0] == 'n' && (t[1] == 'w' || t[1] == 'a')) - { - bool is_array = t[1] == 'a'; - t += 2; - if (t == last) - return first; - bool has_expr_list = false; - bool first_expr = true; - while (*t != '_') - { - const char* t1 = parse_expression(t, last, db); - if (t1 == t || t1 == last) - return first; - has_expr_list = true; - if (!first_expr) - { - if (db.names.empty()) - return first; - auto tmp = db.names.back().move_full(); - db.names.pop_back(); - if (!tmp.empty()) - { - if (db.names.empty()) - return first; - db.names.back().first.append(", "); - db.names.back().first.append(tmp); - first_expr = false; - } - } - t = t1; - } - ++t; - const char* t1 = parse_type(t, last, db); - if (t1 == t || t1 == last) - return first; - t = t1; - bool has_init = false; - if (last - t >= 3 && t[0] == 'p' && t[1] == 'i') - { - t += 2; - has_init = true; - first_expr = true; - while (*t != 'E') - { - t1 = parse_expression(t, last, db); - if (t1 == t || t1 == last) - return first; - if (!first_expr) - { - if (db.names.empty()) - return first; - auto tmp = db.names.back().move_full(); - db.names.pop_back(); - if (!tmp.empty()) - { - if (db.names.empty()) - return first; - db.names.back().first.append(", "); - db.names.back().first.append(tmp); - first_expr = false; - } - } - t = t1; - } - } - if (*t != 'E') - return first; - typename C::String init_list; - if (has_init) - { - if (db.names.empty()) - return first; - init_list = db.names.back().move_full(); - db.names.pop_back(); - } + t = t1; + } + ++t; + const char *t1 = parse_type(t, last, db); + if (t1 == t || t1 == last) + return first; + t = t1; + bool has_init = false; + if (last - t >= 3 && t[0] == 'p' && t[1] == 'i') { + t += 2; + has_init = true; + first_expr = true; + while (*t != 'E') { + t1 = parse_expression(t, last, db); + if (t1 == t || t1 == last) + return first; + if (!first_expr) { if (db.names.empty()) - return first; - auto type = db.names.back().move_full(); + return first; + auto tmp = db.names.back().move_full(); db.names.pop_back(); - typename C::String expr_list; - if (has_expr_list) - { - if (db.names.empty()) - return first; - expr_list = db.names.back().move_full(); - db.names.pop_back(); + if (!tmp.empty()) { + if (db.names.empty()) + return first; + db.names.back().first.append(", "); + db.names.back().first.append(tmp); + first_expr = false; } - typename C::String r; - if (parsed_gs) - r = "::"; - if (is_array) - r += "[] "; - else - r += " "; - if (has_expr_list) - r += "(" + expr_list + ") "; - r += type; - if (has_init) - r += " (" + init_list + ")"; - db.names.push_back(std::move(r)); - first = t+1; + } + t = t1; } + } + if (*t != 'E') + return first; + typename C::String init_list; + if (has_init) { + if (db.names.empty()) + return first; + init_list = db.names.back().move_full(); + db.names.pop_back(); + } + if (db.names.empty()) + return first; + auto type = db.names.back().move_full(); + db.names.pop_back(); + typename C::String expr_list; + if (has_expr_list) { + if (db.names.empty()) + return first; + expr_list = db.names.back().move_full(); + db.names.pop_back(); + } + typename C::String r; + if (parsed_gs) + r = "::"; + if (is_array) + r += "[] "; + else + r += " "; + if (has_expr_list) + r += "(" + expr_list + ") "; + r += type; + if (has_init) + r += " (" + init_list + ")"; + db.names.push_back(std::move(r)); + first = t + 1; } - return first; + } + return first; } -// cv <type> <expression> # conversion with one argument -// cv <type> _ <expression>* E # conversion with a different number of arguments +// cv <type> <expression> # conversion with one +// argument +// cv <type> _ <expression>* E # conversion with a +// different number of arguments template <class C> -const char* -parse_conversion_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 'c' && first[1] == 'v') - { - bool try_to_parse_template_args = db.try_to_parse_template_args; - db.try_to_parse_template_args = false; - const char* t = parse_type(first+2, last, db); - db.try_to_parse_template_args = try_to_parse_template_args; - if (t != first+2 && t != last) - { - if (*t != '_') - { - const char* t1 = parse_expression(t, last, db); - if (t1 == t) - return first; - t = t1; - } - else - { - ++t; - if (t == last) - return first; - if (*t == 'E') - db.names.emplace_back(); - else - { - bool first_expr = true; - while (*t != 'E') - { - const char* t1 = parse_expression(t, last, db); - if (t1 == t || t1 == last) - return first; - if (!first_expr) - { - if (db.names.empty()) - return first; - auto tmp = db.names.back().move_full(); - db.names.pop_back(); - if (!tmp.empty()) - { - if (db.names.empty()) - return first; - db.names.back().first.append(", "); - db.names.back().first.append(tmp); - first_expr = false; - } - } - t = t1; - } - } - ++t; - } - if (db.names.size() < 2) +const char *parse_conversion_expr(const char *first, const char *last, C &db) { + if (last - first >= 3 && first[0] == 'c' && first[1] == 'v') { + bool try_to_parse_template_args = db.try_to_parse_template_args; + db.try_to_parse_template_args = false; + const char *t = parse_type(first + 2, last, db); + db.try_to_parse_template_args = try_to_parse_template_args; + if (t != first + 2 && t != last) { + if (*t != '_') { + const char *t1 = parse_expression(t, last, db); + if (t1 == t) + return first; + t = t1; + } else { + ++t; + if (t == last) + return first; + if (*t == 'E') + db.names.emplace_back(); + else { + bool first_expr = true; + while (*t != 'E') { + const char *t1 = parse_expression(t, last, db); + if (t1 == t || t1 == last) + return first; + if (!first_expr) { + if (db.names.empty()) return first; - auto tmp = db.names.back().move_full(); - db.names.pop_back(); - db.names.back() = "(" + db.names.back().move_full() + ")(" + tmp + ")"; - first = t; + auto tmp = db.names.back().move_full(); + db.names.pop_back(); + if (!tmp.empty()) { + if (db.names.empty()) + return first; + db.names.back().first.append(", "); + db.names.back().first.append(tmp); + first_expr = false; + } + } + t = t1; + } } + ++t; + } + if (db.names.size() < 2) + return first; + auto tmp = db.names.back().move_full(); + db.names.pop_back(); + db.names.back() = "(" + db.names.back().move_full() + ")(" + tmp + ")"; + first = t; } - return first; + } + return first; } // pt <expression> <expression> # expr->name template <class C> -const char* -parse_arrow_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 'p' && first[1] == 't') - { - const char* t = parse_expression(first+2, last, db); - if (t != first+2) - { - const char* t1 = parse_expression(t, last, db); - if (t1 != t) - { - if (db.names.size() < 2) - return first; - auto tmp = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += "->"; - db.names.back().first += tmp; - first = t1; - } - } +const char *parse_arrow_expr(const char *first, const char *last, C &db) { + if (last - first >= 3 && first[0] == 'p' && first[1] == 't') { + const char *t = parse_expression(first + 2, last, db); + if (t != first + 2) { + const char *t1 = parse_expression(t, last, db); + if (t1 != t) { + if (db.names.size() < 2) + return first; + auto tmp = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += "->"; + db.names.back().first += tmp; + first = t1; + } } - return first; + } + return first; } // <ref-qualifier> ::= R # & ref-qualifier @@ -1592,218 +1411,182 @@ parse_arrow_expr(const char* first, const char* last, C& db) // <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E template <class C> -const char* -parse_function_type(const char* first, const char* last, C& db) -{ - if (first != last && *first == 'F') - { - const char* t = first+1; - if (t != last) - { - if (*t == 'Y') - { - /* extern "C" */ - if (++t == last) - return first; - } - const char* t1 = parse_type(t, last, db); - if (t1 != t) - { - t = t1; - typename C::String sig("("); - int ref_qual = 0; - while (true) - { - if (t == last) - { - db.names.pop_back(); - return first; - } - if (*t == 'E') - { - ++t; - break; - } - if (*t == 'v') - { - ++t; - continue; - } - if (*t == 'R' && t+1 != last && t[1] == 'E') - { - ref_qual = 1; - ++t; - continue; - } - if (*t == 'O' && t+1 != last && t[1] == 'E') - { - ref_qual = 2; - ++t; - continue; - } - size_t k0 = db.names.size(); - t1 = parse_type(t, last, db); - size_t k1 = db.names.size(); - if (t1 == t || t1 == last) - return first; - for (size_t k = k0; k < k1; ++k) - { - if (sig.size() > 1) - sig += ", "; - sig += db.names[k].move_full(); - } - for (size_t k = k0; k < k1; ++k) - db.names.pop_back(); - t = t1; - } - sig += ")"; - switch (ref_qual) - { - case 1: - sig += " &"; - break; - case 2: - sig += " &&"; - break; - } - if (db.names.empty()) - return first; - db.names.back().first += " "; - db.names.back().second.insert(0, sig); - first = t; - } +const char *parse_function_type(const char *first, const char *last, C &db) { + if (first != last && *first == 'F') { + const char *t = first + 1; + if (t != last) { + if (*t == 'Y') { + /* extern "C" */ + if (++t == last) + return first; + } + const char *t1 = parse_type(t, last, db); + if (t1 != t) { + t = t1; + typename C::String sig("("); + int ref_qual = 0; + while (true) { + if (t == last) { + db.names.pop_back(); + return first; + } + if (*t == 'E') { + ++t; + break; + } + if (*t == 'v') { + ++t; + continue; + } + if (*t == 'R' && t + 1 != last && t[1] == 'E') { + ref_qual = 1; + ++t; + continue; + } + if (*t == 'O' && t + 1 != last && t[1] == 'E') { + ref_qual = 2; + ++t; + continue; + } + size_t k0 = db.names.size(); + t1 = parse_type(t, last, db); + size_t k1 = db.names.size(); + if (t1 == t || t1 == last) + return first; + for (size_t k = k0; k < k1; ++k) { + if (sig.size() > 1) + sig += ", "; + sig += db.names[k].move_full(); + } + for (size_t k = k0; k < k1; ++k) + db.names.pop_back(); + t = t1; + } + sig += ")"; + switch (ref_qual) { + case 1: + sig += " &"; + break; + case 2: + sig += " &&"; + break; } + if (db.names.empty()) + return first; + db.names.back().first += " "; + db.names.back().second.insert(0, sig); + first = t; + } } - return first; + } + return first; } // <pointer-to-member-type> ::= M <class type> <member type> template <class C> -const char* -parse_pointer_to_member_type(const char* first, const char* last, C& db) -{ - if (first != last && *first == 'M') - { - const char* t = parse_type(first+1, last, db); - if (t != first+1) - { - const char* t2 = parse_type(t, last, db); - if (t2 != t) - { - if (db.names.size() < 2) - return first; - auto func = std::move(db.names.back()); - db.names.pop_back(); - auto class_type = std::move(db.names.back()); - if (!func.second.empty() && func.second.front() == '(') - { - db.names.back().first = std::move(func.first) + "(" + class_type.move_full() + "::*"; - db.names.back().second = ")" + std::move(func.second); - } - else - { - db.names.back().first = std::move(func.first) + " " + class_type.move_full() + "::*"; - db.names.back().second = std::move(func.second); - } - first = t2; - } +const char *parse_pointer_to_member_type(const char *first, const char *last, + C &db) { + if (first != last && *first == 'M') { + const char *t = parse_type(first + 1, last, db); + if (t != first + 1) { + const char *t2 = parse_type(t, last, db); + if (t2 != t) { + if (db.names.size() < 2) + return first; + auto func = std::move(db.names.back()); + db.names.pop_back(); + auto class_type = std::move(db.names.back()); + if (!func.second.empty() && func.second.front() == '(') { + db.names.back().first = + std::move(func.first) + "(" + class_type.move_full() + "::*"; + db.names.back().second = ")" + std::move(func.second); + } else { + db.names.back().first = + std::move(func.first) + " " + class_type.move_full() + "::*"; + db.names.back().second = std::move(func.second); } + first = t2; + } } - return first; + } + return first; } // <array-type> ::= A <positive dimension number> _ <element type> // ::= A [<dimension expression>] _ <element type> template <class C> -const char* -parse_array_type(const char* first, const char* last, C& db) -{ - if (first != last && *first == 'A' && first+1 != last) - { - if (first[1] == '_') - { - const char* t = parse_type(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - if (db.names.back().second.substr(0, 2) == " [") - db.names.back().second.erase(0, 1); - db.names.back().second.insert(0, " []"); - first = t; - } - } - else if ('1' <= first[1] && first[1] <= '9') - { - const char* t = parse_number(first+1, last); - if (t != last && *t == '_') - { - const char* t2 = parse_type(t+1, last, db); - if (t2 != t+1) - { - if (db.names.empty()) - return first; - if (db.names.back().second.substr(0, 2) == " [") - db.names.back().second.erase(0, 1); - db.names.back().second.insert(0, " [" + typename C::String(first+1, t) + "]"); - first = t2; - } - } +const char *parse_array_type(const char *first, const char *last, C &db) { + if (first != last && *first == 'A' && first + 1 != last) { + if (first[1] == '_') { + const char *t = parse_type(first + 2, last, db); + if (t != first + 2) { + if (db.names.empty()) + return first; + if (db.names.back().second.substr(0, 2) == " [") + db.names.back().second.erase(0, 1); + db.names.back().second.insert(0, " []"); + first = t; + } + } else if ('1' <= first[1] && first[1] <= '9') { + const char *t = parse_number(first + 1, last); + if (t != last && *t == '_') { + const char *t2 = parse_type(t + 1, last, db); + if (t2 != t + 1) { + if (db.names.empty()) + return first; + if (db.names.back().second.substr(0, 2) == " [") + db.names.back().second.erase(0, 1); + db.names.back().second.insert( + 0, " [" + typename C::String(first + 1, t) + "]"); + first = t2; } - else - { - const char* t = parse_expression(first+1, last, db); - if (t != first+1 && t != last && *t == '_') - { - const char* t2 = parse_type(++t, last, db); - if (t2 != t) - { - if (db.names.size() < 2) - return first; - auto type = std::move(db.names.back()); - db.names.pop_back(); - auto expr = std::move(db.names.back()); - db.names.back().first = std::move(type.first); - if (type.second.substr(0, 2) == " [") - type.second.erase(0, 1); - db.names.back().second = " [" + expr.move_full() + "]" + std::move(type.second); - first = t2; - } - } + } + } else { + const char *t = parse_expression(first + 1, last, db); + if (t != first + 1 && t != last && *t == '_') { + const char *t2 = parse_type(++t, last, db); + if (t2 != t) { + if (db.names.size() < 2) + return first; + auto type = std::move(db.names.back()); + db.names.pop_back(); + auto expr = std::move(db.names.back()); + db.names.back().first = std::move(type.first); + if (type.second.substr(0, 2) == " [") + type.second.erase(0, 1); + db.names.back().second = + " [" + expr.move_full() + "]" + std::move(type.second); + first = t2; } + } } - return first; + } + return first; } -// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x) +// <decltype> ::= Dt <expression> E # decltype of an id-expression or class +// member access (C++0x) // ::= DT <expression> E # decltype of an expression (C++0x) template <class C> -const char* -parse_decltype(const char* first, const char* last, C& db) -{ - if (last - first >= 4 && first[0] == 'D') - { - switch (first[1]) - { - case 't': - case 'T': - { - const char* t = parse_expression(first+2, last, db); - if (t != first+2 && t != last && *t == 'E') - { - if (db.names.empty()) - return first; - db.names.back() = "decltype(" + db.names.back().move_full() + ")"; - first = t+1; - } - } - break; - } +const char *parse_decltype(const char *first, const char *last, C &db) { + if (last - first >= 4 && first[0] == 'D') { + switch (first[1]) { + case 't': + case 'T': { + const char *t = parse_expression(first + 2, last, db); + if (t != first + 2 && t != last && *t == 'E') { + if (db.names.empty()) + return first; + db.names.back() = "decltype(" + db.names.back().move_full() + ")"; + first = t + 1; + } + } break; } - return first; + } + return first; } // extension: @@ -1814,69 +1597,56 @@ parse_decltype(const char* first, const char* last, C& db) // ::= p # AltiVec vector pixel template <class C> -const char* -parse_vector_type(const char* first, const char* last, C& db) -{ - if (last - first > 3 && first[0] == 'D' && first[1] == 'v') - { - if ('1' <= first[2] && first[2] <= '9') - { - const char* t = parse_number(first+2, last); - if (t == last || *t != '_') - return first; - const char* num = first + 2; - size_t sz = static_cast<size_t>(t - num); - if (++t != last) - { - if (*t != 'p') - { - const char* t1 = parse_type(t, last, db); - if (t1 != t) - { - if (db.names.empty()) - return first; - db.names.back().first += " vector[" + typename C::String(num, sz) + "]"; - first = t1; - } - } - else - { - ++t; - db.names.push_back("pixel vector[" + typename C::String(num, sz) + "]"); - first = t; - } - } +const char *parse_vector_type(const char *first, const char *last, C &db) { + if (last - first > 3 && first[0] == 'D' && first[1] == 'v') { + if ('1' <= first[2] && first[2] <= '9') { + const char *t = parse_number(first + 2, last); + if (t == last || *t != '_') + return first; + const char *num = first + 2; + size_t sz = static_cast<size_t>(t - num); + if (++t != last) { + if (*t != 'p') { + const char *t1 = parse_type(t, last, db); + if (t1 != t) { + if (db.names.empty()) + return first; + db.names.back().first += + " vector[" + typename C::String(num, sz) + "]"; + first = t1; + } + } else { + ++t; + db.names.push_back("pixel vector[" + typename C::String(num, sz) + + "]"); + first = t; } - else - { - typename C::String num; - const char* t1 = first+2; - if (*t1 != '_') - { - const char* t = parse_expression(t1, last, db); - if (t != t1) - { - if (db.names.empty()) - return first; - num = db.names.back().move_full(); - db.names.pop_back(); - t1 = t; - } - } - if (t1 != last && *t1 == '_' && ++t1 != last) - { - const char* t = parse_type(t1, last, db); - if (t != t1) - { - if (db.names.empty()) - return first; - db.names.back().first += " vector[" + num + "]"; - first = t; - } - } + } + } else { + typename C::String num; + const char *t1 = first + 2; + if (*t1 != '_') { + const char *t = parse_expression(t1, last, db); + if (t != t1) { + if (db.names.empty()) + return first; + num = db.names.back().move_full(); + db.names.pop_back(); + t1 = t; } + } + if (t1 != last && *t1 == '_' && ++t1 != last) { + const char *t = parse_type(t1, last, db); + if (t != t1) { + if (db.names.empty()) + return first; + db.names.back().first += " vector[" + num + "]"; + first = t; + } + } } - return first; + } + return first; } // <type> ::= <builtin-type> @@ -1899,1026 +1669,893 @@ parse_vector_type(const char* first, const char* last, C& db) // extension := U <objc-name> <objc-type> # objc-type<identifier> // extension := <vector-type> # <vector-type> starts with Dv -// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1 -// <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name> +// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + +// <number of digits in k1> + k1 +// <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name> +// 11objc_object -> id<source-name> template <class C> -const char* -parse_type(const char* first, const char* last, C& db) -{ - if (first != last) - { - switch (*first) - { - case 'r': - case 'V': - case 'K': - { - unsigned cv = 0; - const char* t = parse_cv_qualifiers(first, last, cv); - if (t != first) - { - bool is_function = *t == 'F'; - size_t k0 = db.names.size(); - const char* t1 = parse_type(t, last, db); - size_t k1 = db.names.size(); - if (t1 != t) - { - if (is_function) - db.subs.pop_back(); - db.subs.emplace_back(db.names.get_allocator()); - for (size_t k = k0; k < k1; ++k) - { - if (is_function) - { - size_t p = db.names[k].second.size(); - if (db.names[k].second[p-2] == '&') - p -= 3; - else if (db.names[k].second.back() == '&') - p -= 2; - if (cv & 1) - { - db.names[k].second.insert(p, " const"); - p += 6; - } - if (cv & 2) - { - db.names[k].second.insert(p, " volatile"); - p += 9; - } - if (cv & 4) - db.names[k].second.insert(p, " restrict"); - } - else - { - if (cv & 1) - db.names[k].first.append(" const"); - if (cv & 2) - db.names[k].first.append(" volatile"); - if (cv & 4) - db.names[k].first.append(" restrict"); - } - db.subs.back().push_back(db.names[k]); - } - first = t1; - } - } +const char *parse_type(const char *first, const char *last, C &db) { + if (first != last) { + switch (*first) { + case 'r': + case 'V': + case 'K': { + unsigned cv = 0; + const char *t = parse_cv_qualifiers(first, last, cv); + if (t != first) { + bool is_function = *t == 'F'; + size_t k0 = db.names.size(); + const char *t1 = parse_type(t, last, db); + size_t k1 = db.names.size(); + if (t1 != t) { + if (is_function) + db.subs.pop_back(); + db.subs.emplace_back(db.names.get_allocator()); + for (size_t k = k0; k < k1; ++k) { + if (is_function) { + size_t p = db.names[k].second.size(); + if (db.names[k].second[p - 2] == '&') + p -= 3; + else if (db.names[k].second.back() == '&') + p -= 2; + if (cv & 1) { + db.names[k].second.insert(p, " const"); + p += 6; } - break; - default: - { - const char* t = parse_builtin_type(first, last, db); - if (t != first) - { - first = t; - } - else - { - switch (*first) - { - case 'A': - t = parse_array_type(first, last, db); - if (t != first) - { - if (db.names.empty()) - return first; - first = t; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - } - break; - case 'C': - t = parse_type(first+1, last, db); - if (t != first+1) - { - if (db.names.empty()) - return first; - db.names.back().first.append(" complex"); - first = t; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - } - break; - case 'F': - t = parse_function_type(first, last, db); - if (t != first) - { - if (db.names.empty()) - return first; - first = t; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - } - break; - case 'G': - t = parse_type(first+1, last, db); - if (t != first+1) - { - if (db.names.empty()) - return first; - db.names.back().first.append(" imaginary"); - first = t; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - } - break; - case 'M': - t = parse_pointer_to_member_type(first, last, db); - if (t != first) - { - if (db.names.empty()) - return first; - first = t; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - } - break; - case 'O': - { - size_t k0 = db.names.size(); - t = parse_type(first+1, last, db); - size_t k1 = db.names.size(); - if (t != first+1) - { - db.subs.emplace_back(db.names.get_allocator()); - for (size_t k = k0; k < k1; ++k) - { - if (db.names[k].second.substr(0, 2) == " [") - { - db.names[k].first += " ("; - db.names[k].second.insert(0, ")"); - } - else if (!db.names[k].second.empty() && - db.names[k].second.front() == '(') - { - db.names[k].first += "("; - db.names[k].second.insert(0, ")"); - } - db.names[k].first.append("&&"); - db.subs.back().push_back(db.names[k]); - } - first = t; - } - break; - } - case 'P': - { - size_t k0 = db.names.size(); - t = parse_type(first+1, last, db); - size_t k1 = db.names.size(); - if (t != first+1) - { - db.subs.emplace_back(db.names.get_allocator()); - for (size_t k = k0; k < k1; ++k) - { - if (db.names[k].second.substr(0, 2) == " [") - { - db.names[k].first += " ("; - db.names[k].second.insert(0, ")"); - } - else if (!db.names[k].second.empty() && - db.names[k].second.front() == '(') - { - db.names[k].first += "("; - db.names[k].second.insert(0, ")"); - } - if (first[1] != 'U' || db.names[k].first.substr(0, 12) != "objc_object<") - { - db.names[k].first.append("*"); - } - else - { - db.names[k].first.replace(0, 11, "id"); - } - db.subs.back().push_back(db.names[k]); - } - first = t; - } - break; - } - case 'R': - { - size_t k0 = db.names.size(); - t = parse_type(first+1, last, db); - size_t k1 = db.names.size(); - if (t != first+1) - { - db.subs.emplace_back(db.names.get_allocator()); - for (size_t k = k0; k < k1; ++k) - { - if (db.names[k].second.substr(0, 2) == " [") - { - db.names[k].first += " ("; - db.names[k].second.insert(0, ")"); - } - else if (!db.names[k].second.empty() && - db.names[k].second.front() == '(') - { - db.names[k].first += "("; - db.names[k].second.insert(0, ")"); - } - db.names[k].first.append("&"); - db.subs.back().push_back(db.names[k]); - } - first = t; - } - break; - } - case 'T': - { - size_t k0 = db.names.size(); - t = parse_template_param(first, last, db); - size_t k1 = db.names.size(); - if (t != first) - { - db.subs.emplace_back(db.names.get_allocator()); - for (size_t k = k0; k < k1; ++k) - db.subs.back().push_back(db.names[k]); - if (db.try_to_parse_template_args && k1 == k0+1) - { - const char* t1 = parse_template_args(t, last, db); - if (t1 != t) - { - auto args = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += std::move(args); - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - t = t1; - } - } - first = t; - } - break; - } - case 'U': - if (first+1 != last) - { - t = parse_source_name(first+1, last, db); - if (t != first+1) - { - const char* t2 = parse_type(t, last, db); - if (t2 != t) - { - if (db.names.size() < 2) - return first; - auto type = db.names.back().move_full(); - db.names.pop_back(); - if (db.names.back().first.substr(0, 9) != "objcproto") - { - db.names.back() = type + " " + db.names.back().move_full(); - } - else - { - auto proto = db.names.back().move_full(); - db.names.pop_back(); - t = parse_source_name(proto.data() + 9, proto.data() + proto.size(), db); - if (t != proto.data() + 9) - { - db.names.back() = type + "<" + db.names.back().move_full() + ">"; - } - else - { - db.names.push_back(type + " " + proto); - } - } - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - first = t2; - } - } - } - break; - case 'S': - if (first+1 != last && first[1] == 't') - { - t = parse_name(first, last, db); - if (t != first) - { - if (db.names.empty()) - return first; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - first = t; - } - } - else - { - t = parse_substitution(first, last, db); - if (t != first) - { - first = t; - // Parsed a substitution. If the substitution is a - // <template-param> it might be followed by <template-args>. - t = parse_template_args(first, last, db); - if (t != first) - { - if (db.names.size() < 2) - return first; - auto template_args = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += template_args; - // Need to create substitution for <template-template-param> <template-args> - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - first = t; - } - } - } - break; - case 'D': - if (first+1 != last) - { - switch (first[1]) - { - case 'p': - { - size_t k0 = db.names.size(); - t = parse_type(first+2, last, db); - size_t k1 = db.names.size(); - if (t != first+2) - { - db.subs.emplace_back(db.names.get_allocator()); - for (size_t k = k0; k < k1; ++k) - db.subs.back().push_back(db.names[k]); - first = t; - return first; - } - break; - } - case 't': - case 'T': - t = parse_decltype(first, last, db); - if (t != first) - { - if (db.names.empty()) - return first; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - first = t; - return first; - } - break; - case 'v': - t = parse_vector_type(first, last, db); - if (t != first) - { - if (db.names.empty()) - return first; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - first = t; - return first; - } - break; - } - } - LLVM_FALLTHROUGH; - default: - // must check for builtin-types before class-enum-types to avoid - // ambiguities with operator-names - t = parse_builtin_type(first, last, db); - if (t != first) - { - first = t; - } - else - { - t = parse_name(first, last, db); - if (t != first) - { - if (db.names.empty()) - return first; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - first = t; - } - } - break; - } + if (cv & 2) { + db.names[k].second.insert(p, " volatile"); + p += 9; } - break; - } + if (cv & 4) + db.names[k].second.insert(p, " restrict"); + } else { + if (cv & 1) + db.names[k].first.append(" const"); + if (cv & 2) + db.names[k].first.append(" volatile"); + if (cv & 4) + db.names[k].first.append(" restrict"); + } + db.subs.back().push_back(db.names[k]); + } + first = t1; } - } - return first; -} - -// <operator-name> -// ::= aa # && -// ::= ad # & (unary) -// ::= an # & -// ::= aN # &= -// ::= aS # = -// ::= cl # () -// ::= cm # , -// ::= co # ~ -// ::= cv <type> # (cast) -// ::= da # delete[] -// ::= de # * (unary) -// ::= dl # delete -// ::= dv # / -// ::= dV # /= -// ::= eo # ^ -// ::= eO # ^= -// ::= eq # == -// ::= ge # >= -// ::= gt # > -// ::= ix # [] -// ::= le # <= -// ::= li <source-name> # operator "" -// ::= ls # << -// ::= lS # <<= -// ::= lt # < -// ::= mi # - -// ::= mI # -= -// ::= ml # * -// ::= mL # *= -// ::= mm # -- (postfix in <expression> context) -// ::= na # new[] -// ::= ne # != -// ::= ng # - (unary) -// ::= nt # ! -// ::= nw # new -// ::= oo # || -// ::= or # | -// ::= oR # |= -// ::= pm # ->* -// ::= pl # + -// ::= pL # += -// ::= pp # ++ (postfix in <expression> context) -// ::= ps # + (unary) -// ::= pt # -> -// ::= qu # ? -// ::= rm # % -// ::= rM # %= -// ::= rs # >> -// ::= rS # >>= -// ::= v <digit> <source-name> # vendor extended operator - -template <class C> -const char* -parse_operator_name(const char* first, const char* last, C& db) -{ - if (last - first >= 2) - { - switch (first[0]) - { - case 'a': - switch (first[1]) - { - case 'a': - db.names.push_back("operator&&"); - first += 2; - break; - case 'd': - case 'n': - db.names.push_back("operator&"); - first += 2; - break; - case 'N': - db.names.push_back("operator&="); - first += 2; - break; - case 'S': - db.names.push_back("operator="); - first += 2; - break; - } - break; - case 'c': - switch (first[1]) - { - case 'l': - db.names.push_back("operator()"); - first += 2; - break; - case 'm': - db.names.push_back("operator,"); - first += 2; - break; - case 'o': - db.names.push_back("operator~"); - first += 2; - break; - case 'v': - { - bool try_to_parse_template_args = db.try_to_parse_template_args; - db.try_to_parse_template_args = false; - const char* t = parse_type(first+2, last, db); - db.try_to_parse_template_args = try_to_parse_template_args; - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "operator "); - db.parsed_ctor_dtor_cv = true; - first = t; - } - } - break; - } - break; - case 'd': - switch (first[1]) - { - case 'a': - db.names.push_back("operator delete[]"); - first += 2; - break; - case 'e': - db.names.push_back("operator*"); - first += 2; - break; - case 'l': - db.names.push_back("operator delete"); - first += 2; - break; - case 'v': - db.names.push_back("operator/"); - first += 2; - break; - case 'V': - db.names.push_back("operator/="); - first += 2; - break; + } + } break; + default: { + const char *t = parse_builtin_type(first, last, db); + if (t != first) { + first = t; + } else { + switch (*first) { + case 'A': + t = parse_array_type(first, last, db); + if (t != first) { + if (db.names.empty()) + return first; + first = t; + db.subs.push_back(typename C::sub_type(1, db.names.back(), + db.names.get_allocator())); + } + break; + case 'C': + t = parse_type(first + 1, last, db); + if (t != first + 1) { + if (db.names.empty()) + return first; + db.names.back().first.append(" complex"); + first = t; + db.subs.push_back(typename C::sub_type(1, db.names.back(), + db.names.get_allocator())); + } + break; + case 'F': + t = parse_function_type(first, last, db); + if (t != first) { + if (db.names.empty()) + return first; + first = t; + db.subs.push_back(typename C::sub_type(1, db.names.back(), + db.names.get_allocator())); + } + break; + case 'G': + t = parse_type(first + 1, last, db); + if (t != first + 1) { + if (db.names.empty()) + return first; + db.names.back().first.append(" imaginary"); + first = t; + db.subs.push_back(typename C::sub_type(1, db.names.back(), + db.names.get_allocator())); + } + break; + case 'M': + t = parse_pointer_to_member_type(first, last, db); + if (t != first) { + if (db.names.empty()) + return first; + first = t; + db.subs.push_back(typename C::sub_type(1, db.names.back(), + db.names.get_allocator())); + } + break; + case 'O': { + size_t k0 = db.names.size(); + t = parse_type(first + 1, last, db); + size_t k1 = db.names.size(); + if (t != first + 1) { + db.subs.emplace_back(db.names.get_allocator()); + for (size_t k = k0; k < k1; ++k) { + if (db.names[k].second.substr(0, 2) == " [") { + db.names[k].first += " ("; + db.names[k].second.insert(0, ")"); + } else if (!db.names[k].second.empty() && + db.names[k].second.front() == '(') { + db.names[k].first += "("; + db.names[k].second.insert(0, ")"); + } + db.names[k].first.append("&&"); + db.subs.back().push_back(db.names[k]); } - break; - case 'e': - switch (first[1]) - { - case 'o': - db.names.push_back("operator^"); - first += 2; - break; - case 'O': - db.names.push_back("operator^="); - first += 2; - break; - case 'q': - db.names.push_back("operator=="); - first += 2; - break; + first = t; + } + break; + } + case 'P': { + size_t k0 = db.names.size(); + t = parse_type(first + 1, last, db); + size_t k1 = db.names.size(); + if (t != first + 1) { + db.subs.emplace_back(db.names.get_allocator()); + for (size_t k = k0; k < k1; ++k) { + if (db.names[k].second.substr(0, 2) == " [") { + db.names[k].first += " ("; + db.names[k].second.insert(0, ")"); + } else if (!db.names[k].second.empty() && + db.names[k].second.front() == '(') { + db.names[k].first += "("; + db.names[k].second.insert(0, ")"); + } + if (first[1] != 'U' || + db.names[k].first.substr(0, 12) != "objc_object<") { + db.names[k].first.append("*"); + } else { + db.names[k].first.replace(0, 11, "id"); + } + db.subs.back().push_back(db.names[k]); } - break; - case 'g': - switch (first[1]) - { - case 'e': - db.names.push_back("operator>="); - first += 2; - break; - case 't': - db.names.push_back("operator>"); - first += 2; - break; + first = t; + } + break; + } + case 'R': { + size_t k0 = db.names.size(); + t = parse_type(first + 1, last, db); + size_t k1 = db.names.size(); + if (t != first + 1) { + db.subs.emplace_back(db.names.get_allocator()); + for (size_t k = k0; k < k1; ++k) { + if (db.names[k].second.substr(0, 2) == " [") { + db.names[k].first += " ("; + db.names[k].second.insert(0, ")"); + } else if (!db.names[k].second.empty() && + db.names[k].second.front() == '(') { + db.names[k].first += "("; + db.names[k].second.insert(0, ")"); + } + db.names[k].first.append("&"); + db.subs.back().push_back(db.names[k]); } - break; - case 'i': - if (first[1] == 'x') - { - db.names.push_back("operator[]"); - first += 2; + first = t; + } + break; + } + case 'T': { + size_t k0 = db.names.size(); + t = parse_template_param(first, last, db); + size_t k1 = db.names.size(); + if (t != first) { + db.subs.emplace_back(db.names.get_allocator()); + for (size_t k = k0; k < k1; ++k) + db.subs.back().push_back(db.names[k]); + if (db.try_to_parse_template_args && k1 == k0 + 1) { + const char *t1 = parse_template_args(t, last, db); + if (t1 != t) { + auto args = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += std::move(args); + db.subs.push_back(typename C::sub_type( + 1, db.names.back(), db.names.get_allocator())); + t = t1; + } } - break; - case 'l': - switch (first[1]) - { - case 'e': - db.names.push_back("operator<="); - first += 2; - break; - case 'i': - { - const char* t = parse_source_name(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "operator\"\" "); - first = t; - } + first = t; + } + break; + } + case 'U': + if (first + 1 != last) { + t = parse_source_name(first + 1, last, db); + if (t != first + 1) { + const char *t2 = parse_type(t, last, db); + if (t2 != t) { + if (db.names.size() < 2) + return first; + auto type = db.names.back().move_full(); + db.names.pop_back(); + if (db.names.back().first.substr(0, 9) != "objcproto") { + db.names.back() = type + " " + db.names.back().move_full(); + } else { + auto proto = db.names.back().move_full(); + db.names.pop_back(); + t = parse_source_name(proto.data() + 9, + proto.data() + proto.size(), db); + if (t != proto.data() + 9) { + db.names.back() = + type + "<" + db.names.back().move_full() + ">"; + } else { + db.names.push_back(type + " " + proto); + } } - break; - case 's': - db.names.push_back("operator<<"); - first += 2; - break; - case 'S': - db.names.push_back("operator<<="); - first += 2; - break; - case 't': - db.names.push_back("operator<"); - first += 2; - break; + db.subs.push_back(typename C::sub_type( + 1, db.names.back(), db.names.get_allocator())); + first = t2; + } } - break; - case 'm': - switch (first[1]) - { - case 'i': - db.names.push_back("operator-"); - first += 2; - break; - case 'I': - db.names.push_back("operator-="); - first += 2; - break; - case 'l': - db.names.push_back("operator*"); - first += 2; - break; - case 'L': - db.names.push_back("operator*="); - first += 2; - break; - case 'm': - db.names.push_back("operator--"); - first += 2; - break; + } + break; + case 'S': + if (first + 1 != last && first[1] == 't') { + t = parse_name(first, last, db); + if (t != first) { + if (db.names.empty()) + return first; + db.subs.push_back(typename C::sub_type(1, db.names.back(), + db.names.get_allocator())); + first = t; } - break; - case 'n': - switch (first[1]) - { - case 'a': - db.names.push_back("operator new[]"); - first += 2; - break; - case 'e': - db.names.push_back("operator!="); - first += 2; - break; - case 'g': - db.names.push_back("operator-"); - first += 2; - break; - case 't': - db.names.push_back("operator!"); - first += 2; - break; - case 'w': - db.names.push_back("operator new"); - first += 2; - break; + } else { + t = parse_substitution(first, last, db); + if (t != first) { + first = t; + // Parsed a substitution. If the substitution is a + // <template-param> it might be followed by <template-args>. + t = parse_template_args(first, last, db); + if (t != first) { + if (db.names.size() < 2) + return first; + auto template_args = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += template_args; + // Need to create substitution for <template-template-param> + // <template-args> + db.subs.push_back(typename C::sub_type( + 1, db.names.back(), db.names.get_allocator())); + first = t; + } } - break; - case 'o': - switch (first[1]) - { - case 'o': - db.names.push_back("operator||"); - first += 2; - break; - case 'r': - db.names.push_back("operator|"); - first += 2; - break; - case 'R': - db.names.push_back("operator|="); - first += 2; - break; + } + break; + case 'D': + if (first + 1 != last) { + switch (first[1]) { + case 'p': { + size_t k0 = db.names.size(); + t = parse_type(first + 2, last, db); + size_t k1 = db.names.size(); + if (t != first + 2) { + db.subs.emplace_back(db.names.get_allocator()); + for (size_t k = k0; k < k1; ++k) + db.subs.back().push_back(db.names[k]); + first = t; + return first; + } + break; } - break; - case 'p': - switch (first[1]) - { - case 'm': - db.names.push_back("operator->*"); - first += 2; - break; - case 'l': - db.names.push_back("operator+"); - first += 2; - break; - case 'L': - db.names.push_back("operator+="); - first += 2; - break; - case 'p': - db.names.push_back("operator++"); - first += 2; - break; - case 's': - db.names.push_back("operator+"); - first += 2; - break; case 't': - db.names.push_back("operator->"); - first += 2; - break; - } - break; - case 'q': - if (first[1] == 'u') - { - db.names.push_back("operator?"); - first += 2; - } - break; - case 'r': - switch (first[1]) - { - case 'm': - db.names.push_back("operator%"); - first += 2; - break; - case 'M': - db.names.push_back("operator%="); - first += 2; - break; - case 's': - db.names.push_back("operator>>"); - first += 2; - break; - case 'S': - db.names.push_back("operator>>="); - first += 2; - break; + case 'T': + t = parse_decltype(first, last, db); + if (t != first) { + if (db.names.empty()) + return first; + db.subs.push_back(typename C::sub_type( + 1, db.names.back(), db.names.get_allocator())); + first = t; + return first; + } + break; + case 'v': + t = parse_vector_type(first, last, db); + if (t != first) { + if (db.names.empty()) + return first; + db.subs.push_back(typename C::sub_type( + 1, db.names.back(), db.names.get_allocator())); + first = t; + return first; + } + break; } - break; - case 'v': - if (std::isdigit(first[1])) - { - const char* t = parse_source_name(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "operator "); - first = t; - } + } + LLVM_FALLTHROUGH; + default: + // must check for builtin-types before class-enum-types to avoid + // ambiguities with operator-names + t = parse_builtin_type(first, last, db); + if (t != first) { + first = t; + } else { + t = parse_name(first, last, db); + if (t != first) { + if (db.names.empty()) + return first; + db.subs.push_back(typename C::sub_type(1, db.names.back(), + db.names.get_allocator())); + first = t; } - break; + } + break; } + } + break; } - return first; + } + } + return first; } +// <operator-name> +// ::= aa # && +// ::= ad # & (unary) +// ::= an # & +// ::= aN # &= +// ::= aS # = +// ::= cl # () +// ::= cm # , +// ::= co # ~ +// ::= cv <type> # (cast) +// ::= da # delete[] +// ::= de # * (unary) +// ::= dl # delete +// ::= dv # / +// ::= dV # /= +// ::= eo # ^ +// ::= eO # ^= +// ::= eq # == +// ::= ge # >= +// ::= gt # > +// ::= ix # [] +// ::= le # <= +// ::= li <source-name> # operator "" +// ::= ls # << +// ::= lS # <<= +// ::= lt # < +// ::= mi # - +// ::= mI # -= +// ::= ml # * +// ::= mL # *= +// ::= mm # -- (postfix in <expression> context) +// ::= na # new[] +// ::= ne # != +// ::= ng # - (unary) +// ::= nt # ! +// ::= nw # new +// ::= oo # || +// ::= or # | +// ::= oR # |= +// ::= pm # ->* +// ::= pl # + +// ::= pL # += +// ::= pp # ++ (postfix in <expression> context) +// ::= ps # + (unary) +// ::= pt # -> +// ::= qu # ? +// ::= rm # % +// ::= rM # %= +// ::= rs # >> +// ::= rS # >>= +// ::= v <digit> <source-name> # vendor extended +// operator + template <class C> -const char* -parse_integer_literal(const char* first, const char* last, const typename C::String& lit, C& db) -{ - const char* t = parse_number(first, last); - if (t != first && t != last && *t == 'E') - { - if (lit.size() > 3) - db.names.push_back("(" + lit + ")"); - else - db.names.emplace_back(); - if (*first == 'n') - { - db.names.back().first += '-'; - ++first; +const char *parse_operator_name(const char *first, const char *last, C &db) { + if (last - first >= 2) { + switch (first[0]) { + case 'a': + switch (first[1]) { + case 'a': + db.names.push_back("operator&&"); + first += 2; + break; + case 'd': + case 'n': + db.names.push_back("operator&"); + first += 2; + break; + case 'N': + db.names.push_back("operator&="); + first += 2; + break; + case 'S': + db.names.push_back("operator="); + first += 2; + break; + } + break; + case 'c': + switch (first[1]) { + case 'l': + db.names.push_back("operator()"); + first += 2; + break; + case 'm': + db.names.push_back("operator,"); + first += 2; + break; + case 'o': + db.names.push_back("operator~"); + first += 2; + break; + case 'v': { + bool try_to_parse_template_args = db.try_to_parse_template_args; + db.try_to_parse_template_args = false; + const char *t = parse_type(first + 2, last, db); + db.try_to_parse_template_args = try_to_parse_template_args; + if (t != first + 2) { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "operator "); + db.parsed_ctor_dtor_cv = true; + first = t; + } + } break; + } + break; + case 'd': + switch (first[1]) { + case 'a': + db.names.push_back("operator delete[]"); + first += 2; + break; + case 'e': + db.names.push_back("operator*"); + first += 2; + break; + case 'l': + db.names.push_back("operator delete"); + first += 2; + break; + case 'v': + db.names.push_back("operator/"); + first += 2; + break; + case 'V': + db.names.push_back("operator/="); + first += 2; + break; + } + break; + case 'e': + switch (first[1]) { + case 'o': + db.names.push_back("operator^"); + first += 2; + break; + case 'O': + db.names.push_back("operator^="); + first += 2; + break; + case 'q': + db.names.push_back("operator=="); + first += 2; + break; + } + break; + case 'g': + switch (first[1]) { + case 'e': + db.names.push_back("operator>="); + first += 2; + break; + case 't': + db.names.push_back("operator>"); + first += 2; + break; + } + break; + case 'i': + if (first[1] == 'x') { + db.names.push_back("operator[]"); + first += 2; + } + break; + case 'l': + switch (first[1]) { + case 'e': + db.names.push_back("operator<="); + first += 2; + break; + case 'i': { + const char *t = parse_source_name(first + 2, last, db); + if (t != first + 2) { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "operator\"\" "); + first = t; + } + } break; + case 's': + db.names.push_back("operator<<"); + first += 2; + break; + case 'S': + db.names.push_back("operator<<="); + first += 2; + break; + case 't': + db.names.push_back("operator<"); + first += 2; + break; + } + break; + case 'm': + switch (first[1]) { + case 'i': + db.names.push_back("operator-"); + first += 2; + break; + case 'I': + db.names.push_back("operator-="); + first += 2; + break; + case 'l': + db.names.push_back("operator*"); + first += 2; + break; + case 'L': + db.names.push_back("operator*="); + first += 2; + break; + case 'm': + db.names.push_back("operator--"); + first += 2; + break; + } + break; + case 'n': + switch (first[1]) { + case 'a': + db.names.push_back("operator new[]"); + first += 2; + break; + case 'e': + db.names.push_back("operator!="); + first += 2; + break; + case 'g': + db.names.push_back("operator-"); + first += 2; + break; + case 't': + db.names.push_back("operator!"); + first += 2; + break; + case 'w': + db.names.push_back("operator new"); + first += 2; + break; + } + break; + case 'o': + switch (first[1]) { + case 'o': + db.names.push_back("operator||"); + first += 2; + break; + case 'r': + db.names.push_back("operator|"); + first += 2; + break; + case 'R': + db.names.push_back("operator|="); + first += 2; + break; + } + break; + case 'p': + switch (first[1]) { + case 'm': + db.names.push_back("operator->*"); + first += 2; + break; + case 'l': + db.names.push_back("operator+"); + first += 2; + break; + case 'L': + db.names.push_back("operator+="); + first += 2; + break; + case 'p': + db.names.push_back("operator++"); + first += 2; + break; + case 's': + db.names.push_back("operator+"); + first += 2; + break; + case 't': + db.names.push_back("operator->"); + first += 2; + break; + } + break; + case 'q': + if (first[1] == 'u') { + db.names.push_back("operator?"); + first += 2; + } + break; + case 'r': + switch (first[1]) { + case 'm': + db.names.push_back("operator%"); + first += 2; + break; + case 'M': + db.names.push_back("operator%="); + first += 2; + break; + case 's': + db.names.push_back("operator>>"); + first += 2; + break; + case 'S': + db.names.push_back("operator>>="); + first += 2; + break; + } + break; + case 'v': + if (std::isdigit(first[1])) { + const char *t = parse_source_name(first + 2, last, db); + if (t != first + 2) { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "operator "); + first = t; } - db.names.back().first.append(first, t); - if (lit.size() <= 3) - db.names.back().first += lit; - first = t+1; + } + break; + } + } + return first; +} + +template <class C> +const char *parse_integer_literal(const char *first, const char *last, + const typename C::String &lit, C &db) { + const char *t = parse_number(first, last); + if (t != first && t != last && *t == 'E') { + if (lit.size() > 3) + db.names.push_back("(" + lit + ")"); + else + db.names.emplace_back(); + if (*first == 'n') { + db.names.back().first += '-'; + ++first; } - return first; + db.names.back().first.append(first, t); + if (lit.size() <= 3) + db.names.back().first += lit; + first = t + 1; + } + return first; } -// <expr-primary> ::= L <type> <value number> E # integer literal -// ::= L <type> <value float> E # floating literal -// ::= L <string type> E # string literal -// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE") -// ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000) -// ::= L <mangled-name> E # external name +// <expr-primary> ::= L <type> <value number> E # +// integer literal +// ::= L <type> <value float> E # +// floating literal +// ::= L <string type> E # +// string literal +// ::= L <nullptr type> E # +// nullptr literal (i.e., "LDnE") +// ::= L <type> <real-part float> _ <imag-part float> E # +// complex floating point literal (C 2000) +// ::= L <mangled-name> E # +// external name template <class C> -const char* -parse_expr_primary(const char* first, const char* last, C& db) -{ - if (last - first >= 4 && *first == 'L') - { - switch (first[1]) - { - case 'w': - { - const char* t = parse_integer_literal(first+2, last, "wchar_t", db); - if (t != first+2) - first = t; - } - break; - case 'b': - if (first[3] == 'E') - { - switch (first[2]) - { - case '0': - db.names.push_back("false"); - first += 4; - break; - case '1': - db.names.push_back("true"); - first += 4; - break; - } - } - break; - case 'c': - { - const char* t = parse_integer_literal(first+2, last, "char", db); - if (t != first+2) - first = t; - } - break; - case 'a': - { - const char* t = parse_integer_literal(first+2, last, "signed char", db); - if (t != first+2) - first = t; - } - break; - case 'h': - { - const char* t = parse_integer_literal(first+2, last, "unsigned char", db); - if (t != first+2) - first = t; - } - break; - case 's': - { - const char* t = parse_integer_literal(first+2, last, "short", db); - if (t != first+2) - first = t; - } - break; - case 't': - { - const char* t = parse_integer_literal(first+2, last, "unsigned short", db); - if (t != first+2) - first = t; - } - break; - case 'i': - { - const char* t = parse_integer_literal(first+2, last, "", db); - if (t != first+2) - first = t; - } - break; - case 'j': - { - const char* t = parse_integer_literal(first+2, last, "u", db); - if (t != first+2) - first = t; - } - break; - case 'l': - { - const char* t = parse_integer_literal(first+2, last, "l", db); - if (t != first+2) - first = t; - } - break; - case 'm': - { - const char* t = parse_integer_literal(first+2, last, "ul", db); - if (t != first+2) - first = t; - } - break; - case 'x': - { - const char* t = parse_integer_literal(first+2, last, "ll", db); - if (t != first+2) - first = t; - } - break; - case 'y': - { - const char* t = parse_integer_literal(first+2, last, "ull", db); - if (t != first+2) - first = t; - } - break; - case 'n': - { - const char* t = parse_integer_literal(first+2, last, "__int128", db); - if (t != first+2) - first = t; - } - break; - case 'o': - { - const char* t = parse_integer_literal(first+2, last, "unsigned __int128", db); - if (t != first+2) - first = t; - } - break; - case 'f': - { - const char* t = parse_floating_number<float>(first+2, last, db); - if (t != first+2) - first = t; - } - break; - case 'd': - { - const char* t = parse_floating_number<double>(first+2, last, db); - if (t != first+2) - first = t; - } - break; - case 'e': - { - const char* t = parse_floating_number<long double>(first+2, last, db); - if (t != first+2) - first = t; - } - break; - case '_': - if (first[2] == 'Z') - { - const char* t = parse_encoding(first+3, last, db); - if (t != first+3 && t != last && *t == 'E') - first = t+1; - } - break; - case 'T': - // Invalid mangled name per - // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html +const char *parse_expr_primary(const char *first, const char *last, C &db) { + if (last - first >= 4 && *first == 'L') { + switch (first[1]) { + case 'w': { + const char *t = parse_integer_literal(first + 2, last, "wchar_t", db); + if (t != first + 2) + first = t; + } break; + case 'b': + if (first[3] == 'E') { + switch (first[2]) { + case '0': + db.names.push_back("false"); + first += 4; + break; + case '1': + db.names.push_back("true"); + first += 4; + break; + } + } + break; + case 'c': { + const char *t = parse_integer_literal(first + 2, last, "char", db); + if (t != first + 2) + first = t; + } break; + case 'a': { + const char *t = parse_integer_literal(first + 2, last, "signed char", db); + if (t != first + 2) + first = t; + } break; + case 'h': { + const char *t = + parse_integer_literal(first + 2, last, "unsigned char", db); + if (t != first + 2) + first = t; + } break; + case 's': { + const char *t = parse_integer_literal(first + 2, last, "short", db); + if (t != first + 2) + first = t; + } break; + case 't': { + const char *t = + parse_integer_literal(first + 2, last, "unsigned short", db); + if (t != first + 2) + first = t; + } break; + case 'i': { + const char *t = parse_integer_literal(first + 2, last, "", db); + if (t != first + 2) + first = t; + } break; + case 'j': { + const char *t = parse_integer_literal(first + 2, last, "u", db); + if (t != first + 2) + first = t; + } break; + case 'l': { + const char *t = parse_integer_literal(first + 2, last, "l", db); + if (t != first + 2) + first = t; + } break; + case 'm': { + const char *t = parse_integer_literal(first + 2, last, "ul", db); + if (t != first + 2) + first = t; + } break; + case 'x': { + const char *t = parse_integer_literal(first + 2, last, "ll", db); + if (t != first + 2) + first = t; + } break; + case 'y': { + const char *t = parse_integer_literal(first + 2, last, "ull", db); + if (t != first + 2) + first = t; + } break; + case 'n': { + const char *t = parse_integer_literal(first + 2, last, "__int128", db); + if (t != first + 2) + first = t; + } break; + case 'o': { + const char *t = + parse_integer_literal(first + 2, last, "unsigned __int128", db); + if (t != first + 2) + first = t; + } break; + case 'f': { + const char *t = parse_floating_number<float>(first + 2, last, db); + if (t != first + 2) + first = t; + } break; + case 'd': { + const char *t = parse_floating_number<double>(first + 2, last, db); + if (t != first + 2) + first = t; + } break; + case 'e': { + const char *t = parse_floating_number<long double>(first + 2, last, db); + if (t != first + 2) + first = t; + } break; + case '_': + if (first[2] == 'Z') { + const char *t = parse_encoding(first + 3, last, db); + if (t != first + 3 && t != last && *t == 'E') + first = t + 1; + } + break; + case 'T': + // Invalid mangled name per + // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html + break; + default: { + // might be named type + const char *t = parse_type(first + 1, last, db); + if (t != first + 1 && t != last) { + if (*t != 'E') { + const char *n = t; + for (; n != last && isdigit(*n); ++n) + ; + if (n != t && n != last && *n == 'E') { + if (db.names.empty()) + return first; + db.names.back() = "(" + db.names.back().move_full() + ")" + + typename C::String(t, n); + first = n + 1; break; - default: - { - // might be named type - const char* t = parse_type(first+1, last, db); - if (t != first+1 && t != last) - { - if (*t != 'E') - { - const char* n = t; - for (; n != last && isdigit(*n); ++n) - ; - if (n != t && n != last && *n == 'E') - { - if (db.names.empty()) - return first; - db.names.back() = "(" + db.names.back().move_full() + ")" + typename C::String(t, n); - first = n+1; - break; - } - } - else - { - first = t+1; - break; - } - } - } + } + } else { + first = t + 1; + break; } + } + } } - return first; + } + return first; } -template <class String> -String -base_name(String& s) -{ - if (s.empty()) - return s; - if (s == "std::string") - { - s = "std::basic_string<char, std::char_traits<char>, std::allocator<char> >"; - return "basic_string"; - } - if (s == "std::istream") - { - s = "std::basic_istream<char, std::char_traits<char> >"; - return "basic_istream"; - } - if (s == "std::ostream") - { - s = "std::basic_ostream<char, std::char_traits<char> >"; - return "basic_ostream"; - } - if (s == "std::iostream") - { - s = "std::basic_iostream<char, std::char_traits<char> >"; - return "basic_iostream"; - } - const char* const pf = s.data(); - const char* pe = pf + s.size(); - if (pe[-1] == '>') - { - unsigned c = 1; - while (true) - { - if (--pe == pf) - return String(); - if (pe[-1] == '<') - { - if (--c == 0) - { - --pe; - break; - } - } - else if (pe[-1] == '>') - ++c; +template <class String> String base_name(String &s) { + if (s.empty()) + return s; + if (s == "std::string") { + s = "std::basic_string<char, std::char_traits<char>, std::allocator<char> " + ">"; + return "basic_string"; + } + if (s == "std::istream") { + s = "std::basic_istream<char, std::char_traits<char> >"; + return "basic_istream"; + } + if (s == "std::ostream") { + s = "std::basic_ostream<char, std::char_traits<char> >"; + return "basic_ostream"; + } + if (s == "std::iostream") { + s = "std::basic_iostream<char, std::char_traits<char> >"; + return "basic_iostream"; + } + const char *const pf = s.data(); + const char *pe = pf + s.size(); + if (pe[-1] == '>') { + unsigned c = 1; + while (true) { + if (--pe == pf) + return String(); + if (pe[-1] == '<') { + if (--c == 0) { + --pe; + break; } + } else if (pe[-1] == '>') + ++c; } - const char* p0 = pe - 1; - for (; p0 != pf; --p0) - { - if (*p0 == ':') - { - ++p0; - break; - } + } + const char *p0 = pe - 1; + for (; p0 != pf; --p0) { + if (*p0 == ':') { + ++p0; + break; } - return String(p0, pe); + } + return String(p0, pe); } // <ctor-dtor-name> ::= C1 # complete object constructor @@ -2931,209 +2568,180 @@ base_name(String& s) // extension ::= D5 # ? template <class C> -const char* -parse_ctor_dtor_name(const char* first, const char* last, C& db) -{ - if (last-first >= 2 && !db.names.empty()) - { - switch (first[0]) - { - case 'C': - switch (first[1]) - { - case '1': - case '2': - case '3': - case '5': - if (db.names.empty()) - return first; - db.names.push_back(base_name(db.names.back().first)); - first += 2; - db.parsed_ctor_dtor_cv = true; - break; - } - break; - case 'D': - switch (first[1]) - { - case '0': - case '1': - case '2': - case '5': - if (db.names.empty()) - return first; - db.names.push_back("~" + base_name(db.names.back().first)); - first += 2; - db.parsed_ctor_dtor_cv = true; - break; - } - break; - } +const char *parse_ctor_dtor_name(const char *first, const char *last, C &db) { + if (last - first >= 2 && !db.names.empty()) { + switch (first[0]) { + case 'C': + switch (first[1]) { + case '1': + case '2': + case '3': + case '5': + if (db.names.empty()) + return first; + db.names.push_back(base_name(db.names.back().first)); + first += 2; + db.parsed_ctor_dtor_cv = true; + break; + } + break; + case 'D': + switch (first[1]) { + case '0': + case '1': + case '2': + case '5': + if (db.names.empty()) + return first; + db.names.push_back("~" + base_name(db.names.back().first)); + first += 2; + db.parsed_ctor_dtor_cv = true; + break; + } + break; } - return first; + } + return first; } // <unnamed-type-name> ::= Ut [ <nonnegative number> ] _ // ::= <closure-type-name> -// -// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _ -// -// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters +// +// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _ +// +// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda +// has no parameters template <class C> -const char* -parse_unnamed_type_name(const char* first, const char* last, C& db) -{ - if (last - first > 2 && first[0] == 'U') - { - char type = first[1]; - switch (type) - { - case 't': - { - db.names.push_back(typename C::String("'unnamed")); - const char* t0 = first+2; - if (t0 == last) - { - db.names.pop_back(); - return first; - } - if (std::isdigit(*t0)) - { - const char* t1 = t0 + 1; - while (t1 != last && std::isdigit(*t1)) - ++t1; - db.names.back().first.append(t0, t1); - t0 = t1; - } - db.names.back().first.push_back('\''); - if (t0 == last || *t0 != '_') - { - db.names.pop_back(); - return first; - } - first = t0 + 1; - } +const char *parse_unnamed_type_name(const char *first, const char *last, + C &db) { + if (last - first > 2 && first[0] == 'U') { + char type = first[1]; + switch (type) { + case 't': { + db.names.push_back(typename C::String("'unnamed")); + const char *t0 = first + 2; + if (t0 == last) { + db.names.pop_back(); + return first; + } + if (std::isdigit(*t0)) { + const char *t1 = t0 + 1; + while (t1 != last && std::isdigit(*t1)) + ++t1; + db.names.back().first.append(t0, t1); + t0 = t1; + } + db.names.back().first.push_back('\''); + if (t0 == last || *t0 != '_') { + db.names.pop_back(); + return first; + } + first = t0 + 1; + } break; + case 'l': { + db.names.push_back(typename C::String("'lambda'(")); + const char *t0 = first + 2; + if (first[2] == 'v') { + db.names.back().first += ')'; + ++t0; + } else { + const char *t1 = parse_type(t0, last, db); + if (t1 == t0) { + db.names.pop_back(); + return first; + } + if (db.names.size() < 2) + return first; + auto tmp = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first.append(tmp); + t0 = t1; + while (true) { + t1 = parse_type(t0, last, db); + if (t1 == t0) break; - case 'l': - { - db.names.push_back(typename C::String("'lambda'(")); - const char* t0 = first+2; - if (first[2] == 'v') - { - db.names.back().first += ')'; - ++t0; - } - else - { - const char* t1 = parse_type(t0, last, db); - if (t1 == t0) - { - db.names.pop_back(); - return first; - } - if (db.names.size() < 2) - return first; - auto tmp = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first.append(tmp); - t0 = t1; - while (true) - { - t1 = parse_type(t0, last, db); - if (t1 == t0) - break; - if (db.names.size() < 2) - return first; - tmp = db.names.back().move_full(); - db.names.pop_back(); - if (!tmp.empty()) - { - db.names.back().first.append(", "); - db.names.back().first.append(tmp); - } - t0 = t1; - } - db.names.back().first.append(")"); - } - if (t0 == last || *t0 != 'E') - { - db.names.pop_back(); - return first; - } - ++t0; - if (t0 == last) - { - db.names.pop_back(); - return first; - } - if (std::isdigit(*t0)) - { - const char* t1 = t0 + 1; - while (t1 != last && std::isdigit(*t1)) - ++t1; - db.names.back().first.insert(db.names.back().first.begin()+7, t0, t1); - t0 = t1; - } - if (t0 == last || *t0 != '_') - { - db.names.pop_back(); - return first; - } - first = t0 + 1; + if (db.names.size() < 2) + return first; + tmp = db.names.back().move_full(); + db.names.pop_back(); + if (!tmp.empty()) { + db.names.back().first.append(", "); + db.names.back().first.append(tmp); } - break; + t0 = t1; } + db.names.back().first.append(")"); + } + if (t0 == last || *t0 != 'E') { + db.names.pop_back(); + return first; + } + ++t0; + if (t0 == last) { + db.names.pop_back(); + return first; + } + if (std::isdigit(*t0)) { + const char *t1 = t0 + 1; + while (t1 != last && std::isdigit(*t1)) + ++t1; + db.names.back().first.insert(db.names.back().first.begin() + 7, t0, t1); + t0 = t1; + } + if (t0 == last || *t0 != '_') { + db.names.pop_back(); + return first; + } + first = t0 + 1; + } break; } - return first; + } + return first; } // <unqualified-name> ::= <operator-name> // ::= <ctor-dtor-name> -// ::= <source-name> +// ::= <source-name> // ::= <unnamed-type-name> template <class C> -const char* -parse_unqualified_name(const char* first, const char* last, C& db) -{ - if (first != last) - { - const char* t; - switch (*first) - { - case 'C': - case 'D': - t = parse_ctor_dtor_name(first, last, db); - if (t != first) - first = t; - break; - case 'U': - t = parse_unnamed_type_name(first, last, db); - if (t != first) - first = t; - break; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - t = parse_source_name(first, last, db); - if (t != first) - first = t; - break; - default: - t = parse_operator_name(first, last, db); - if (t != first) - first = t; - break; - }; - } - return first; +const char *parse_unqualified_name(const char *first, const char *last, C &db) { + if (first != last) { + const char *t; + switch (*first) { + case 'C': + case 'D': + t = parse_ctor_dtor_name(first, last, db); + if (t != first) + first = t; + break; + case 'U': + t = parse_unnamed_type_name(first, last, db); + if (t != first) + first = t; + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + t = parse_source_name(first, last, db); + if (t != first) + first = t; + break; + default: + t = parse_operator_name(first, last, db); + if (t != first) + first = t; + break; + }; + } + return first; } // <unscoped-name> ::= <unqualified-name> @@ -3141,775 +2749,743 @@ parse_unqualified_name(const char* first, const char* last, C& db) // extension ::= StL<unqualified-name> template <class C> -const char* -parse_unscoped_name(const char* first, const char* last, C& db) -{ - if (last - first >= 2) - { - const char* t0 = first; - bool St = false; - if (first[0] == 'S' && first[1] == 't') - { - t0 += 2; - St = true; - if (t0 != last && *t0 == 'L') - ++t0; - } - const char* t1 = parse_unqualified_name(t0, last, db); - if (t1 != t0) - { - if (St) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "std::"); - } - first = t1; - } +const char *parse_unscoped_name(const char *first, const char *last, C &db) { + if (last - first >= 2) { + const char *t0 = first; + bool St = false; + if (first[0] == 'S' && first[1] == 't') { + t0 += 2; + St = true; + if (t0 != last && *t0 == 'L') + ++t0; + } + const char *t1 = parse_unqualified_name(t0, last, db); + if (t1 != t0) { + if (St) { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "std::"); + } + first = t1; } - return first; + } + return first; } // at <type> # alignof (a type) template <class C> -const char* -parse_alignof_type(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 'a' && first[1] == 't') - { - const char* t = parse_type(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first = "alignof (" + db.names.back().move_full() + ")"; - first = t; - } +const char *parse_alignof_type(const char *first, const char *last, C &db) { + if (last - first >= 3 && first[0] == 'a' && first[1] == 't') { + const char *t = parse_type(first + 2, last, db); + if (t != first + 2) { + if (db.names.empty()) + return first; + db.names.back().first = "alignof (" + db.names.back().move_full() + ")"; + first = t; } - return first; + } + return first; } -// az <expression> # alignof (a expression) +// az <expression> # alignof (a +// expression) template <class C> -const char* -parse_alignof_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 'a' && first[1] == 'z') - { - const char* t = parse_expression(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first = "alignof (" + db.names.back().move_full() + ")"; - first = t; - } +const char *parse_alignof_expr(const char *first, const char *last, C &db) { + if (last - first >= 3 && first[0] == 'a' && first[1] == 'z') { + const char *t = parse_expression(first + 2, last, db); + if (t != first + 2) { + if (db.names.empty()) + return first; + db.names.back().first = "alignof (" + db.names.back().move_full() + ")"; + first = t; } - return first; + } + return first; } template <class C> -const char* -parse_noexcept_expression(const char* first, const char* last, C& db) -{ - const char* t1 = parse_expression(first, last, db); - if (t1 != first) - { - if (db.names.empty()) - return first; - db.names.back().first = "noexcept (" + db.names.back().move_full() + ")"; - first = t1; - } - return first; +const char *parse_noexcept_expression(const char *first, const char *last, + C &db) { + const char *t1 = parse_expression(first, last, db); + if (t1 != first) { + if (db.names.empty()) + return first; + db.names.back().first = "noexcept (" + db.names.back().move_full() + ")"; + first = t1; + } + return first; } template <class C> -const char* -parse_prefix_expression(const char* first, const char* last, const typename C::String& op, C& db) -{ - const char* t1 = parse_expression(first, last, db); - if (t1 != first) - { - if (db.names.empty()) - return first; - db.names.back().first = op + "(" + db.names.back().move_full() + ")"; - first = t1; - } - return first; +const char *parse_prefix_expression(const char *first, const char *last, + const typename C::String &op, C &db) { + const char *t1 = parse_expression(first, last, db); + if (t1 != first) { + if (db.names.empty()) + return first; + db.names.back().first = op + "(" + db.names.back().move_full() + ")"; + first = t1; + } + return first; } template <class C> -const char* -parse_binary_expression(const char* first, const char* last, const typename C::String& op, C& db) -{ - const char* t1 = parse_expression(first, last, db); - if (t1 != first) - { - const char* t2 = parse_expression(t1, last, db); - if (t2 != t1) - { - if (db.names.size() < 2) - return first; - auto op2 = db.names.back().move_full(); - db.names.pop_back(); - auto op1 = db.names.back().move_full(); - auto& nm = db.names.back().first; - nm.clear(); - if (op == ">") - nm += '('; - nm += "(" + op1 + ") " + op + " (" + op2 + ")"; - if (op == ">") - nm += ')'; - first = t2; - } - else - db.names.pop_back(); - } - return first; +const char *parse_binary_expression(const char *first, const char *last, + const typename C::String &op, C &db) { + const char *t1 = parse_expression(first, last, db); + if (t1 != first) { + const char *t2 = parse_expression(t1, last, db); + if (t2 != t1) { + if (db.names.size() < 2) + return first; + auto op2 = db.names.back().move_full(); + db.names.pop_back(); + auto op1 = db.names.back().move_full(); + auto &nm = db.names.back().first; + nm.clear(); + if (op == ">") + nm += '('; + nm += "(" + op1 + ") " + op + " (" + op2 + ")"; + if (op == ">") + nm += ')'; + first = t2; + } else + db.names.pop_back(); + } + return first; } // <expression> ::= <unary operator-name> <expression> // ::= <binary operator-name> <expression> <expression> -// ::= <ternary operator-name> <expression> <expression> <expression> +// ::= <ternary operator-name> <expression> <expression> +// <expression> // ::= cl <expression>+ E # call -// ::= cv <type> <expression> # conversion with one argument -// ::= cv <type> _ <expression>* E # conversion with a different number of arguments -// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type -// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init) -// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type -// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init) -// ::= [gs] dl <expression> # delete expression -// ::= [gs] da <expression> # delete[] expression -// ::= pp_ <expression> # prefix ++ -// ::= mm_ <expression> # prefix -- -// ::= ti <type> # typeid (type) -// ::= te <expression> # typeid (expression) -// ::= dc <type> <expression> # dynamic_cast<type> (expression) -// ::= sc <type> <expression> # static_cast<type> (expression) -// ::= cc <type> <expression> # const_cast<type> (expression) -// ::= rc <type> <expression> # reinterpret_cast<type> (expression) -// ::= st <type> # sizeof (a type) -// ::= sz <expression> # sizeof (an expression) -// ::= at <type> # alignof (a type) -// ::= az <expression> # alignof (an expression) -// ::= nx <expression> # noexcept (expression) +// ::= cv <type> <expression> # +// conversion with one argument +// ::= cv <type> _ <expression>* E # +// conversion with a different number of arguments +// ::= [gs] nw <expression>* _ <type> E # new +// (expr-list) type +// ::= [gs] nw <expression>* _ <type> <initializer> # new +// (expr-list) type (init) +// ::= [gs] na <expression>* _ <type> E # new[] +// (expr-list) type +// ::= [gs] na <expression>* _ <type> <initializer> # new[] +// (expr-list) type (init) +// ::= [gs] dl <expression> # +// delete expression +// ::= [gs] da <expression> # +// delete[] expression +// ::= pp_ <expression> # +// prefix ++ +// ::= mm_ <expression> # +// prefix -- +// ::= ti <type> # +// typeid (type) +// ::= te <expression> # +// typeid (expression) +// ::= dc <type> <expression> # +// dynamic_cast<type> (expression) +// ::= sc <type> <expression> # +// static_cast<type> (expression) +// ::= cc <type> <expression> # +// const_cast<type> (expression) +// ::= rc <type> <expression> # +// reinterpret_cast<type> (expression) +// ::= st <type> # +// sizeof (a type) +// ::= sz <expression> # +// sizeof (an expression) +// ::= at <type> # +// alignof (a type) +// ::= az <expression> # +// alignof (an expression) +// ::= nx <expression> # +// noexcept (expression) // ::= <template-param> // ::= <function-param> -// ::= dt <expression> <unresolved-name> # expr.name -// ::= pt <expression> <unresolved-name> # expr->name -// ::= ds <expression> <expression> # expr.*expr -// ::= sZ <template-param> # size of a parameter pack -// ::= sZ <function-param> # size of a function parameter pack -// ::= sp <expression> # pack expansion -// ::= tw <expression> # throw expression -// ::= tr # throw with no operand (rethrow) -// ::= <unresolved-name> # f(p), N::f(p), ::f(p), -// # freestanding dependent name (e.g., T::x), -// # objectless nonstatic member reference +// ::= dt <expression> <unresolved-name> # +// expr.name +// ::= pt <expression> <unresolved-name> # +// expr->name +// ::= ds <expression> <expression> # +// expr.*expr +// ::= sZ <template-param> # size +// of a parameter pack +// ::= sZ <function-param> # size +// of a function parameter pack +// ::= sp <expression> # pack +// expansion +// ::= tw <expression> # throw +// expression +// ::= tr # throw +// with no operand (rethrow) +// ::= <unresolved-name> # f(p), +// N::f(p), ::f(p), +// # +// freestanding +// dependent +// name +// (e.g., +// T::x), +// # +// objectless +// nonstatic +// member +// reference // ::= <expr-primary> template <class C> -const char* -parse_expression(const char* first, const char* last, C& db) -{ - if (last - first >= 2) - { - const char* t = first; - bool parsed_gs = false; - if (last - first >= 4 && t[0] == 'g' && t[1] == 's') - { - t += 2; - parsed_gs = true; +const char *parse_expression(const char *first, const char *last, C &db) { + if (last - first >= 2) { + const char *t = first; + bool parsed_gs = false; + if (last - first >= 4 && t[0] == 'g' && t[1] == 's') { + t += 2; + parsed_gs = true; + } + switch (*t) { + case 'L': + first = parse_expr_primary(first, last, db); + break; + case 'T': + first = parse_template_param(first, last, db); + break; + case 'f': + first = parse_function_param(first, last, db); + break; + case 'a': + switch (t[1]) { + case 'a': + t = parse_binary_expression(first + 2, last, "&&", db); + if (t != first + 2) + first = t; + break; + case 'd': + t = parse_prefix_expression(first + 2, last, "&", db); + if (t != first + 2) + first = t; + break; + case 'n': + t = parse_binary_expression(first + 2, last, "&", db); + if (t != first + 2) + first = t; + break; + case 'N': + t = parse_binary_expression(first + 2, last, "&=", db); + if (t != first + 2) + first = t; + break; + case 'S': + t = parse_binary_expression(first + 2, last, "=", db); + if (t != first + 2) + first = t; + break; + case 't': + first = parse_alignof_type(first, last, db); + break; + case 'z': + first = parse_alignof_expr(first, last, db); + break; + } + break; + case 'c': + switch (t[1]) { + case 'c': + first = parse_const_cast_expr(first, last, db); + break; + case 'l': + first = parse_call_expr(first, last, db); + break; + case 'm': + t = parse_binary_expression(first + 2, last, ",", db); + if (t != first + 2) + first = t; + break; + case 'o': + t = parse_prefix_expression(first + 2, last, "~", db); + if (t != first + 2) + first = t; + break; + case 'v': + first = parse_conversion_expr(first, last, db); + break; + } + break; + case 'd': + switch (t[1]) { + case 'a': { + const char *t1 = parse_expression(t + 2, last, db); + if (t1 != t + 2) { + if (db.names.empty()) + return first; + db.names.back().first = + (parsed_gs ? typename C::String("::") : typename C::String()) + + "delete[] " + db.names.back().move_full(); + first = t1; } - switch (*t) - { - case 'L': - first = parse_expr_primary(first, last, db); - break; - case 'T': - first = parse_template_param(first, last, db); - break; - case 'f': - first = parse_function_param(first, last, db); - break; - case 'a': - switch (t[1]) - { - case 'a': - t = parse_binary_expression(first+2, last, "&&", db); - if (t != first+2) - first = t; - break; - case 'd': - t = parse_prefix_expression(first+2, last, "&", db); - if (t != first+2) - first = t; - break; - case 'n': - t = parse_binary_expression(first+2, last, "&", db); - if (t != first+2) - first = t; - break; - case 'N': - t = parse_binary_expression(first+2, last, "&=", db); - if (t != first+2) - first = t; - break; - case 'S': - t = parse_binary_expression(first+2, last, "=", db); - if (t != first+2) - first = t; - break; - case 't': - first = parse_alignof_type(first, last, db); - break; - case 'z': - first = parse_alignof_expr(first, last, db); - break; - } - break; - case 'c': - switch (t[1]) - { - case 'c': - first = parse_const_cast_expr(first, last, db); - break; - case 'l': - first = parse_call_expr(first, last, db); - break; - case 'm': - t = parse_binary_expression(first+2, last, ",", db); - if (t != first+2) - first = t; - break; - case 'o': - t = parse_prefix_expression(first+2, last, "~", db); - if (t != first+2) - first = t; - break; - case 'v': - first = parse_conversion_expr(first, last, db); - break; - } - break; - case 'd': - switch (t[1]) - { - case 'a': - { - const char* t1 = parse_expression(t+2, last, db); - if (t1 != t+2) - { - if (db.names.empty()) - return first; - db.names.back().first = (parsed_gs ? typename C::String("::") : typename C::String()) + - "delete[] " + db.names.back().move_full(); - first = t1; - } - } - break; - case 'c': - first = parse_dynamic_cast_expr(first, last, db); - break; - case 'e': - t = parse_prefix_expression(first+2, last, "*", db); - if (t != first+2) - first = t; - break; - case 'l': - { - const char* t1 = parse_expression(t+2, last, db); - if (t1 != t+2) - { - if (db.names.empty()) - return first; - db.names.back().first = (parsed_gs ? typename C::String("::") : typename C::String()) + - "delete " + db.names.back().move_full(); - first = t1; - } - } - break; - case 'n': - return parse_unresolved_name(first, last, db); - case 's': - first = parse_dot_star_expr(first, last, db); - break; - case 't': - first = parse_dot_expr(first, last, db); - break; - case 'v': - t = parse_binary_expression(first+2, last, "/", db); - if (t != first+2) - first = t; - break; - case 'V': - t = parse_binary_expression(first+2, last, "/=", db); - if (t != first+2) - first = t; - break; - } - break; - case 'e': - switch (t[1]) - { - case 'o': - t = parse_binary_expression(first+2, last, "^", db); - if (t != first+2) - first = t; - break; - case 'O': - t = parse_binary_expression(first+2, last, "^=", db); - if (t != first+2) - first = t; - break; - case 'q': - t = parse_binary_expression(first+2, last, "==", db); - if (t != first+2) - first = t; - break; - } - break; - case 'g': - switch (t[1]) - { - case 'e': - t = parse_binary_expression(first+2, last, ">=", db); - if (t != first+2) - first = t; - break; - case 't': - t = parse_binary_expression(first+2, last, ">", db); - if (t != first+2) - first = t; - break; - } - break; - case 'i': - if (t[1] == 'x') - { - const char* t1 = parse_expression(first+2, last, db); - if (t1 != first+2) - { - const char* t2 = parse_expression(t1, last, db); - if (t2 != t1) - { - if (db.names.size() < 2) - return first; - auto op2 = db.names.back().move_full(); - db.names.pop_back(); - auto op1 = db.names.back().move_full(); - db.names.back() = "(" + op1 + ")[" + op2 + "]"; - first = t2; - } - else - db.names.pop_back(); - } - } - break; - case 'l': - switch (t[1]) - { - case 'e': - t = parse_binary_expression(first+2, last, "<=", db); - if (t != first+2) - first = t; - break; - case 's': - t = parse_binary_expression(first+2, last, "<<", db); - if (t != first+2) - first = t; - break; - case 'S': - t = parse_binary_expression(first+2, last, "<<=", db); - if (t != first+2) - first = t; - break; - case 't': - t = parse_binary_expression(first+2, last, "<", db); - if (t != first+2) - first = t; - break; - } - break; - case 'm': - switch (t[1]) - { - case 'i': - t = parse_binary_expression(first+2, last, "-", db); - if (t != first+2) - first = t; - break; - case 'I': - t = parse_binary_expression(first+2, last, "-=", db); - if (t != first+2) - first = t; - break; - case 'l': - t = parse_binary_expression(first+2, last, "*", db); - if (t != first+2) - first = t; - break; - case 'L': - t = parse_binary_expression(first+2, last, "*=", db); - if (t != first+2) - first = t; - break; - case 'm': - if (first+2 != last && first[2] == '_') - { - t = parse_prefix_expression(first+3, last, "--", db); - if (t != first+3) - first = t; - } - else - { - const char* t1 = parse_expression(first+2, last, db); - if (t1 != first+2) - { - if (db.names.empty()) - return first; - db.names.back() = "(" + db.names.back().move_full() + ")--"; - first = t1; - } - } - break; - } - break; - case 'n': - switch (t[1]) - { - case 'a': - case 'w': - first = parse_new_expr(first, last, db); - break; - case 'e': - t = parse_binary_expression(first+2, last, "!=", db); - if (t != first+2) - first = t; - break; - case 'g': - t = parse_prefix_expression(first+2, last, "-", db); - if (t != first+2) - first = t; - break; - case 't': - t = parse_prefix_expression(first+2, last, "!", db); - if (t != first+2) - first = t; - break; - case 'x': - t = parse_noexcept_expression(first+2, last, db); - if (t != first+2) - first = t; - break; - } - break; - case 'o': - switch (t[1]) - { - case 'n': - return parse_unresolved_name(first, last, db); - case 'o': - t = parse_binary_expression(first+2, last, "||", db); - if (t != first+2) - first = t; - break; - case 'r': - t = parse_binary_expression(first+2, last, "|", db); - if (t != first+2) - first = t; - break; - case 'R': - t = parse_binary_expression(first+2, last, "|=", db); - if (t != first+2) - first = t; - break; - } - break; - case 'p': - switch (t[1]) - { - case 'm': - t = parse_binary_expression(first+2, last, "->*", db); - if (t != first+2) - first = t; - break; - case 'l': - t = parse_binary_expression(first+2, last, "+", db); - if (t != first+2) - first = t; - break; - case 'L': - t = parse_binary_expression(first+2, last, "+=", db); - if (t != first+2) - first = t; - break; - case 'p': - if (first+2 != last && first[2] == '_') - { - t = parse_prefix_expression(first+3, last, "++", db); - if (t != first+3) - first = t; - } - else - { - const char* t1 = parse_expression(first+2, last, db); - if (t1 != first+2) - { - if (db.names.empty()) - return first; - db.names.back() = "(" + db.names.back().move_full() + ")++"; - first = t1; - } - } - break; - case 's': - t = parse_prefix_expression(first+2, last, "+", db); - if (t != first+2) - first = t; - break; - case 't': - first = parse_arrow_expr(first, last, db); - break; - } - break; - case 'q': - if (t[1] == 'u') - { - const char* t1 = parse_expression(first+2, last, db); - if (t1 != first+2) - { - const char* t2 = parse_expression(t1, last, db); - if (t2 != t1) - { - const char* t3 = parse_expression(t2, last, db); - if (t3 != t2) - { - if (db.names.size() < 3) - return first; - auto op3 = db.names.back().move_full(); - db.names.pop_back(); - auto op2 = db.names.back().move_full(); - db.names.pop_back(); - auto op1 = db.names.back().move_full(); - db.names.back() = "(" + op1 + ") ? (" + op2 + ") : (" + op3 + ")"; - first = t3; - } - else - { - db.names.pop_back(); - db.names.pop_back(); - } - } - else - db.names.pop_back(); - } - } - break; - case 'r': - switch (t[1]) - { - case 'c': - first = parse_reinterpret_cast_expr(first, last, db); - break; - case 'm': - t = parse_binary_expression(first+2, last, "%", db); - if (t != first+2) - first = t; - break; - case 'M': - t = parse_binary_expression(first+2, last, "%=", db); - if (t != first+2) - first = t; - break; - case 's': - t = parse_binary_expression(first+2, last, ">>", db); - if (t != first+2) - first = t; - break; - case 'S': - t = parse_binary_expression(first+2, last, ">>=", db); - if (t != first+2) - first = t; - break; - } - break; - case 's': - switch (t[1]) - { - case 'c': - first = parse_static_cast_expr(first, last, db); - break; - case 'p': - first = parse_pack_expansion(first, last, db); - break; - case 'r': - return parse_unresolved_name(first, last, db); - case 't': - first = parse_sizeof_type_expr(first, last, db); - break; - case 'z': - first = parse_sizeof_expr_expr(first, last, db); - break; - case 'Z': - if (last - t >= 3) - { - switch (t[2]) - { - case 'T': - first = parse_sizeof_param_pack_expr(first, last, db); - break; - case 'f': - first = parse_sizeof_function_param_pack_expr(first, last, db); - break; - } - } - break; - } + } break; + case 'c': + first = parse_dynamic_cast_expr(first, last, db); + break; + case 'e': + t = parse_prefix_expression(first + 2, last, "*", db); + if (t != first + 2) + first = t; + break; + case 'l': { + const char *t1 = parse_expression(t + 2, last, db); + if (t1 != t + 2) { + if (db.names.empty()) + return first; + db.names.back().first = + (parsed_gs ? typename C::String("::") : typename C::String()) + + "delete " + db.names.back().move_full(); + first = t1; + } + } break; + case 'n': + return parse_unresolved_name(first, last, db); + case 's': + first = parse_dot_star_expr(first, last, db); + break; + case 't': + first = parse_dot_expr(first, last, db); + break; + case 'v': + t = parse_binary_expression(first + 2, last, "/", db); + if (t != first + 2) + first = t; + break; + case 'V': + t = parse_binary_expression(first + 2, last, "/=", db); + if (t != first + 2) + first = t; + break; + } + break; + case 'e': + switch (t[1]) { + case 'o': + t = parse_binary_expression(first + 2, last, "^", db); + if (t != first + 2) + first = t; + break; + case 'O': + t = parse_binary_expression(first + 2, last, "^=", db); + if (t != first + 2) + first = t; + break; + case 'q': + t = parse_binary_expression(first + 2, last, "==", db); + if (t != first + 2) + first = t; + break; + } + break; + case 'g': + switch (t[1]) { + case 'e': + t = parse_binary_expression(first + 2, last, ">=", db); + if (t != first + 2) + first = t; + break; + case 't': + t = parse_binary_expression(first + 2, last, ">", db); + if (t != first + 2) + first = t; + break; + } + break; + case 'i': + if (t[1] == 'x') { + const char *t1 = parse_expression(first + 2, last, db); + if (t1 != first + 2) { + const char *t2 = parse_expression(t1, last, db); + if (t2 != t1) { + if (db.names.size() < 2) + return first; + auto op2 = db.names.back().move_full(); + db.names.pop_back(); + auto op1 = db.names.back().move_full(); + db.names.back() = "(" + op1 + ")[" + op2 + "]"; + first = t2; + } else + db.names.pop_back(); + } + } + break; + case 'l': + switch (t[1]) { + case 'e': + t = parse_binary_expression(first + 2, last, "<=", db); + if (t != first + 2) + first = t; + break; + case 's': + t = parse_binary_expression(first + 2, last, "<<", db); + if (t != first + 2) + first = t; + break; + case 'S': + t = parse_binary_expression(first + 2, last, "<<=", db); + if (t != first + 2) + first = t; + break; + case 't': + t = parse_binary_expression(first + 2, last, "<", db); + if (t != first + 2) + first = t; + break; + } + break; + case 'm': + switch (t[1]) { + case 'i': + t = parse_binary_expression(first + 2, last, "-", db); + if (t != first + 2) + first = t; + break; + case 'I': + t = parse_binary_expression(first + 2, last, "-=", db); + if (t != first + 2) + first = t; + break; + case 'l': + t = parse_binary_expression(first + 2, last, "*", db); + if (t != first + 2) + first = t; + break; + case 'L': + t = parse_binary_expression(first + 2, last, "*=", db); + if (t != first + 2) + first = t; + break; + case 'm': + if (first + 2 != last && first[2] == '_') { + t = parse_prefix_expression(first + 3, last, "--", db); + if (t != first + 3) + first = t; + } else { + const char *t1 = parse_expression(first + 2, last, db); + if (t1 != first + 2) { + if (db.names.empty()) + return first; + db.names.back() = "(" + db.names.back().move_full() + ")--"; + first = t1; + } + } + break; + } + break; + case 'n': + switch (t[1]) { + case 'a': + case 'w': + first = parse_new_expr(first, last, db); + break; + case 'e': + t = parse_binary_expression(first + 2, last, "!=", db); + if (t != first + 2) + first = t; + break; + case 'g': + t = parse_prefix_expression(first + 2, last, "-", db); + if (t != first + 2) + first = t; + break; + case 't': + t = parse_prefix_expression(first + 2, last, "!", db); + if (t != first + 2) + first = t; + break; + case 'x': + t = parse_noexcept_expression(first + 2, last, db); + if (t != first + 2) + first = t; + break; + } + break; + case 'o': + switch (t[1]) { + case 'n': + return parse_unresolved_name(first, last, db); + case 'o': + t = parse_binary_expression(first + 2, last, "||", db); + if (t != first + 2) + first = t; + break; + case 'r': + t = parse_binary_expression(first + 2, last, "|", db); + if (t != first + 2) + first = t; + break; + case 'R': + t = parse_binary_expression(first + 2, last, "|=", db); + if (t != first + 2) + first = t; + break; + } + break; + case 'p': + switch (t[1]) { + case 'm': + t = parse_binary_expression(first + 2, last, "->*", db); + if (t != first + 2) + first = t; + break; + case 'l': + t = parse_binary_expression(first + 2, last, "+", db); + if (t != first + 2) + first = t; + break; + case 'L': + t = parse_binary_expression(first + 2, last, "+=", db); + if (t != first + 2) + first = t; + break; + case 'p': + if (first + 2 != last && first[2] == '_') { + t = parse_prefix_expression(first + 3, last, "++", db); + if (t != first + 3) + first = t; + } else { + const char *t1 = parse_expression(first + 2, last, db); + if (t1 != first + 2) { + if (db.names.empty()) + return first; + db.names.back() = "(" + db.names.back().move_full() + ")++"; + first = t1; + } + } + break; + case 's': + t = parse_prefix_expression(first + 2, last, "+", db); + if (t != first + 2) + first = t; + break; + case 't': + first = parse_arrow_expr(first, last, db); + break; + } + break; + case 'q': + if (t[1] == 'u') { + const char *t1 = parse_expression(first + 2, last, db); + if (t1 != first + 2) { + const char *t2 = parse_expression(t1, last, db); + if (t2 != t1) { + const char *t3 = parse_expression(t2, last, db); + if (t3 != t2) { + if (db.names.size() < 3) + return first; + auto op3 = db.names.back().move_full(); + db.names.pop_back(); + auto op2 = db.names.back().move_full(); + db.names.pop_back(); + auto op1 = db.names.back().move_full(); + db.names.back() = "(" + op1 + ") ? (" + op2 + ") : (" + op3 + ")"; + first = t3; + } else { + db.names.pop_back(); + db.names.pop_back(); + } + } else + db.names.pop_back(); + } + } + break; + case 'r': + switch (t[1]) { + case 'c': + first = parse_reinterpret_cast_expr(first, last, db); + break; + case 'm': + t = parse_binary_expression(first + 2, last, "%", db); + if (t != first + 2) + first = t; + break; + case 'M': + t = parse_binary_expression(first + 2, last, "%=", db); + if (t != first + 2) + first = t; + break; + case 's': + t = parse_binary_expression(first + 2, last, ">>", db); + if (t != first + 2) + first = t; + break; + case 'S': + t = parse_binary_expression(first + 2, last, ">>=", db); + if (t != first + 2) + first = t; + break; + } + break; + case 's': + switch (t[1]) { + case 'c': + first = parse_static_cast_expr(first, last, db); + break; + case 'p': + first = parse_pack_expansion(first, last, db); + break; + case 'r': + return parse_unresolved_name(first, last, db); + case 't': + first = parse_sizeof_type_expr(first, last, db); + break; + case 'z': + first = parse_sizeof_expr_expr(first, last, db); + break; + case 'Z': + if (last - t >= 3) { + switch (t[2]) { + case 'T': + first = parse_sizeof_param_pack_expr(first, last, db); break; - case 't': - switch (t[1]) - { - case 'e': - case 'i': - first = parse_typeid_expr(first, last, db); - break; - case 'r': - db.names.push_back("throw"); - first += 2; - break; - case 'w': - first = parse_throw_expr(first, last, db); - break; - } + case 'f': + first = parse_sizeof_function_param_pack_expr(first, last, db); break; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return parse_unresolved_name(first, last, db); + } } + break; + } + break; + case 't': + switch (t[1]) { + case 'e': + case 'i': + first = parse_typeid_expr(first, last, db); + break; + case 'r': + db.names.push_back("throw"); + first += 2; + break; + case 'w': + first = parse_throw_expr(first, last, db); + break; + } + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return parse_unresolved_name(first, last, db); } - return first; + } + return first; } -// <template-arg> ::= <type> # type or template -// ::= X <expression> E # expression -// ::= <expr-primary> # simple expressions -// ::= J <template-arg>* E # argument pack -// ::= LZ <encoding> E # extension +// <template-arg> ::= <type> # type +// or template +// ::= X <expression> E # +// expression +// ::= <expr-primary> # +// simple expressions +// ::= J <template-arg>* E # +// argument pack +// ::= LZ <encoding> E # +// extension template <class C> -const char* -parse_template_arg(const char* first, const char* last, C& db) -{ - if (first != last) - { - const char* t; - switch (*first) - { - case 'X': - t = parse_expression(first+1, last, db); - if (t != first+1) - { - if (t != last && *t == 'E') - first = t+1; - } - break; - case 'J': - t = first+1; - if (t == last) - return first; - while (*t != 'E') - { - const char* t1 = parse_template_arg(t, last, db); - if (t1 == t) - return first; - t = t1; - } - first = t+1; - break; - case 'L': - // <expr-primary> or LZ <encoding> E - if (first+1 != last && first[1] == 'Z') - { - t = parse_encoding(first+2, last, db); - if (t != first+2 && t != last && *t == 'E') - first = t+1; - } - else - first = parse_expr_primary(first, last, db); - break; - default: - // <type> - first = parse_type(first, last, db); - break; - } +const char *parse_template_arg(const char *first, const char *last, C &db) { + if (first != last) { + const char *t; + switch (*first) { + case 'X': + t = parse_expression(first + 1, last, db); + if (t != first + 1) { + if (t != last && *t == 'E') + first = t + 1; + } + break; + case 'J': + t = first + 1; + if (t == last) + return first; + while (*t != 'E') { + const char *t1 = parse_template_arg(t, last, db); + if (t1 == t) + return first; + t = t1; + } + first = t + 1; + break; + case 'L': + // <expr-primary> or LZ <encoding> E + if (first + 1 != last && first[1] == 'Z') { + t = parse_encoding(first + 2, last, db); + if (t != first + 2 && t != last && *t == 'E') + first = t + 1; + } else + first = parse_expr_primary(first, last, db); + break; + default: + // <type> + first = parse_type(first, last, db); + break; } - return first; + } + return first; } // <template-args> ::= I <template-arg>* E // extension, the abi says <template-arg>+ template <class C> -const char* -parse_template_args(const char* first, const char* last, C& db) -{ - if (last - first >= 2 && *first == 'I') - { - if (db.tag_templates) - db.template_param.back().clear(); - const char* t = first+1; - typename C::String args("<"); - while (*t != 'E') - { - if (db.tag_templates) - db.template_param.emplace_back(db.names.get_allocator()); - size_t k0 = db.names.size(); - const char* t1 = parse_template_arg(t, last, db); - size_t k1 = db.names.size(); - if (db.tag_templates) - db.template_param.pop_back(); - if (t1 == t || t1 == last) - return first; - if (db.tag_templates) - { - db.template_param.back().emplace_back(db.names.get_allocator()); - for (size_t k = k0; k < k1; ++k) - db.template_param.back().back().push_back(db.names[k]); - } - for (size_t k = k0; k < k1; ++k) - { - if (args.size() > 1) - args += ", "; - args += db.names[k].move_full(); - } - for (; k1 != k0; --k1) - db.names.pop_back(); - t = t1; - } - first = t + 1; - if (args.back() != '>') - args += ">"; - else - args += " >"; - db.names.push_back(std::move(args)); - +const char *parse_template_args(const char *first, const char *last, C &db) { + if (last - first >= 2 && *first == 'I') { + if (db.tag_templates) + db.template_param.back().clear(); + const char *t = first + 1; + typename C::String args("<"); + while (*t != 'E') { + if (db.tag_templates) + db.template_param.emplace_back(db.names.get_allocator()); + size_t k0 = db.names.size(); + const char *t1 = parse_template_arg(t, last, db); + size_t k1 = db.names.size(); + if (db.tag_templates) + db.template_param.pop_back(); + if (t1 == t || t1 == last) + return first; + if (db.tag_templates) { + db.template_param.back().emplace_back(db.names.get_allocator()); + for (size_t k = k0; k < k1; ++k) + db.template_param.back().back().push_back(db.names[k]); + } + for (size_t k = k0; k < k1; ++k) { + if (args.size() > 1) + args += ", "; + args += db.names[k].move_full(); + } + for (; k1 != k0; --k1) + db.names.pop_back(); + t = t1; } - return first; + first = t + 1; + if (args.back() != '>') + args += ">"; + else + args += " >"; + db.names.push_back(std::move(args)); + } + return first; } -// <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E -// ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E -// +// <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> +// <unqualified-name> E +// ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> +// <template-args> E +// // <prefix> ::= <prefix> <unqualified-name> // ::= <template-prefix> <template-args> // ::= <template-param> @@ -3918,262 +3494,223 @@ parse_template_args(const char* first, const char* last, C& db) // ::= <substitution> // ::= <prefix> <data-member-prefix> // extension ::= L -// +// // <template-prefix> ::= <prefix> <template unqualified-name> // ::= <template-param> // ::= <substitution> template <class C> -const char* -parse_nested_name(const char* first, const char* last, C& db, - bool* ends_with_template_args) -{ - if (first != last && *first == 'N') - { - unsigned cv; - const char* t0 = parse_cv_qualifiers(first+1, last, cv); - if (t0 == last) - return first; - db.ref = 0; - if (*t0 == 'R') - { - db.ref = 1; - ++t0; - } - else if (*t0 == 'O') - { - db.ref = 2; - ++t0; - } - db.names.emplace_back(); - if (last - t0 >= 2 && t0[0] == 'S' && t0[1] == 't') - { - t0 += 2; - db.names.back().first = "std"; - } - if (t0 == last) - { - db.names.pop_back(); - return first; - } - bool pop_subs = false; - bool component_ends_with_template_args = false; - while (*t0 != 'E') - { - component_ends_with_template_args = false; - const char* t1; - switch (*t0) - { - case 'S': - if (t0 + 1 != last && t0[1] == 't') - goto do_parse_unqualified_name; - t1 = parse_substitution(t0, last, db); - if (t1 != t0 && t1 != last) - { - auto name = db.names.back().move_full(); - db.names.pop_back(); - if (!db.names.back().first.empty()) - { - db.names.back().first += "::" + name; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - } - else - db.names.back().first = name; - pop_subs = true; - t0 = t1; - } - else - return first; - break; - case 'T': - t1 = parse_template_param(t0, last, db); - if (t1 != t0 && t1 != last) - { - auto name = db.names.back().move_full(); - db.names.pop_back(); - if (!db.names.back().first.empty()) - db.names.back().first += "::" + name; - else - db.names.back().first = name; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - pop_subs = true; - t0 = t1; - } - else - return first; - break; - case 'D': - if (t0 + 1 != last && t0[1] != 't' && t0[1] != 'T') - goto do_parse_unqualified_name; - t1 = parse_decltype(t0, last, db); - if (t1 != t0 && t1 != last) - { - auto name = db.names.back().move_full(); - db.names.pop_back(); - if (!db.names.back().first.empty()) - db.names.back().first += "::" + name; - else - db.names.back().first = name; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - pop_subs = true; - t0 = t1; - } - else - return first; - break; - case 'I': - t1 = parse_template_args(t0, last, db); - if (t1 != t0 && t1 != last) - { - auto name = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += name; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - t0 = t1; - component_ends_with_template_args = true; - } - else - return first; - break; - case 'L': - if (++t0 == last) - return first; - break; - default: - do_parse_unqualified_name: - t1 = parse_unqualified_name(t0, last, db); - if (t1 != t0 && t1 != last) - { - auto name = db.names.back().move_full(); - db.names.pop_back(); - if (!db.names.back().first.empty()) - db.names.back().first += "::" + name; - else - db.names.back().first = name; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - pop_subs = true; - t0 = t1; - } - else - return first; - } - } - first = t0 + 1; - db.cv = cv; - if (pop_subs && !db.subs.empty()) - db.subs.pop_back(); - if (ends_with_template_args) - *ends_with_template_args = component_ends_with_template_args; +const char *parse_nested_name(const char *first, const char *last, C &db, + bool *ends_with_template_args) { + if (first != last && *first == 'N') { + unsigned cv; + const char *t0 = parse_cv_qualifiers(first + 1, last, cv); + if (t0 == last) + return first; + db.ref = 0; + if (*t0 == 'R') { + db.ref = 1; + ++t0; + } else if (*t0 == 'O') { + db.ref = 2; + ++t0; } - return first; + db.names.emplace_back(); + if (last - t0 >= 2 && t0[0] == 'S' && t0[1] == 't') { + t0 += 2; + db.names.back().first = "std"; + } + if (t0 == last) { + db.names.pop_back(); + return first; + } + bool pop_subs = false; + bool component_ends_with_template_args = false; + while (*t0 != 'E') { + component_ends_with_template_args = false; + const char *t1; + switch (*t0) { + case 'S': + if (t0 + 1 != last && t0[1] == 't') + goto do_parse_unqualified_name; + t1 = parse_substitution(t0, last, db); + if (t1 != t0 && t1 != last) { + auto name = db.names.back().move_full(); + db.names.pop_back(); + if (!db.names.back().first.empty()) { + db.names.back().first += "::" + name; + db.subs.push_back(typename C::sub_type(1, db.names.back(), + db.names.get_allocator())); + } else + db.names.back().first = name; + pop_subs = true; + t0 = t1; + } else + return first; + break; + case 'T': + t1 = parse_template_param(t0, last, db); + if (t1 != t0 && t1 != last) { + auto name = db.names.back().move_full(); + db.names.pop_back(); + if (!db.names.back().first.empty()) + db.names.back().first += "::" + name; + else + db.names.back().first = name; + db.subs.push_back(typename C::sub_type(1, db.names.back(), + db.names.get_allocator())); + pop_subs = true; + t0 = t1; + } else + return first; + break; + case 'D': + if (t0 + 1 != last && t0[1] != 't' && t0[1] != 'T') + goto do_parse_unqualified_name; + t1 = parse_decltype(t0, last, db); + if (t1 != t0 && t1 != last) { + auto name = db.names.back().move_full(); + db.names.pop_back(); + if (!db.names.back().first.empty()) + db.names.back().first += "::" + name; + else + db.names.back().first = name; + db.subs.push_back(typename C::sub_type(1, db.names.back(), + db.names.get_allocator())); + pop_subs = true; + t0 = t1; + } else + return first; + break; + case 'I': + t1 = parse_template_args(t0, last, db); + if (t1 != t0 && t1 != last) { + auto name = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += name; + db.subs.push_back(typename C::sub_type(1, db.names.back(), + db.names.get_allocator())); + t0 = t1; + component_ends_with_template_args = true; + } else + return first; + break; + case 'L': + if (++t0 == last) + return first; + break; + default: + do_parse_unqualified_name: + t1 = parse_unqualified_name(t0, last, db); + if (t1 != t0 && t1 != last) { + auto name = db.names.back().move_full(); + db.names.pop_back(); + if (!db.names.back().first.empty()) + db.names.back().first += "::" + name; + else + db.names.back().first = name; + db.subs.push_back(typename C::sub_type(1, db.names.back(), + db.names.get_allocator())); + pop_subs = true; + t0 = t1; + } else + return first; + } + } + first = t0 + 1; + db.cv = cv; + if (pop_subs && !db.subs.empty()) + db.subs.pop_back(); + if (ends_with_template_args) + *ends_with_template_args = component_ends_with_template_args; + } + return first; } // <discriminator> := _ <non-negative number> # when number < 10 // := __ <non-negative number> _ # when number >= 10 // extension := decimal-digit+ -const char* -parse_discriminator(const char* first, const char* last) -{ - // parse but ignore discriminator - if (first != last) - { - if (*first == '_') - { - const char* t1 = first+1; - if (t1 != last) - { - if (std::isdigit(*t1)) - first = t1+1; - else if (*t1 == '_') - { - for (++t1; t1 != last && std::isdigit(*t1); ++t1) - ; - if (t1 != last && *t1 == '_') - first = t1 + 1; - } - } - } - else if (std::isdigit(*first)) - { - const char* t1 = first+1; - for (; t1 != last && std::isdigit(*t1); ++t1) - ; - first = t1; +const char *parse_discriminator(const char *first, const char *last) { + // parse but ignore discriminator + if (first != last) { + if (*first == '_') { + const char *t1 = first + 1; + if (t1 != last) { + if (std::isdigit(*t1)) + first = t1 + 1; + else if (*t1 == '_') { + for (++t1; t1 != last && std::isdigit(*t1); ++t1) + ; + if (t1 != last && *t1 == '_') + first = t1 + 1; } + } + } else if (std::isdigit(*first)) { + const char *t1 = first + 1; + for (; t1 != last && std::isdigit(*t1); ++t1) + ; + first = t1; } - return first; + } + return first; } // <local-name> := Z <function encoding> E <entity name> [<discriminator>] // := Z <function encoding> E s [<discriminator>] -// := Z <function encoding> Ed [ <parameter number> ] _ <entity name> +// := Z <function encoding> Ed [ <parameter number> ] _ <entity +// name> template <class C> -const char* -parse_local_name(const char* first, const char* last, C& db, - bool* ends_with_template_args) -{ - if (first != last && *first == 'Z') - { - const char* t = parse_encoding(first+1, last, db); - if (t != first+1 && t != last && *t == 'E' && ++t != last) - { - switch (*t) - { - case 's': - first = parse_discriminator(t+1, last); - if (db.names.empty()) - return first; - db.names.back().first.append("::string literal"); - break; - case 'd': - if (++t != last) - { - const char* t1 = parse_number(t, last); - if (t1 != last && *t1 == '_') - { - t = t1 + 1; - t1 = parse_name(t, last, db, - ends_with_template_args); - if (t1 != t) - { - if (db.names.size() < 2) - return first; - auto name = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first.append("::"); - db.names.back().first.append(name); - first = t1; - } - else - db.names.pop_back(); - } - } - break; - default: - { - const char* t1 = parse_name(t, last, db, - ends_with_template_args); - if (t1 != t) - { - // parse but ignore discriminator - first = parse_discriminator(t1, last); - if (db.names.size() < 2) - return first; - auto name = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first.append("::"); - db.names.back().first.append(name); - } - else - db.names.pop_back(); - } - break; - } +const char *parse_local_name(const char *first, const char *last, C &db, + bool *ends_with_template_args) { + if (first != last && *first == 'Z') { + const char *t = parse_encoding(first + 1, last, db); + if (t != first + 1 && t != last && *t == 'E' && ++t != last) { + switch (*t) { + case 's': + first = parse_discriminator(t + 1, last); + if (db.names.empty()) + return first; + db.names.back().first.append("::string literal"); + break; + case 'd': + if (++t != last) { + const char *t1 = parse_number(t, last); + if (t1 != last && *t1 == '_') { + t = t1 + 1; + t1 = parse_name(t, last, db, ends_with_template_args); + if (t1 != t) { + if (db.names.size() < 2) + return first; + auto name = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first.append("::"); + db.names.back().first.append(name); + first = t1; + } else + db.names.pop_back(); + } } + break; + default: { + const char *t1 = parse_name(t, last, db, ends_with_template_args); + if (t1 != t) { + // parse but ignore discriminator + first = parse_discriminator(t1, last); + if (db.names.size() < 2) + return first; + auto name = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first.append("::"); + db.names.back().first.append(name); + } else + db.names.pop_back(); + } break; + } } - return first; + } + return first; } // <name> ::= <nested-name> // N @@ -4185,125 +3722,102 @@ parse_local_name(const char* first, const char* last, C& db, // ::= <substitution> template <class C> -const char* -parse_name(const char* first, const char* last, C& db, - bool* ends_with_template_args) -{ - if (last - first >= 2) - { - const char* t0 = first; - // extension: ignore L here - if (*t0 == 'L') - ++t0; - switch (*t0) +const char *parse_name(const char *first, const char *last, C &db, + bool *ends_with_template_args) { + if (last - first >= 2) { + const char *t0 = first; + // extension: ignore L here + if (*t0 == 'L') + ++t0; + switch (*t0) { + case 'N': { + const char *t1 = parse_nested_name(t0, last, db, ends_with_template_args); + if (t1 != t0) + first = t1; + break; + } + case 'Z': { + const char *t1 = parse_local_name(t0, last, db, ends_with_template_args); + if (t1 != t0) + first = t1; + break; + } + default: { + const char *t1 = parse_unscoped_name(t0, last, db); + if (t1 != t0) { + if (t1 != last && + *t1 == 'I') // <unscoped-template-name> <template-args> { - case 'N': - { - const char* t1 = parse_nested_name(t0, last, db, - ends_with_template_args); - if (t1 != t0) - first = t1; - break; - } - case 'Z': - { - const char* t1 = parse_local_name(t0, last, db, - ends_with_template_args); - if (t1 != t0) - first = t1; - break; + if (db.names.empty()) + return first; + db.subs.push_back(typename C::sub_type(1, db.names.back(), + db.names.get_allocator())); + t0 = t1; + t1 = parse_template_args(t0, last, db); + if (t1 != t0) { + if (db.names.size() < 2) + return first; + auto tmp = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += tmp; + first = t1; + if (ends_with_template_args) + *ends_with_template_args = true; } - default: - { - const char* t1 = parse_unscoped_name(t0, last, db); - if (t1 != t0) - { - if (t1 != last && *t1 == 'I') // <unscoped-template-name> <template-args> - { - if (db.names.empty()) - return first; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - t0 = t1; - t1 = parse_template_args(t0, last, db); - if (t1 != t0) - { - if (db.names.size() < 2) - return first; - auto tmp = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += tmp; - first = t1; - if (ends_with_template_args) - *ends_with_template_args = true; - } - } - else // <unscoped-name> - first = t1; - } - else - { // try <substitution> <template-args> - t1 = parse_substitution(t0, last, db); - if (t1 != t0 && t1 != last && *t1 == 'I') - { - t0 = t1; - t1 = parse_template_args(t0, last, db); - if (t1 != t0) - { - if (db.names.size() < 2) - return first; - auto tmp = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += tmp; - first = t1; - if (ends_with_template_args) - *ends_with_template_args = true; - } - } - } - break; + } else // <unscoped-name> + first = t1; + } else { // try <substitution> <template-args> + t1 = parse_substitution(t0, last, db); + if (t1 != t0 && t1 != last && *t1 == 'I') { + t0 = t1; + t1 = parse_template_args(t0, last, db); + if (t1 != t0) { + if (db.names.size() < 2) + return first; + auto tmp = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first += tmp; + first = t1; + if (ends_with_template_args) + *ends_with_template_args = true; } } + } + break; + } } - return first; + } + return first; } // <call-offset> ::= h <nv-offset> _ // ::= v <v-offset> _ -// +// // <nv-offset> ::= <offset number> // # non-virtual base override -// +// // <v-offset> ::= <offset number> _ <virtual offset number> // # virtual base override, with vcall offset -const char* -parse_call_offset(const char* first, const char* last) -{ - if (first != last) - { - switch (*first) - { - case 'h': - { - const char* t = parse_number(first + 1, last); - if (t != first + 1 && t != last && *t == '_') - first = t + 1; - } - break; - case 'v': - { - const char* t = parse_number(first + 1, last); - if (t != first + 1 && t != last && *t == '_') - { - const char* t2 = parse_number(++t, last); - if (t2 != t && t2 != last && *t2 == '_') - first = t2 + 1; - } - } - break; - } +const char *parse_call_offset(const char *first, const char *last) { + if (first != last) { + switch (*first) { + case 'h': { + const char *t = parse_number(first + 1, last); + if (t != first + 1 && t != last && *t == '_') + first = t + 1; + } break; + case 'v': { + const char *t = parse_number(first + 1, last); + if (t != first + 1 && t != last && *t == '_') { + const char *t2 = parse_number(++t, last); + if (t2 != t && t2 != last && *t2 == '_') + first = t2 + 1; + } + } break; } - return first; + } + return first; } // <special-name> ::= TV <type> # virtual table @@ -4316,185 +3830,161 @@ parse_call_offset(const char* first, const char* last) // # second call-offset is result adjustment // ::= T <call-offset> <base encoding> // # base is the nominal target function of thunk -// ::= GV <object name> # Guard variable for one-time initialization +// ::= GV <object name> # Guard variable for one-time +// initialization // # No <type> -// extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first +// extension ::= TC <first type> <number> _ <second type> # construction +// vtable for second-in-first // extension ::= GR <object name> # reference temporary for object template <class C> -const char* -parse_special_name(const char* first, const char* last, C& db) -{ - if (last - first > 2) - { - const char* t; - switch (*first) +const char *parse_special_name(const char *first, const char *last, C &db) { + if (last - first > 2) { + const char *t; + switch (*first) { + case 'T': + switch (first[1]) { + case 'V': + // TV <type> # virtual table + t = parse_type(first + 2, last, db); + if (t != first + 2) { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "vtable for "); + first = t; + } + break; + case 'T': + // TT <type> # VTT structure (construction vtable index) + t = parse_type(first + 2, last, db); + if (t != first + 2) { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "VTT for "); + first = t; + } + break; + case 'I': + // TI <type> # typeinfo structure + t = parse_type(first + 2, last, db); + if (t != first + 2) { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "typeinfo for "); + first = t; + } + break; + case 'S': + // TS <type> # typeinfo name (null-terminated byte string) + t = parse_type(first + 2, last, db); + if (t != first + 2) { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "typeinfo name for "); + first = t; + } + break; + case 'c': + // Tc <call-offset> <call-offset> <base encoding> { - case 'T': - switch (first[1]) - { - case 'V': - // TV <type> # virtual table - t = parse_type(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "vtable for "); - first = t; - } - break; - case 'T': - // TT <type> # VTT structure (construction vtable index) - t = parse_type(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "VTT for "); - first = t; - } - break; - case 'I': - // TI <type> # typeinfo structure - t = parse_type(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "typeinfo for "); - first = t; - } - break; - case 'S': - // TS <type> # typeinfo name (null-terminated byte string) - t = parse_type(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "typeinfo name for "); - first = t; - } - break; - case 'c': - // Tc <call-offset> <call-offset> <base encoding> - { - const char* t0 = parse_call_offset(first+2, last); - if (t0 == first+2) - break; - const char* t1 = parse_call_offset(t0, last); - if (t1 == t0) - break; - t = parse_encoding(t1, last, db); - if (t != t1) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "covariant return thunk to "); - first = t; - } - } - break; - case 'C': - // extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first - t = parse_type(first+2, last, db); - if (t != first+2) - { - const char* t0 = parse_number(t, last); - if (t0 != t && t0 != last && *t0 == '_') - { - const char* t1 = parse_type(++t0, last, db); - if (t1 != t0) - { - if (db.names.size() < 2) - return first; - auto left = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first = "construction vtable for " + - std::move(left) + "-in-" + - db.names.back().move_full(); - first = t1; - } - } - } - break; - default: - // T <call-offset> <base encoding> - { - const char* t0 = parse_call_offset(first+1, last); - if (t0 == first+1) - break; - t = parse_encoding(t0, last, db); - if (t != t0) - { - if (db.names.empty()) - return first; - if (first[2] == 'v') - { - db.names.back().first.insert(0, "virtual thunk to "); - first = t; - } - else - { - db.names.back().first.insert(0, "non-virtual thunk to "); - first = t; - } - } - } - break; - } + const char *t0 = parse_call_offset(first + 2, last); + if (t0 == first + 2) break; - case 'G': - switch (first[1]) - { - case 'V': - // GV <object name> # Guard variable for one-time initialization - t = parse_name(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "guard variable for "); - first = t; - } - break; - case 'R': - // extension ::= GR <object name> # reference temporary for object - t = parse_name(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "reference temporary for "); - first = t; - } - break; + const char *t1 = parse_call_offset(t0, last); + if (t1 == t0) + break; + t = parse_encoding(t1, last, db); + if (t != t1) { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "covariant return thunk to "); + first = t; + } + } + break; + case 'C': + // extension ::= TC <first type> <number> _ <second type> # construction + // vtable for second-in-first + t = parse_type(first + 2, last, db); + if (t != first + 2) { + const char *t0 = parse_number(t, last); + if (t0 != t && t0 != last && *t0 == '_') { + const char *t1 = parse_type(++t0, last, db); + if (t1 != t0) { + if (db.names.size() < 2) + return first; + auto left = db.names.back().move_full(); + db.names.pop_back(); + db.names.back().first = "construction vtable for " + + std::move(left) + "-in-" + + db.names.back().move_full(); + first = t1; } + } + } + break; + default: + // T <call-offset> <base encoding> + { + const char *t0 = parse_call_offset(first + 1, last); + if (t0 == first + 1) break; + t = parse_encoding(t0, last, db); + if (t != t0) { + if (db.names.empty()) + return first; + if (first[2] == 'v') { + db.names.back().first.insert(0, "virtual thunk to "); + first = t; + } else { + db.names.back().first.insert(0, "non-virtual thunk to "); + first = t; + } + } + } + break; + } + break; + case 'G': + switch (first[1]) { + case 'V': + // GV <object name> # Guard variable for one-time initialization + t = parse_name(first + 2, last, db); + if (t != first + 2) { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "guard variable for "); + first = t; + } + break; + case 'R': + // extension ::= GR <object name> # reference temporary for object + t = parse_name(first + 2, last, db); + if (t != first + 2) { + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "reference temporary for "); + first = t; } + break; + } + break; } - return first; + } + return first; } -template <class T> -class save_value -{ - T& restore_; - T original_value_; +template <class T> class save_value { + T &restore_; + T original_value_; + public: - save_value(T& restore) - : restore_(restore), - original_value_(restore) - {} - - ~save_value() - { - restore_ = std::move(original_value_); - } + save_value(T &restore) : restore_(restore), original_value_(restore) {} + + ~save_value() { restore_ = std::move(original_value_); } - save_value(const save_value&) = delete; - save_value& operator=(const save_value&) = delete; + save_value(const save_value &) = delete; + save_value &operator=(const save_value &) = delete; }; // <encoding> ::= <function name> <bare-function-type> @@ -4502,121 +3992,104 @@ public: // ::= <special-name> template <class C> -const char* -parse_encoding(const char* first, const char* last, C& db) -{ - if (first != last) - { - save_value<decltype(db.encoding_depth)> su(db.encoding_depth); - ++db.encoding_depth; - save_value<decltype(db.tag_templates)> sb(db.tag_templates); - if (db.encoding_depth > 1) - db.tag_templates = true; - switch (*first) - { - case 'G': - case 'T': - first = parse_special_name(first, last, db); - break; - default: - { - bool ends_with_template_args = false; - const char* t = parse_name(first, last, db, - &ends_with_template_args); - unsigned cv = db.cv; - unsigned ref = db.ref; - if (t != first) - { - if (t != last && *t != 'E' && *t != '.') - { - save_value<bool> sb2(db.tag_templates); - db.tag_templates = false; - const char* t2; - typename C::String ret2; - if (db.names.empty()) - return first; - const typename C::String& nm = db.names.back().first; - if (nm.empty()) - return first; - if (!db.parsed_ctor_dtor_cv && ends_with_template_args) - { - t2 = parse_type(t, last, db); - if (t2 == t) - return first; - if (db.names.size() < 2) - return first; - auto ret1 = std::move(db.names.back().first); - ret2 = std::move(db.names.back().second); - if (ret2.empty()) - ret1 += ' '; - db.names.pop_back(); - db.names.back().first.insert(0, ret1); - t = t2; - } - db.names.back().first += '('; - if (t != last && *t == 'v') - { - ++t; - } - else - { - bool first_arg = true; - while (true) - { - size_t k0 = db.names.size(); - t2 = parse_type(t, last, db); - size_t k1 = db.names.size(); - if (t2 == t) - break; - if (k1 > k0) - { - typename C::String tmp; - for (size_t k = k0; k < k1; ++k) - { - if (!tmp.empty()) - tmp += ", "; - tmp += db.names[k].move_full(); - } - for (size_t k = k0; k < k1; ++k) - db.names.pop_back(); - if (!tmp.empty()) - { - if (db.names.empty()) - return first; - if (!first_arg) - db.names.back().first += ", "; - else - first_arg = false; - db.names.back().first += tmp; - } - } - t = t2; - } - } - if (db.names.empty()) - return first; - db.names.back().first += ')'; - if (cv & 1) - db.names.back().first.append(" const"); - if (cv & 2) - db.names.back().first.append(" volatile"); - if (cv & 4) - db.names.back().first.append(" restrict"); - if (ref == 1) - db.names.back().first.append(" &"); - else if (ref == 2) - db.names.back().first.append(" &&"); - db.names.back().first += ret2; - first = t; +const char *parse_encoding(const char *first, const char *last, C &db) { + if (first != last) { + save_value<decltype(db.encoding_depth)> su(db.encoding_depth); + ++db.encoding_depth; + save_value<decltype(db.tag_templates)> sb(db.tag_templates); + if (db.encoding_depth > 1) + db.tag_templates = true; + switch (*first) { + case 'G': + case 'T': + first = parse_special_name(first, last, db); + break; + default: { + bool ends_with_template_args = false; + const char *t = parse_name(first, last, db, &ends_with_template_args); + unsigned cv = db.cv; + unsigned ref = db.ref; + if (t != first) { + if (t != last && *t != 'E' && *t != '.') { + save_value<bool> sb2(db.tag_templates); + db.tag_templates = false; + const char *t2; + typename C::String ret2; + if (db.names.empty()) + return first; + const typename C::String &nm = db.names.back().first; + if (nm.empty()) + return first; + if (!db.parsed_ctor_dtor_cv && ends_with_template_args) { + t2 = parse_type(t, last, db); + if (t2 == t) + return first; + if (db.names.size() < 2) + return first; + auto ret1 = std::move(db.names.back().first); + ret2 = std::move(db.names.back().second); + if (ret2.empty()) + ret1 += ' '; + db.names.pop_back(); + db.names.back().first.insert(0, ret1); + t = t2; + } + db.names.back().first += '('; + if (t != last && *t == 'v') { + ++t; + } else { + bool first_arg = true; + while (true) { + size_t k0 = db.names.size(); + t2 = parse_type(t, last, db); + size_t k1 = db.names.size(); + if (t2 == t) + break; + if (k1 > k0) { + typename C::String tmp; + for (size_t k = k0; k < k1; ++k) { + if (!tmp.empty()) + tmp += ", "; + tmp += db.names[k].move_full(); + } + for (size_t k = k0; k < k1; ++k) + db.names.pop_back(); + if (!tmp.empty()) { + if (db.names.empty()) + return first; + if (!first_arg) + db.names.back().first += ", "; + else + first_arg = false; + db.names.back().first += tmp; } - else - first = t; + } + t = t2; } - break; } - } + if (db.names.empty()) + return first; + db.names.back().first += ')'; + if (cv & 1) + db.names.back().first.append(" const"); + if (cv & 2) + db.names.back().first.append(" volatile"); + if (cv & 4) + db.names.back().first.append(" restrict"); + if (ref == 1) + db.names.back().first.append(" &"); + else if (ref == 2) + db.names.back().first.append(" &&"); + db.names.back().first += ret2; + first = t; + } else + first = t; + } + break; } - return first; + } + } + return first; } // _block_invoke @@ -4624,54 +4097,45 @@ parse_encoding(const char* first, const char* last, C& db) // _block_invoke_<decimal-digit>+ template <class C> -const char* -parse_block_invoke(const char* first, const char* last, C& db) -{ - if (last - first >= 13) - { - const char test[] = "_block_invoke"; - const char* t = first; - for (int i = 0; i < 13; ++i, ++t) - { - if (*t != test[i]) - return first; - } - if (t != last) - { - if (*t == '_') - { - // must have at least 1 decimal digit - if (++t == last || !std::isdigit(*t)) - return first; - ++t; - } - // parse zero or more digits - while (t != last && isdigit(*t)) - ++t; - } - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "invocation function for block in "); - first = t; +const char *parse_block_invoke(const char *first, const char *last, C &db) { + if (last - first >= 13) { + const char test[] = "_block_invoke"; + const char *t = first; + for (int i = 0; i < 13; ++i, ++t) { + if (*t != test[i]) + return first; + } + if (t != last) { + if (*t == '_') { + // must have at least 1 decimal digit + if (++t == last || !std::isdigit(*t)) + return first; + ++t; + } + // parse zero or more digits + while (t != last && isdigit(*t)) + ++t; } - return first; + if (db.names.empty()) + return first; + db.names.back().first.insert(0, "invocation function for block in "); + first = t; + } + return first; } // extension // <dot-suffix> := .<anything and everything> template <class C> -const char* -parse_dot_suffix(const char* first, const char* last, C& db) -{ - if (first != last && *first == '.') - { - if (db.names.empty()) - return first; - db.names.back().first += " (" + typename C::String(first, last) + ")"; - first = last; - } - return first; +const char *parse_dot_suffix(const char *first, const char *last, C &db) { + if (first != last && *first == '.') { + if (db.names.empty()) + return first; + db.names.back().first += " (" + typename C::String(first, last) + ")"; + first = last; + } + return first; } // <block-involcaton-function> ___Z<encoding>_block_invoke @@ -4681,333 +4145,258 @@ parse_dot_suffix(const char* first, const char* last, C& db) // ::= <type> template <class C> -void -demangle(const char* first, const char* last, C& db, int& status) -{ - if (first >= last) - { - status = invalid_mangled_name; - return; - } - if (*first == '_') - { - if (last - first >= 4) - { - if (first[1] == 'Z') - { - const char* t = parse_encoding(first+2, last, db); - if (t != first+2 && t != last && *t == '.') - t = parse_dot_suffix(t, last, db); - if (t != last) - status = invalid_mangled_name; - } - else if (first[1] == '_' && first[2] == '_' && first[3] == 'Z') - { - const char* t = parse_encoding(first+4, last, db); - if (t != first+4 && t != last) - { - const char* t1 = parse_block_invoke(t, last, db); - if (t1 != last) - status = invalid_mangled_name; - } - else - status = invalid_mangled_name; - } - else - status = invalid_mangled_name; - } - else - status = invalid_mangled_name; - } - else - { - const char* t = parse_type(first, last, db); +void demangle(const char *first, const char *last, C &db, int &status) { + if (first >= last) { + status = invalid_mangled_name; + return; + } + if (*first == '_') { + if (last - first >= 4) { + if (first[1] == 'Z') { + const char *t = parse_encoding(first + 2, last, db); + if (t != first + 2 && t != last && *t == '.') + t = parse_dot_suffix(t, last, db); if (t != last) + status = invalid_mangled_name; + } else if (first[1] == '_' && first[2] == '_' && first[3] == 'Z') { + const char *t = parse_encoding(first + 4, last, db); + if (t != first + 4 && t != last) { + const char *t1 = parse_block_invoke(t, last, db); + if (t1 != last) status = invalid_mangled_name; - } - if (status == success && db.names.empty()) + } else + status = invalid_mangled_name; + } else status = invalid_mangled_name; + } else + status = invalid_mangled_name; + } else { + const char *t = parse_type(first, last, db); + if (t != last) + status = invalid_mangled_name; + } + if (status == success && db.names.empty()) + status = invalid_mangled_name; } -template <std::size_t N> -class arena -{ - static const std::size_t alignment = 16; - LLVM_ALIGNAS(16) char buf_[N]; - char* ptr_; +template <std::size_t N> class arena { + static const std::size_t alignment = 16; + LLVM_ALIGNAS(16) char buf_[N]; + char *ptr_; - std::size_t - align_up(std::size_t n) LLVM_NOEXCEPT - {return (n + (alignment-1)) & ~(alignment-1);} + std::size_t align_up(std::size_t n) LLVM_NOEXCEPT { + return (n + (alignment - 1)) & ~(alignment - 1); + } - bool - pointer_in_buffer(char* p) LLVM_NOEXCEPT - {return buf_ <= p && p <= buf_ + N;} + bool pointer_in_buffer(char *p) LLVM_NOEXCEPT { + return buf_ <= p && p <= buf_ + N; + } public: - arena() LLVM_NOEXCEPT : ptr_(buf_) {} - ~arena() {ptr_ = nullptr;} - arena(const arena&) = delete; - arena& operator=(const arena&) = delete; + arena() LLVM_NOEXCEPT : ptr_(buf_) {} + ~arena() { ptr_ = nullptr; } + arena(const arena &) = delete; + arena &operator=(const arena &) = delete; - char* allocate(std::size_t n); - void deallocate(char* p, std::size_t n) LLVM_NOEXCEPT; + char *allocate(std::size_t n); + void deallocate(char *p, std::size_t n) LLVM_NOEXCEPT; - static LLVM_CONSTEXPR std::size_t size() {return N;} - std::size_t used() const {return static_cast<std::size_t>(ptr_ - buf_);} - void reset() {ptr_ = buf_;} + static LLVM_CONSTEXPR std::size_t size() { return N; } + std::size_t used() const { return static_cast<std::size_t>(ptr_ - buf_); } + void reset() { ptr_ = buf_; } }; -template <std::size_t N> -char* -arena<N>::allocate(std::size_t n) -{ - n = align_up(n); - if (static_cast<std::size_t>(buf_ + N - ptr_) >= n) - { - char* r = ptr_; - ptr_ += n; - return r; - } - return static_cast<char*>(std::malloc(n)); +template <std::size_t N> char *arena<N>::allocate(std::size_t n) { + n = align_up(n); + if (static_cast<std::size_t>(buf_ + N - ptr_) >= n) { + char *r = ptr_; + ptr_ += n; + return r; + } + return static_cast<char *>(std::malloc(n)); } template <std::size_t N> -void -arena<N>::deallocate(char* p, std::size_t n) LLVM_NOEXCEPT -{ - if (pointer_in_buffer(p)) - { - n = align_up(n); - if (p + n == ptr_) - ptr_ = p; - } - else - std::free(p); +void arena<N>::deallocate(char *p, std::size_t n) LLVM_NOEXCEPT { + if (pointer_in_buffer(p)) { + n = align_up(n); + if (p + n == ptr_) + ptr_ = p; + } else + std::free(p); } -template <class T, std::size_t N> -class short_alloc -{ - arena<N>& a_; -public: - typedef T value_type; +template <class T, std::size_t N> class short_alloc { + arena<N> &a_; public: - template <class _Up> struct rebind {typedef short_alloc<_Up, N> other;}; - - short_alloc(arena<N>& a) LLVM_NOEXCEPT : a_(a) {} - template <class U> - short_alloc(const short_alloc<U, N>& a) LLVM_NOEXCEPT - : a_(a.a_) {} - short_alloc(const short_alloc&) = default; - short_alloc& operator=(const short_alloc&) = delete; - - T* allocate(std::size_t n) - { - return reinterpret_cast<T*>(a_.allocate(n*sizeof(T))); - } - void deallocate(T* p, std::size_t n) LLVM_NOEXCEPT - { - a_.deallocate(reinterpret_cast<char*>(p), n*sizeof(T)); - } - - template <class T1, std::size_t N1, class U, std::size_t M> - friend - bool - operator==(const short_alloc<T1, N1>& x, const short_alloc<U, M>& y) LLVM_NOEXCEPT; + typedef T value_type; - template <class U, std::size_t M> friend class short_alloc; +public: + template <class _Up> struct rebind { typedef short_alloc<_Up, N> other; }; + + short_alloc(arena<N> &a) LLVM_NOEXCEPT : a_(a) {} + template <class U> + short_alloc(const short_alloc<U, N> &a) LLVM_NOEXCEPT : a_(a.a_) {} + short_alloc(const short_alloc &) = default; + short_alloc &operator=(const short_alloc &) = delete; + + T *allocate(std::size_t n) { + return reinterpret_cast<T *>(a_.allocate(n * sizeof(T))); + } + void deallocate(T *p, std::size_t n) LLVM_NOEXCEPT { + a_.deallocate(reinterpret_cast<char *>(p), n * sizeof(T)); + } + + template <class T1, std::size_t N1, class U, std::size_t M> + friend bool operator==(const short_alloc<T1, N1> &x, + const short_alloc<U, M> &y) LLVM_NOEXCEPT; + + template <class U, std::size_t M> friend class short_alloc; }; template <class T, std::size_t N, class U, std::size_t M> -inline -bool -operator==(const short_alloc<T, N>& x, const short_alloc<U, M>& y) LLVM_NOEXCEPT -{ - return N == M && &x.a_ == &y.a_; +inline bool operator==(const short_alloc<T, N> &x, + const short_alloc<U, M> &y) LLVM_NOEXCEPT { + return N == M && &x.a_ == &y.a_; } template <class T, std::size_t N, class U, std::size_t M> -inline -bool -operator!=(const short_alloc<T, N>& x, const short_alloc<U, M>& y) LLVM_NOEXCEPT -{ - return !(x == y); +inline bool operator!=(const short_alloc<T, N> &x, + const short_alloc<U, M> &y) LLVM_NOEXCEPT { + return !(x == y); } -template <class T> -class malloc_alloc -{ +template <class T> class malloc_alloc { public: - typedef T value_type; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef T* pointer; - typedef const T* const_pointer; - typedef T& reference; - typedef const T& const_reference; - - malloc_alloc() = default; - template <class U> malloc_alloc(const malloc_alloc<U>&) LLVM_NOEXCEPT {} - - T* allocate(std::size_t n) - { - return static_cast<T*>(std::malloc(n*sizeof(T))); - } - void deallocate(T* p, std::size_t) LLVM_NOEXCEPT - { - std::free(p); - } - template<class Other> - struct rebind - { - typedef malloc_alloc<Other> other; - }; - void construct(T *p) - { - ::new (p) T(); - } - void construct(T *p, const T& t) - { - ::new (p) T(t); - } - void destroy(T *p) - { - p->~T(); - } + typedef T value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T *pointer; + typedef const T *const_pointer; + typedef T &reference; + typedef const T &const_reference; + + malloc_alloc() = default; + template <class U> malloc_alloc(const malloc_alloc<U> &) LLVM_NOEXCEPT {} + + T *allocate(std::size_t n) { + return static_cast<T *>(std::malloc(n * sizeof(T))); + } + void deallocate(T *p, std::size_t) LLVM_NOEXCEPT { std::free(p); } + template <class Other> struct rebind { typedef malloc_alloc<Other> other; }; + void construct(T *p) { ::new (p) T(); } + void construct(T *p, const T &t) { ::new (p) T(t); } + void destroy(T *p) { p->~T(); } }; template <class T, class U> -inline -bool -operator==(const malloc_alloc<T>&, const malloc_alloc<U>&) LLVM_NOEXCEPT -{ - return true; +inline bool operator==(const malloc_alloc<T> &, + const malloc_alloc<U> &) LLVM_NOEXCEPT { + return true; } template <class T, class U> -inline -bool -operator!=(const malloc_alloc<T>& x, const malloc_alloc<U>& y) LLVM_NOEXCEPT -{ - return !(x == y); +inline bool operator!=(const malloc_alloc<T> &x, + const malloc_alloc<U> &y) LLVM_NOEXCEPT { + return !(x == y); } const size_t bs = 4 * 1024; template <class T> using Alloc = short_alloc<T, bs>; template <class T> using Vector = std::vector<T, Alloc<T>>; -template <class StrT> -struct string_pair -{ - StrT first; - StrT second; - - string_pair() = default; - string_pair(StrT f) : first(std::move(f)) {} - string_pair(StrT f, StrT s) - : first(std::move(f)), second(std::move(s)) {} - template <size_t N> - string_pair(const char (&s)[N]) : first(s, N-1) {} - - size_t size() const {return first.size() + second.size();} - StrT full() const {return first + second;} - StrT move_full() {return std::move(first) + std::move(second);} +template <class StrT> struct string_pair { + StrT first; + StrT second; + + string_pair() = default; + string_pair(StrT f) : first(std::move(f)) {} + string_pair(StrT f, StrT s) : first(std::move(f)), second(std::move(s)) {} + template <size_t N> string_pair(const char (&s)[N]) : first(s, N - 1) {} + + size_t size() const { return first.size() + second.size(); } + StrT full() const { return first + second; } + StrT move_full() { return std::move(first) + std::move(second); } }; -struct Db -{ - typedef std::basic_string<char, std::char_traits<char>, - malloc_alloc<char>> String; - typedef Vector<string_pair<String>> sub_type; - typedef Vector<sub_type> template_param_type; - sub_type names; - template_param_type subs; - Vector<template_param_type> template_param; - unsigned cv; - unsigned ref; - unsigned encoding_depth; - bool parsed_ctor_dtor_cv; - bool tag_templates; - bool fix_forward_references; - bool try_to_parse_template_args; - - template <size_t N> - Db(arena<N>& ar) : - names(ar), - subs(0, names, ar), - template_param(0, subs, ar) - {} +struct Db { + typedef std::basic_string<char, std::char_traits<char>, malloc_alloc<char>> + String; + typedef Vector<string_pair<String>> sub_type; + typedef Vector<sub_type> template_param_type; + sub_type names; + template_param_type subs; + Vector<template_param_type> template_param; + unsigned cv; + unsigned ref; + unsigned encoding_depth; + bool parsed_ctor_dtor_cv; + bool tag_templates; + bool fix_forward_references; + bool try_to_parse_template_args; + + template <size_t N> + Db(arena<N> &ar) + : names(ar), subs(0, names, ar), template_param(0, subs, ar) {} }; -} // unnamed namespace +} // unnamed namespace -char* -__cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status) -{ - if (mangled_name == nullptr || (buf != nullptr && n == nullptr)) - { - if (status) - *status = invalid_args; - return nullptr; - } - size_t internal_size = buf != nullptr ? *n : 0; - arena<bs> a; - Db db(a); - db.cv = 0; - db.ref = 0; - db.encoding_depth = 0; - db.parsed_ctor_dtor_cv = false; - db.tag_templates = true; - db.template_param.emplace_back(a); +char *__cxa_demangle(const char *mangled_name, char *buf, size_t *n, + int *status) { + if (mangled_name == nullptr || (buf != nullptr && n == nullptr)) { + if (status) + *status = invalid_args; + return nullptr; + } + size_t internal_size = buf != nullptr ? *n : 0; + arena<bs> a; + Db db(a); + db.cv = 0; + db.ref = 0; + db.encoding_depth = 0; + db.parsed_ctor_dtor_cv = false; + db.tag_templates = true; + db.template_param.emplace_back(a); + db.fix_forward_references = false; + db.try_to_parse_template_args = true; + int internal_status = success; + size_t len = std::strlen(mangled_name); + demangle(mangled_name, mangled_name + len, db, internal_status); + if (internal_status == success && db.fix_forward_references && + !db.template_param.empty() && !db.template_param.front().empty()) { db.fix_forward_references = false; - db.try_to_parse_template_args = true; - int internal_status = success; - size_t len = std::strlen(mangled_name); - demangle(mangled_name, mangled_name + len, db, - internal_status); - if (internal_status == success && db.fix_forward_references && - !db.template_param.empty() && !db.template_param.front().empty()) - { - db.fix_forward_references = false; - db.tag_templates = false; - db.names.clear(); - db.subs.clear(); - demangle(mangled_name, mangled_name + len, db, internal_status); - if (db.fix_forward_references) - internal_status = invalid_mangled_name; + db.tag_templates = false; + db.names.clear(); + db.subs.clear(); + demangle(mangled_name, mangled_name + len, db, internal_status); + if (db.fix_forward_references) + internal_status = invalid_mangled_name; + } + if (internal_status == success) { + size_t sz = db.names.back().size() + 1; + if (sz > internal_size) { + char *newbuf = static_cast<char *>(std::realloc(buf, sz)); + if (newbuf == nullptr) { + internal_status = memory_alloc_failure; + buf = nullptr; + } else { + buf = newbuf; + if (n != nullptr) + *n = sz; + } } - if (internal_status == success) - { - size_t sz = db.names.back().size() + 1; - if (sz > internal_size) - { - char* newbuf = static_cast<char*>(std::realloc(buf, sz)); - if (newbuf == nullptr) - { - internal_status = memory_alloc_failure; - buf = nullptr; - } - else - { - buf = newbuf; - if (n != nullptr) - *n = sz; - } - } - if (buf != nullptr) - { - db.names.back().first += db.names.back().second; - std::memcpy(buf, db.names.back().first.data(), sz-1); - buf[sz-1] = char(0); - } + if (buf != nullptr) { + db.names.back().first += db.names.back().second; + std::memcpy(buf, db.names.back().first.data(), sz - 1); + buf[sz - 1] = char(0); } - else - buf = nullptr; - if (status) - *status = internal_status; - return buf; + } else + buf = nullptr; + if (status) + *status = internal_status; + return buf; } -} // lldb_private +} // lldb_private |