diff options
author | Andrei Karas <akaras@inbox.ru> | 2015-06-22 17:31:24 +0300 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2015-06-22 17:31:24 +0300 |
commit | cea1bf35ade4362d0a9e46980b1fdba44764ff61 (patch) | |
tree | f927a9a0272acc53e35b05133c62ba05f0405807 | |
parent | 3aa8413b91ca6838f3b58abcafeb4d545d05117e (diff) | |
download | paranucker-cea1bf35ade4362d0a9e46980b1fdba44764ff61.tar.gz paranucker-cea1bf35ade4362d0a9e46980b1fdba44764ff61.tar.bz2 paranucker-cea1bf35ade4362d0a9e46980b1fdba44764ff61.tar.xz paranucker-cea1bf35ade4362d0a9e46980b1fdba44764ff61.zip |
Add support for related checks for "linked" variables.
Example:
void func(int *ptr1)
{
int *ptr2 = ptr1;
if (!ptr1)
return;
*ptr2 = 10;
}
here will be no warning.
-rw-r--r-- | src/analysis/analysis.cpp | 40 | ||||
-rw-r--r-- | src/analysis/analysis.h | 4 | ||||
-rw-r--r-- | src/analysis/expression.cpp | 1 | ||||
-rw-r--r-- | src/analysis/walkitem.h | 17 | ||||
-rw-r--r-- | src/logger.cpp | 59 |
5 files changed, 72 insertions, 49 deletions
diff --git a/src/analysis/analysis.cpp b/src/analysis/analysis.cpp index d22646a..5a47151 100644 --- a/src/analysis/analysis.cpp +++ b/src/analysis/analysis.cpp @@ -57,18 +57,7 @@ namespace Analysis // remove check null vars. void removeCheckNullVars(WalkItem &wi) { - FOR_EACH (std::set<std::string>::const_iterator, it, wi.removeNullVars) - { - // found var for deletion - if (wi.checkNullVars.find(*it) != wi.checkNullVars.end()) - { - wi.checkNullVars.erase(*it); - } - if (wi.addNullVars.find(*it) != wi.addNullVars.end()) - { - wi.addNullVars.erase(*it); - } - } + removeCheckNullVarsSet(wi, wi.removeNullVars); } void addCheckNullVars(WalkItem &wi, WalkItem &wo) @@ -88,9 +77,35 @@ void removeCheckNullVarsSet(WalkItem &wi, std::set<std::string> &vars) { wi.checkNullVars.erase(*it); } + if (wi.addNullVars.find(*it) != wi.addNullVars.end()) + { + wi.addNullVars.erase(*it); + } + StringMapSet::const_iterator it2 = wi.linkedVars.find(*it); + if (it2 != wi.linkedVars.end()) + { + const StringSet &linked = (*it2).second; + FOR_EACH (StringSet::const_iterator, it3, linked) + { + if (wi.checkNullVars.find(*it3) != wi.checkNullVars.end()) + { + wi.checkNullVars.erase(*it3); + } + } + wi.linkedVars.erase(*it); + } } } +void addLinkedVar(WalkItem &wi, + const std::string &parent, + const std::string &var) +{ + if (wi.linkedVars.find(parent) == wi.linkedVars.end()) + wi.linkedVars[parent] = std::set<std::string>(); + wi.linkedVars[parent].insert(var); +} + void startWalkTree(Node *node) { WalkItem wi; @@ -108,6 +123,7 @@ void walkTree(Node *node, const WalkItem &wi, WalkItem &wo) removeCheckNullVars(wi2); addCheckNullVars(wo, wi2); addCheckNullVars(wi2, wi2); + wi2.linkedVars = wo.linkedVars; // Log::dumpAttr(node, 1, wo.isReturned); const bool isReturned = wo.isReturned; diff --git a/src/analysis/analysis.h b/src/analysis/analysis.h index fe4bf67..fe3d295 100644 --- a/src/analysis/analysis.h +++ b/src/analysis/analysis.h @@ -45,6 +45,10 @@ namespace Analysis bool checkForReport(Node *node, const WalkItem &wi); + void addLinkedVar(WalkItem &wi, + const std::string &parent, + const std::string &var); + void removeCheckNullVars(WalkItem &wi); void removeCheckNullVarsSet(WalkItem &wi, diff --git a/src/analysis/expression.cpp b/src/analysis/expression.cpp index e460438..34f4998 100644 --- a/src/analysis/expression.cpp +++ b/src/analysis/expression.cpp @@ -362,6 +362,7 @@ void analyseBindExpr(BindExprNode *node, const WalkItem &wi, WalkItem &wo) if (checkForReport(initial, wi)) { wo.addNullVars.insert(varDecl->label); + addLinkedVar(wo, initial->label, varDecl->label); } } Log::dumpWI(node, "wo out ", wo); diff --git a/src/analysis/walkitem.h b/src/analysis/walkitem.h index 046ece0..3db62f8 100644 --- a/src/analysis/walkitem.h +++ b/src/analysis/walkitem.h @@ -20,9 +20,13 @@ #ifndef ANALYSIS_WALKITEM_H #define ANALYSIS_WALKITEM_H +#include <map> #include <set> #include <string> +typedef std::set<std::string> StringSet; +typedef std::map<std::string, StringSet> StringMapSet; + struct WalkItem { WalkItem() : @@ -31,6 +35,7 @@ struct WalkItem addNullVars(), checkedNullVars(), checkedNonNullVars(), + linkedVars(), stopWalking(false), isReturned(false), cleanExpr(false), @@ -44,6 +49,7 @@ struct WalkItem addNullVars(item.addNullVars), checkedNullVars(item.checkedNullVars), checkedNonNullVars(item.checkedNonNullVars), + linkedVars(item.linkedVars), stopWalking(item.stopWalking), isReturned(item.isReturned), cleanExpr(item.cleanExpr), @@ -51,11 +57,12 @@ struct WalkItem { } - std::set<std::string> checkNullVars; // need check for usage without null pointer check - std::set<std::string> removeNullVars; // need remove vars from parent checkNullVars - std::set<std::string> addNullVars; // need add vars to parent checkNullVars - std::set<std::string> checkedNullVars; // vars checked for null in expressions - std::set<std::string> checkedNonNullVars; // vars checked for nonnull in expressions + StringSet checkNullVars; // need check for usage without null pointer check + StringSet removeNullVars; // need remove vars from parent checkNullVars + StringSet addNullVars; // need add vars to parent checkNullVars + StringSet checkedNullVars; // vars checked for null in expressions + StringSet checkedNonNullVars; // vars checked for nonnull in expressions + StringMapSet linkedVars; // linked vars. map <parent, set(vars)> bool stopWalking; // stop walking on tree after this node bool isReturned; // set if return present in child nodes bool cleanExpr; // set if expression is only variable check without compound conditions diff --git a/src/logger.cpp b/src/logger.cpp index 1a1428d..af52e26 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -192,6 +192,15 @@ void dumpAttr(const Node *const node, int num, bool isReturned) fprintf(stderr, " walkTree%d: %d\n", num, isReturned ? 1 : 0); } +#define dumpWIProps(comment, name) \ + Log::log(comment); \ + FOR_EACH (StringSet::const_iterator, \ + it, \ + name) \ + { \ + Log::log("%s, ", (*it).c_str()); \ + } + void dumpWI(Node *const node, const std::string &name, const WalkItem &wi) @@ -207,40 +216,26 @@ void dumpWI(Node *const node, Log::log(" useless"); if (wi.isReturned) Log::log(" returned"); - Log::log(" checkedNullVars:"); - FOR_EACH (std::set<std::string>::const_iterator, - it, - wi.checkedNullVars) - { - Log::log("%s, ", (*it).c_str()); - } - Log::log(" checkedNonNullVars:"); - FOR_EACH (std::set<std::string>::const_iterator, - it, - wi.checkedNonNullVars) - { - Log::log("%s, ", (*it).c_str()); - } - Log::log(" checkNullVars:"); - FOR_EACH (std::set<std::string>::const_iterator, - it, - wi.checkNullVars) - { - Log::log("%s, ", (*it).c_str()); - } - Log::log(" removeNullVars:"); - FOR_EACH (std::set<std::string>::const_iterator, - it, - wi.removeNullVars) - { - Log::log("%s, ", (*it).c_str()); - } - Log::log(" addNullVars:"); - FOR_EACH (std::set<std::string>::const_iterator, + dumpWIProps(" checkedNullVars:", wi.checkedNullVars) + dumpWIProps(" checkedNonNullVars:", wi.checkedNonNullVars) + dumpWIProps(" checkNullVars:", wi.checkNullVars) + dumpWIProps(" removeNullVars:", wi.removeNullVars) + dumpWIProps(" addNullVars:", wi.addNullVars) + + Log::log(" linkedVars:"); + FOR_EACH (StringMapSet::const_iterator, it, - wi.addNullVars) + wi.linkedVars) { - Log::log("%s, ", (*it).c_str()); + Log::log("%s -> (", ((*it).first).c_str()); + const StringSet &vars = (*it).second; + FOR_EACH (StringSet::const_iterator, + it2, + vars) + { + Log::log("%s, ", (*it2).c_str()); + } + Log::log("), "); } Log::log("\n"); } |