-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathast_filter.cpp
143 lines (111 loc) · 4.06 KB
/
ast_filter.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "ast_filter.hpp"
namespace ASTFilter {
SourceManager::SourceManager(std::string file) {
init(file);
}
bool SourceManager::isSystem(std::string file) {
// path is a full file path
for (auto system_path : system_includes) {
if (file.rfind(system_path, 0) == 0) {
return true;
}
}
return false;
}
void SourceManager::print() {
std::cout << "System paths: " << std::endl;
for (auto path : system_includes) {
std::cout << "\t" << path << std::endl;
}
}
void SourceManager::init (std::string file) {
FILE *fp;
char path[20480];
std::stringstream ss;
// Open the command for reading
std::string clang_ast_dump_cmd = "clang -### " + file + " 2>&1";
fp = popen(clang_ast_dump_cmd.c_str(), "r");
if (fp == NULL) {
std::cerr << "Could not run command." << std::endl;
}
while (fgets(path, sizeof(path), fp) != NULL) {
ss << path;
}
pclose(fp);
std::string clang_output = ss.str();
std::regex internal_isystem_match("\"-internal-isystem\" \"(\\S*)\"");
std::smatch match;
while (std::regex_search(clang_output, match, internal_isystem_match)) {
// Capturing group is at index 1
system_includes.insert(match.str(1));
// suffix to find the rest of the string.
clang_output = match.suffix().str();
}
clang_output = ss.str();
std::regex internal_externc_match("\"-internal-externc-isystem\" \"(\\S*)\"");
while (std::regex_search(clang_output, match, internal_externc_match)) {
// Capturing group is at index 1
system_includes.insert(match.str(1));
// suffix to find the rest of the string.
clang_output = match.suffix().str();
}
}
json generateFilteredAST (std::string filename) {
SourceManager s(filename);
json ast = generateFullAST(filename);
filter_ast(ast, s);
return ast;
}
json generateFullAST (std::string file) {
FILE *fp;
char path[1035];
std::stringstream ss;
// Open the command for reading
std::string clang_ast_dump_cmd = "clang -Xclang -ast-dump=json " + file;
fp = popen(clang_ast_dump_cmd.c_str(), "r");
if (fp == NULL) {
std::cout << "Could not generate AST for file " << file << std::endl;
return std::move(json());
}
while (fgets(path, sizeof(path), fp) != NULL) {
ss << path;
}
pclose(fp);
return json::parse(ss);
}
void filter_ast(json& full_ast, SourceManager& source_manager) {
json new_inner;
bool previous_included = false;
for (auto entry : full_ast["inner"]) {
if (entry.contains("isImplicit") && entry["isImplicit"] == true) {
continue;
}
if (entry.contains("loc")) {
std::string filename = "";
json loc = entry["loc"];
if (loc.contains("file")) {
filename = loc["file"];
}
if (loc.contains("expansionLoc")) {
if (loc["expansionLoc"].contains("file")) {
filename = loc["expansionLoc"]["file"];
}
}
if (filename == "") {
// If no location was found, then we are still in the last entry's location
if (previous_included) {
new_inner.push_back(entry);
}
continue;
}
if (!source_manager.isSystem(filename)) {
new_inner.push_back(entry);
previous_included = true;
} else {
previous_included = false;
}
}
}
full_ast["inner"] = new_inner;
}
}