简体   繁体   English

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

[英]Retrieve template parameters from CXXConstructExpr in Clang AST

Say I have a variable declaration like this: 说我有一个这样的变量声明:

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

This is represented as a CXXConstructExpr in the Clang AST. 在Clang AST中将其表示为CXXConstructExpr I have a matcher that finds this CXXConstructExpr , but I'd like to extract the decl for MyType from it. 我有一个匹配器,可以找到此CXXConstructExpr ,但我想从中提取MyType的decl。

I've tried all sorts of things, but nothing seems to work: 我已经尝试过各种方法,但是似乎没有任何效果:

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

Here's a matcher: 这是一个匹配器:

varDecl(
  has(
    cxxConstructExpr()
  )
 ,hasType(
    classTemplateSpecializationDecl().bind(sp_dcl_bd_name_)
  )
).bind(var_bd_name_);

It starts with the VarDecl and traverses to the type, which is a ClassTemplateSpecializationDecl buried in vector's ClassTemplateDecl . 它开始与VarDecl和横梁的类型,这是一个ClassTemplateSpecializationDecl埋在载体的ClassTemplateDecl In the callback, one can work from the ClassTemplateSpecializationDecl to the template argument list, and operate on the individual template arguments: 在回调中,可以从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

For this code: 对于此代码:

struct B{int b_;};
std::vector<B> vb(1);

this produces: 这将产生:

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>

The full example is in the Code Analysis and Refactoring with Clang Tools examples repo at github: https://github.com/lanl/CoARCT (see apps/TemplateType.cc) 完整的示例在github上的代码分析和使用Clang工具重构示例存储库中: https//github.com/lanl/CoARCT (请参阅apps / TemplateType.cc)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM