diff options
author | Andrei Karas <akaras@inbox.ru> | 2015-07-06 00:42:06 +0300 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2015-07-06 00:42:06 +0300 |
commit | b260f025a974fca63c6a5ac01af346bc71d5e955 (patch) | |
tree | 176d99cdaf3856c352326d186944476b2650af38 /src | |
parent | b106e3bb6c7fe99a53d12679db8a0315d051f955 (diff) | |
download | paranucker-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.cpp | 17 | ||||
-rw-r--r-- | src/analysis/collections.h | 7 | ||||
-rw-r--r-- | src/analysis/expression.cpp | 78 | ||||
-rw-r--r-- | src/analysis/expression.h | 4 | ||||
-rw-r--r-- | src/analysis/function.cpp | 28 | ||||
-rw-r--r-- | src/analysis/function.h | 6 |
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 |