diff --git a/llvm/docs/CommandGuide/llvm-cxxmap.rst b/llvm/docs/CommandGuide/llvm-cxxmap.rst index b0bf1c49fc20..dd38f3194b17 100644 --- a/llvm/docs/CommandGuide/llvm-cxxmap.rst +++ b/llvm/docs/CommandGuide/llvm-cxxmap.rst @@ -71,6 +71,14 @@ indicating whether the following mangled name fragments are respectively. Blank lines and lines starting with ``#`` are ignored. +Unmangled C names can be expressed as an ``encoding`` that is a (length-prefixed) +<`source-name `_>: + +.. code-block:: none + + # C function "void foo_bar()" is remapped to C++ function "void foo::bar()". + encoding 7foo_bar _Z3foo3barv + For convenience, built-in s such as ``St`` and ``Ss`` are accepted as s (even though they technically are not s). diff --git a/llvm/lib/Support/ItaniumManglingCanonicalizer.cpp b/llvm/lib/Support/ItaniumManglingCanonicalizer.cpp index 3db27c3f9ff3..bbc06d186fba 100644 --- a/llvm/lib/Support/ItaniumManglingCanonicalizer.cpp +++ b/llvm/lib/Support/ItaniumManglingCanonicalizer.cpp @@ -296,16 +296,32 @@ ItaniumManglingCanonicalizer::addEquivalence(FragmentKind Kind, StringRef First, return EquivalenceError::Success; } +static ItaniumManglingCanonicalizer::Key +parseMaybeMangledName(CanonicalizingDemangler &Demangler, StringRef Mangling, + bool CreateNewNodes) { + Demangler.ASTAllocator.setCreateNewNodes(CreateNewNodes); + Demangler.reset(Mangling.begin(), Mangling.end()); + // Attempt demangling only for names that look like C++ mangled names. + // Otherwise, treat them as extern "C" names. We permit the latter to + // be remapped by (eg) + // encoding 6memcpy 7memmove + // consistent with how they are encoded as local-names inside a C++ mangling. + Node *N; + if (Mangling.startswith("_Z") || Mangling.startswith("__Z") || + Mangling.startswith("___Z") || Mangling.startswith("____Z")) + N = Demangler.parse(); + else + N = Demangler.make( + StringView(Mangling.data(), Mangling.size())); + return reinterpret_cast(N); +} + ItaniumManglingCanonicalizer::Key ItaniumManglingCanonicalizer::canonicalize(StringRef Mangling) { - P->Demangler.ASTAllocator.setCreateNewNodes(true); - P->Demangler.reset(Mangling.begin(), Mangling.end()); - return reinterpret_cast(P->Demangler.parse()); + return parseMaybeMangledName(P->Demangler, Mangling, true); } ItaniumManglingCanonicalizer::Key ItaniumManglingCanonicalizer::lookup(StringRef Mangling) { - P->Demangler.ASTAllocator.setCreateNewNodes(false); - P->Demangler.reset(Mangling.begin(), Mangling.end()); - return reinterpret_cast(P->Demangler.parse()); + return parseMaybeMangledName(P->Demangler, Mangling, false); } diff --git a/llvm/unittests/Support/ItaniumManglingCanonicalizerTest.cpp b/llvm/unittests/Support/ItaniumManglingCanonicalizerTest.cpp index 91432899d145..b20cdcf340b1 100644 --- a/llvm/unittests/Support/ItaniumManglingCanonicalizerTest.cpp +++ b/llvm/unittests/Support/ItaniumManglingCanonicalizerTest.cpp @@ -249,6 +249,19 @@ static std::vector getTestcases() { {"_Z1fRA1_i"}, {"_Z1fRA_f"}, } }, + + // Unmangled names can be remapped as complete encodings. + { + { + {FragmentKind::Encoding, "3foo", "3bar"}, + }, + { + // foo == bar + {"foo", "bar"}, + // void f() == void f() + {"_Z1fIL_Z3fooEEvv", "_Z1fIL_Z3barEEvv"}, + } + }, }; } @@ -343,7 +356,7 @@ TEST(ItaniumManglingCanonicalizerTest, TestInvalidManglings) { EquivalenceError::InvalidSecondMangling); EXPECT_EQ(Canonicalizer.canonicalize("_Z3fooE"), llvm::ItaniumManglingCanonicalizer::Key()); - EXPECT_EQ(Canonicalizer.canonicalize("foo"), + EXPECT_EQ(Canonicalizer.canonicalize("_Zfoo"), llvm::ItaniumManglingCanonicalizer::Key()); // A reference to a template parameter ('T_' etc) cannot appear in a ,