diff options
author | Andrei Karas <akaras@inbox.ru> | 2015-06-28 21:56:24 +0300 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2015-06-28 21:56:24 +0300 |
commit | e5f7f28cdaa1d344b9daa6826fa3d8c5c746fed5 (patch) | |
tree | a214bc2bfcddd933a373698f920e571f1a9faf69 /src/analysis/expression.cpp | |
parent | 1c32401aa8613eba857bc56b5f0c31880ca2191f (diff) | |
download | paranucker-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.cpp | 80 |
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; |