Clang ast-dump 不显示一些全局变量

Clang ast-dump doesn't show some global variables

我有一个 CPP 文件,我正在使用 clang 打印全局范围内的所有变量。问题如下:command clang -cc1 -ast-dump filename.cpp doesn't show some global variables:

|-VarDecl 0x2094370 N 'int' invalid

|-VarDecl 0x20943e0 MAXN 'const int' invalid

|-VarDecl 0x2094470 p 'int' invalid

|-VarDecl 0x20944e0 u '_Bool' invalid

|-VarDecl 0x2094550 ansv 'int' invalid

|-VarDecl 0x20945c0 cost 'int' invalid

我的 cpp 文件有以下全局变量:

size_t N,M;
const size_t MAXN = 40000;
std::vector<std::pair<size_t,size_t> > graph[MAXN],query[MAXN],qr;
size_t p[MAXN], ancestor[MAXN];
bool u[MAXN];
size_t ansv[MAXN];
size_t cost[MAXN];

可以看出,ast-dump 没有打印出一些全局变量(例如,所有 std::vector 变量都被遗漏了)。我做错了什么?

UPD:完整的 cpp 文件:

#include<iostream>
#include<vector>
#include<algorithm>

size_t N,M;
const size_t MAXN = 40000;
std::vector<std::pair<size_t,size_t> > graph[MAXN],query[MAXN],qr;
size_t p[MAXN], ancestor[MAXN];
bool u[MAXN];
size_t ansv[MAXN];
size_t cost[MAXN];

size_t find_set(size_t x){
    //not important for my problem
}

void unite(size_t a, size_t b, size_t new_ancestor){
    //not important for my problem
}

void dfs(size_t v,size_t ct){
    //not important for my problem
}

int main(int argc, char* argv[]){
    //not important for my problem
}

看起来 clang 无法找出声明中所有声明符的类型 size_t N,M 并为所有声明符创建 VarDecl,但首先创建。注意这些声明后的 "invalid"。

有完整的例子,有

|-VarDecl 0x102bf5d60 <blah.cpp:4:1, col:8> N 'size_t':'unsigned long'
|-VarDecl 0x102bf5dd0 <col:1, col:10> M 'size_t':'unsigned long'

等全部。

一旦我删除了定义 size_tstd::vector 的包含,clang 开始抱怨未定义的类型并且不会生成 VarDecl 因为它之前没有创建 Type .

您正在使用 clang++ -cc1 -ast-dump,它假定输入已经过预处理。当我这样做时,我得到了错误,因为它找不到 std::vectorstd::pairsize_t,这就是为什么它在这样的行中说无效:

|-VarDecl 0x3149810 <testing.cpp:19:1, col:8> col:8 invalid N 'int'
|-VarDecl 0x3149880 <line:20:1, col:14> col:14 invalid MAXN 'const int'

请注意这些行中的 "invalid" - 这意味着它是 "not a valid declaration"。

在这种情况下,部分编译器错误恢复是 "assume there is only one variable in each declaration and skip to the next semicolon"。

我把你的代码修改成这样:

namespace std
{
    template <typename T>
    class vector
    {
    };

    template <typename T1, typename T2>
    class pair
    {
    };
};

typedef int size_t;

size_t N,M;
const size_t MAXN = 40000;
std::vector<std::pair<size_t,size_t> > graph[MAXN],query[MAXN],qr;
size_t p[MAXN], ancestor[MAXN];
bool u[MAXN];
size_t ansv[MAXN];
size_t cost[MAXN];

size_t find_set(size_t x){
    //not important for my problem
    return 0;
}

void unite(size_t a, size_t b, size_t new_ancestor){
    //not important for my problem
}

void dfs(size_t v,size_t ct){
    //not important for my problem
}

int main(int argc, char* argv[]){
    //not important for my problem
}

此时我得到:

