[PATCH] D41261: [libcxxabi][demangler] Special case demangling for pass_object_size attribute

Erik Pilkington via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 14 15:13:39 PST 2017


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;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D41261.127031.patch
Type: text/x-patch
Size: 3747 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20171214/af7a7d1e/attachment.bin>


More information about the cfe-commits mailing list