如何在 Clang 中获取 NamedDecl 的损坏名称?

问题描述 投票:0回答:2

我正在使用 Clang 解析一些 C++ 代码。我想打印我遇到的每个

FunctionDecl
的名称和损坏的名称。

通过将其添加到我的

RecursiveASTVisitor
中,我可以相当轻松地打印函数名称:

bool VisitFunctionDecl(FunctionDecl* f) {

  auto declName = f->getNameInfo().getName();
  auto functionName = declName.getAsString();

  std::cout << functionName << std::endl;

  return true;
}

如何打印损坏的名字?


我按照塞巴斯蒂安的指示生成的工作代码:

const auto getMangledName = [&](FunctionDecl* decl) {

  auto mangleContext = context.createMangleContext();

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

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

  mangleContext->mangleName(decl, ostream);

  ostream.flush();

  delete mangleContext;

  return mangledName;
};
c++ clang llvm name-mangling
2个回答
9
投票

损坏的名称不是 AST 的一部分,因为它取决于 ABI。要获得损坏的名称,您需要创建适当的

clang::MangleContext
子类(来自
clang/AST/Mangle.h
)。目前有
MicrosoftMangleContext
用于与 Visual Studio 兼容的修改,以及
ItaniumMangleContext
用于常见的 C++ ABI 修改。

在最简单的版本中,您只需调用

mangleName
,传入要修改其名称的
NamedDecl
,以及写入修改后的名称的
raw_ostream

对于像 lambda 之类的更复杂的东西,您可能还需要在适当的时候调用

startNewFunction
,因为它们的损坏取决于它们所在的函数。


0
投票

我找到了更安全的解决方案。

让我们看看

JSONNodeDumper
是如何工作的:

llvm-project-llvmorg-16.0.4/clang/lib/AST/JSONNodeDumper.cpp

void JSONNodeDumper::VisitNamedDecl(const NamedDecl *ND) {
  if (ND && ND->getDeclName()) {
    JOS.attribute("name", ND->getNameAsString());
    // FIXME: There are likely other contexts in which it makes no sense to ask
    // for a mangled name.
    if (isa<RequiresExprBodyDecl>(ND->getDeclContext()))
      return;

    // Mangled names are not meaningful for locals, and may not be well-defined
    // in the case of VLAs.
    auto *VD = dyn_cast<VarDecl>(ND);
    if (VD && VD->hasLocalStorage())
      return;

    std::string MangledName = ASTNameGen.getName(ND);
    if (!MangledName.empty())
      JOS.attribute("mangledName", MangledName);
  }
}

JSONNodeDumper
利用
ASTNameGenerator::getName
来破坏
NamedDecl

如果你阅读了

ASTNameGenerator::getName
的源代码,你会发现它最终通过
MangleContext::mangleName
破坏了名字。在调用
MangleContext::mangleName
之前,
ASTNameGenerator::getName
会执行许多检查以防止异常。

创建

ASTNameGenerator
对象非常简单,只需将
ASTContext
传递给其构造函数即可:

explicit ASTNameGenerator(ASTContext &Ctx);

不确定如何获得

ASTContext
?首先查看这些官方教程:
https://clang.llvm.org/docs/Tooling.html
https://clang.llvm.org/docs/RAVFrontendAction.html

最终代码如下:

#include "clang/AST/Mangle.h"

std::string getMangledName(const NamedDecl* decl) {
    if (decl && decl->getDeclName()) {
        if (isa<RequiresExprBodyDecl>(decl->getDeclContext()))
            return "";

        auto *varDecl = dyn_cast<VarDecl>(decl);
        if (varDecl && varDecl->hasLocalStorage())
            return "";

        // astNameGenerator is your ASTNameGenerator object
        return astNameGenerator.getName(decl);
    }
    return "";
}
© www.soinside.com 2019 - 2024. All rights reserved.