TranslationUnitDecl 0x4916de0 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x4917320 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
|-TypedefDecl 0x4917380 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
|-TypedefDecl 0x4917780 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list '__va_list_tag [1]'
|-NamespaceDecl 0x49177d0 <testing.cpp:1:1, line:12:1> line:1:11 std
| |-ClassTemplateDecl 0x4917970 <line:3:5, line:6:5> line:4:11 vector
| | |-TemplateTypeParmDecl 0x4917830 <line:3:15, col:24> col:24 typename T
| | |-CXXRecordDecl 0x49178e0 <line:4:5, line:6:5> line:4:11 class vector definition
| | | `-CXXRecordDecl 0x49588f0 <col:5, col:11> col:11 implicit class vector
| | `-ClassTemplateSpecializationDecl 0x49593b0 <line:3:5, line:6:5> line:4:11 class vector definition
| |   |-TemplateArgument type 'class std::pair<int, int>'
| |   |-CXXRecordDecl 0x4959750 prev 0x49593b0 <col:5, col:11> col:11 implicit class vector
| |   |-CXXConstructorDecl 0x495ff30 <col:11> col:11 implicit used vector 'void (void) throw()' inline
| |   | `-CompoundStmt 0x4960260 <col:11>
| |   `-CXXConstructorDecl 0x4960090 <col:11> col:11 implicit vector 'void (const class std::vector<class std::pair<int, int> > &)' inline noexcept-unevaluated 0x4960090
| |     `-ParmVarDecl 0x49601d0 <col:11> col:11 'const class std::vector<class std::pair<int, int> > &'
| `-ClassTemplateDecl 0x4958b40 <line:8:5, line:11:5> line:9:11 pair
|   |-TemplateTypeParmDecl 0x4958980 <line:8:15, col:24> col:24 typename T1
|   |-TemplateTypeParmDecl 0x49589f0 <col:28, col:37> col:37 typename T2
|   |-CXXRecordDecl 0x4958ab0 <line:9:5, line:11:5> line:9:11 class pair definition
|   | `-CXXRecordDecl 0x4958de0 <col:5, col:11> col:11 implicit class pair
|   `-ClassTemplateSpecializationDecl 0x4959140 <line:8:5, line:11:5> line:9:11 class pair
|     |-TemplateArgument type 'int'
|     `-TemplateArgument type 'int'
|-EmptyDecl 0x4958e70 <line:12:2> col:2
|-TypedefDecl 0x4958ea0 <line:14:1, col:13> col:13 referenced size_t 'int'
|-VarDecl 0x4958f20 <line:17:1, col:8> col:8 N 'size_t':'int'
|-VarDecl 0x4958f90 <col:1, col:10> col:10 M 'size_t':'int'
|-VarDecl 0x4959010 <line:18:1, col:21> col:14 referenced MAXN 'const size_t':'const int' cinit
| `-IntegerLiteral 0x4959068 <col:21> 'int' 40000
|-VarDecl 0x4959690 <line:19:1, col:50> col:40 graph 'std::vector<std::pair<size_t, size_t> > [40000]' callinit
| `-CXXConstructExpr 0x4960278 <col:40> 'std::vector<std::pair<size_t, size_t> > [40000]' 'void (void) throw()'
|-VarDecl 0x49603f0 <col:1, col:62> col:52 query 'std::vector<std::pair<size_t, size_t> > [40000]' callinit
| `-CXXConstructExpr 0x4960448 <col:52> 'std::vector<std::pair<size_t, size_t> > [40000]' 'void (void) throw()'
|-VarDecl 0x49604c0 <col:1, col:64> col:64 qr 'std::vector<std::pair<size_t, size_t> >':'class std::vector<class std::pair<int, int> >' callinit
| `-CXXConstructExpr 0x4960518 <col:64> 'std::vector<std::pair<size_t, size_t> >':'class std::vector<class std::pair<int, int> >' 'void (void) throw()'
|-VarDecl 0x4960650 <line:20:1, col:14> col:8 p 'size_t [40000]'
|-VarDecl 0x4960710 <col:1, col:30> col:17 ancestor 'size_t [40000]'
|-VarDecl 0x4960820 <line:21:1, col:12> col:6 u '_Bool [40000]'
|-VarDecl 0x49608e0 <line:22:1, col:17> col:8 ansv 'size_t [40000]'
|-VarDecl 0x49609a0 <line:23:1, col:17> col:8 cost 'size_t [40000]'
|-FunctionDecl 0x4960b10 <line:25:1, line:28:1> line:25:8 find_set 'size_t (size_t)'
| |-ParmVarDecl 0x4960a10 <col:17, col:24> col:24 x 'size_t':'int'
| `-CompoundStmt 0x4960bf8 <col:26, line:28:1>
|   `-ReturnStmt 0x4960bd8 <line:27:5, col:12>
|     `-IntegerLiteral 0x4960bb8 <col:12> 'int' 0
|-FunctionDecl 0x4960e40 <line:30:1, line:32:1> line:30:6 unite 'void (size_t, size_t, size_t)'
| |-ParmVarDecl 0x4960c30 <col:12, col:19> col:19 a 'size_t':'int'
| |-ParmVarDecl 0x4960ca0 <col:22, col:29> col:29 b 'size_t':'int'
| |-ParmVarDecl 0x4960d10 <col:32, col:39> col:39 new_ancestor 'size_t':'int'
| `-CompoundStmt 0x4960ef8 <col:52, line:32:1>
|-FunctionDecl 0x49618d0 <line:34:1, line:36:1> line:34:6 dfs 'void (size_t, size_t)'
| |-ParmVarDecl 0x4961750 <col:10, col:17> col:17 v 'size_t':'int'
| |-ParmVarDecl 0x49617c0 <col:19, col:26> col:26 ct 'size_t':'int'
| `-CompoundStmt 0x4961980 <col:29, line:36:1>
`-FunctionDecl 0x4961c00 <line:38:1, line:40:1> line:38:5 main 'int (int, char **)'
  |-ParmVarDecl 0x49619b0 <col:10, col:14> col:14 argc 'int'
  |-ParmVarDecl 0x4961af0 <col:20, col:31> col:26 argv 'char **':'char **'
  `-CompoundStmt 0x4961cb0 <col:33, line:40:1>

正确的解决办法当然是不使用-cc1,直接使用原文件-c -Xclang -ast-dump,但是会产生相当大的文本量(vector的所有成员函数,对、iostream 等)。因此,如果您对特定部分感兴趣,也许可以从 headers 中删除所需的部分,只处理您实际需要的部分——当然,这一切都取决于您实际想要实现的目标。