【问题标题】:Retrieve template parameters from CXXConstructExpr in Clang AST在 Clang AST 中从 CXXConstructExpr 中检索模板参数
【发布时间】:2023-03-04 18:49:01
【问题描述】:

假设我有一个这样的变量声明:

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

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

我尝试了各种方法,但似乎没有任何效果:

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

【问题讨论】:

    标签: c++ clang abstract-syntax-tree


    【解决方案1】:

    这是一个匹配器:

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

    它以 VarDecl 开始并遍历类型,即埋在向量的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 的直接子代,但这样可以正常工作。
    猜你喜欢
    • 1970-01-01
    • 2013-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多