Clang:抽象语法树(AST)长什么样?

11

嗨,我是编译器开发新手,想知道AST是什么样子的。我有一小段代码,并使用Clang生成AST,但没有获取到太多信息。 从外观上看,语法树与源代码完全相同,除了几乎任何测试样例中都添加了一个结构体。

class A {
public:
  int *a, *b, *c;
  int i;
  void sum() {
    a = new int[5];
    b = new int[5];
    c = new int[5];
    for (i = 0; i < 5; i++) {
      a[i] = i;
      b[i] = i;
    }
    for (i = 0; i < 5; i++) {
      c[i] = a[i] + b[i];
    }
    delete[] a;   delete[] b;   delete[] c;
  }
};

class B : public A {
};

int main() {
  B bclass; 
  bclass.sum();
  return 0;
} 

生成AST的命令:

clang++ -cc1 -ast-print ~/sum.cpp

AST 输出:

struct __va_list_tag {
    unsigned int gp_offset;
    unsigned int fp_offset;
    void *overflow_arg_area;
    void *reg_save_area;
};
typedef struct __va_list_tag __va_list_tag;
class A {
public:
    int *a;
    int *b;
    int *c;
    int i;
    void sum()     {
        this->a = new int [5];
        this->b = new int [5];
        this->c = new int [5];
        for (this->i = 0; this->i < 5; this->i++) {
            this->a[this->i] = this->i;
            this->b[this->i] = this->i;
        }
        for (this->i = 0; this->i < 5; this->i++) {
            this->c[this->i] = this->a[this->i] + this->b[this->i];
        }
        delete [] this->a;
        delete [] this->b;
        delete [] this->c;
    }


};
class B : public A {
};
int main() {
    B bclass;
    bclass.sum();
    return 0;
}

感谢


2
如果问题是 AST 是什么样子,而不是 Clang 的 AST 是什么样子,您可能会发现这个答案有用:https://dev59.com/jWw15IYBdhLWcg3w0fGh#6378997 - Ira Baxter
6
提示:你可能希望尝试使用-ast-dump而不是-ast-print;该表示可能更接近您要查找的内容。 - servn
3个回答

17

不同选项之间存在一些小的混淆:

  • -ast-print 将美观地打印出当前AST,即尽可能准确地呈现它解析得到的代码(但会使一些东西变得明确,例如this的出现)。
  • -ast-dump 将生成一个类似lisp的当前AST的表示形式。

漂亮的打印机可以用来检查AST是否无损(即保留了诸如表达式的const等内容),但并不是真正与开发有关。

如果您想要对编译器进行修改,那么您需要使用 -ast-dump,它将生成一个直接映射已解析代码的内存中表示形式的输出。


7
AST是内存中的链接结构(“树”并不能真正反映其复杂性,但这是人们使用的名称)。-ast-print生成的是AST的文本表示。由于设置选项的人已经熟悉类似C/C++的语法,因此它以遵循该语法的表示形式打印。这是一个设计选择,而不是偶然事件。
如果您想看看当意图不是以熟悉的语法打印时AST的样子,例如,您可以查看GIMPLE,GCC的内部表示。

谢谢Pascal。我尝试打印AST的原因是为了理解clang在做什么。我认为这将是逐步了解AST创建的起点,最终添加新类型/函数到Clang中的方法,并且更好地理解它。我想我必须找到另一种替代方案。 - Sriram Murali
3
警告:GIMPLE 难以理解且操作繁琐。 - Alexandre C.

3
如果您想使用GIMPLE进行操作,甚至可以使用GCC MELT。MELT是一种高级领域特定语言,用于处理GIMPLE!在编译器内部表示中经常不是树形结构,而是某种循环结构。在GCC中,基本块知道它们的gimple-s,但gimple-s也可能知道它们的基本块...(这有点复杂,但您已经理解了)。

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