【问题标题】:How to clone or create an AST Stmt node of clang?如何克隆或创建 clang 的 AST Stmt 节点?
【发布时间】:2015-05-26 06:54:59
【问题描述】:

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

【问题讨论】:

    标签: clang llvm


    【解决方案1】:

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

    其他类没有这个方法,但有公共构造函数,你可以用来实例化对象。但是,普通的 newdelete 运算符是故意隐藏的,因此您不能使用它们来实例化堆上的对象。相反,您必须使用提供 ASTContext 实例作为参数的 placement new/delete 运算符。

    就个人而言,我更喜欢使用 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 用于为各种 AST 节点生成新语句的方法。

    如果您只需要用另一个 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);
    

    【讨论】:

    【解决方案2】:

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

    请参阅this article 和与其链接的其他文章(和代码示例),了解有关正确方法的更多信息。

    【讨论】:

    • 谢谢,我已经在我的 clang 上运行过它,但仍然不知道如何克隆一个 BinaryOperator 节点以及如何“新建 BinaryOperator()”。我想一定有办法做到这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-28
    • 1970-01-01
    • 1970-01-01
    • 2017-05-23
    • 2014-02-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多