summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2015-07-06 00:42:06 +0300
committerAndrei Karas <akaras@inbox.ru>2015-07-06 00:42:06 +0300
commitb260f025a974fca63c6a5ac01af346bc71d5e955 (patch)
tree176d99cdaf3856c352326d186944476b2650af38 /src
parentb106e3bb6c7fe99a53d12679db8a0315d051f955 (diff)
downloadparanucker-b260f025a974fca63c6a5ac01af346bc71d5e955.tar.gz
paranucker-b260f025a974fca63c6a5ac01af346bc71d5e955.tar.bz2
paranucker-b260f025a974fca63c6a5ac01af346bc71d5e955.tar.xz
paranucker-b260f025a974fca63c6a5ac01af346bc71d5e955.zip
Add way to track variables if to it was assigned function result.
Diffstat (limited to 'src')
-rw-r--r--src/analysis/collections.cpp17
-rw-r--r--src/analysis/collections.h7
-rw-r--r--src/analysis/expression.cpp78
-rw-r--r--src/analysis/expression.h4
-rw-r--r--src/analysis/function.cpp28
-rw-r--r--src/analysis/function.h6
6 files changed, 129 insertions, 11 deletions
diff --git a/src/analysis/collections.cpp b/src/analysis/collections.cpp
index 3d4f5e2..a475acc 100644
--- a/src/analysis/collections.cpp
+++ b/src/analysis/collections.cpp
@@ -137,13 +137,26 @@ void removeNeedCheckNullVarsSet(WalkItem &wi, std::set<std::string> &vars)
}
}
-void addNullVar(WalkItem &wi,
- const std::string &var)
+void addUnknownVar(WalkItem &wi,
+ const std::string &var)
{
+ wi.knownVars.insert(var);
+ wi.knownNullVars.erase(var);
+ wi.knownNonNullVars.erase(var);
wi.addNullVars.insert(var);
wi.removeNullVars.erase(var);
}
+void addNonNullVar(WalkItem &wi,
+ const std::string &var)
+{
+ wi.knownVars.insert(var);
+ wi.knownNullVars.erase(var);
+ wi.knownNonNullVars.insert(var);
+ wi.addNullVars.erase(var);
+ wi.removeNullVars.insert(var);
+}
+
// link var to parent. (type var = parent)
void addLinkedVar(WalkItem &wi,
std::string parent,
diff --git a/src/analysis/collections.h b/src/analysis/collections.h
index 738b8a8..388a50f 100644
--- a/src/analysis/collections.h
+++ b/src/analysis/collections.h
@@ -33,8 +33,11 @@ namespace Analysis
void addNeedCheckNullVars(WalkItem &wi,
WalkItem &wo);
- void addNullVar(WalkItem &wi,
- const std::string &var);
+ void addUnknownVar(WalkItem &wi,
+ const std::string &var);
+
+ void addNonNullVar(WalkItem &wi,
+ const std::string &var);
void addLinkedVar(WalkItem &wi,
std::string parent,
diff --git a/src/analysis/expression.cpp b/src/analysis/expression.cpp
index 53f13c5..7c5194e 100644
--- a/src/analysis/expression.cpp
+++ b/src/analysis/expression.cpp
@@ -83,6 +83,29 @@ std::string getVariableName(Node *node)
return "";
}
+bool isPointerArg(Node *node)
+{
+ if (!node)
+ return false;
+
+ node = skipNop(node);
+ if (!node)
+ return false;
+ if (node == PARM_DECL)
+ {
+ ParmDeclNode *decl = static_cast<ParmDeclNode*>(node);
+ if (skipNop(decl->declType) == POINTER_TYPE)
+ return true;
+ }
+ else if (node == VAR_DECL)
+ {
+ VarDeclNode *var = static_cast<VarDeclNode*>(node);
+ if (skipNop(var->varType) == POINTER_TYPE)
+ return true;
+ }
+ return false;
+}
+
// return variable name in format object->field for component node
std::string getComponentRefVariable(Node *node)
{
@@ -137,7 +160,13 @@ void analyseModifyExpr(ModifyExprNode *node, const WalkItem &wi, WalkItem &wo)
{
if (var2.empty())
{ // have var1 only (var1 = UNKNOWN)
- removeVar(wo, var1);
+ bool handled(false);
+ if (node->args[1] == CALL_EXPR && isPointerArg(arg))
+ {
+ handled = handleSetVarToFunction(var1, node->args[1], wo);
+ }
+ if (!handled)
+ removeVar(wo, var1);
}
else
{ // have var1 and var2 (var1 = var2)
@@ -704,6 +733,37 @@ void handleSetVarDecl(Node *node,
}
}
+bool handleSetVarToFunction(const std::string &var,
+ Node *node2,
+ WalkItem &wo)
+{
+ CallExprNode *call = static_cast<CallExprNode*>(node2);
+ if (call->function != ADDR_EXPR)
+ return false;
+ AddrExprNode *addr = static_cast<AddrExprNode*>(call->function);
+ if (!addr ||
+ addr->args.empty() ||
+ addr->args[0] != FUNCTION_DECL)
+ {
+ return false;
+ }
+ FunctionDeclNode *func = static_cast<FunctionDeclNode*>(addr->args[0]);
+ removeVar(wo, var);
+ if (!func->functionType)
+ return false;
+
+ if (findTreeListPurpose(static_cast<TreeListNode*>(func->functionType->attribute),
+ "returns_nonnull"))
+ { // function have attribute returns_nonnull. This mean result cant be null
+ addNonNullVar(wo, var);
+ }
+ else
+ { // function not have attribute returns_nonnull. This mean result can be null
+ addUnknownVar(wo, var);
+ }
+ return true;
+}
+
void handleSetVar(Node *node1,
Node *node2,
const WalkItem &wi,
@@ -712,11 +772,21 @@ void handleSetVar(Node *node1,
// var1 = var2
const std::string var1 = getVariableName(node1);
const std::string var2 = getVariableName(node2);
- if (var1.empty() || var2.empty())
+ if (var1.empty())
return;
- if (isNotIn(var2, wi.knownVars))
+ if (var2.empty())
+ {
+ node2 = skipNop(node2);
+ if (node2 == CALL_EXPR && isPointerArg(node1))
+ handleSetVarToFunction(var1, node2, wo);
return;
- addLinkedVar(wo, var2, var1);
+ }
+ else
+ {
+ if (isNotIn(var2, wi.knownVars))
+ return;
+ addLinkedVar(wo, var2, var1);
+ }
}
// field = var
diff --git a/src/analysis/expression.h b/src/analysis/expression.h
index ccba0ca..8d8bb8c 100644
--- a/src/analysis/expression.h
+++ b/src/analysis/expression.h
@@ -94,6 +94,10 @@ namespace Analysis
WalkItem &wo);
std::string getComponentRefVariable(Node *node);
+
+ bool handleSetVarToFunction(const std::string &var,
+ Node *node2,
+ WalkItem &wo);
}
#endif // ANALYSIS_EXPRESSION_H
diff --git a/src/analysis/function.cpp b/src/analysis/function.cpp
index e9de29a..8bb9566 100644
--- a/src/analysis/function.cpp
+++ b/src/analysis/function.cpp
@@ -57,6 +57,19 @@ void getFunctionArgTypes(FunctionDeclNode *node,
}
}
+bool findTreeListPurpose(TreeListNode *list,
+ const std::string &name)
+{
+ FOR_TREE_LIST(list)
+ {
+ if (list->purpose && list->purpose->label == name)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
// find in TREE_LIST purpose with given label and get value
TreeListNode *findTreeListPurposeValue(TreeListNode *list,
const std::string &name)
@@ -71,15 +84,24 @@ TreeListNode *findTreeListPurposeValue(TreeListNode *list,
return nullptr;
}
+TreeListNode *findFunctionDeclAttribute(FunctionDeclNode *node,
+ const std::string &name)
+{
+ // function not have type
+ if (!node->functionType)
+ return nullptr;
+ return findTreeListPurposeValue(
+ static_cast<TreeListNode*>(node->functionType->attribute),
+ name);
+}
+
void getFunctionParamsNonNullAttributes(FunctionDeclNode *node,
std::set<int> &arr)
{
// function not have type
if (!node->functionType)
return;
- TreeListNode *list = findTreeListPurposeValue(
- static_cast<TreeListNode*>(node->functionType->attribute),
- "nonnull");
+ TreeListNode *list = findFunctionDeclAttribute(node, "nonnull");
// no attribute nonnull
if (!list)
return;
diff --git a/src/analysis/function.h b/src/analysis/function.h
index f7e0a66..9358efe 100644
--- a/src/analysis/function.h
+++ b/src/analysis/function.h
@@ -38,6 +38,12 @@ namespace Analysis
void getFunctionParamsNonNullAttributes(FunctionDeclNode *node,
std::set<int> &arr);
+
+ TreeListNode *findFunctionDeclAttribute(FunctionDeclNode *node,
+ const std::string &name);
+
+ bool findTreeListPurpose(TreeListNode *list,
+ const std::string &name);
}
#endif // ANALYSIS_FUNCTION_H