/* * Copyright (C) 2015 Andrei Karas * * This file is part of Paranoid null checker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "analysis/function.h" #include "command.h" #include "logger.h" #include "analysis/analysis.h" #include "analysis/walkitem.h" #include "nodes/decl/function_decl.h" #include "nodes/list/tree_list.h" #include "nodes/type/method_type.h" #include #include "localconsts.h" namespace Analysis { // put arg types into arr void getFunctionArgTypes(FunctionDeclNode *node, std::vector &arr) { TreeListNode *types = nullptr; if (node->functionType == FUNCTION_TYPE) types = static_cast(node->functionType)->argTypes; else if (node->functionType == METHOD_TYPE) types = static_cast(node->functionType)->argTypes; else return; // walk in TREE_LIST and get value nodes FOR_TREE_LIST2(list, types) { arr.push_back(static_cast(list->value)); } } // find in TREE_LIST purpose with given label and get value TreeListNode *findTreeListPurposeValue(TreeListNode *list, const std::string &name) { FOR_TREE_LIST(list) { if (list->purpose && list->purpose->label == name) { return static_cast(list->value); } } return nullptr; } void getFunctionParamsNonNullAttributes(FunctionDeclNode *node, std::set &arr) { // function not have type if (!node->functionType) return; TreeListNode *list = findTreeListPurposeValue( static_cast(node->functionType->attribute), "nonnull"); // no attribute nonnull if (!list) return; // get all labels from TREE_LIST and convert to int. // tree based on constants for attribute nonnull FOR_TREE_LIST(list) { if (list->value) { arr.insert(atoi(list->value->label.c_str())); } } } void getPossibleNullParameters(FunctionDeclNode *node, WalkItem &wi) { std::vector types; std::set nonNull; getFunctionArgTypes(node, types); getFunctionParamsNonNullAttributes(node, nonNull); if (checkCommand(FindArgs)) Log::log("%s: ", node->label.c_str()); size_t sz = node->args.size(); if (types.size() < sz) sz = types.size(); for (size_t f = 0; f < sz; f ++) { const TypeNode *const type = types[f]; if (!type || type != POINTER_TYPE) continue; const ParmDeclNode *const name = node->args[f]; if (f == 0 && name->label == "this") continue; if (nonNull.find(f + 1) == nonNull.end()) { if (checkCommand(FindArgs)) { Log::log("%s %s, ", type->nodeTypeName.c_str(), name->label.c_str()); } wi.needCheckNullVars.insert(name->label); wi.knownVars.insert(name->label); } } if (checkCommand(FindArgs)) Log::log("\n"); } void analyseFunction(FunctionDeclNode *node, const WalkItem &wi, WalkItem &wo) { // ignore external functions if (node->isExternal) { wo.stopWalking = true; return; } if (node->code) { // probably function definition WalkItem wi2 = wi; getPossibleNullParameters(node, wi2); walkTree(node->code, wi2, wo); } wo.stopWalking = true; } }