summaryrefslogtreecommitdiff
path: root/src/analysis/expression.cpp
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2015-06-28 21:56:24 +0300
committerAndrei Karas <akaras@inbox.ru>2015-06-28 21:56:24 +0300
commite5f7f28cdaa1d344b9daa6826fa3d8c5c746fed5 (patch)
treea214bc2bfcddd933a373698f920e571f1a9faf69 /src/analysis/expression.cpp
parent1c32401aa8613eba857bc56b5f0c31880ca2191f (diff)
downloadparanucker-e5f7f28cdaa1d344b9daa6826fa3d8c5c746fed5.tar.gz
paranucker-e5f7f28cdaa1d344b9daa6826fa3d8c5c746fed5.tar.bz2
paranucker-e5f7f28cdaa1d344b9daa6826fa3d8c5c746fed5.tar.xz
paranucker-e5f7f28cdaa1d344b9daa6826fa3d8c5c746fed5.zip
Add exception for delete operator in checks for multiply non null checks.
Diffstat (limited to 'src/analysis/expression.cpp')
-rw-r--r--src/analysis/expression.cpp80
1 files changed, 79 insertions, 1 deletions
diff --git a/src/analysis/expression.cpp b/src/analysis/expression.cpp
index 523b96d..2b5e66f 100644
--- a/src/analysis/expression.cpp
+++ b/src/analysis/expression.cpp
@@ -54,6 +54,7 @@
#include "nodes/ref/array_ref.h"
#include "nodes/ref/component_ref.h"
#include "nodes/ref/indirect_ref.h"
+#include "nodes/ref/objtype_ref.h"
#include <set>
@@ -204,7 +205,84 @@ void analyseNeExpr(NeExprNode *node, const WalkItem &wi, WalkItem &wo)
}
else if (wi.knownVars.find(var) != wi.knownVars.end())
{
- reportUselessCheck(node, var);
+ bool doReport(true);
+ // exception for delete operator. it check for var != 0 before really delete
+ node1 = skipBackNop(node->parent);
+ if (node1 == COND_EXPR)
+ {
+ CondExprNode *cond = static_cast<CondExprNode*>(node1);
+ if (cond->args.size() >= 2 &&
+ skipNop(cond->args[0]) == NE_EXPR)
+ {
+ if (skipNop(cond->args[1]) == COMPOUND_EXPR)
+ {
+ CompoundExprNode *compound = static_cast<CompoundExprNode*>(
+ skipNop(cond->args[1]));
+ if (compound &&
+ compound->args.size() == 2 &&
+ compound->args[0] == CALL_EXPR &&
+ compound->args[1] == CALL_EXPR)
+ {
+ CallExprNode *call = static_cast<CallExprNode*>(
+ skipNop(compound->args[1]));
+ if (call && call->function == ADDR_EXPR)
+ {
+ AddrExprNode *addr = static_cast<AddrExprNode*>(
+ skipNop(call->function));
+ if (addr &&
+ !addr->args.empty() &&
+ skipNop(addr->args[0]) == FUNCTION_DECL &&
+ skipNop(addr->args[0])->label == "operator delete")
+ {
+ doReport = false;
+ }
+ }
+ }
+ }
+ else if (!cond->args.empty() &&
+ skipNop(cond->args[1]) == CALL_EXPR)
+ {
+ CallExprNode *call = static_cast<CallExprNode*>(
+ skipNop(cond->args[1]));
+ if (call && skipNop(call->function) == OBJ_TYPE_REF)
+ {
+ ObjTypeRefNode *typeRef = static_cast<ObjTypeRefNode*>(
+ skipNop(call->function));
+ if (typeRef &&
+ !typeRef->args.empty() &&
+ skipNop(typeRef->args[0]) == INDIRECT_REF)
+ {
+ IndirectRefNode *indirect = static_cast<IndirectRefNode*>(
+ skipNop(typeRef->args[0]));
+ if (indirect &&
+ skipNop(indirect->ref) == POINTER_PLUS_EXPR)
+ {
+ PointerPlusExprNode *plusExpr = static_cast<PointerPlusExprNode*>(
+ skipNop(indirect->ref));
+ if (plusExpr &&
+ !plusExpr->args.empty() &&
+ skipNop(plusExpr->args[0]) == COMPONENT_REF)
+ {
+ ComponentRefNode *comp = static_cast<ComponentRefNode*>(
+ skipNop(plusExpr->args[0]));
+ if (comp &&
+ skipNop(comp->object) == INDIRECT_REF &&
+ skipNop(comp->field) == FIELD_DECL)
+ {
+ std::string label = skipNop(comp->field)->label;
+ if (label.size() > 6 && label.substr(0, 6) == "_vptr.")
+ doReport = false;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (doReport)
+ reportUselessCheck(node, var);
}
}
wo.cleanExpr = false;