summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2015-06-22 17:31:24 +0300
committerAndrei Karas <akaras@inbox.ru>2015-06-22 17:31:24 +0300
commitcea1bf35ade4362d0a9e46980b1fdba44764ff61 (patch)
treef927a9a0272acc53e35b05133c62ba05f0405807
parent3aa8413b91ca6838f3b58abcafeb4d545d05117e (diff)
downloadparanucker-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.cpp40
-rw-r--r--src/analysis/analysis.h4
-rw-r--r--src/analysis/expression.cpp1
-rw-r--r--src/analysis/walkitem.h17
-rw-r--r--src/logger.cpp59
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");
}