Given a C++ source code, I want to find the class fields that every function writes and reads. What is the best way of doing this using the Clang frontend?
(I'm not asking for a detailed explanation of all the steps; however a starting point for an efficient solution would be great.)
So far I tried parsing statements using the RecursiveASTVisitor, but keeping track of node connections is difficult. Also, I cannot figure out how to keep track of something like below:
int& x = m_int_field;
x++;
This clearly modifies m_int_field
; but given a single Stmt
it is impossible to know that; so AST traversal by itself seems insufficient.
A bonus for me is being able to separately count fields and sub-fields (e.g. Accessing three fields of a member struct).
Example:
typedef struct Y {
int m_structfield1;
float m_structfield2;
Y () {
m_structfield1 = 0;
m_structfield2 = 1.0f;
}
} Y;
class X {
int m_field1;
std::string m_field2;
Y m_field3;
public:
X () : m_field2("lel") {}
virtual ~X() {}
void func1 (std::string s) {
m_field1 += 2;
m_field2 = s;
}
int func2 () {
return m_field1 + 5;
}
void func3 (Y& y) {
int& i = m_field1;
y.m_structfield2 = 1.2f + i++;
}
int func4 () {
func3 (m_field3);
return m_field3.m_structfield1;
}
};
should return
X::X() -> m_field1 (w), m_field3.m_structfield1 (w), m_field3.m_structfield2 (w)
X::func1(std::string) -> m_field1 (r+w), m_field2 (w)
X::func2() -> m_field1 (r)
X::func3(Y&) -> m_field1 (r+w)
X::func4() -> m_field1 (r+w), m_field3.m_structfield2 (w), m_field3.m_structfield1 (r)
We can assume for simplicity that there is no inheritance.