从Clang AST中检索CXXConstructExpr的模板参数

5

假设我有一个变量声明如下:

std::vector<MyType> myVector(1);

在Clang AST中,这表示为CXXConstructExpr。我有一个匹配器可以找到这个CXXConstructExpr,但我想从中提取出MyType的声明。

我尝试了各种方法,但似乎都不起作用:

const CXXConstructExpr* construct = Result.Nodes.getNodeAs<CXXConstructExpr>("expr");
construct->getConstructor()->getTemplateSpecializationArgs()  // Always nullptr
construct->getConstructor()->getParent()  // Seems to lose the template parameters
construct->getConstructor()->getDescribedTemplate()  // Always nullptr
1个回答

1
这是一个匹配器:
varDecl(
  has(
    cxxConstructExpr()
  )
 ,hasType(
    classTemplateSpecializationDecl().bind(sp_dcl_bd_name_)
  )
).bind(var_bd_name_);

它始于VarDecl,遍历到类型,这是一个嵌入在vector的ClassTemplateDecl中的ClassTemplateSpecializationDecl。在回调中,可以从ClassTemplateSpecializationDecl转到模板参数列表,并对各个模板参数进行操作:
using CTSD = ClassTemplateSpecializationDecl;
CTSD * spec_decl =
    const_cast<CTSD *>(result.Nodes.getNodeAs<CTSD>(sp_dcl_bd_name_));
VarDecl * var_decl =
    const_cast<VarDecl *>(result.Nodes.getNodeAs<VarDecl>(var_bd_name_));
if(spec_decl && var_decl) {
  // get the template args
  TemplateArgumentList const &tal(spec_decl->getTemplateArgs());
  for(unsigned i = 0; i < tal.size(); ++i){
    TemplateArgument const &ta(tal[i]);
    // is this arg a type arg? If so, get that type
    TemplateArgument::ArgKind k(ta.getKind());
    std::string argName = "";
    if(k==TemplateArgument::ArgKind::Type){
      QualType t = ta.getAsType();
      argName = t.getAsString();
    }
    // Could do similar actions for integral args, etc...
    std::cout << "For variable declared at "
      << corct::sourceRangeAsString(var_decl->getSourceRange(),&sm) << ":"
      << spec_decl->getNameAsString()
      << ": template arg " << (i+1) << ": " << argName << std::endl;
  } // for template args
} // if

对于这段代码:
struct B{int b_;};
std::vector<B> vb(1);

这个产生:
For variable declared at <line:14:1, col:20>:vector: template arg 1: struct B
For variable declared at <col:1, col:20>:vector: template arg 2: class std::__1::allocator<struct B>

完整的示例在 Github 上的 Code Analysis and Refactoring with Clang Tools 示例存储库中:https://github.com/lanl/CoARCT(请参见 apps/TemplateType.cc)。

我不得不使用hasDescendant()而不是has(),因为CXXConstructExpr并不总是VarDecl的直接子级,但这样做仍然有效。 - IanPudney

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接