erik.pilkington created this revision. erik.pilkington added reviewers: EricWF, george.burgess.iv.
This patch adds demangling for pass_object_size attribute (https://clang.llvm.org/docs/AttributeReference.html#pass-object-size). This attribute applies to function parameters. This attribute is mangled as if it was meant to match the <extended-qualifier> production (https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangle.qualified-type), but clang emits it after the type it refers to instead of before. I think this was a mistake, but its probably too late to fix it because of the ABI break. Thanks for taking a look! Erik Repository: rCXXA libc++abi https://reviews.llvm.org/D41261 Files: src/cxa_demangle.cpp test/test_demangle.pass.cpp Index: test/test_demangle.pass.cpp =================================================================== --- test/test_demangle.pass.cpp +++ test/test_demangle.pass.cpp @@ -29611,6 +29611,11 @@ {"_ZN1SB5outer1fB5innerEv", "S[abi:outer]::f[abi:inner]()"}, {"_ZN1SC2B8ctor_tagEv", "S::S[abi:ctor_tag]()"}, {"_ZplB4MERP1SS_", "operator+[abi:MERP](S, S)"}, + // attribute pass_object_size + {"_Z27NoViableOverloadObjectSize0PvU17pass_object_size0", "NoViableOverloadObjectSize0(pass_object_size0 void*)"}, + {"_ZN14noninline_virt1AC2EiO1QPvU17pass_object_size0", "noninline_virt::A::A(int, Q&&, pass_object_size0 void*)"}, + {"_ZZN7lambdas7LambdasEPcENK3$_0clEPvU17pass_object_size0", "lambdas::Lambdas(char*)::$_0::operator()(pass_object_size0 void*) const"}, + {"_ZN8variadic6AsCtorC1EPKcU17pass_object_size0dz", "variadic::AsCtor::AsCtor(pass_object_size0 char const*, double, ...)"}, }; const unsigned N = sizeof(cases) / sizeof(cases[0]); Index: src/cxa_demangle.cpp =================================================================== --- src/cxa_demangle.cpp +++ src/cxa_demangle.cpp @@ -12,6 +12,7 @@ // - enable_if attribute // - decomposition declarations // - C++ modules TS +// - inheriting constructors #define _LIBCPP_NO_EXCEPTIONS @@ -3128,11 +3129,33 @@ return first; } +// Parse a type in the context of a function parameter. Here, the type can be +// optionally followed by a pass_object_size attribute. Unlike other vendor +// extension attributes, clang emits this attribute after the mangling for the +// type it applies to, so we have to special-case it. +// +// <type> ::= <type> U17pass_object_size [0-9] # extension +const char* +parse_function_param_type(const char* first, const char* last, Db& db) +{ + const char* t = parse_type(first, last, db); + if (t != first && StringView(t, last).startsWith("U17pass_object_size")) + { + const char* t2 = t + std::strlen("U17pass_object_size"); + if (t2 != last && *t2 >= '0' && *t2 <= '9' && !db.Names.empty()) + { + db.Names.back() = db.make<VendorExtQualType>( + db.make<NameType>(StringView(t+3, t2+1)), db.Names.back()); + t = t2+1; + } + } + return t; +} + // <ref-qualifier> ::= R # & ref-qualifier // <ref-qualifier> ::= O # && ref-qualifier - -// <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E - +// +// <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E const char* parse_function_type(const char* first, const char* last, Db& db) { @@ -3186,7 +3209,7 @@ continue; } size_t k0 = db.Names.size(); - t1 = parse_type(t, last, db); + t1 = parse_function_param_type(t, last, db); size_t k1 = db.Names.size(); if (t1 == t || t1 == last || k1 < k0) return first; @@ -4454,7 +4477,7 @@ { while (true) { - const char* t1 = parse_type(t0, last, db); + const char* t1 = parse_function_param_type(t0, last, db); if (t1 == t0) break; t0 = t1; @@ -6021,7 +6044,7 @@ size_t params_begin = db.Names.size(); while (true) { - t2 = parse_type(t, last, db); + t2 = parse_function_param_type(t, last, db); if (t2 == t) break; t = t2;
Index: test/test_demangle.pass.cpp =================================================================== --- test/test_demangle.pass.cpp +++ test/test_demangle.pass.cpp @@ -29611,6 +29611,11 @@ {"_ZN1SB5outer1fB5innerEv", "S[abi:outer]::f[abi:inner]()"}, {"_ZN1SC2B8ctor_tagEv", "S::S[abi:ctor_tag]()"}, {"_ZplB4MERP1SS_", "operator+[abi:MERP](S, S)"}, + // attribute pass_object_size + {"_Z27NoViableOverloadObjectSize0PvU17pass_object_size0", "NoViableOverloadObjectSize0(pass_object_size0 void*)"}, + {"_ZN14noninline_virt1AC2EiO1QPvU17pass_object_size0", "noninline_virt::A::A(int, Q&&, pass_object_size0 void*)"}, + {"_ZZN7lambdas7LambdasEPcENK3$_0clEPvU17pass_object_size0", "lambdas::Lambdas(char*)::$_0::operator()(pass_object_size0 void*) const"}, + {"_ZN8variadic6AsCtorC1EPKcU17pass_object_size0dz", "variadic::AsCtor::AsCtor(pass_object_size0 char const*, double, ...)"}, }; const unsigned N = sizeof(cases) / sizeof(cases[0]); Index: src/cxa_demangle.cpp =================================================================== --- src/cxa_demangle.cpp +++ src/cxa_demangle.cpp @@ -12,6 +12,7 @@ // - enable_if attribute // - decomposition declarations // - C++ modules TS +// - inheriting constructors #define _LIBCPP_NO_EXCEPTIONS @@ -3128,11 +3129,33 @@ return first; } +// Parse a type in the context of a function parameter. Here, the type can be +// optionally followed by a pass_object_size attribute. Unlike other vendor +// extension attributes, clang emits this attribute after the mangling for the +// type it applies to, so we have to special-case it. +// +// <type> ::= <type> U17pass_object_size [0-9] # extension +const char* +parse_function_param_type(const char* first, const char* last, Db& db) +{ + const char* t = parse_type(first, last, db); + if (t != first && StringView(t, last).startsWith("U17pass_object_size")) + { + const char* t2 = t + std::strlen("U17pass_object_size"); + if (t2 != last && *t2 >= '0' && *t2 <= '9' && !db.Names.empty()) + { + db.Names.back() = db.make<VendorExtQualType>( + db.make<NameType>(StringView(t+3, t2+1)), db.Names.back()); + t = t2+1; + } + } + return t; +} + // <ref-qualifier> ::= R # & ref-qualifier // <ref-qualifier> ::= O # && ref-qualifier - -// <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E - +// +// <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E const char* parse_function_type(const char* first, const char* last, Db& db) { @@ -3186,7 +3209,7 @@ continue; } size_t k0 = db.Names.size(); - t1 = parse_type(t, last, db); + t1 = parse_function_param_type(t, last, db); size_t k1 = db.Names.size(); if (t1 == t || t1 == last || k1 < k0) return first; @@ -4454,7 +4477,7 @@ { while (true) { - const char* t1 = parse_type(t0, last, db); + const char* t1 = parse_function_param_type(t0, last, db); if (t1 == t0) break; t0 = t1; @@ -6021,7 +6044,7 @@ size_t params_begin = db.Names.size(); while (true) { - t2 = parse_type(t, last, db); + t2 = parse_function_param_type(t, last, db); if (t2 == t) break; t = t2;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits