Search code examples
c++clangllvmname-mangling

How to generate the same cxx method mangled name with LLVM?


I have an iOS project, and in my project I have a c++ method:

ClassA::getElements(vector<vector<int> >&ovElements) {
    // ...
}

I built my project by xcodebuild command, and from the .o file, I get to know its mangled name is __ZN25ClassA18getElementsERNSt3__16vectorINS1_IiNS0_9allocatorIiEEEENS2_IS4_EEEE. its demangled name should be ClassA::getElements(std::__1::vector<std::__1::vector<int, std::__1::allocator<int> >, std::__1::allocator<std::__1::vector<int, std::__1::allocator<int> > > >&)

I am trying to develop a clang tool to export all functions/methods boundaries along with their names from source files. I could make use of MatchFinder to find all cxxMethod and function and get their FunctionDecl, then I use the following method to get their mangled names:

std::string getMangledName(const FunctionDecl *FD, const MatchFinder::MatchResult &Result) {
    auto mangleContext = Result.Context->createMangleContext();

    if (!mangleContext->shouldMangleDeclName(FD)) {
      return FD->getNameInfo().getName().getAsString();
    }

    std::string mangledName;
    llvm::raw_string_ostream ostream(mangledName);

    mangleContext->mangleName(FD, ostream);

    ostream.flush();

    delete mangleContext;

    return mangledName;
  }

But for this ClassA::getElements method, I get _ZN25ClassA18getElementsERii, which is not I want. After demangling it, I find its name is ClassA::getElements(int&).

BTW, the compilation database I used is generated by xcpretty,

xcodebuild ... | xcpretty -r json-compilation-database

My question is why I get int& rather than std::__1::vector<std::__1::vector<int, std::__1::allocator<int> >, std::__1::allocator<std::__1::vector<int, std::__1::allocator<int> > > >&. How can I get the same mangled name that the compiler generated?


I followed the comment from @user17732522 and set up a minimal project that only contains Test.hpp

#ifndef Test_hpp
#define Test_hpp

#include <stdio.h>
#include <vector>

class ClassA {
public:
    void foo(std::vector<std::vector<int> >& ov);
};

#endif /* Test_hpp */

and Test.cpp

#include "Test.hpp"

using namespace std;

void ClassA::foo(vector<vector<int> >& ov) {
    return;
}

I still got the mangled name _ZN6ClassA3fooERi. But I noticed that there was an error from clang:

Test.hpp:11:10: fatal error: 'stdio.h' file not found

However, I can build it successfully by either Xcode or xcodebuild command.


Solution

  • I figured it out! The root cause is when parsing my source file, there is a fatal error 'xxx.h' file not found. Once I fixed this error manually, Clang could output the correct results.