如何克隆或创建clang的AST Stmt节点?

时间:2015-05-26 06:55:00

标签: clang llvm

我想通过clang LibTooling修改AST。如何克隆AST节点或添加新节点,例如我想创建一个带有ADD操作码的BinaryOperator

2 个答案:

答案 0 :(得分:2)

在Clang中创建新的AST节点非常麻烦,并且不推荐使用libTooling。相反,您应该“读取”AST并发回代码或代码更改(重写,替换等)。

请参阅this article以及与其相关联的其他文章(和代码示例),以获取有关正确方法的更多信息。

答案 1 :(得分:2)

某些clang的AST节点(类)有一个静态的 Create 方法,该方法用于分配该节点的实例,该节点的内存由传递的ASTContext实例管理它。对于这些类,您可以使用此方法进行实例化。例如,检查 clang :: DeclRefExpr 类。

其他类错过了这个方法,但是使用了可用于实例化对象的公共构造函数。但是,有意隐藏了vanilla new delete 运算符,因此您无法使用它们来实例化堆上的对象。相反,您必须使用 展示位置新/删除 运算符,将 ASTContext 实例作为参数。

就个人而言,我更喜欢使用ASTContext实例分配所有与clang相关的对象,并让它在内部管理内存,所以我不必费心(当ASTContext实例被销毁时,所有内存都会被释放)。

这是一个简单的类,它使用placement new运算符和ASTContext实例为clang对象分配内存:

#ifndef CLANG_ALLOCATOR_H
#define CLANG_ALLOCATOR_H

#include <clang/AST/ASTContext.h>

/// Allocator that relies on clang's AST context for actual memory
/// allocation. Any class that wishes to allocated an AST node may
/// create an instance of this class for that purpose
class ClangAllocator
{
public:

    explicit ClangAllocator(clang::ASTContext& ast_context)
        : m_ast_context(ast_context)
    {
    }

    template<class ClassType, class ... Args>
    inline ClassType* Alloc(Args&& ... args)
    {
        return new (m_ast_context) ClassType(std::forward<Args&&>(args)...);
    }

private:

    clang::ASTContext& m_ast_context;
};

#endif /// CLANG_ALLOCATOR_H

关于AST修改,可能最好的方法是继承 TreeTransform 类并覆盖其 Rebuild < / strong>为各种AST节点生成新语句而调用的方法。

如果您只需要将一个AST节点替换为另一个节点,那么实现此目的的非常简单的方法是找到它的直接父语句,然后在其子节点上使用std :: replace。例如:

/// immediate_parent is immediate parent of the old_stmt
std::replace(
    immediate_parent->child_begin()
    , immediate_parent->child_end()
    , old_stmt
    , new_stmt);