summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2015-07-19 01:05:26 +0300
committerAndrei Karas <akaras@inbox.ru>2015-07-19 01:05:26 +0300
commit63c96de147bcdd5dd2edc7acee872f768eca916c (patch)
tree774617e41ecd641032429fee7360a6a9e24f3d45
parent04c30021f7097fd3d2aafdbe159d39510ba22e49 (diff)
downloadparanucker-63c96de147bcdd5dd2edc7acee872f768eca916c.tar.gz
paranucker-63c96de147bcdd5dd2edc7acee872f768eca916c.tar.bz2
paranucker-63c96de147bcdd5dd2edc7acee872f768eca916c.tar.xz
paranucker-63c96de147bcdd5dd2edc7acee872f768eca916c.zip
Add ability for detect what variable will be non null after if block.
Example: if (!ptr) { ptr1 = new data; } // here ptr1 always non null
-rw-r--r--src/analysis/collections.cpp31
-rw-r--r--src/analysis/collections.h6
-rw-r--r--src/analysis/statement.cpp4
3 files changed, 41 insertions, 0 deletions
diff --git a/src/analysis/collections.cpp b/src/analysis/collections.cpp
index 4fb861d..d8d9510 100644
--- a/src/analysis/collections.cpp
+++ b/src/analysis/collections.cpp
@@ -58,6 +58,20 @@ void addNeedCheckNullVars2(WalkItem &wi, WalkItem &wo)
}
}
+void removeNeedCheckNullVars2(WalkItem &wco, WalkItem &wi, WalkItem &wo)
+{
+ FOR_EACH (it, wi.knownNonNullVars)
+ {
+ // check what it presend in if condition like if (!it) and in else like if (it)
+ if (isIn(it, wco.checkedThenNullVars) &&
+ isIn(it, wco.checkedElseNonNullVars))
+ {
+ removeNeedCheckNullVarOnly(wo, it);
+ addNonNullVar(wo, it);
+ }
+ }
+}
+
// remove one variable from null pointer checks
void removeNeedCheckNullVar(WalkItem &wi, std::string str)
{
@@ -379,6 +393,23 @@ void addKnownNonNullVarsWithLinked(WalkItem &wo, WalkItem &wi, std::set<std::str
}
}
+void addKnownNonNullVarWithLinked(WalkItem &wo, WalkItem &wi, const std::string &var)
+{
+ wo.knownNonNullVars.insert(var);
+ auto it2 = wi.linkedVars.find(var);
+ if (it2 == wi.linkedVars.end() &&
+ isIn(var, wi.linkedReverseVars))
+ {
+ wo.knownNonNullVars.insert(wi.linkedReverseVars[var]);
+ it2 = wi.linkedVars.find(wi.linkedReverseVars[var]);
+ }
+ if (it2 != wi.linkedVars.end())
+ {
+ const StringSet &linked = (*it2).second;
+ wo.knownNonNullVars.insert(linked.begin(), linked.end());
+ }
+}
+
void removeVar(WalkItem &wi, const std::string &var)
{
wi.removeNullVars.insert(var);
diff --git a/src/analysis/collections.h b/src/analysis/collections.h
index a03cbe5..1e36bf0 100644
--- a/src/analysis/collections.h
+++ b/src/analysis/collections.h
@@ -86,6 +86,12 @@ namespace Analysis
void enforceNeedCheckNullVars(WalkItem &wi);
void removeLinkVarOnly(WalkItem &wi, const std::string &var);
+
+ void removeNeedCheckNullVars2(WalkItem &wco, WalkItem &wi, WalkItem &wo);
+
+ void addKnownNonNullVarWithLinked(WalkItem &wo, WalkItem &wi, const std::string &var);
+
+ void removeNeedCheckNullVarOnly(WalkItem &wi, const std::string &var);
}
#endif // ANALYSIS_COLLECTIONS_H
diff --git a/src/analysis/statement.cpp b/src/analysis/statement.cpp
index 5f1f95b..39c03d2 100644
--- a/src/analysis/statement.cpp
+++ b/src/analysis/statement.cpp
@@ -126,6 +126,7 @@ void analyseCondition(Node *node,
else if (thenNode)
{
addNeedCheckNullVars2(wo2, wo);
+ removeNeedCheckNullVars2(wco, wo2, wo);
}
if (wo3.isReturned || wo3.isContinued)
{
@@ -144,6 +145,7 @@ void analyseCondition(Node *node,
else if (elseNode)
{
addNeedCheckNullVars2(wo3, wo);
+ removeNeedCheckNullVars2(wco, wo2, wo);
}
if ((wo2.isReturned || wo2.isContinued) && (wo3.isReturned || wo3.isContinued))
{
@@ -242,6 +244,8 @@ void analyseWhileStmt(WhileStmtNode *node, const WalkItem &wi, WalkItem &wo)
walkTree(condNode, wci, wco);
command = oldCommand;
Log::dumpWI(node, "wco2 ", wco);
+
+ removeNeedCheckNullVars2(wco, wo2, wo);
}
wo.isReturned = false;