我正在使用clang生成AST。我有以下文件(lambda.cpp)来解析:
#include <iostream>
void my_lambda()
{
auto lambda = [](auto x, auto y) {return x + y;};
std::cout << "fabricati diem";
}
我正在使用以下命令解析它:
clang -Xclang -ast-dump -fsyntax-only lambda.cpp
问题是clang还解析了标题内容。结果,我有相当大的(~3000行)文件与无用(对我来说)的内容。
生成AST时如何排除标题?
答案 0 :(得分:15)
clang-check
可能对此事有用,clang-check
选项-ast-dump-filter=<string>
记录如下
-ast转储滤波器= LT;串GT; - 与-ast-dump或-ast-print一起使用仅转储/打印在a中具有某个子字符串的AST声明节点 合格的名字。使用-ast-list列出所有可过滤的声明节点 名。
当clang-check
在示例代码(lambda.cpp)上使用-ast-dump-filter=my_lambda
运行时
#include <iostream>
void my_lambda()
{
auto lambda = [](auto x, auto y) {return x + y;};
std::cout << "fabricati diem";
}
它只转储匹配的声明节点FunctionDecl my_lambda 'void (void)'
这是命令行参数和输出中的几行。
$ clang-check -extra-arg=-std=c++1y -ast-dump -ast-dump-filter=my_lambda lambda.cpp --
FunctionDecl 0x2ddf630 <lambda.cpp:3:1, line:7:1> line:3:6 my_lambda 'void (void)'
`-CompoundStmt 0x2de1558 <line:4:1, line:7:1>
|-DeclStmt 0x2de0960 <line:5:9, col:57>
答案 1 :(得分:2)
使用-ast-dump-filter
过滤特定标识符即可。但是如果你想从一个文件中的所有标识符
我提出了以下解决方案:
在包含后添加一行可识别的行:
#include <iostream>
int XX_MARKER_XX = 123234; // marker line for ast-dump
void my_lambda()
...
然后用
转储astclang-check -extra-arg=-std=c++1y -ast-dump lambda.cpp > ast.txt
您可以使用XX_MARKER_XX
轻松剪切sed
之前的所有内容:
cat ast.txt | sed -n '/XX_MARKER_XX/,$p' | less
仍然很多,但对于更大的文件更有用。
答案 2 :(得分:1)
这是C ++的一个问题,而不是clang:C ++中没有文件,只有编译单元。当你#include
一个文件时,你将所有文件中的定义(递归地)包含在你的编译单元中,并且没有办法区分它们(它是标准期望编译器做的事情)。
想象一下不同的场景:
/////////////////////////////
// headertmp.h
#if defined(A)
struct Foo {
int bar;
};
#elif defined(B)
struct Foo {
short bar;
};
#endif
/////////////////////////////
// foobar.cpp
#ifndef A
# define B
#endif
#include "headertmp.h"
void foobar(Foo foo) {
// do stuff to foo.bar
}
你的foobar.cpp声明了一个名为Foo
的结构和一个名为foobar
的函数,但headertmp.h
本身并没有定义任何Foo
,除非A
或B
已定义。只有在foobar的编译单元中,两者结合在一起才能理解headertmp.h
。
如果您对编译单元中的声明子集感兴趣,则必须直接从生成的AST中提取必要的信息(类似于链接器将不同的编译单元链接在一起时必须执行的操作)。当然,您可以在解析器提取的任何元数据上过滤此编译单元的AST。