diff options
author | Sergio Martins <iamsergio@gmail.com> | 2017-12-10 19:26:32 +0000 |
---|---|---|
committer | Sergio Martins <iamsergio@gmail.com> | 2017-12-10 19:27:04 +0000 |
commit | a7c06b5eaf88af38096c0f66f30c6f15a9e21bd1 (patch) | |
tree | 072332f0a75e6070b806fe8c68ca60108be04ae5 /src | |
parent | 3509599f3e897f31c72541679fc4c90f02f3237c (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.cpp | 62 |
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; } |