I 'm having a question to match uninit double field in constructor. Given the code below
class un_init_double {
public:
un_init_double() {
init_param_ = 0;
}
bool compare(un_init_double& other) {
if (other.un_init_param_ == un_init_param_) {
return true;
}
return false;
}
private:
double un_init_param_;
double init_param_;
};
I want to match the un_init_param_ field, which didn't call binary operator = in constructor. But I don't find the method to do that.
I type below command in clang-query
clang-query> match cxxRecordDecl(
has(fieldDecl(hasType(asString("double"))).bind("double_field")), has(cxxConstructorDecl(hasDescendant(binaryOperator(hasEitherOperand(memberExpr()))))))
But how to specify memberExpr is related with prew part fieldDecl? In another word, how to specify the connection of fieldDecl and the memberExpr?
I find a method to match init_param_, but how to find no match field?
clang-query> match cxxRecordDecl(has(cxxConstructorDecl(hasDescendant(binaryOperator(hasEitherOperand(memberExpr(hasDeclaration(fieldDecl(hasType(asString("double"))))).bind("member")))))))
Match #1:
~/code_test/ast_matcher/test.cc:9:7: note: "member" binds here
init_param_ = 0;
^~~~~~~~~~~
~/code_test/ast_matcher/test.cc:6:1: note: "root" binds here
class un_init_double {
^~~~~~~~~~~~~~~~~~~~~~
1 match.
clang-query>
When debuging, I write a complicated method to perform this check
// match record
cxxRecordDecl(
has(
// constuctor has init double fieldDecl with binaryoperator = , bind to init_double_field
cxxConstructorDecl(
hasDescendant(
binaryOperator(
hasOperatorName("="),
hasEitherOperand(memberExpr(hasDeclaration(fieldDecl(hasType(asString("double"))).bind("init_double_field"))))
)
)
)
),
has(
// match double field which didn't call binaryoperator = in constructor
fieldDecl(hasType(asString("double")), unless(equalsBoundNode("init_double_field"))).bind("un_init_double_field")
)
)
It seems work, but if i add a sentence: "un_init_param_ = 1;" in constructor, it still take un_init_param_ as uninit_field. Find that it's caused by ast matcher will only match first one rather than match all. So I modify matcher to
cxxRecordDecl(
has(
cxxConstructorDecl(
forEachDescendant(
binaryOperator(
hasOperatorName("="),
hasEitherOperand(memberExpr(hasDeclaration(fieldDecl(hasType(asString("double"))).bind("init_double_field"))))
)
)
)
),
has(
fieldDecl(hasType(asString("double")), unless(equalsBoundNode("init_double_field"))).bind("un_init_double_field")
)
)
I modify original test.cpp to
int f(int x) {
int result = (x / 42);
return result;
}
class un_init_double {
public:
un_init_double() {
init_param_0_ = 0;
init_param_1_ = 0;
}
bool compare(un_init_double& other) {
if (other.un_init_param_ == un_init_param_) {
return true;
}
return false;
}
private:
double un_init_param_;
double init_param_0_;
double init_param_1_;
};
new ast matcher can match it as below
Match #1:
/home/qcraft/code_test/ast_dump/test.cpp:20:5: note: "init_double_field" binds here
double init_param_0_;
^~~~~~~~~~~~~~~~~~~~
/home/qcraft/code_test/ast_dump/test.cpp:6:1: note: "root" binds here
class un_init_double {
^~~~~~~~~~~~~~~~~~~~~~
/home/qcraft/code_test/ast_dump/test.cpp:19:5: note: "un_init_double_field" binds here
double un_init_param_;
^~~~~~~~~~~~~~~~~~~~~
Match #2:
/home/qcraft/code_test/ast_dump/test.cpp:21:5: note: "init_double_field" binds here
double init_param_1_;
^~~~~~~~~~~~~~~~~~~~
/home/qcraft/code_test/ast_dump/test.cpp:6:1: note: "root" binds here
class un_init_double {
^~~~~~~~~~~~~~~~~~~~~~
/home/qcraft/code_test/ast_dump/test.cpp:19:5: note: "un_init_double_field" binds here
double un_init_param_;
^~~~~~~~~~~~~~~~~~~~~
2 matches.
clang-query>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.