/*
* 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/reports.h"
#include "command.h"
#include "logger.h"
#include "analysis/analysis.h"
#include "analysis/expression.h"
#include "analysis/varitem.h"
#include "analysis/walkitem.h"
#include "nodes/base/node.h"
#include "nodes/decl/parm_decl.h"
#include "nodes/decl/var_decl.h"
#include "localconsts.h"
namespace Analysis
{
// check is var from node can be checked for null pointer
bool checkForReport(Node *node,
const WalkItem &wi)
{
node = skipNop(node);
return node &&
(node == PARM_DECL || node == VAR_DECL) &&
isIn(node->label, wi.needCheckNullVars);
}
// report about useless check for null pointer
void reportUselessCheck(Node *node,
const std::string &var)
{
if (!checkCommand(DetectUseless))
return;
Log::warn(findBackLocation(node),
"Useless variable check '%s'. It already was checked before",
var);
}
// report about null pointer if need for node
void reportParmDeclNullPointer(Node *mainNode,
Node *node,
const WalkItem &wi)
{
node = skipNop(node);
if (node)
{
if (!node->label.empty())
{
if (node == PARM_DECL)
{
ParmDeclNode *parmDecl = static_cast(node);
if (parmDecl->declType == POINTER_TYPE &&
isIn(node->label, wi.needCheckNullVars))
{
Log::warn(findBackLocation(mainNode),
"Using variable '%s' without checking for null pointer",
node->label);
}
}
else if (node == VAR_DECL)
{
VarDeclNode *varDecl = static_cast(node);
if (varDecl->varType == POINTER_TYPE &&
isIn(node->label, wi.needCheckNullVars))
{
Log::warn(findBackLocation(mainNode),
"Using variable '%s' without checking for null pointer",
node->label);
}
}
}
else if (node == COMPONENT_REF)
{
auto vars = getComponentRefParts(node);
FOR_EACH (var, vars)
{
if (!var.isNonNull &&
(isIn(var.name, wi.needCheckNullVars) ||
isNotIn(var.name, wi.knownVars)))
{
Log::warn(findBackLocation(mainNode),
"Using variable '%s' without checking for null pointer",
var.name);
}
}
}
}
}
// report about null pointer if need for node
void reportParmDeclLeftNullPointer(Node *mainNode,
Node *node,
const WalkItem &wi)
{
node = skipNop(node);
if (node)
{
if (node == COMPONENT_REF)
{
auto vars = getComponentRefLeftParts(node);
FOR_EACH (var, vars)
{
if (!var.isNonNull &&
(isIn(var.name, wi.needCheckNullVars) ||
isNotIn(var.name, wi.knownVars)))
{
Log::warn(findBackLocation(mainNode),
"Using variable '%s' without checking for null pointer",
var.name);
}
}
}
}
}
// report about null pointer if need for node
void reportComponentRefNullPointer(Node *mainNode,
Node *node,
const WalkItem &wi)
{
node = skipNop(node);
if (node)
{
if (node == COMPONENT_REF)
{
auto vars = getComponentRefParts(node);
FOR_EACH (var, vars)
{
if (!var.isNonNull &&
isIn(var.name, wi.needCheckNullVars))
{
Log::warn(findBackLocation(mainNode),
"Using variable '%s' without checking for null pointer",
var.name);
}
}
}
}
}
void reportPossibleNullPointer(Node *node,
const std::string &label)
{
Log::warn(findBackLocation(node),
"warning: possible null argument '%s' where non-null required",
label);
}
void reportParmDeclAttrNullPointer(Node *mainNode,
Node *node,
const WalkItem &wi)
{
node = skipNop(node);
if (node)
{
if (!node->label.empty())
{
if (node == PARM_DECL)
{
ParmDeclNode *parmDecl = static_cast(node);
if (parmDecl->declType == POINTER_TYPE &&
isIn(node->label, wi.needCheckNullVars))
{
reportPossibleNullPointer(mainNode, node->label);
}
}
else if (node == VAR_DECL)
{
VarDeclNode *varDecl = static_cast(node);
if (varDecl->varType == POINTER_TYPE &&
isIn(node->label, wi.needCheckNullVars))
{
reportPossibleNullPointer(mainNode, node->label);
}
}
}
else if (node == COMPONENT_REF)
{
VarItem var = getComponentRefVariable(node);
if (!var.isNonNull && isIn(var.name, wi.needCheckNullVars))
reportPossibleNullPointer(mainNode, node->label);
}
}
}
void reportWrongCheck(Node *node)
{
Log::warn(findBackLocation(node),
"warning: wrong call to internal debug function. Three arguments required",
"");
}
void reportCollectionsDifferent(Node *node,
const std::string &name,
const std::string& str1,
const std::string& str2)
{
std::string str = "internal collections '%s' is different.\nwant: " +
str2 +
"\n get: " +
str1;
Log::warn(findBackLocation(node),
str,
name);
}
}