aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSergio Martins <iamsergio@gmail.com>2017-12-10 19:26:32 +0000
committerSergio Martins <iamsergio@gmail.com>2017-12-10 19:27:04 +0000
commita7c06b5eaf88af38096c0f66f30c6f15a9e21bd1 (patch)
tree072332f0a75e6070b806fe8c68ca60108be04ae5 /src
parent3509599f3e897f31c72541679fc4c90f02f3237c (diff)
Fix Utils::containsNonConstMemberCall()
The parent() calls were not working since those nodes weren't visited yet. Also fixes the unit-tests.
Diffstat (limited to 'src')
-rw-r--r--src/Utils.cpp62
1 files changed, 41 insertions, 21 deletions
diff --git a/src/Utils.cpp b/src/Utils.cpp
index c24f5b7c..34fa57da 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -232,40 +232,60 @@ clang::ValueDecl * Utils::valueDeclForCallExpr(clang::CallExpr *expr)
return nullptr;
}
+static bool referencesVar(Stmt *s, const VarDecl *varDecl)
+{
+ // look for a DeclRefExpr that references varDecl
+ while (s) {
+ auto it = s->child_begin();
+ Stmt *child = it == s->child_end() ? nullptr : *it;
+ if (auto declRef = dyn_cast_or_null<DeclRefExpr>(child)) {
+ if (declRef->getDecl() == varDecl)
+ return true;
+ }
+ s = child;
+ }
+
+ return false;
+}
+
+
bool Utils::containsNonConstMemberCall(clang::ParentMap *map, Stmt *body, const VarDecl *varDecl)
{
if (!varDecl)
return false;
- std::vector<MemberExpr*> memberExprs;
- HierarchyUtils::getChilds<MemberExpr>(body, memberExprs);
+ std::vector<CXXMemberCallExpr*> memberCallExprs;
+ HierarchyUtils::getChilds<CXXMemberCallExpr>(body, memberCallExprs);
+ for (auto memberCall : memberCallExprs) {
+ CXXMethodDecl *methodDecl = memberCall->getMethodDecl();
+ if (methodDecl && !methodDecl->isConst()) {
+ ValueDecl *valueDecl = Utils::valueDeclForMemberCall(memberCall);
+ if (valueDecl == varDecl)
+ return true;
+ }
+ }
- for (MemberExpr *memberExpr : memberExprs) {
- auto memberCall = HierarchyUtils::getFirstParentOfType<CXXMemberCallExpr>(map, memberExpr);
- if (memberCall) {
- CXXMethodDecl *methodDecl = memberCall->getMethodDecl();
+ std::vector<CXXOperatorCallExpr*> operatorCalls;
+ HierarchyUtils::getChilds<CXXOperatorCallExpr>(body, operatorCalls);
+ for (auto operatorCall : operatorCalls) {
+ FunctionDecl *fDecl = operatorCall->getDirectCallee();
+ if (fDecl) {
+ auto methodDecl = dyn_cast<CXXMethodDecl>(fDecl);
if (methodDecl && !methodDecl->isConst()) {
- ValueDecl *valueDecl = Utils::valueDeclForMemberCall(memberCall);
+ ValueDecl *valueDecl = Utils::valueDeclForOperatorCall(operatorCall);
if (valueDecl == varDecl)
return true;
}
}
+ }
- auto operatorExpr = HierarchyUtils::getFirstParentOfType<CXXOperatorCallExpr>(map, memberExpr);
- if (operatorExpr) {
- FunctionDecl *fDecl = operatorExpr->getDirectCallee();
- if (fDecl) {
- auto methodDecl = dyn_cast<CXXMethodDecl>(fDecl);
- if (methodDecl && methodDecl->isConst()) {
- ValueDecl *valueDecl = Utils::valueDeclForOperatorCall(operatorExpr);
- if (valueDecl == varDecl)
- return true;
- }
- }
- }
+ std::vector<BinaryOperator*> assignmentOperators;
+ HierarchyUtils::getChilds<BinaryOperator>(body, assignmentOperators);
+ for (auto op : assignmentOperators) {
+ if (!op->isAssignmentOp())
+ continue;
- auto binaryOperator = HierarchyUtils::getFirstParentOfType<BinaryOperator>(map, memberExpr);
- if (binaryOperator && binaryOperator->isAssignmentOp())
+ if (referencesVar(op, varDecl))
return true;
}