Formatting: uniformize end of lines.
This commit is contained in:
parent
c56779c9ae
commit
a5fa323a0b
File diff suppressed because it is too large
Load Diff
|
@ -1,54 +1,54 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#ifndef CheckBufferOverrunH
|
#ifndef CheckBufferOverrunH
|
||||||
#define CheckBufferOverrunH
|
#define CheckBufferOverrunH
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
#include "errorlogger.h"
|
#include "errorlogger.h"
|
||||||
|
|
||||||
class CheckBufferOverrunClass
|
class CheckBufferOverrunClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CheckBufferOverrunClass( const Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger );
|
CheckBufferOverrunClass( const Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger );
|
||||||
~CheckBufferOverrunClass();
|
~CheckBufferOverrunClass();
|
||||||
|
|
||||||
// Buffer overrun..
|
// Buffer overrun..
|
||||||
void CheckBufferOverrun();
|
void CheckBufferOverrun();
|
||||||
|
|
||||||
|
|
||||||
// Dangerous functions that can cause buffer overruns
|
// Dangerous functions that can cause buffer overruns
|
||||||
void WarningDangerousFunctions();
|
void WarningDangerousFunctions();
|
||||||
private:
|
private:
|
||||||
void CheckBufferOverrun_StructVariable();
|
void CheckBufferOverrun_StructVariable();
|
||||||
void CheckBufferOverrun_LocalVariable();
|
void CheckBufferOverrun_LocalVariable();
|
||||||
void CheckBufferOverrun_CheckScope( const TOKEN *tok, const char *varname[], const int size, const int total_size, unsigned int varid );
|
void CheckBufferOverrun_CheckScope( const TOKEN *tok, const char *varname[], const int size, const int total_size, unsigned int varid );
|
||||||
void ReportError(const TOKEN *tok, const char errmsg[]);
|
void ReportError(const TOKEN *tok, const char errmsg[]);
|
||||||
|
|
||||||
const Tokenizer *_tokenizer;
|
const Tokenizer *_tokenizer;
|
||||||
const Settings _settings;
|
const Settings _settings;
|
||||||
ErrorLogger *_errorLogger;
|
ErrorLogger *_errorLogger;
|
||||||
std::list<const TOKEN *> _callStack;
|
std::list<const TOKEN *> _callStack;
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
1496
checkclass.cpp
1496
checkclass.cpp
File diff suppressed because it is too large
Load Diff
134
checkclass.h
134
checkclass.h
|
@ -1,67 +1,67 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#ifndef CheckClassH
|
#ifndef CheckClassH
|
||||||
#define CheckClassH
|
#define CheckClassH
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "errorlogger.h"
|
#include "errorlogger.h"
|
||||||
|
|
||||||
class CheckClass
|
class CheckClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CheckClass( const Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger );
|
CheckClass( const Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger );
|
||||||
~CheckClass();
|
~CheckClass();
|
||||||
|
|
||||||
void CheckConstructors();
|
void CheckConstructors();
|
||||||
|
|
||||||
void CheckUnusedPrivateFunctions();
|
void CheckUnusedPrivateFunctions();
|
||||||
|
|
||||||
void CheckMemset();
|
void CheckMemset();
|
||||||
|
|
||||||
void CheckOperatorEq1(); // Warning upon "void operator=(.."
|
void CheckOperatorEq1(); // Warning upon "void operator=(.."
|
||||||
|
|
||||||
// The destructor in a base class should be virtual
|
// The destructor in a base class should be virtual
|
||||||
void virtualDestructor();
|
void virtualDestructor();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct VAR
|
struct VAR
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
bool init;
|
bool init;
|
||||||
struct VAR *next;
|
struct VAR *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
void ClassChecking_VarList_Initialize(const TOKEN *tok1, const TOKEN *ftok, struct VAR *varlist, const char classname[], std::list<std::string> &callstack);
|
void ClassChecking_VarList_Initialize(const TOKEN *tok1, const TOKEN *ftok, struct VAR *varlist, const char classname[], std::list<std::string> &callstack);
|
||||||
void InitVar(struct VAR *varlist, const char varname[]);
|
void InitVar(struct VAR *varlist, const char varname[]);
|
||||||
const TOKEN *FindClassFunction( const TOKEN *tok, const char classname[], const char funcname[], int &indentlevel );
|
const TOKEN *FindClassFunction( const TOKEN *tok, const char classname[], const char funcname[], int &indentlevel );
|
||||||
struct VAR *ClassChecking_GetVarList(const TOKEN *tok1);
|
struct VAR *ClassChecking_GetVarList(const TOKEN *tok1);
|
||||||
|
|
||||||
// Check constructors for a specified class
|
// Check constructors for a specified class
|
||||||
void CheckConstructors(const TOKEN *tok1, struct VAR *varlist, const char funcname[]);
|
void CheckConstructors(const TOKEN *tok1, struct VAR *varlist, const char funcname[]);
|
||||||
|
|
||||||
const Tokenizer *_tokenizer;
|
const Tokenizer *_tokenizer;
|
||||||
Settings _settings;
|
Settings _settings;
|
||||||
ErrorLogger *_errorLogger;
|
ErrorLogger *_errorLogger;
|
||||||
};
|
};
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,167 +1,167 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#include "checkfunctionusage.h"
|
#include "checkfunctionusage.h"
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// FUNCTION USAGE - Check for unused functions etc
|
// FUNCTION USAGE - Check for unused functions etc
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
CheckFunctionUsage::CheckFunctionUsage( ErrorLogger *errorLogger )
|
CheckFunctionUsage::CheckFunctionUsage( ErrorLogger *errorLogger )
|
||||||
{
|
{
|
||||||
_errorLogger = errorLogger;
|
_errorLogger = errorLogger;
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckFunctionUsage::~CheckFunctionUsage()
|
CheckFunctionUsage::~CheckFunctionUsage()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CheckFunctionUsage::parseTokens( const Tokenizer &tokenizer )
|
void CheckFunctionUsage::parseTokens( const Tokenizer &tokenizer )
|
||||||
{
|
{
|
||||||
// Function declarations..
|
// Function declarations..
|
||||||
for ( const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next() )
|
for ( const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next() )
|
||||||
{
|
{
|
||||||
if ( tok->fileIndex() != 0 )
|
if ( tok->fileIndex() != 0 )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const TOKEN *funcname = 0;
|
const TOKEN *funcname = 0;
|
||||||
|
|
||||||
if ( TOKEN::Match( tok, "%type% %var% (" ) )
|
if ( TOKEN::Match( tok, "%type% %var% (" ) )
|
||||||
funcname = tok->tokAt(1);
|
funcname = tok->tokAt(1);
|
||||||
else if ( TOKEN::Match(tok, "%type% * %var% (") )
|
else if ( TOKEN::Match(tok, "%type% * %var% (") )
|
||||||
funcname = tok->tokAt(2);
|
funcname = tok->tokAt(2);
|
||||||
else if ( TOKEN::Match(tok, "%type% :: %var% (") && !TOKEN::Match(tok, tok->strAt(2)) )
|
else if ( TOKEN::Match(tok, "%type% :: %var% (") && !TOKEN::Match(tok, tok->strAt(2)) )
|
||||||
funcname = tok->tokAt(2);
|
funcname = tok->tokAt(2);
|
||||||
|
|
||||||
// Check that ") {" is found..
|
// Check that ") {" is found..
|
||||||
for (const TOKEN *tok2 = funcname; tok2; tok2 = tok2->next())
|
for (const TOKEN *tok2 = funcname; tok2; tok2 = tok2->next())
|
||||||
{
|
{
|
||||||
if ( TOKEN::Match(tok2, ")") )
|
if ( TOKEN::Match(tok2, ")") )
|
||||||
{
|
{
|
||||||
if ( ! TOKEN::Match(tok2, ") {") && ! TOKEN::Match(tok2, ") const {") )
|
if ( ! TOKEN::Match(tok2, ") {") && ! TOKEN::Match(tok2, ") const {") )
|
||||||
funcname = NULL;
|
funcname = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( funcname )
|
if ( funcname )
|
||||||
{
|
{
|
||||||
FunctionUsage &func = _functions[ funcname->str() ];
|
FunctionUsage &func = _functions[ funcname->str() ];
|
||||||
|
|
||||||
// No filename set yet..
|
// No filename set yet..
|
||||||
if (func.filename.empty())
|
if (func.filename.empty())
|
||||||
func.filename = tokenizer.getFiles()->at(0);
|
func.filename = tokenizer.getFiles()->at(0);
|
||||||
|
|
||||||
// Multiple files => filename = "+"
|
// Multiple files => filename = "+"
|
||||||
else if (func.filename != tokenizer.getFiles()->at(0))
|
else if (func.filename != tokenizer.getFiles()->at(0))
|
||||||
{
|
{
|
||||||
func.filename = "+";
|
func.filename = "+";
|
||||||
func.usedOtherFile |= func.usedSameFile;
|
func.usedOtherFile |= func.usedSameFile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function usage..
|
// Function usage..
|
||||||
for ( const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next() )
|
for ( const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next() )
|
||||||
{
|
{
|
||||||
const TOKEN *funcname = 0;
|
const TOKEN *funcname = 0;
|
||||||
|
|
||||||
if ( TOKEN::Match( tok, "[;{}.,()[=+-/&|!?:] %var% [(),;:}]" ) ||
|
if ( TOKEN::Match( tok, "[;{}.,()[=+-/&|!?:] %var% [(),;:}]" ) ||
|
||||||
TOKEN::Match(tok, ":: %var% (") ||
|
TOKEN::Match(tok, ":: %var% (") ||
|
||||||
TOKEN::Match(tok, "|= %var% (") ||
|
TOKEN::Match(tok, "|= %var% (") ||
|
||||||
TOKEN::Match(tok, "&= %var% (") ||
|
TOKEN::Match(tok, "&= %var% (") ||
|
||||||
TOKEN::Match(tok, "&& %var% (") ||
|
TOKEN::Match(tok, "&& %var% (") ||
|
||||||
TOKEN::Match(tok, "|| %var% (") ||
|
TOKEN::Match(tok, "|| %var% (") ||
|
||||||
TOKEN::Match(tok, "else %var% (") ||
|
TOKEN::Match(tok, "else %var% (") ||
|
||||||
TOKEN::Match(tok, "return %var% (") )
|
TOKEN::Match(tok, "return %var% (") )
|
||||||
funcname = tok->next();
|
funcname = tok->next();
|
||||||
|
|
||||||
// funcname ( => Assert that the end paranthesis isn't followed by {
|
// funcname ( => Assert that the end paranthesis isn't followed by {
|
||||||
if ( TOKEN::Match(funcname, "%var% (") )
|
if ( TOKEN::Match(funcname, "%var% (") )
|
||||||
{
|
{
|
||||||
int parlevel = 0;
|
int parlevel = 0;
|
||||||
for ( const TOKEN *tok2 = funcname; tok2; tok2 = tok2->next() )
|
for ( const TOKEN *tok2 = funcname; tok2; tok2 = tok2->next() )
|
||||||
{
|
{
|
||||||
if (tok2->str() == "(")
|
if (tok2->str() == "(")
|
||||||
++parlevel;
|
++parlevel;
|
||||||
|
|
||||||
else if (tok2->str() == ")")
|
else if (tok2->str() == ")")
|
||||||
{
|
{
|
||||||
--parlevel;
|
--parlevel;
|
||||||
if (parlevel == 0 && (TOKEN::Match(tok2, ") {") || TOKEN::Match(tok2, ") const")))
|
if (parlevel == 0 && (TOKEN::Match(tok2, ") {") || TOKEN::Match(tok2, ") const")))
|
||||||
funcname = NULL;
|
funcname = NULL;
|
||||||
if ( parlevel <= 0 )
|
if ( parlevel <= 0 )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( funcname )
|
if ( funcname )
|
||||||
{
|
{
|
||||||
FunctionUsage &func = _functions[ funcname->str() ];
|
FunctionUsage &func = _functions[ funcname->str() ];
|
||||||
|
|
||||||
if ( func.filename.empty() || func.filename == "+" )
|
if ( func.filename.empty() || func.filename == "+" )
|
||||||
func.usedOtherFile = true;
|
func.usedOtherFile = true;
|
||||||
|
|
||||||
else
|
else
|
||||||
func.usedSameFile = true;
|
func.usedSameFile = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void CheckFunctionUsage::check()
|
void CheckFunctionUsage::check()
|
||||||
{
|
{
|
||||||
for ( std::map<std::string, FunctionUsage>::const_iterator it = _functions.begin(); it != _functions.end(); ++it )
|
for ( std::map<std::string, FunctionUsage>::const_iterator it = _functions.begin(); it != _functions.end(); ++it )
|
||||||
{
|
{
|
||||||
const FunctionUsage &func = it->second;
|
const FunctionUsage &func = it->second;
|
||||||
if ( func.usedOtherFile || func.filename.empty() )
|
if ( func.usedOtherFile || func.filename.empty() )
|
||||||
continue;
|
continue;
|
||||||
if ( ! func.usedSameFile )
|
if ( ! func.usedSameFile )
|
||||||
{
|
{
|
||||||
std::ostringstream errmsg;
|
std::ostringstream errmsg;
|
||||||
if ( func.filename != "+" )
|
if ( func.filename != "+" )
|
||||||
errmsg << "[" << func.filename << "] ";
|
errmsg << "[" << func.filename << "] ";
|
||||||
errmsg << "The function '" << it->first << "' is never used.";
|
errmsg << "The function '" << it->first << "' is never used.";
|
||||||
_errorLogger->reportErr( errmsg.str() );
|
_errorLogger->reportErr( errmsg.str() );
|
||||||
}
|
}
|
||||||
else if ( ! func.usedOtherFile )
|
else if ( ! func.usedOtherFile )
|
||||||
{
|
{
|
||||||
/* TODO - add error message "function is only used in <file> it can be static"
|
/* TODO - add error message "function is only used in <file> it can be static"
|
||||||
std::ostringstream errmsg;
|
std::ostringstream errmsg;
|
||||||
errmsg << "The function '" << it->first << "' is only used in the file it was declared in so it should have local linkage.";
|
errmsg << "The function '" << it->first << "' is only used in the file it was declared in so it should have local linkage.";
|
||||||
_errorLogger->reportErr( errmsg.str() );
|
_errorLogger->reportErr( errmsg.str() );
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,66 +1,66 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#ifndef CheckFunctionUsageH
|
#ifndef CheckFunctionUsageH
|
||||||
#define CheckFunctionUsageH
|
#define CheckFunctionUsageH
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
#include "errorlogger.h"
|
#include "errorlogger.h"
|
||||||
|
|
||||||
class CheckFunctionUsage
|
class CheckFunctionUsage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CheckFunctionUsage( ErrorLogger *errorLogger );
|
CheckFunctionUsage( ErrorLogger *errorLogger );
|
||||||
~CheckFunctionUsage();
|
~CheckFunctionUsage();
|
||||||
|
|
||||||
// Parse current tokens and determine..
|
// Parse current tokens and determine..
|
||||||
// * Check what functions are used
|
// * Check what functions are used
|
||||||
// * What functions are declared
|
// * What functions are declared
|
||||||
void parseTokens( const Tokenizer &tokenizer );
|
void parseTokens( const Tokenizer &tokenizer );
|
||||||
|
|
||||||
|
|
||||||
void check();
|
void check();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ErrorLogger *_errorLogger;
|
ErrorLogger *_errorLogger;
|
||||||
|
|
||||||
|
|
||||||
class FunctionUsage
|
class FunctionUsage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FunctionUsage()
|
FunctionUsage()
|
||||||
{
|
{
|
||||||
filename = "";
|
filename = "";
|
||||||
usedOtherFile = false;
|
usedOtherFile = false;
|
||||||
usedSameFile = false;
|
usedSameFile = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string filename;
|
std::string filename;
|
||||||
bool usedSameFile;
|
bool usedSameFile;
|
||||||
bool usedOtherFile;
|
bool usedOtherFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<std::string, FunctionUsage> _functions;
|
std::map<std::string, FunctionUsage> _functions;
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
512
checkheaders.cpp
512
checkheaders.cpp
|
@ -1,256 +1,256 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#include "checkheaders.h"
|
#include "checkheaders.h"
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// HEADERS - No implementation in a header
|
// HEADERS - No implementation in a header
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
CheckHeaders::CheckHeaders( const Tokenizer *tokenizer, ErrorLogger *errorLogger )
|
CheckHeaders::CheckHeaders( const Tokenizer *tokenizer, ErrorLogger *errorLogger )
|
||||||
{
|
{
|
||||||
_tokenizer = tokenizer;
|
_tokenizer = tokenizer;
|
||||||
_errorLogger = errorLogger;
|
_errorLogger = errorLogger;
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckHeaders::~CheckHeaders()
|
CheckHeaders::~CheckHeaders()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckHeaders::WarningHeaderWithImplementation()
|
void CheckHeaders::WarningHeaderWithImplementation()
|
||||||
{
|
{
|
||||||
for ( const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
for ( const TOKEN *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||||
{
|
{
|
||||||
// Only interested in included file
|
// Only interested in included file
|
||||||
if (tok->fileIndex() == 0)
|
if (tok->fileIndex() == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (TOKEN::Match(tok, ") {"))
|
if (TOKEN::Match(tok, ") {"))
|
||||||
{
|
{
|
||||||
std::ostringstream ostr;
|
std::ostringstream ostr;
|
||||||
ostr << _tokenizer->fileLine(tok) << ": Found implementation in header";
|
ostr << _tokenizer->fileLine(tok) << ": Found implementation in header";
|
||||||
_errorLogger->reportErr(ostr.str());
|
_errorLogger->reportErr(ostr.str());
|
||||||
|
|
||||||
// Goto next file..
|
// Goto next file..
|
||||||
unsigned int fileindex = tok->fileIndex();
|
unsigned int fileindex = tok->fileIndex();
|
||||||
while ( tok->next() && tok->fileIndex() == fileindex )
|
while ( tok->next() && tok->fileIndex() == fileindex )
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// HEADERS - Unneeded include
|
// HEADERS - Unneeded include
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
void CheckHeaders::WarningIncludeHeader()
|
void CheckHeaders::WarningIncludeHeader()
|
||||||
{
|
{
|
||||||
// Including..
|
// Including..
|
||||||
for ( const TOKEN *includetok = _tokenizer->tokens(); includetok; includetok = includetok->next())
|
for ( const TOKEN *includetok = _tokenizer->tokens(); includetok; includetok = includetok->next())
|
||||||
{
|
{
|
||||||
if (includetok->str() != "#include")
|
if (includetok->str() != "#include")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Get fileindex of included file..
|
// Get fileindex of included file..
|
||||||
unsigned int hfile = 0;
|
unsigned int hfile = 0;
|
||||||
const char *includefile = includetok->next()->aaaa();
|
const char *includefile = includetok->next()->aaaa();
|
||||||
while (hfile < _tokenizer->getFiles()->size())
|
while (hfile < _tokenizer->getFiles()->size())
|
||||||
{
|
{
|
||||||
if ( Tokenizer::SameFileName( _tokenizer->getFiles()->at(hfile).c_str(), includefile ) )
|
if ( Tokenizer::SameFileName( _tokenizer->getFiles()->at(hfile).c_str(), includefile ) )
|
||||||
break;
|
break;
|
||||||
hfile++;
|
hfile++;
|
||||||
}
|
}
|
||||||
if (hfile == _tokenizer->getFiles()->size())
|
if (hfile == _tokenizer->getFiles()->size())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// This header is needed if:
|
// This header is needed if:
|
||||||
// * It contains some needed class declaration
|
// * It contains some needed class declaration
|
||||||
// * It contains some needed function declaration
|
// * It contains some needed function declaration
|
||||||
// * It contains some needed constant value
|
// * It contains some needed constant value
|
||||||
// * It contains some needed variable
|
// * It contains some needed variable
|
||||||
// * It contains some needed enum
|
// * It contains some needed enum
|
||||||
|
|
||||||
std::list<std::string> classlist;
|
std::list<std::string> classlist;
|
||||||
std::list<std::string> namelist;
|
std::list<std::string> namelist;
|
||||||
|
|
||||||
// Extract classes and names in the header..
|
// Extract classes and names in the header..
|
||||||
int indentlevel = 0;
|
int indentlevel = 0;
|
||||||
for ( const TOKEN *tok1 = _tokenizer->tokens(); tok1; tok1 = tok1->next() )
|
for ( const TOKEN *tok1 = _tokenizer->tokens(); tok1; tok1 = tok1->next() )
|
||||||
{
|
{
|
||||||
if ( tok1->fileIndex() != hfile )
|
if ( tok1->fileIndex() != hfile )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// I'm only interested in stuff that is declared at indentlevel 0
|
// I'm only interested in stuff that is declared at indentlevel 0
|
||||||
if (tok1->str() == "{")
|
if (tok1->str() == "{")
|
||||||
++indentlevel;
|
++indentlevel;
|
||||||
|
|
||||||
else if (tok1->str() == "}")
|
else if (tok1->str() == "}")
|
||||||
--indentlevel;
|
--indentlevel;
|
||||||
|
|
||||||
if (indentlevel != 0)
|
if (indentlevel != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Class or namespace declaration..
|
// Class or namespace declaration..
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
if (TOKEN::Match(tok1,"class %var% {") || TOKEN::Match(tok1,"class %var% :") || TOKEN::Match(tok1,"namespace %var% {"))
|
if (TOKEN::Match(tok1,"class %var% {") || TOKEN::Match(tok1,"class %var% :") || TOKEN::Match(tok1,"namespace %var% {"))
|
||||||
classlist.push_back(tok1->strAt(1));
|
classlist.push_back(tok1->strAt(1));
|
||||||
|
|
||||||
// Variable declaration..
|
// Variable declaration..
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
else if (TOKEN::Match(tok1, "%type% %var% ;") || TOKEN::Match(tok1, "%type% %var% ["))
|
else if (TOKEN::Match(tok1, "%type% %var% ;") || TOKEN::Match(tok1, "%type% %var% ["))
|
||||||
namelist.push_back(tok1->strAt(1));
|
namelist.push_back(tok1->strAt(1));
|
||||||
|
|
||||||
else if (TOKEN::Match(tok1, "%type% * %var% ;") || TOKEN::Match(tok1, "%type% * %var% ["))
|
else if (TOKEN::Match(tok1, "%type% * %var% ;") || TOKEN::Match(tok1, "%type% * %var% ["))
|
||||||
namelist.push_back(tok1->strAt(2));
|
namelist.push_back(tok1->strAt(2));
|
||||||
|
|
||||||
else if (TOKEN::Match(tok1, "const %type% %var% =") || TOKEN::Match(tok1, "const %type% %var% ["))
|
else if (TOKEN::Match(tok1, "const %type% %var% =") || TOKEN::Match(tok1, "const %type% %var% ["))
|
||||||
namelist.push_back(tok1->strAt(2));
|
namelist.push_back(tok1->strAt(2));
|
||||||
|
|
||||||
else if (TOKEN::Match(tok1, "const %type% * %var% =") || TOKEN::Match(tok1, "const %type% * %var% ["))
|
else if (TOKEN::Match(tok1, "const %type% * %var% =") || TOKEN::Match(tok1, "const %type% * %var% ["))
|
||||||
namelist.push_back(tok1->strAt(3));
|
namelist.push_back(tok1->strAt(3));
|
||||||
|
|
||||||
// enum..
|
// enum..
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
else if (tok1->str() == "enum")
|
else if (tok1->str() == "enum")
|
||||||
{
|
{
|
||||||
tok1 = tok1->next();
|
tok1 = tok1->next();
|
||||||
while ( ! TOKEN::Match( tok1, "; %any%" ) )
|
while ( ! TOKEN::Match( tok1, "; %any%" ) )
|
||||||
{
|
{
|
||||||
if ( tok1->isName() )
|
if ( tok1->isName() )
|
||||||
namelist.push_back(tok1->str());
|
namelist.push_back(tok1->str());
|
||||||
tok1 = tok1->next();
|
tok1 = tok1->next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// function..
|
// function..
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
else if (TOKEN::Match(tok1,"%type% %var% ("))
|
else if (TOKEN::Match(tok1,"%type% %var% ("))
|
||||||
namelist.push_back(tok1->strAt(1));
|
namelist.push_back(tok1->strAt(1));
|
||||||
|
|
||||||
else if (TOKEN::Match(tok1,"%type% * %var% ("))
|
else if (TOKEN::Match(tok1,"%type% * %var% ("))
|
||||||
namelist.push_back(tok1->strAt(2));
|
namelist.push_back(tok1->strAt(2));
|
||||||
|
|
||||||
else if (TOKEN::Match(tok1,"const %type% %var% ("))
|
else if (TOKEN::Match(tok1,"const %type% %var% ("))
|
||||||
namelist.push_back(tok1->strAt(2));
|
namelist.push_back(tok1->strAt(2));
|
||||||
|
|
||||||
else if (TOKEN::Match(tok1,"const %type% * %var% ("))
|
else if (TOKEN::Match(tok1,"const %type% * %var% ("))
|
||||||
namelist.push_back(tok1->strAt(3));
|
namelist.push_back(tok1->strAt(3));
|
||||||
|
|
||||||
// typedef..
|
// typedef..
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
else if (tok1->str() == "typedef")
|
else if (tok1->str() == "typedef")
|
||||||
{
|
{
|
||||||
if (strcmp(tok1->strAt(1),"enum")==0)
|
if (strcmp(tok1->strAt(1),"enum")==0)
|
||||||
continue;
|
continue;
|
||||||
int parlevel = 0;
|
int parlevel = 0;
|
||||||
while (tok1->next())
|
while (tok1->next())
|
||||||
{
|
{
|
||||||
if ( TOKEN::Match(tok1, "[({]") )
|
if ( TOKEN::Match(tok1, "[({]") )
|
||||||
parlevel++;
|
parlevel++;
|
||||||
|
|
||||||
else if ( TOKEN::Match(tok1, "[)}]") )
|
else if ( TOKEN::Match(tok1, "[)}]") )
|
||||||
parlevel--;
|
parlevel--;
|
||||||
|
|
||||||
else if (parlevel == 0)
|
else if (parlevel == 0)
|
||||||
{
|
{
|
||||||
if ( tok1->str() == ";" )
|
if ( tok1->str() == ";" )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if ( TOKEN::Match(tok1, "%var% ;") )
|
if ( TOKEN::Match(tok1, "%var% ;") )
|
||||||
namelist.push_back(tok1->str());
|
namelist.push_back(tok1->str());
|
||||||
}
|
}
|
||||||
|
|
||||||
tok1 = tok1->next();
|
tok1 = tok1->next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Check if the extracted names are used...
|
// Check if the extracted names are used...
|
||||||
bool Needed = false;
|
bool Needed = false;
|
||||||
bool NeedDeclaration = false;
|
bool NeedDeclaration = false;
|
||||||
for ( const TOKEN *tok1 = _tokenizer->tokens(); tok1; tok1 = tok1->next())
|
for ( const TOKEN *tok1 = _tokenizer->tokens(); tok1; tok1 = tok1->next())
|
||||||
{
|
{
|
||||||
if (tok1->fileIndex() != includetok->fileIndex())
|
if (tok1->fileIndex() != includetok->fileIndex())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ( TOKEN::Match(tok1, ": %var% {") || TOKEN::Match(tok1, ": %type% %var% {") )
|
if ( TOKEN::Match(tok1, ": %var% {") || TOKEN::Match(tok1, ": %type% %var% {") )
|
||||||
{
|
{
|
||||||
std::string classname = tok1->strAt((strcmp(tok1->strAt(2),"{")) ? 2 : 1);
|
std::string classname = tok1->strAt((strcmp(tok1->strAt(2),"{")) ? 2 : 1);
|
||||||
if (std::find(classlist.begin(),classlist.end(),classname)!=classlist.end())
|
if (std::find(classlist.begin(),classlist.end(),classname)!=classlist.end())
|
||||||
{
|
{
|
||||||
Needed = true;
|
Needed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! tok1->isName() )
|
if ( ! tok1->isName() )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (std::find(namelist.begin(),namelist.end(),tok1->aaaa() ) != namelist.end())
|
if (std::find(namelist.begin(),namelist.end(),tok1->aaaa() ) != namelist.end())
|
||||||
{
|
{
|
||||||
Needed = true;
|
Needed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! NeedDeclaration )
|
if ( ! NeedDeclaration )
|
||||||
NeedDeclaration = (std::find(classlist.begin(),classlist.end(),tok1->aaaa() ) != classlist.end());
|
NeedDeclaration = (std::find(classlist.begin(),classlist.end(),tok1->aaaa() ) != classlist.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Not a header file?
|
// Not a header file?
|
||||||
if (includetok->fileIndex() == 0)
|
if (includetok->fileIndex() == 0)
|
||||||
Needed |= NeedDeclaration;
|
Needed |= NeedDeclaration;
|
||||||
|
|
||||||
// Not needed!
|
// Not needed!
|
||||||
if (!Needed)
|
if (!Needed)
|
||||||
{
|
{
|
||||||
std::ostringstream ostr;
|
std::ostringstream ostr;
|
||||||
ostr << _tokenizer->fileLine(includetok) << ": The included header '" << includefile << "' is not needed";
|
ostr << _tokenizer->fileLine(includetok) << ": The included header '" << includefile << "' is not needed";
|
||||||
if (NeedDeclaration)
|
if (NeedDeclaration)
|
||||||
ostr << " (but a forward declaration is needed)";
|
ostr << " (but a forward declaration is needed)";
|
||||||
_errorLogger->reportErr(ostr.str());
|
_errorLogger->reportErr(ostr.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,43 +1,43 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#ifndef CheckHeadersH
|
#ifndef CheckHeadersH
|
||||||
#define CheckHeadersH
|
#define CheckHeadersH
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
#include "errorlogger.h"
|
#include "errorlogger.h"
|
||||||
|
|
||||||
class CheckHeaders
|
class CheckHeaders
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CheckHeaders( const Tokenizer *tokenizer, ErrorLogger *errorLogger );
|
CheckHeaders( const Tokenizer *tokenizer, ErrorLogger *errorLogger );
|
||||||
~CheckHeaders();
|
~CheckHeaders();
|
||||||
void WarningHeaderWithImplementation();
|
void WarningHeaderWithImplementation();
|
||||||
void WarningIncludeHeader();
|
void WarningIncludeHeader();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Tokenizer *_tokenizer;
|
const Tokenizer *_tokenizer;
|
||||||
ErrorLogger *_errorLogger;
|
ErrorLogger *_errorLogger;
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
2602
checkmemoryleak.cpp
2602
checkmemoryleak.cpp
File diff suppressed because it is too large
Load Diff
|
@ -1,108 +1,108 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#ifndef CheckMemoryLeakH
|
#ifndef CheckMemoryLeakH
|
||||||
#define CheckMemoryLeakH
|
#define CheckMemoryLeakH
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
/** \brief Check for memory leaks */
|
/** \brief Check for memory leaks */
|
||||||
|
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "errorlogger.h"
|
#include "errorlogger.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class CheckMemoryLeakClass
|
class CheckMemoryLeakClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CheckMemoryLeakClass( const Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger );
|
CheckMemoryLeakClass( const Tokenizer *tokenizer, const Settings &settings, ErrorLogger *errorLogger );
|
||||||
~CheckMemoryLeakClass();
|
~CheckMemoryLeakClass();
|
||||||
void CheckMemoryLeak();
|
void CheckMemoryLeak();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum AllocType { No, Malloc, gMalloc, New, NewA, FOPEN, POPEN };
|
enum AllocType { No, Malloc, gMalloc, New, NewA, FOPEN, POPEN };
|
||||||
|
|
||||||
// Extra allocation..
|
// Extra allocation..
|
||||||
class AllocFunc
|
class AllocFunc
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const char *funcname;
|
const char *funcname;
|
||||||
AllocType alloctype;
|
AllocType alloctype;
|
||||||
|
|
||||||
AllocFunc(const char f[], AllocType a)
|
AllocFunc(const char f[], AllocType a)
|
||||||
{
|
{
|
||||||
funcname = f;
|
funcname = f;
|
||||||
alloctype = a;
|
alloctype = a;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void CheckMemoryLeak_ClassMembers_Variable( const std::vector<const char *> &classname, const char varname[] );
|
void CheckMemoryLeak_ClassMembers_Variable( const std::vector<const char *> &classname, const char varname[] );
|
||||||
void CheckMemoryLeak_ClassMembers_ParseClass( const TOKEN *tok1, std::vector<const char *> &classname );
|
void CheckMemoryLeak_ClassMembers_ParseClass( const TOKEN *tok1, std::vector<const char *> &classname );
|
||||||
void CheckMemoryLeak_ClassMembers();
|
void CheckMemoryLeak_ClassMembers();
|
||||||
void CheckMemoryLeak_InFunction();
|
void CheckMemoryLeak_InFunction();
|
||||||
void CheckMemoryLeak_CheckScope( const TOKEN *Tok1, const char varname[] );
|
void CheckMemoryLeak_CheckScope( const TOKEN *Tok1, const char varname[] );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simplify code e.g. by replacing empty "{ }" with ";"
|
* Simplify code e.g. by replacing empty "{ }" with ";"
|
||||||
* @param tok first token. The tokens list can be modified.
|
* @param tok first token. The tokens list can be modified.
|
||||||
*/
|
*/
|
||||||
void simplifycode(TOKEN *tok);
|
void simplifycode(TOKEN *tok);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete tokens between begin and end. E.g. if begin = 1
|
* Delete tokens between begin and end. E.g. if begin = 1
|
||||||
* and end = 5, tokens 2,3 and 4 would be erased.
|
* and end = 5, tokens 2,3 and 4 would be erased.
|
||||||
*
|
*
|
||||||
* @param begin Tokens after this will be erased.
|
* @param begin Tokens after this will be erased.
|
||||||
* @param end Tokens before this will be erased.
|
* @param end Tokens before this will be erased.
|
||||||
*/
|
*/
|
||||||
void erase(TOKEN *begin, const TOKEN *end);
|
void erase(TOKEN *begin, const TOKEN *end);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract a new tokens list that is easier to parse than the "tokens"
|
* Extract a new tokens list that is easier to parse than the "tokens"
|
||||||
* @param tok start parse token
|
* @param tok start parse token
|
||||||
* @param callstack callstack
|
* @param callstack callstack
|
||||||
* @param varname name of variable
|
* @param varname name of variable
|
||||||
* @param alloctype
|
* @param alloctype
|
||||||
* @param dealloctype
|
* @param dealloctype
|
||||||
* @return Newly allocated token array. Caller needs to release reserved
|
* @return Newly allocated token array. Caller needs to release reserved
|
||||||
* memory by calling Tokenizer::deleteTokens(returnValue);
|
* memory by calling Tokenizer::deleteTokens(returnValue);
|
||||||
*/
|
*/
|
||||||
TOKEN *getcode(const TOKEN *tok, std::list<const TOKEN *> callstack, const char varname[], AllocType &alloctype, AllocType &dealloctype);
|
TOKEN *getcode(const TOKEN *tok, std::list<const TOKEN *> callstack, const char varname[], AllocType &alloctype, AllocType &dealloctype);
|
||||||
bool notvar(const TOKEN *tok, const char *varnames[]);
|
bool notvar(const TOKEN *tok, const char *varnames[]);
|
||||||
void instoken(TOKEN *tok, const char str[]);
|
void instoken(TOKEN *tok, const char str[]);
|
||||||
void MemoryLeak( const TOKEN *tok, const char varname[], AllocType alloctype );
|
void MemoryLeak( const TOKEN *tok, const char varname[], AllocType alloctype );
|
||||||
void MismatchError( const TOKEN *Tok1, const std::list<const TOKEN *> &callstack, const char varname[] );
|
void MismatchError( const TOKEN *Tok1, const std::list<const TOKEN *> &callstack, const char varname[] );
|
||||||
const char * call_func( const TOKEN *tok, std::list<const TOKEN *> callstack, const char *varnames[], AllocType &alloctype, AllocType &dealloctype );
|
const char * call_func( const TOKEN *tok, std::list<const TOKEN *> callstack, const char *varnames[], AllocType &alloctype, AllocType &dealloctype );
|
||||||
AllocType GetDeallocationType( const TOKEN *tok, const char *varnames[]);
|
AllocType GetDeallocationType( const TOKEN *tok, const char *varnames[]);
|
||||||
AllocType GetAllocationType( const TOKEN *tok2 );
|
AllocType GetAllocationType( const TOKEN *tok2 );
|
||||||
AllocType GetReallocationType( const TOKEN *tok2 );
|
AllocType GetReallocationType( const TOKEN *tok2 );
|
||||||
bool isclass( const TOKEN *typestr );
|
bool isclass( const TOKEN *typestr );
|
||||||
|
|
||||||
const Tokenizer *_tokenizer;
|
const Tokenizer *_tokenizer;
|
||||||
ErrorLogger *_errorLogger;
|
ErrorLogger *_errorLogger;
|
||||||
const Settings _settings;
|
const Settings _settings;
|
||||||
std::list<AllocFunc> _listAllocFunc;
|
std::list<AllocFunc> _listAllocFunc;
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#endif
|
#endif
|
||||||
|
|
1720
checkother.cpp
1720
checkother.cpp
File diff suppressed because it is too large
Load Diff
166
checkother.h
166
checkother.h
|
@ -1,90 +1,90 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#ifndef CheckOtherH
|
#ifndef CheckOtherH
|
||||||
#define CheckOtherH
|
#define CheckOtherH
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
#include "errorlogger.h"
|
#include "errorlogger.h"
|
||||||
|
|
||||||
class CheckOther
|
class CheckOther
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CheckOther( const Tokenizer *tokenizer, ErrorLogger *errorLogger );
|
CheckOther( const Tokenizer *tokenizer, ErrorLogger *errorLogger );
|
||||||
~CheckOther();
|
~CheckOther();
|
||||||
|
|
||||||
// Casting
|
// Casting
|
||||||
void WarningOldStylePointerCast();
|
void WarningOldStylePointerCast();
|
||||||
|
|
||||||
// Redundant code
|
// Redundant code
|
||||||
void WarningRedundantCode();
|
void WarningRedundantCode();
|
||||||
|
|
||||||
// Warning upon: if (condition);
|
// Warning upon: if (condition);
|
||||||
void WarningIf();
|
void WarningIf();
|
||||||
|
|
||||||
// Assignment in condition
|
// Assignment in condition
|
||||||
void CheckIfAssignment();
|
void CheckIfAssignment();
|
||||||
|
|
||||||
// Invalid function usage..
|
// Invalid function usage..
|
||||||
void InvalidFunctionUsage();
|
void InvalidFunctionUsage();
|
||||||
|
|
||||||
// Check for unsigned division that might create bad results
|
// Check for unsigned division that might create bad results
|
||||||
void CheckUnsignedDivision();
|
void CheckUnsignedDivision();
|
||||||
|
|
||||||
// Check scope of variables
|
// Check scope of variables
|
||||||
void CheckVariableScope();
|
void CheckVariableScope();
|
||||||
|
|
||||||
// Check for constant function parameter
|
// Check for constant function parameter
|
||||||
void CheckConstantFunctionParameter();
|
void CheckConstantFunctionParameter();
|
||||||
|
|
||||||
// Check that all struct members are used
|
// Check that all struct members are used
|
||||||
void CheckStructMemberUsage();
|
void CheckStructMemberUsage();
|
||||||
|
|
||||||
// Using char variable as array index / as operand in bit operation
|
// Using char variable as array index / as operand in bit operation
|
||||||
void CheckCharVariable();
|
void CheckCharVariable();
|
||||||
|
|
||||||
// Incomplete statement. A statement that only contains a constant or variable
|
// Incomplete statement. A statement that only contains a constant or variable
|
||||||
void CheckIncompleteStatement();
|
void CheckIncompleteStatement();
|
||||||
|
|
||||||
/** Unreachable code below a 'return' */
|
/** Unreachable code below a 'return' */
|
||||||
void unreachableCode();
|
void unreachableCode();
|
||||||
|
|
||||||
/** Unused function variables */
|
/** Unused function variables */
|
||||||
void functionVariableUsage();
|
void functionVariableUsage();
|
||||||
|
|
||||||
#ifndef UNIT_TESTING
|
#ifndef UNIT_TESTING
|
||||||
private:
|
private:
|
||||||
#endif
|
#endif
|
||||||
void CheckVariableScope_LookupVar( const TOKEN *tok1, const char varname[] );
|
void CheckVariableScope_LookupVar( const TOKEN *tok1, const char varname[] );
|
||||||
|
|
||||||
// Redundant condition
|
// Redundant condition
|
||||||
// if (haystack.find(needle) != haystack.end())
|
// if (haystack.find(needle) != haystack.end())
|
||||||
// haystack.remove(needle);
|
// haystack.remove(needle);
|
||||||
void redundantCondition2();
|
void redundantCondition2();
|
||||||
|
|
||||||
const Tokenizer *_tokenizer;
|
const Tokenizer *_tokenizer;
|
||||||
ErrorLogger *_errorLogger;
|
ErrorLogger *_errorLogger;
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
720
cppcheck.cpp
720
cppcheck.cpp
|
@ -1,360 +1,360 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi
|
* Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
#include "cppcheck.h"
|
#include "cppcheck.h"
|
||||||
|
|
||||||
#include "preprocessor.h" // preprocessor.
|
#include "preprocessor.h" // preprocessor.
|
||||||
#include "tokenize.h" // <- Tokenizer
|
#include "tokenize.h" // <- Tokenizer
|
||||||
|
|
||||||
#include "checkmemoryleak.h"
|
#include "checkmemoryleak.h"
|
||||||
#include "checkbufferoverrun.h"
|
#include "checkbufferoverrun.h"
|
||||||
#include "checkclass.h"
|
#include "checkclass.h"
|
||||||
#include "checkheaders.h"
|
#include "checkheaders.h"
|
||||||
#include "checkother.h"
|
#include "checkother.h"
|
||||||
#include "checkfunctionusage.h"
|
#include "checkfunctionusage.h"
|
||||||
#include "filelister.h"
|
#include "filelister.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
CppCheck::CppCheck( ErrorLogger &errorLogger ) : _checkFunctionUsage( this )
|
CppCheck::CppCheck( ErrorLogger &errorLogger ) : _checkFunctionUsage( this )
|
||||||
{
|
{
|
||||||
_errorLogger = &errorLogger;
|
_errorLogger = &errorLogger;
|
||||||
}
|
}
|
||||||
|
|
||||||
CppCheck::~CppCheck()
|
CppCheck::~CppCheck()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppCheck::settings( const Settings &settings )
|
void CppCheck::settings( const Settings &settings )
|
||||||
{
|
{
|
||||||
_settings = settings;
|
_settings = settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppCheck::addFile( const std::string &path )
|
void CppCheck::addFile( const std::string &path )
|
||||||
{
|
{
|
||||||
_filenames.push_back( path );
|
_filenames.push_back( path );
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppCheck::addFile( const std::string &path, const std::string &content )
|
void CppCheck::addFile( const std::string &path, const std::string &content )
|
||||||
{
|
{
|
||||||
_filenames.push_back( path );
|
_filenames.push_back( path );
|
||||||
_fileContents[ path ] = content;
|
_fileContents[ path ] = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CppCheck::parseFromArgs( int argc, const char* const argv[] )
|
std::string CppCheck::parseFromArgs( int argc, const char* const argv[] )
|
||||||
{
|
{
|
||||||
std::vector<std::string> pathnames;
|
std::vector<std::string> pathnames;
|
||||||
bool Recursive = false;
|
bool Recursive = false;
|
||||||
|
|
||||||
for (int i = 1; i < argc; i++)
|
for (int i = 1; i < argc; i++)
|
||||||
{
|
{
|
||||||
// Flag used for various purposes during debugging
|
// Flag used for various purposes during debugging
|
||||||
if (strcmp(argv[i],"--debug") == 0)
|
if (strcmp(argv[i],"--debug") == 0)
|
||||||
_settings._debug = true;
|
_settings._debug = true;
|
||||||
|
|
||||||
// Show all messages
|
// Show all messages
|
||||||
else if (strcmp(argv[i],"--all") == 0)
|
else if (strcmp(argv[i],"--all") == 0)
|
||||||
_settings._showAll = true;
|
_settings._showAll = true;
|
||||||
|
|
||||||
// Only print something when there are errors
|
// Only print something when there are errors
|
||||||
else if (strcmp(argv[i],"--errorsonly")==0)
|
else if (strcmp(argv[i],"--errorsonly")==0)
|
||||||
_settings._errorsOnly = true;
|
_settings._errorsOnly = true;
|
||||||
|
|
||||||
// Checking coding style
|
// Checking coding style
|
||||||
else if (strcmp(argv[i],"--style")==0)
|
else if (strcmp(argv[i],"--style")==0)
|
||||||
_settings._checkCodingStyle = true;
|
_settings._checkCodingStyle = true;
|
||||||
|
|
||||||
// Recursively check source files
|
// Recursively check source files
|
||||||
else if (strcmp(argv[i],"--recursive")==0)
|
else if (strcmp(argv[i],"--recursive")==0)
|
||||||
Recursive = true;
|
Recursive = true;
|
||||||
|
|
||||||
// Verbose error messages (configuration info)
|
// Verbose error messages (configuration info)
|
||||||
else if (strcmp(argv[i],"--verbose")==0)
|
else if (strcmp(argv[i],"--verbose")==0)
|
||||||
_settings._verbose = true;
|
_settings._verbose = true;
|
||||||
|
|
||||||
else
|
else
|
||||||
pathnames.push_back( argv[i] );
|
pathnames.push_back( argv[i] );
|
||||||
}
|
}
|
||||||
|
|
||||||
// --recursive was used
|
// --recursive was used
|
||||||
if ( Recursive )
|
if ( Recursive )
|
||||||
{
|
{
|
||||||
if( pathnames.size() == 0 )
|
if( pathnames.size() == 0 )
|
||||||
{
|
{
|
||||||
// Handle situation: cppcheck --recursive
|
// Handle situation: cppcheck --recursive
|
||||||
FileLister::RecursiveAddFiles( _filenames, "", true );
|
FileLister::RecursiveAddFiles( _filenames, "", true );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Handle situation: cppcheck --recursive path1 path2
|
// Handle situation: cppcheck --recursive path1 path2
|
||||||
|
|
||||||
// Execute RecursiveAddFiles() to each given file parameter
|
// Execute RecursiveAddFiles() to each given file parameter
|
||||||
std::vector<std::string>::const_iterator iter;
|
std::vector<std::string>::const_iterator iter;
|
||||||
for(iter=pathnames.begin(); iter!=pathnames.end(); iter++)
|
for(iter=pathnames.begin(); iter!=pathnames.end(); iter++)
|
||||||
FileLister::RecursiveAddFiles( _filenames, iter->c_str(), true );
|
FileLister::RecursiveAddFiles( _filenames, iter->c_str(), true );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::vector<std::string>::const_iterator iter;
|
std::vector<std::string>::const_iterator iter;
|
||||||
for(iter=pathnames.begin(); iter!=pathnames.end(); iter++)
|
for(iter=pathnames.begin(); iter!=pathnames.end(); iter++)
|
||||||
FileLister::RecursiveAddFiles( _filenames, iter->c_str(), false );
|
FileLister::RecursiveAddFiles( _filenames, iter->c_str(), false );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_filenames.empty())
|
if (_filenames.empty())
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "c++check 1.26\n"
|
oss << "c++check 1.26\n"
|
||||||
"\n"
|
"\n"
|
||||||
"C/C++ code checking\n"
|
"C/C++ code checking\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Syntax:\n"
|
"Syntax:\n"
|
||||||
" cppcheck [--all] [--errorsonly] [--recursive] [--style] [--verbose] [filename1] [filename2]\n"
|
" cppcheck [--all] [--errorsonly] [--recursive] [--style] [--verbose] [filename1] [filename2]\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
" --all Make the checking more sensitive. More bugs are detected,\n"
|
" --all Make the checking more sensitive. More bugs are detected,\n"
|
||||||
" but there are also more false positives\n"
|
" but there are also more false positives\n"
|
||||||
" --errorsonly Only print error messages\n"
|
" --errorsonly Only print error messages\n"
|
||||||
" --recursive Recursively check all *.cpp, *.cxx, *.cc and *.c files\n"
|
" --recursive Recursively check all *.cpp, *.cxx, *.cc and *.c files\n"
|
||||||
" --style Check coding style\n"
|
" --style Check coding style\n"
|
||||||
" --verbose More detailed error reports\n";
|
" --verbose More detailed error reports\n";
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check function usage if "--style" and "--all" was given.
|
// Check function usage if "--style" and "--all" was given.
|
||||||
// There will be false positives for exported library functions
|
// There will be false positives for exported library functions
|
||||||
if ( _settings._showAll && _settings._checkCodingStyle )
|
if ( _settings._showAll && _settings._checkCodingStyle )
|
||||||
_settings._checkFunctionUsage = true;
|
_settings._checkFunctionUsage = true;
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppCheck::check()
|
void CppCheck::check()
|
||||||
{
|
{
|
||||||
std::sort( _filenames.begin(), _filenames.end() );
|
std::sort( _filenames.begin(), _filenames.end() );
|
||||||
for (unsigned int c = 0; c < _filenames.size(); c++)
|
for (unsigned int c = 0; c < _filenames.size(); c++)
|
||||||
{
|
{
|
||||||
_errout.str("");
|
_errout.str("");
|
||||||
std::string fname = _filenames[c];
|
std::string fname = _filenames[c];
|
||||||
|
|
||||||
// If only errors are printed, print filename after the check
|
// If only errors are printed, print filename after the check
|
||||||
if ( _settings._errorsOnly == false )
|
if ( _settings._errorsOnly == false )
|
||||||
_errorLogger->reportOut( std::string( "Checking " ) + fname + std::string( "..." ) );
|
_errorLogger->reportOut( std::string( "Checking " ) + fname + std::string( "..." ) );
|
||||||
|
|
||||||
Preprocessor preprocessor;
|
Preprocessor preprocessor;
|
||||||
std::map<std::string, std::string> code;
|
std::map<std::string, std::string> code;
|
||||||
if( _fileContents.size() > 0 && _fileContents.find( _filenames[c] ) != _fileContents.end() )
|
if( _fileContents.size() > 0 && _fileContents.find( _filenames[c] ) != _fileContents.end() )
|
||||||
{
|
{
|
||||||
// File content was given as a string
|
// File content was given as a string
|
||||||
std::istringstream iss( _fileContents[ _filenames[c] ] );
|
std::istringstream iss( _fileContents[ _filenames[c] ] );
|
||||||
preprocessor.preprocess(iss, code, fname);
|
preprocessor.preprocess(iss, code, fname);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Only file name was given, read the content from file
|
// Only file name was given, read the content from file
|
||||||
std::ifstream fin( fname.c_str() );
|
std::ifstream fin( fname.c_str() );
|
||||||
preprocessor.preprocess(fin, code, fname);
|
preprocessor.preprocess(fin, code, fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( std::map<std::string,std::string>::const_iterator it = code.begin(); it != code.end(); ++it )
|
for ( std::map<std::string,std::string>::const_iterator it = code.begin(); it != code.end(); ++it )
|
||||||
{
|
{
|
||||||
cfg = it->first;
|
cfg = it->first;
|
||||||
checkFile(it->second, _filenames[c].c_str());
|
checkFile(it->second, _filenames[c].c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( _settings._errorsOnly == false && _errout.str().empty() )
|
if ( _settings._errorsOnly == false && _errout.str().empty() )
|
||||||
_errorLogger->reportOut( "No errors found" );
|
_errorLogger->reportOut( "No errors found" );
|
||||||
}
|
}
|
||||||
|
|
||||||
// This generates false positives - especially for libraries
|
// This generates false positives - especially for libraries
|
||||||
_settings._verbose = false;
|
_settings._verbose = false;
|
||||||
if ( _settings._checkFunctionUsage )
|
if ( _settings._checkFunctionUsage )
|
||||||
{
|
{
|
||||||
_errout.str("");
|
_errout.str("");
|
||||||
if( _settings._errorsOnly == false )
|
if( _settings._errorsOnly == false )
|
||||||
_errorLogger->reportOut( "Checking usage of global functions (this may take several minutes).." );
|
_errorLogger->reportOut( "Checking usage of global functions (this may take several minutes).." );
|
||||||
|
|
||||||
_checkFunctionUsage.check();
|
_checkFunctionUsage.check();
|
||||||
}
|
}
|
||||||
|
|
||||||
_errorList.clear();
|
_errorList.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// CppCheck - A function that checks a specified file
|
// CppCheck - A function that checks a specified file
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
void CppCheck::checkFile(const std::string &code, const char FileName[])
|
void CppCheck::checkFile(const std::string &code, const char FileName[])
|
||||||
{
|
{
|
||||||
Tokenizer _tokenizer;
|
Tokenizer _tokenizer;
|
||||||
|
|
||||||
// Tokenize the file
|
// Tokenize the file
|
||||||
{
|
{
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
_tokenizer.tokenize(istr, FileName);
|
_tokenizer.tokenize(istr, FileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set variable id
|
// Set variable id
|
||||||
_tokenizer.setVarId();
|
_tokenizer.setVarId();
|
||||||
|
|
||||||
_tokenizer.fillFunctionList();
|
_tokenizer.fillFunctionList();
|
||||||
|
|
||||||
// Check that the memsets are valid.
|
// Check that the memsets are valid.
|
||||||
// The 'memset' function can do dangerous things if used wrong.
|
// The 'memset' function can do dangerous things if used wrong.
|
||||||
// Important: The checking doesn't work on simplified tokens list.
|
// Important: The checking doesn't work on simplified tokens list.
|
||||||
CheckClass checkClass( &_tokenizer, _settings, this );
|
CheckClass checkClass( &_tokenizer, _settings, this );
|
||||||
checkClass.CheckMemset();
|
checkClass.CheckMemset();
|
||||||
|
|
||||||
|
|
||||||
// Check for unsigned divisions where one operand is signed
|
// Check for unsigned divisions where one operand is signed
|
||||||
// Very important to run it before 'SimplifyTokenList'
|
// Very important to run it before 'SimplifyTokenList'
|
||||||
CheckOther checkOther( &_tokenizer, this );
|
CheckOther checkOther( &_tokenizer, this );
|
||||||
if ( _settings._checkCodingStyle )
|
if ( _settings._checkCodingStyle )
|
||||||
checkOther.CheckUnsignedDivision();
|
checkOther.CheckUnsignedDivision();
|
||||||
|
|
||||||
// Give warning when using char variable as array index
|
// Give warning when using char variable as array index
|
||||||
// Doesn't work on simplified token list ('unsigned')
|
// Doesn't work on simplified token list ('unsigned')
|
||||||
if ( _settings._checkCodingStyle )
|
if ( _settings._checkCodingStyle )
|
||||||
checkOther.CheckCharVariable();
|
checkOther.CheckCharVariable();
|
||||||
|
|
||||||
|
|
||||||
// Including header which is not needed (too many false positives)
|
// Including header which is not needed (too many false positives)
|
||||||
// if ( _settings._checkCodingStyle )
|
// if ( _settings._checkCodingStyle )
|
||||||
// {
|
// {
|
||||||
// CheckHeaders checkHeaders( &tokenizer );
|
// CheckHeaders checkHeaders( &tokenizer );
|
||||||
// checkHeaders.WarningIncludeHeader();
|
// checkHeaders.WarningIncludeHeader();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
_tokenizer.simplifyTokenList();
|
_tokenizer.simplifyTokenList();
|
||||||
|
|
||||||
|
|
||||||
if ( _settings._checkFunctionUsage )
|
if ( _settings._checkFunctionUsage )
|
||||||
_checkFunctionUsage.parseTokens(_tokenizer);
|
_checkFunctionUsage.parseTokens(_tokenizer);
|
||||||
|
|
||||||
// Memory leak
|
// Memory leak
|
||||||
CheckMemoryLeakClass checkMemoryLeak( &_tokenizer, _settings, this );
|
CheckMemoryLeakClass checkMemoryLeak( &_tokenizer, _settings, this );
|
||||||
checkMemoryLeak.CheckMemoryLeak();
|
checkMemoryLeak.CheckMemoryLeak();
|
||||||
|
|
||||||
// Buffer overruns..
|
// Buffer overruns..
|
||||||
CheckBufferOverrunClass checkBufferOverrun( &_tokenizer, _settings, this );
|
CheckBufferOverrunClass checkBufferOverrun( &_tokenizer, _settings, this );
|
||||||
checkBufferOverrun.CheckBufferOverrun();
|
checkBufferOverrun.CheckBufferOverrun();
|
||||||
|
|
||||||
// Check that all class constructors are ok.
|
// Check that all class constructors are ok.
|
||||||
checkClass.CheckConstructors();
|
checkClass.CheckConstructors();
|
||||||
|
|
||||||
// Check that all base classes have virtual destructors
|
// Check that all base classes have virtual destructors
|
||||||
checkClass.virtualDestructor();
|
checkClass.virtualDestructor();
|
||||||
|
|
||||||
if (_settings._showAll)
|
if (_settings._showAll)
|
||||||
{
|
{
|
||||||
// Check for "if (a=b)"
|
// Check for "if (a=b)"
|
||||||
checkOther.CheckIfAssignment();
|
checkOther.CheckIfAssignment();
|
||||||
|
|
||||||
// Check for case without break
|
// Check for case without break
|
||||||
// Disabled because it generates many false positives
|
// Disabled because it generates many false positives
|
||||||
// CheckCaseWithoutBreak();
|
// CheckCaseWithoutBreak();
|
||||||
|
|
||||||
// Dangerous usage of strtok
|
// Dangerous usage of strtok
|
||||||
// Disabled because it generates false positives
|
// Disabled because it generates false positives
|
||||||
//WarningStrTok();
|
//WarningStrTok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Dangerous functions, such as 'gets' and 'scanf'
|
// Dangerous functions, such as 'gets' and 'scanf'
|
||||||
checkBufferOverrun.WarningDangerousFunctions();
|
checkBufferOverrun.WarningDangerousFunctions();
|
||||||
|
|
||||||
|
|
||||||
// Invalid function usage..
|
// Invalid function usage..
|
||||||
checkOther.InvalidFunctionUsage();
|
checkOther.InvalidFunctionUsage();
|
||||||
|
|
||||||
|
|
||||||
if (_settings._checkCodingStyle)
|
if (_settings._checkCodingStyle)
|
||||||
{
|
{
|
||||||
// Check that all private functions are called.
|
// Check that all private functions are called.
|
||||||
checkClass.CheckUnusedPrivateFunctions();
|
checkClass.CheckUnusedPrivateFunctions();
|
||||||
|
|
||||||
// Warning upon c-style pointer casts
|
// Warning upon c-style pointer casts
|
||||||
const char *ext = strrchr(FileName, '.');
|
const char *ext = strrchr(FileName, '.');
|
||||||
if (ext && strcmp(ext,".cpp")==0)
|
if (ext && strcmp(ext,".cpp")==0)
|
||||||
checkOther.WarningOldStylePointerCast();
|
checkOther.WarningOldStylePointerCast();
|
||||||
|
|
||||||
checkClass.CheckOperatorEq1();
|
checkClass.CheckOperatorEq1();
|
||||||
|
|
||||||
// if (a) delete a;
|
// if (a) delete a;
|
||||||
checkOther.WarningRedundantCode();
|
checkOther.WarningRedundantCode();
|
||||||
|
|
||||||
// if (condition);
|
// if (condition);
|
||||||
checkOther.WarningIf();
|
checkOther.WarningIf();
|
||||||
|
|
||||||
// Variable scope (check if the scope could be limited)
|
// Variable scope (check if the scope could be limited)
|
||||||
//CheckVariableScope();
|
//CheckVariableScope();
|
||||||
|
|
||||||
// Check if a constant function parameter is passed by value
|
// Check if a constant function parameter is passed by value
|
||||||
checkOther.CheckConstantFunctionParameter();
|
checkOther.CheckConstantFunctionParameter();
|
||||||
|
|
||||||
// Unused struct members..
|
// Unused struct members..
|
||||||
checkOther.CheckStructMemberUsage();
|
checkOther.CheckStructMemberUsage();
|
||||||
|
|
||||||
// Check for various types of incomplete statements that could for example
|
// Check for various types of incomplete statements that could for example
|
||||||
// mean that an ';' has been added by accident
|
// mean that an ';' has been added by accident
|
||||||
checkOther.CheckIncompleteStatement();
|
checkOther.CheckIncompleteStatement();
|
||||||
|
|
||||||
// Unreachable code below a 'return' statement
|
// Unreachable code below a 'return' statement
|
||||||
checkOther.unreachableCode();
|
checkOther.unreachableCode();
|
||||||
|
|
||||||
// Usage of local functions
|
// Usage of local functions
|
||||||
checkOther.functionVariableUsage();
|
checkOther.functionVariableUsage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
void CppCheck::reportErr( const std::string &errmsg)
|
void CppCheck::reportErr( const std::string &errmsg)
|
||||||
{
|
{
|
||||||
if ( /*OnlyReportUniqueErrors*/ true )
|
if ( /*OnlyReportUniqueErrors*/ true )
|
||||||
{
|
{
|
||||||
if ( std::find( _errorList.begin(), _errorList.end(), errmsg ) != _errorList.end() )
|
if ( std::find( _errorList.begin(), _errorList.end(), errmsg ) != _errorList.end() )
|
||||||
return;
|
return;
|
||||||
_errorList.push_back( errmsg );
|
_errorList.push_back( errmsg );
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string errmsg2( errmsg );
|
std::string errmsg2( errmsg );
|
||||||
if ( _settings._verbose )
|
if ( _settings._verbose )
|
||||||
{
|
{
|
||||||
errmsg2 += "\n Defines=\'" + cfg + "\'\n";
|
errmsg2 += "\n Defines=\'" + cfg + "\'\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_errorLogger->reportErr( errmsg2 );
|
_errorLogger->reportErr( errmsg2 );
|
||||||
|
|
||||||
_errout << errmsg2 << std::endl;
|
_errout << errmsg2 << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppCheck::reportOut( const std::string &outmsg)
|
void CppCheck::reportOut( const std::string &outmsg)
|
||||||
{
|
{
|
||||||
// This is currently never called. It is here just to comply with
|
// This is currently never called. It is here just to comply with
|
||||||
// the interface.
|
// the interface.
|
||||||
}
|
}
|
||||||
|
|
252
cppcheck.h
252
cppcheck.h
|
@ -1,126 +1,126 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi
|
* Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CPPCHECK_H
|
#ifndef CPPCHECK_H
|
||||||
#define CPPCHECK_H
|
#define CPPCHECK_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "errorlogger.h"
|
#include "errorlogger.h"
|
||||||
#include "checkfunctionusage.h"
|
#include "checkfunctionusage.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the base class which will use other classes to do
|
* This is the base class which will use other classes to do
|
||||||
* static code analysis for C and C++ code to find possible
|
* static code analysis for C and C++ code to find possible
|
||||||
* errors or places that could be improved.
|
* errors or places that could be improved.
|
||||||
* Usage: See check() for more info.
|
* Usage: See check() for more info.
|
||||||
*/
|
*/
|
||||||
class CppCheck : public ErrorLogger
|
class CppCheck : public ErrorLogger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*/
|
*/
|
||||||
CppCheck( ErrorLogger &errorLogger );
|
CppCheck( ErrorLogger &errorLogger );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destructor.
|
* Destructor.
|
||||||
*/
|
*/
|
||||||
virtual ~CppCheck();
|
virtual ~CppCheck();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This starts the actual checking. Note that you must call
|
* This starts the actual checking. Note that you must call
|
||||||
* parseFromArgs() or settings() and addFile() before calling this.
|
* parseFromArgs() or settings() and addFile() before calling this.
|
||||||
*/
|
*/
|
||||||
void check();
|
void check();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adjust the settings before doing the check. E.g. show only
|
* Adjust the settings before doing the check. E.g. show only
|
||||||
* actual bugs or also coding style issues.
|
* actual bugs or also coding style issues.
|
||||||
*
|
*
|
||||||
* @param settings New settings which will overwrite the old.
|
* @param settings New settings which will overwrite the old.
|
||||||
*/
|
*/
|
||||||
void settings( const Settings &settings );
|
void settings( const Settings &settings );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add new file to be checked.
|
* Add new file to be checked.
|
||||||
*
|
*
|
||||||
* @param path Relative or absolute path to the file to be checked,
|
* @param path Relative or absolute path to the file to be checked,
|
||||||
* e.g. "cppcheck.cpp". Note that only source files (.c, .cc or .cpp)
|
* e.g. "cppcheck.cpp". Note that only source files (.c, .cc or .cpp)
|
||||||
* should be added to the list. Include filese are gathered automatically.
|
* should be added to the list. Include filese are gathered automatically.
|
||||||
*/
|
*/
|
||||||
void addFile( const std::string &path );
|
void addFile( const std::string &path );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add new unreal file to be checked.
|
* Add new unreal file to be checked.
|
||||||
*
|
*
|
||||||
* @param path File name (used for error reporting).
|
* @param path File name (used for error reporting).
|
||||||
* @param content If the file would be a real file, this should be
|
* @param content If the file would be a real file, this should be
|
||||||
* the content of the file.
|
* the content of the file.
|
||||||
*/
|
*/
|
||||||
void addFile( const std::string &path, const std::string &content );
|
void addFile( const std::string &path, const std::string &content );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse command line args and get settings and file lists
|
* Parse command line args and get settings and file lists
|
||||||
* from there.
|
* from there.
|
||||||
*
|
*
|
||||||
* @param argc argc from main()
|
* @param argc argc from main()
|
||||||
* @param argv argv from main()
|
* @param argv argv from main()
|
||||||
* @return Empty string if parameters were accepted, or
|
* @return Empty string if parameters were accepted, or
|
||||||
* string containing "help" text if no files were found to be
|
* string containing "help" text if no files were found to be
|
||||||
* checked.
|
* checked.
|
||||||
*/
|
*/
|
||||||
std::string parseFromArgs( int argc, const char* const argv[] );
|
std::string parseFromArgs( int argc, const char* const argv[] );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void checkFile(const std::string &code, const char FileName[]);
|
void checkFile(const std::string &code, const char FileName[]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Errors and warnings are directed here.
|
* Errors and warnings are directed here.
|
||||||
*
|
*
|
||||||
* @param errmsg Errors messages are normally in format
|
* @param errmsg Errors messages are normally in format
|
||||||
* "[filepath:line number] Message", e.g.
|
* "[filepath:line number] Message", e.g.
|
||||||
* "[main.cpp:4] Uninitialized member variable"
|
* "[main.cpp:4] Uninitialized member variable"
|
||||||
*/
|
*/
|
||||||
virtual void reportErr( const std::string &errmsg);
|
virtual void reportErr( const std::string &errmsg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information about progress is directed here.
|
* Information about progress is directed here.
|
||||||
*
|
*
|
||||||
* @param outmsg, E.g. "Checking main.cpp..."
|
* @param outmsg, E.g. "Checking main.cpp..."
|
||||||
*/
|
*/
|
||||||
virtual void reportOut( const std::string &outmsg);
|
virtual void reportOut( const std::string &outmsg);
|
||||||
|
|
||||||
std::list<std::string> _errorList;
|
std::list<std::string> _errorList;
|
||||||
std::ostringstream _errout;
|
std::ostringstream _errout;
|
||||||
Settings _settings;
|
Settings _settings;
|
||||||
std::vector<std::string> _filenames;
|
std::vector<std::string> _filenames;
|
||||||
/** Key is file name, and value is the content of the file */
|
/** Key is file name, and value is the content of the file */
|
||||||
std::map<std::string,std::string> _fileContents;
|
std::map<std::string,std::string> _fileContents;
|
||||||
CheckFunctionUsage _checkFunctionUsage;
|
CheckFunctionUsage _checkFunctionUsage;
|
||||||
ErrorLogger *_errorLogger;
|
ErrorLogger *_errorLogger;
|
||||||
|
|
||||||
/** Current configuration */
|
/** Current configuration */
|
||||||
std::string cfg;
|
std::string cfg;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CPPCHECK_H
|
#endif // CPPCHECK_H
|
||||||
|
|
|
@ -1,51 +1,51 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi
|
* Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cppcheckexecutor.h"
|
#include "cppcheckexecutor.h"
|
||||||
#include "cppcheck.h"
|
#include "cppcheck.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
CppCheckExecutor::CppCheckExecutor()
|
CppCheckExecutor::CppCheckExecutor()
|
||||||
{
|
{
|
||||||
//ctor
|
//ctor
|
||||||
}
|
}
|
||||||
|
|
||||||
CppCheckExecutor::~CppCheckExecutor()
|
CppCheckExecutor::~CppCheckExecutor()
|
||||||
{
|
{
|
||||||
//dtor
|
//dtor
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppCheckExecutor::check( int argc, const char* const argv[] )
|
void CppCheckExecutor::check( int argc, const char* const argv[] )
|
||||||
{
|
{
|
||||||
CppCheck cppCheck( *this );
|
CppCheck cppCheck( *this );
|
||||||
std::string result = cppCheck.parseFromArgs( argc, argv );
|
std::string result = cppCheck.parseFromArgs( argc, argv );
|
||||||
if( result.length() == 0 )
|
if( result.length() == 0 )
|
||||||
cppCheck.check();
|
cppCheck.check();
|
||||||
else
|
else
|
||||||
std::cout << result;
|
std::cout << result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppCheckExecutor::reportErr( const std::string &errmsg)
|
void CppCheckExecutor::reportErr( const std::string &errmsg)
|
||||||
{
|
{
|
||||||
std::cerr << errmsg << std::endl;
|
std::cerr << errmsg << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppCheckExecutor::reportOut( const std::string &outmsg)
|
void CppCheckExecutor::reportOut( const std::string &outmsg)
|
||||||
{
|
{
|
||||||
std::cout << outmsg << std::endl;
|
std::cout << outmsg << std::endl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,71 +1,71 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi
|
* Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CPPCHECKEXECUTOR_H
|
#ifndef CPPCHECKEXECUTOR_H
|
||||||
#define CPPCHECKEXECUTOR_H
|
#define CPPCHECKEXECUTOR_H
|
||||||
|
|
||||||
#include "errorlogger.h"
|
#include "errorlogger.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class works as an example of how CppCheck can be used in external
|
* This class works as an example of how CppCheck can be used in external
|
||||||
* programs without very little knowledge of the internal parts of the
|
* programs without very little knowledge of the internal parts of the
|
||||||
* program itself. If you wish to use cppcheck e.g. as a part of IDE,
|
* program itself. If you wish to use cppcheck e.g. as a part of IDE,
|
||||||
* just rewrite this class for your needs and possibly use other methods
|
* just rewrite this class for your needs and possibly use other methods
|
||||||
* from CppCheck class instead the ones used here.
|
* from CppCheck class instead the ones used here.
|
||||||
*/
|
*/
|
||||||
class CppCheckExecutor : public ErrorLogger
|
class CppCheckExecutor : public ErrorLogger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
CppCheckExecutor();
|
CppCheckExecutor();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destructor
|
* Destructor
|
||||||
*/
|
*/
|
||||||
virtual ~CppCheckExecutor();
|
virtual ~CppCheckExecutor();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the checking.
|
* Starts the checking.
|
||||||
*
|
*
|
||||||
* @param argc from main()
|
* @param argc from main()
|
||||||
* @param argv from main()
|
* @param argv from main()
|
||||||
*/
|
*/
|
||||||
void check( int argc, const char* const argv[] );
|
void check( int argc, const char* const argv[] );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Errors and warnings are directed here. This should be
|
* Errors and warnings are directed here. This should be
|
||||||
* called by the CppCheck class only.
|
* called by the CppCheck class only.
|
||||||
*
|
*
|
||||||
* @param errmsg Errors messages are normally in format
|
* @param errmsg Errors messages are normally in format
|
||||||
* "[filepath:line number] Message", e.g.
|
* "[filepath:line number] Message", e.g.
|
||||||
* "[main.cpp:4] Uninitialized member variable"
|
* "[main.cpp:4] Uninitialized member variable"
|
||||||
*/
|
*/
|
||||||
virtual void reportErr( const std::string &errmsg);
|
virtual void reportErr( const std::string &errmsg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information about progress is directed here. This should be
|
* Information about progress is directed here. This should be
|
||||||
* called by the CppCheck class only.
|
* called by the CppCheck class only.
|
||||||
*
|
*
|
||||||
* @param outmsg, E.g. "Checking main.cpp..."
|
* @param outmsg, E.g. "Checking main.cpp..."
|
||||||
*/
|
*/
|
||||||
virtual void reportOut( const std::string &outmsg);
|
virtual void reportOut( const std::string &outmsg);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CPPCHECKEXECUTOR_H
|
#endif // CPPCHECKEXECUTOR_H
|
||||||
|
|
100
errorlogger.h
100
errorlogger.h
|
@ -1,50 +1,50 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi
|
* Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ERRORLOGGER_H
|
#ifndef ERRORLOGGER_H
|
||||||
#define ERRORLOGGER_H
|
#define ERRORLOGGER_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is an interface, which the class responsible of error logging
|
* This is an interface, which the class responsible of error logging
|
||||||
* should implement.
|
* should implement.
|
||||||
*/
|
*/
|
||||||
class ErrorLogger
|
class ErrorLogger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~ErrorLogger() {}
|
virtual ~ErrorLogger() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Errors and warnings are directed here.
|
* Errors and warnings are directed here.
|
||||||
*
|
*
|
||||||
* @param errmsg Errors messages are normally in format
|
* @param errmsg Errors messages are normally in format
|
||||||
* "[filepath:line number] Message", e.g.
|
* "[filepath:line number] Message", e.g.
|
||||||
* "[main.cpp:4] Uninitialized member variable"
|
* "[main.cpp:4] Uninitialized member variable"
|
||||||
*/
|
*/
|
||||||
virtual void reportErr( const std::string &errmsg) = 0;
|
virtual void reportErr( const std::string &errmsg) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information about progress is directed here.
|
* Information about progress is directed here.
|
||||||
*
|
*
|
||||||
* @param outmsg, E.g. "Checking main.cpp..."
|
* @param outmsg, E.g. "Checking main.cpp..."
|
||||||
*/
|
*/
|
||||||
virtual void reportOut( const std::string &outmsg) = 0;
|
virtual void reportOut( const std::string &outmsg) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // #ifndef ERRORLOGGER_H
|
#endif // #ifndef ERRORLOGGER_H
|
||||||
|
|
420
filelister.cpp
420
filelister.cpp
|
@ -1,210 +1,210 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi
|
* Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "filelister.h"
|
#include "filelister.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#include <glob.h>
|
#include <glob.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
#if defined(__BORLANDC__) || defined(_MSC_VER)
|
#if defined(__BORLANDC__) || defined(_MSC_VER)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string FileLister::simplifyPath( const char *originalPath )
|
std::string FileLister::simplifyPath( const char *originalPath )
|
||||||
{
|
{
|
||||||
std::string subPath = "";
|
std::string subPath = "";
|
||||||
std::vector<std::string> pathParts;
|
std::vector<std::string> pathParts;
|
||||||
for( ; *originalPath; ++originalPath )
|
for( ; *originalPath; ++originalPath )
|
||||||
{
|
{
|
||||||
if( *originalPath == '/' )
|
if( *originalPath == '/' )
|
||||||
{
|
{
|
||||||
if( subPath.length() > 0 )
|
if( subPath.length() > 0 )
|
||||||
{
|
{
|
||||||
pathParts.push_back( subPath );
|
pathParts.push_back( subPath );
|
||||||
subPath = "";
|
subPath = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
pathParts.push_back( "/" );
|
pathParts.push_back( "/" );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
subPath.append( 1, *originalPath );
|
subPath.append( 1, *originalPath );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( subPath.length() > 0 )
|
if( subPath.length() > 0 )
|
||||||
pathParts.push_back( subPath );
|
pathParts.push_back( subPath );
|
||||||
|
|
||||||
for( std::vector<std::string>::size_type i = 0; i < pathParts.size(); ++i )
|
for( std::vector<std::string>::size_type i = 0; i < pathParts.size(); ++i )
|
||||||
{
|
{
|
||||||
if( pathParts[i] == ".." && i > 1 )
|
if( pathParts[i] == ".." && i > 1 )
|
||||||
{
|
{
|
||||||
pathParts.erase( pathParts.begin() + i );
|
pathParts.erase( pathParts.begin() + i );
|
||||||
pathParts.erase( pathParts.begin()+i-1 );
|
pathParts.erase( pathParts.begin()+i-1 );
|
||||||
pathParts.erase( pathParts.begin()+i-2 );
|
pathParts.erase( pathParts.begin()+i-2 );
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
else if( i > 0 && pathParts[i] == "." )
|
else if( i > 0 && pathParts[i] == "." )
|
||||||
{
|
{
|
||||||
pathParts.erase( pathParts.begin()+i );
|
pathParts.erase( pathParts.begin()+i );
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
else if( pathParts[i] == "/" && i > 0 && pathParts[i-1] == "/" )
|
else if( pathParts[i] == "/" && i > 0 && pathParts[i-1] == "/" )
|
||||||
{
|
{
|
||||||
pathParts.erase( pathParts.begin()+i-1 );
|
pathParts.erase( pathParts.begin()+i-1 );
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
for( std::vector<std::string>::size_type i = 0; i < pathParts.size(); ++i )
|
for( std::vector<std::string>::size_type i = 0; i < pathParts.size(); ++i )
|
||||||
{
|
{
|
||||||
oss << pathParts[i];
|
oss << pathParts[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool FileLister::AcceptFile( const std::string &filename )
|
bool FileLister::AcceptFile( const std::string &filename )
|
||||||
{
|
{
|
||||||
std::string::size_type dotLocation = filename.find_last_of ( '.' );
|
std::string::size_type dotLocation = filename.find_last_of ( '.' );
|
||||||
if ( dotLocation == std::string::npos )
|
if ( dotLocation == std::string::npos )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::string extension = filename.substr( dotLocation );
|
std::string extension = filename.substr( dotLocation );
|
||||||
|
|
||||||
if( extension == ".cpp" ||
|
if( extension == ".cpp" ||
|
||||||
extension == ".cxx" ||
|
extension == ".cxx" ||
|
||||||
extension == ".cc" ||
|
extension == ".cc" ||
|
||||||
extension == ".c" )
|
extension == ".c" )
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
////// This code is for __GNUC__ only /////////////////////////////////////////
|
////// This code is for __GNUC__ only /////////////////////////////////////////
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
// gcc / cygwin..
|
// gcc / cygwin..
|
||||||
void FileLister::RecursiveAddFiles( std::vector<std::string> &filenames, const std::string &path, bool recursive )
|
void FileLister::RecursiveAddFiles( std::vector<std::string> &filenames, const std::string &path, bool recursive )
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << path;
|
oss << path;
|
||||||
if( recursive )
|
if( recursive )
|
||||||
{
|
{
|
||||||
if ( path.length() > 0 && path[path.length()-1] != '/' )
|
if ( path.length() > 0 && path[path.length()-1] != '/' )
|
||||||
oss << "/";
|
oss << "/";
|
||||||
|
|
||||||
oss << "*";
|
oss << "*";
|
||||||
}
|
}
|
||||||
|
|
||||||
glob_t glob_results;
|
glob_t glob_results;
|
||||||
glob( oss.str().c_str(), GLOB_MARK, 0, &glob_results);
|
glob( oss.str().c_str(), GLOB_MARK, 0, &glob_results);
|
||||||
for ( unsigned int i = 0; i < glob_results.gl_pathc; i++ )
|
for ( unsigned int i = 0; i < glob_results.gl_pathc; i++ )
|
||||||
{
|
{
|
||||||
std::string filename = glob_results.gl_pathv[i];
|
std::string filename = glob_results.gl_pathv[i];
|
||||||
if ( filename == "." || filename == ".." || filename.length() == 0 )
|
if ( filename == "." || filename == ".." || filename.length() == 0 )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ( filename[filename.length()-1] != '/' )
|
if ( filename[filename.length()-1] != '/' )
|
||||||
{
|
{
|
||||||
// File
|
// File
|
||||||
|
|
||||||
// If recursive is not used, accept all files given by user
|
// If recursive is not used, accept all files given by user
|
||||||
if( !recursive || FileLister::AcceptFile( filename ) )
|
if( !recursive || FileLister::AcceptFile( filename ) )
|
||||||
filenames.push_back( filename );
|
filenames.push_back( filename );
|
||||||
}
|
}
|
||||||
else if( recursive )
|
else if( recursive )
|
||||||
{
|
{
|
||||||
// Directory
|
// Directory
|
||||||
FileLister::RecursiveAddFiles( filenames, filename, recursive );
|
FileLister::RecursiveAddFiles( filenames, filename, recursive );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
globfree(&glob_results);
|
globfree(&glob_results);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
////// This code is for Borland C++ and Visual C++ ////////////////////////////
|
////// This code is for Borland C++ and Visual C++ ////////////////////////////
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#if defined(__BORLANDC__) || defined(_MSC_VER)
|
#if defined(__BORLANDC__) || defined(_MSC_VER)
|
||||||
|
|
||||||
void FileLister::RecursiveAddFiles( std::vector<std::string> &filenames, const std::string &path, bool recursive )
|
void FileLister::RecursiveAddFiles( std::vector<std::string> &filenames, const std::string &path, bool recursive )
|
||||||
{
|
{
|
||||||
std::ostringstream bdir, oss;
|
std::ostringstream bdir, oss;
|
||||||
oss << path;
|
oss << path;
|
||||||
if (recursive)
|
if (recursive)
|
||||||
{
|
{
|
||||||
bdir << path;
|
bdir << path;
|
||||||
if ( path.length() > 0 && path[path.length()-1] != '/' )
|
if ( path.length() > 0 && path[path.length()-1] != '/' )
|
||||||
{
|
{
|
||||||
bdir << "/";
|
bdir << "/";
|
||||||
oss << "/";
|
oss << "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
oss << "*";
|
oss << "*";
|
||||||
}
|
}
|
||||||
|
|
||||||
WIN32_FIND_DATA ffd;
|
WIN32_FIND_DATA ffd;
|
||||||
HANDLE hFind = FindFirstFile(oss.str().c_str(), &ffd);
|
HANDLE hFind = FindFirstFile(oss.str().c_str(), &ffd);
|
||||||
if ( INVALID_HANDLE_VALUE == hFind )
|
if ( INVALID_HANDLE_VALUE == hFind )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
std::ostringstream fname;
|
std::ostringstream fname;
|
||||||
fname << bdir.str().c_str() << ffd.cFileName;
|
fname << bdir.str().c_str() << ffd.cFileName;
|
||||||
|
|
||||||
if ( ffd.cFileName[0] == '.' || ffd.cFileName[0] == '\0' )
|
if ( ffd.cFileName[0] == '.' || ffd.cFileName[0] == '\0' )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ( ( ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) == 0 )
|
if ( ( ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) == 0 )
|
||||||
{
|
{
|
||||||
// File
|
// File
|
||||||
|
|
||||||
// If recursive is not used, accept all files given by user
|
// If recursive is not used, accept all files given by user
|
||||||
if ( !recursive || FileLister::AcceptFile( ffd.cFileName ) )
|
if ( !recursive || FileLister::AcceptFile( ffd.cFileName ) )
|
||||||
filenames.push_back( fname.str() );
|
filenames.push_back( fname.str() );
|
||||||
}
|
}
|
||||||
else if ( recursive )
|
else if ( recursive )
|
||||||
{
|
{
|
||||||
// Directory
|
// Directory
|
||||||
fname << "/";
|
fname << "/";
|
||||||
FileLister::RecursiveAddFiles( filenames, fname.str().c_str(), recursive );
|
FileLister::RecursiveAddFiles( filenames, fname.str().c_str(), recursive );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (FindNextFile(hFind, &ffd) != FALSE);
|
while (FindNextFile(hFind, &ffd) != FALSE);
|
||||||
|
|
||||||
FindClose(hFind);
|
FindClose(hFind);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
94
filelister.h
94
filelister.h
|
@ -1,47 +1,47 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi
|
* Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef FileListerH
|
#ifndef FileListerH
|
||||||
#define FileListerH
|
#define FileListerH
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
// Check that the compiler are supported
|
// Check that the compiler are supported
|
||||||
// This program should be compiled with either GCC/BORLAND/MSC to work..
|
// This program should be compiled with either GCC/BORLAND/MSC to work..
|
||||||
#ifndef __GNUC__
|
#ifndef __GNUC__
|
||||||
#ifndef __BORLANDC__
|
#ifndef __BORLANDC__
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
#error "C++Check must be compiled by either GCC/BORLAND/MSC to work fully.\n"
|
#error "C++Check must be compiled by either GCC/BORLAND/MSC to work fully.\n"
|
||||||
#error "Please report that you couldn't compile c++check through the web page:\n"
|
#error "Please report that you couldn't compile c++check through the web page:\n"
|
||||||
#error " https://sourceforge.net/projects/cppcheck/"
|
#error " https://sourceforge.net/projects/cppcheck/"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
class FileLister
|
class FileLister
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void RecursiveAddFiles( std::vector<std::string> &filenames, const std::string &path, bool recursive );
|
static void RecursiveAddFiles( std::vector<std::string> &filenames, const std::string &path, bool recursive );
|
||||||
static std::string simplifyPath( const char *originalPath );
|
static std::string simplifyPath( const char *originalPath );
|
||||||
private:
|
private:
|
||||||
static bool AcceptFile( const std::string &filename );
|
static bool AcceptFile( const std::string &filename );
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // #ifndef FILELISTER_H
|
#endif // #ifndef FILELISTER_H
|
||||||
|
|
66
main.cpp
66
main.cpp
|
@ -1,33 +1,33 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cppcheckexecutor.h"
|
#include "cppcheckexecutor.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main function of cppcheck
|
* Main function of cppcheck
|
||||||
*
|
*
|
||||||
* @param argc Passed to CppCheck::parseFromArgs()
|
* @param argc Passed to CppCheck::parseFromArgs()
|
||||||
* @param argv Passed to CppCheck::parseFromArgs()
|
* @param argv Passed to CppCheck::parseFromArgs()
|
||||||
* @return 0
|
* @return 0
|
||||||
*/
|
*/
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
CppCheckExecutor exec;
|
CppCheckExecutor exec;
|
||||||
exec.check( argc, argv );
|
exec.check( argc, argv );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
750
preprocessor.cpp
750
preprocessor.cpp
|
@ -1,375 +1,375 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "preprocessor.h"
|
#include "preprocessor.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#ifdef __BORLANDC__
|
#ifdef __BORLANDC__
|
||||||
#include <ctype>
|
#include <ctype>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
Preprocessor::Preprocessor()
|
Preprocessor::Preprocessor()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Just read the code into a string. Perform simple cleanup of the code */
|
/** Just read the code into a string. Perform simple cleanup of the code */
|
||||||
std::string Preprocessor::read(std::istream &istr, const std::string &filename)
|
std::string Preprocessor::read(std::istream &istr, const std::string &filename)
|
||||||
{
|
{
|
||||||
// Get filedata from stream..
|
// Get filedata from stream..
|
||||||
bool ignoreSpace = true;
|
bool ignoreSpace = true;
|
||||||
|
|
||||||
// For the error report
|
// For the error report
|
||||||
int lineno = 1;
|
int lineno = 1;
|
||||||
|
|
||||||
std::ostringstream code;
|
std::ostringstream code;
|
||||||
for (char ch = (char)istr.get(); istr.good(); ch = (char)istr.get())
|
for (char ch = (char)istr.get(); istr.good(); ch = (char)istr.get())
|
||||||
{
|
{
|
||||||
if ( ch < 0 )
|
if ( ch < 0 )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ( ch == '\n' )
|
if ( ch == '\n' )
|
||||||
++lineno;
|
++lineno;
|
||||||
|
|
||||||
// Replace assorted special chars with spaces..
|
// Replace assorted special chars with spaces..
|
||||||
if ( (ch != '\n') && (isspace(ch) || iscntrl(ch)) )
|
if ( (ch != '\n') && (isspace(ch) || iscntrl(ch)) )
|
||||||
ch = ' ';
|
ch = ' ';
|
||||||
|
|
||||||
// Skip spaces after ' ' and after '#'
|
// Skip spaces after ' ' and after '#'
|
||||||
if ( ch == ' ' && ignoreSpace )
|
if ( ch == ' ' && ignoreSpace )
|
||||||
continue;
|
continue;
|
||||||
ignoreSpace = bool(ch == ' ' || ch == '#' || ch == '/');
|
ignoreSpace = bool(ch == ' ' || ch == '#' || ch == '/');
|
||||||
|
|
||||||
// Remove comments..
|
// Remove comments..
|
||||||
if ( ch == '/' )
|
if ( ch == '/' )
|
||||||
{
|
{
|
||||||
char chNext = (char)istr.get();
|
char chNext = (char)istr.get();
|
||||||
|
|
||||||
if ( chNext == '/' )
|
if ( chNext == '/' )
|
||||||
{
|
{
|
||||||
while (istr.good() && ch!='\n')
|
while (istr.good() && ch!='\n')
|
||||||
ch = (char)istr.get();
|
ch = (char)istr.get();
|
||||||
code << "\n";
|
code << "\n";
|
||||||
++lineno;
|
++lineno;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if ( chNext == '*' )
|
else if ( chNext == '*' )
|
||||||
{
|
{
|
||||||
char chPrev = 0;
|
char chPrev = 0;
|
||||||
while (istr.good() && (chPrev!='*' || ch!='/'))
|
while (istr.good() && (chPrev!='*' || ch!='/'))
|
||||||
{
|
{
|
||||||
chPrev = ch;
|
chPrev = ch;
|
||||||
ch = (char)istr.get();
|
ch = (char)istr.get();
|
||||||
if (ch == '\n')
|
if (ch == '\n')
|
||||||
{
|
{
|
||||||
code << "\n";
|
code << "\n";
|
||||||
++lineno;
|
++lineno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( chNext == '\n' )
|
if ( chNext == '\n' )
|
||||||
++lineno;
|
++lineno;
|
||||||
code << std::string(1,ch) << std::string(1,chNext);
|
code << std::string(1,ch) << std::string(1,chNext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// String constants..
|
// String constants..
|
||||||
else if ( ch == '\"' )
|
else if ( ch == '\"' )
|
||||||
{
|
{
|
||||||
code << "\"";
|
code << "\"";
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
ch = (char)istr.get();
|
ch = (char)istr.get();
|
||||||
code << std::string(1,ch);
|
code << std::string(1,ch);
|
||||||
if ( ch == '\\' )
|
if ( ch == '\\' )
|
||||||
{
|
{
|
||||||
ch = (char)istr.get();
|
ch = (char)istr.get();
|
||||||
code << std::string(1,ch);
|
code << std::string(1,ch);
|
||||||
|
|
||||||
// Avoid exiting loop if string contains "-characters
|
// Avoid exiting loop if string contains "-characters
|
||||||
ch = 0;
|
ch = 0;
|
||||||
}
|
}
|
||||||
} while ( istr.good() && ch != '\"' );
|
} while ( istr.good() && ch != '\"' );
|
||||||
}
|
}
|
||||||
|
|
||||||
// char constants..
|
// char constants..
|
||||||
else if ( ch == '\'' )
|
else if ( ch == '\'' )
|
||||||
{
|
{
|
||||||
code << "\'";
|
code << "\'";
|
||||||
ch = (char)istr.get();
|
ch = (char)istr.get();
|
||||||
code << std::string(1,ch);
|
code << std::string(1,ch);
|
||||||
if ( ch == '\\' )
|
if ( ch == '\\' )
|
||||||
{
|
{
|
||||||
ch = (char)istr.get();
|
ch = (char)istr.get();
|
||||||
code << std::string(1,ch);
|
code << std::string(1,ch);
|
||||||
}
|
}
|
||||||
ch = (char)istr.get();
|
ch = (char)istr.get();
|
||||||
code << "\'";
|
code << "\'";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Just some code..
|
// Just some code..
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
code << std::string(1, ch);
|
code << std::string(1, ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return code.str();
|
return code.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the code for each configuration
|
* Extract the code for each configuration
|
||||||
* \param istr The (file/string) stream to read from.
|
* \param istr The (file/string) stream to read from.
|
||||||
* \param result The map that will get the results
|
* \param result The map that will get the results
|
||||||
*/
|
*/
|
||||||
void Preprocessor::preprocess(std::istream &istr, std::map<std::string, std::string> &result, const std::string &filename)
|
void Preprocessor::preprocess(std::istream &istr, std::map<std::string, std::string> &result, const std::string &filename)
|
||||||
{
|
{
|
||||||
std::string codestr( read(istr, filename) );
|
std::string codestr( read(istr, filename) );
|
||||||
|
|
||||||
// Replace all tabs with spaces..
|
// Replace all tabs with spaces..
|
||||||
std::string::size_type loc = 0;
|
std::string::size_type loc = 0;
|
||||||
while ( (loc = codestr.find("\t", loc)) != std::string::npos )
|
while ( (loc = codestr.find("\t", loc)) != std::string::npos )
|
||||||
codestr[loc] = ' ';
|
codestr[loc] = ' ';
|
||||||
|
|
||||||
// Remove all indentation..
|
// Remove all indentation..
|
||||||
if ( !codestr.empty() && codestr[0] == ' ' )
|
if ( !codestr.empty() && codestr[0] == ' ' )
|
||||||
codestr.erase( 0, codestr.find_first_not_of(" ") );
|
codestr.erase( 0, codestr.find_first_not_of(" ") );
|
||||||
loc = 0;
|
loc = 0;
|
||||||
while ( (loc = codestr.find("\n ", loc)) != std::string::npos )
|
while ( (loc = codestr.find("\n ", loc)) != std::string::npos )
|
||||||
codestr.erase( 1 + loc, 1 );
|
codestr.erase( 1 + loc, 1 );
|
||||||
|
|
||||||
// Remove all trailing spaces..
|
// Remove all trailing spaces..
|
||||||
loc = 0;
|
loc = 0;
|
||||||
while ( (loc = codestr.find(" \n", loc)) != std::string::npos )
|
while ( (loc = codestr.find(" \n", loc)) != std::string::npos )
|
||||||
{
|
{
|
||||||
codestr.erase( loc, 1 );
|
codestr.erase( loc, 1 );
|
||||||
if ( loc > 0 )
|
if ( loc > 0 )
|
||||||
--loc;
|
--loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Using the backslash at the end of a line..
|
// Using the backslash at the end of a line..
|
||||||
while ( (loc = codestr.rfind("\\\n")) != std::string::npos )
|
while ( (loc = codestr.rfind("\\\n")) != std::string::npos )
|
||||||
{
|
{
|
||||||
codestr.erase(loc, 2);
|
codestr.erase(loc, 2);
|
||||||
if (loc > 0 && codestr[loc-1] != ' ')
|
if (loc > 0 && codestr[loc-1] != ' ')
|
||||||
codestr.insert(loc, " ");
|
codestr.insert(loc, " ");
|
||||||
if ( (loc = codestr.find("\n", loc)) != std::string::npos)
|
if ( (loc = codestr.find("\n", loc)) != std::string::npos)
|
||||||
codestr.insert( loc, "\n" );
|
codestr.insert( loc, "\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all possible configurations..
|
// Get all possible configurations..
|
||||||
std::list<std::string> cfgs = getcfgs( codestr );
|
std::list<std::string> cfgs = getcfgs( codestr );
|
||||||
|
|
||||||
// Extract the code for each possible configuration..
|
// Extract the code for each possible configuration..
|
||||||
result.clear();
|
result.clear();
|
||||||
for ( std::list<std::string>::const_iterator it = cfgs.begin(); it != cfgs.end(); ++it )
|
for ( std::list<std::string>::const_iterator it = cfgs.begin(); it != cfgs.end(); ++it )
|
||||||
{
|
{
|
||||||
result[ *it ] = getcode( codestr, *it );
|
result[ *it ] = getcode( codestr, *it );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Get the DEF in this line: "#ifdef DEF"
|
// Get the DEF in this line: "#ifdef DEF"
|
||||||
std::string Preprocessor::getdef(std::string line, bool def)
|
std::string Preprocessor::getdef(std::string line, bool def)
|
||||||
{
|
{
|
||||||
// If def is true, the line must start with "#ifdef"
|
// If def is true, the line must start with "#ifdef"
|
||||||
if ( def && line.find("#ifdef ") != 0 && line.find("#if ") != 0 && line.find("#elif ") != 0 )
|
if ( def && line.find("#ifdef ") != 0 && line.find("#if ") != 0 && line.find("#elif ") != 0 )
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// If def is false, the line must start with "#ifndef"
|
// If def is false, the line must start with "#ifndef"
|
||||||
if ( !def && line.find("#ifndef ") != 0 )
|
if ( !def && line.find("#ifndef ") != 0 )
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the "#ifdef" or "#ifndef"
|
// Remove the "#ifdef" or "#ifndef"
|
||||||
line.erase( 0, line.find(" ") );
|
line.erase( 0, line.find(" ") );
|
||||||
|
|
||||||
// Remove all spaces.
|
// Remove all spaces.
|
||||||
while ( line.find(" ") != std::string::npos )
|
while ( line.find(" ") != std::string::npos )
|
||||||
line.erase( line.find(" "), 1 );
|
line.erase( line.find(" "), 1 );
|
||||||
|
|
||||||
// The remaining string is our result.
|
// The remaining string is our result.
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::list<std::string> Preprocessor::getcfgs( const std::string &filedata )
|
std::list<std::string> Preprocessor::getcfgs( const std::string &filedata )
|
||||||
{
|
{
|
||||||
std::list<std::string> ret;
|
std::list<std::string> ret;
|
||||||
ret.push_back("");
|
ret.push_back("");
|
||||||
|
|
||||||
std::list<std::string> deflist;
|
std::list<std::string> deflist;
|
||||||
|
|
||||||
std::istringstream istr(filedata);
|
std::istringstream istr(filedata);
|
||||||
std::string line;
|
std::string line;
|
||||||
while ( getline(istr, line) )
|
while ( getline(istr, line) )
|
||||||
{
|
{
|
||||||
std::string def = getdef(line, true) + getdef(line, false);
|
std::string def = getdef(line, true) + getdef(line, false);
|
||||||
if (!def.empty())
|
if (!def.empty())
|
||||||
{
|
{
|
||||||
if ( ! deflist.empty() && line.find("#elif ") == 0 )
|
if ( ! deflist.empty() && line.find("#elif ") == 0 )
|
||||||
deflist.pop_back();
|
deflist.pop_back();
|
||||||
deflist.push_back(def);
|
deflist.push_back(def);
|
||||||
def = "";
|
def = "";
|
||||||
for ( std::list<std::string>::const_iterator it = deflist.begin(); it != deflist.end(); ++it)
|
for ( std::list<std::string>::const_iterator it = deflist.begin(); it != deflist.end(); ++it)
|
||||||
{
|
{
|
||||||
if ( *it == "0" )
|
if ( *it == "0" )
|
||||||
break;
|
break;
|
||||||
if ( *it == "1" )
|
if ( *it == "1" )
|
||||||
continue;
|
continue;
|
||||||
if ( ! def.empty() )
|
if ( ! def.empty() )
|
||||||
def += ";";
|
def += ";";
|
||||||
def += *it;
|
def += *it;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::find(ret.begin(), ret.end(), def) == ret.end())
|
if (std::find(ret.begin(), ret.end(), def) == ret.end())
|
||||||
ret.push_back( def );
|
ret.push_back( def );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( line.find("#else") == 0 && ! deflist.empty() )
|
if ( line.find("#else") == 0 && ! deflist.empty() )
|
||||||
{
|
{
|
||||||
std::string def( ( deflist.back() == "1" ) ? "0" : "1" );
|
std::string def( ( deflist.back() == "1" ) ? "0" : "1" );
|
||||||
deflist.pop_back();
|
deflist.pop_back();
|
||||||
deflist.push_back( def );
|
deflist.push_back( def );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( line.find("#endif") == 0 && ! deflist.empty() )
|
if ( line.find("#endif") == 0 && ! deflist.empty() )
|
||||||
deflist.pop_back();
|
deflist.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool Preprocessor::match_cfg_def( std::string cfg, const std::string &def )
|
bool Preprocessor::match_cfg_def( std::string cfg, const std::string &def )
|
||||||
{
|
{
|
||||||
if ( def == "0" )
|
if ( def == "0" )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ( def == "1" )
|
if ( def == "1" )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if ( cfg.empty() )
|
if ( cfg.empty() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
while ( ! cfg.empty() )
|
while ( ! cfg.empty() )
|
||||||
{
|
{
|
||||||
if ( cfg.find(";") == std::string::npos )
|
if ( cfg.find(";") == std::string::npos )
|
||||||
return bool(cfg == def);
|
return bool(cfg == def);
|
||||||
std::string _cfg = cfg.substr( 0, cfg.find(";") );
|
std::string _cfg = cfg.substr( 0, cfg.find(";") );
|
||||||
if ( _cfg == def )
|
if ( _cfg == def )
|
||||||
return true;
|
return true;
|
||||||
cfg.erase( 0, cfg.find(";") + 1 );
|
cfg.erase( 0, cfg.find(";") + 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string Preprocessor::getcode(const std::string &filedata, std::string cfg)
|
std::string Preprocessor::getcode(const std::string &filedata, std::string cfg)
|
||||||
{
|
{
|
||||||
std::ostringstream ret;
|
std::ostringstream ret;
|
||||||
|
|
||||||
bool match = true;
|
bool match = true;
|
||||||
std::list<bool> matching_ifdef;
|
std::list<bool> matching_ifdef;
|
||||||
std::list<bool> matched_ifdef;
|
std::list<bool> matched_ifdef;
|
||||||
|
|
||||||
std::istringstream istr(filedata);
|
std::istringstream istr(filedata);
|
||||||
std::string line;
|
std::string line;
|
||||||
while ( getline(istr, line) )
|
while ( getline(istr, line) )
|
||||||
{
|
{
|
||||||
std::string def = getdef( line, true );
|
std::string def = getdef( line, true );
|
||||||
std::string ndef = getdef( line, false );
|
std::string ndef = getdef( line, false );
|
||||||
|
|
||||||
if ( line.find("#elif ") == 0 )
|
if ( line.find("#elif ") == 0 )
|
||||||
{
|
{
|
||||||
if ( matched_ifdef.back() )
|
if ( matched_ifdef.back() )
|
||||||
{
|
{
|
||||||
matching_ifdef.back() = false;
|
matching_ifdef.back() = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( match_cfg_def(cfg, def) )
|
if ( match_cfg_def(cfg, def) )
|
||||||
{
|
{
|
||||||
matching_ifdef.back() = true;
|
matching_ifdef.back() = true;
|
||||||
matched_ifdef.back() = true;
|
matched_ifdef.back() = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if ( ! def.empty() )
|
else if ( ! def.empty() )
|
||||||
{
|
{
|
||||||
matching_ifdef.push_back( match_cfg_def(cfg, def) );
|
matching_ifdef.push_back( match_cfg_def(cfg, def) );
|
||||||
matched_ifdef.push_back( matching_ifdef.back() );
|
matched_ifdef.push_back( matching_ifdef.back() );
|
||||||
}
|
}
|
||||||
|
|
||||||
else if ( ! ndef.empty() )
|
else if ( ! ndef.empty() )
|
||||||
{
|
{
|
||||||
matching_ifdef.push_back( ! match_cfg_def(cfg, ndef) );
|
matching_ifdef.push_back( ! match_cfg_def(cfg, ndef) );
|
||||||
matched_ifdef.push_back( matching_ifdef.back() );
|
matched_ifdef.push_back( matching_ifdef.back() );
|
||||||
}
|
}
|
||||||
|
|
||||||
else if ( line == "#else" )
|
else if ( line == "#else" )
|
||||||
{
|
{
|
||||||
if ( ! matched_ifdef.empty() )
|
if ( ! matched_ifdef.empty() )
|
||||||
matching_ifdef.back() = ! matched_ifdef.back();
|
matching_ifdef.back() = ! matched_ifdef.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
else if ( line == "#endif" )
|
else if ( line == "#endif" )
|
||||||
{
|
{
|
||||||
if ( ! matched_ifdef.empty() )
|
if ( ! matched_ifdef.empty() )
|
||||||
matched_ifdef.pop_back();
|
matched_ifdef.pop_back();
|
||||||
if ( ! matching_ifdef.empty() )
|
if ( ! matching_ifdef.empty() )
|
||||||
matching_ifdef.pop_back();
|
matching_ifdef.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !line.empty() && line[0] == '#' )
|
if ( !line.empty() && line[0] == '#' )
|
||||||
{
|
{
|
||||||
match = true;
|
match = true;
|
||||||
for ( std::list<bool>::const_iterator it = matching_ifdef.begin(); it != matching_ifdef.end(); ++it )
|
for ( std::list<bool>::const_iterator it = matching_ifdef.begin(); it != matching_ifdef.end(); ++it )
|
||||||
match &= bool(*it);
|
match &= bool(*it);
|
||||||
}
|
}
|
||||||
if ( ! match )
|
if ( ! match )
|
||||||
line = "";
|
line = "";
|
||||||
|
|
||||||
if ( line.find("#if") == 0 ||
|
if ( line.find("#if") == 0 ||
|
||||||
line.find("#else") == 0 ||
|
line.find("#else") == 0 ||
|
||||||
line.find("#elif") == 0 ||
|
line.find("#elif") == 0 ||
|
||||||
line.find("#endif") == 0 )
|
line.find("#endif") == 0 )
|
||||||
line = "";
|
line = "";
|
||||||
|
|
||||||
ret << line << "\n";
|
ret << line << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret.str();
|
return ret.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
116
preprocessor.h
116
preprocessor.h
|
@ -1,58 +1,58 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#ifndef preprocessorH
|
#ifndef preprocessorH
|
||||||
#define preprocessorH
|
#define preprocessorH
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <istream>
|
#include <istream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
|
|
||||||
class Preprocessor
|
class Preprocessor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Preprocessor();
|
Preprocessor();
|
||||||
|
|
||||||
void preprocess(std::istream &istr, std::map<std::string, std::string> &result, const std::string &filename);
|
void preprocess(std::istream &istr, std::map<std::string, std::string> &result, const std::string &filename);
|
||||||
|
|
||||||
/** Just read the code into a string. Perform simple cleanup of the code */
|
/** Just read the code into a string. Perform simple cleanup of the code */
|
||||||
std::string read(std::istream &istr, const std::string &filename);
|
std::string read(std::istream &istr, const std::string &filename);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Get preprocessed code for a given configuration
|
* Get preprocessed code for a given configuration
|
||||||
*/
|
*/
|
||||||
std::string getcode(const std::string &filedata, std::string cfg);
|
std::string getcode(const std::string &filedata, std::string cfg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all possible configurations. By looking at the ifdefs and ifndefs in filedata
|
* Get all possible configurations. By looking at the ifdefs and ifndefs in filedata
|
||||||
*/
|
*/
|
||||||
std::list<std::string> getcfgs( const std::string &filedata );
|
std::list<std::string> getcfgs( const std::string &filedata );
|
||||||
|
|
||||||
std::string getdef(std::string line, bool def);
|
std::string getdef(std::string line, bool def);
|
||||||
|
|
||||||
bool match_cfg_def( std::string cfg, const std::string &def );
|
bool match_cfg_def( std::string cfg, const std::string &def );
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
68
settings.cpp
68
settings.cpp
|
@ -1,34 +1,34 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi
|
* Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
Settings::Settings()
|
Settings::Settings()
|
||||||
{
|
{
|
||||||
_debug = false;
|
_debug = false;
|
||||||
_showAll = false;
|
_showAll = false;
|
||||||
_checkCodingStyle = false;
|
_checkCodingStyle = false;
|
||||||
_errorsOnly = false;
|
_errorsOnly = false;
|
||||||
_checkFunctionUsage = false;
|
_checkFunctionUsage = false;
|
||||||
_verbose = false;
|
_verbose = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Settings::~Settings()
|
Settings::~Settings()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
82
settings.h
82
settings.h
|
@ -1,41 +1,41 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi
|
* Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SETTINGS_H
|
#ifndef SETTINGS_H
|
||||||
#define SETTINGS_H
|
#define SETTINGS_H
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is just a container for general settings so that we don't need
|
* This is just a container for general settings so that we don't need
|
||||||
* to pass individual values to functions or constructors now or in the
|
* to pass individual values to functions or constructors now or in the
|
||||||
* future when we might have even more detailed settings.
|
* future when we might have even more detailed settings.
|
||||||
*/
|
*/
|
||||||
class Settings
|
class Settings
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Settings();
|
Settings();
|
||||||
virtual ~Settings();
|
virtual ~Settings();
|
||||||
|
|
||||||
bool _debug;
|
bool _debug;
|
||||||
bool _showAll;
|
bool _showAll;
|
||||||
bool _checkCodingStyle;
|
bool _checkCodingStyle;
|
||||||
bool _errorsOnly;
|
bool _errorsOnly;
|
||||||
bool _checkFunctionUsage;
|
bool _checkFunctionUsage;
|
||||||
bool _verbose;
|
bool _verbose;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SETTINGS_H
|
#endif // SETTINGS_H
|
||||||
|
|
|
@ -1,397 +1,397 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#define UNIT_TESTING
|
#define UNIT_TESTING
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
#include "checkbufferoverrun.h"
|
#include "checkbufferoverrun.h"
|
||||||
#include "testsuite.h"
|
#include "testsuite.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
extern std::ostringstream errout;
|
extern std::ostringstream errout;
|
||||||
|
|
||||||
class TestBufferOverrun : public TestFixture
|
class TestBufferOverrun : public TestFixture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TestBufferOverrun() : TestFixture("TestBufferOverrun")
|
TestBufferOverrun() : TestFixture("TestBufferOverrun")
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void check( const char code[] )
|
void check( const char code[] )
|
||||||
{
|
{
|
||||||
// Tokenize..
|
// Tokenize..
|
||||||
Tokenizer tokenizer;
|
Tokenizer tokenizer;
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
tokenizer.tokenize( istr, "test.cpp" );
|
tokenizer.tokenize( istr, "test.cpp" );
|
||||||
tokenizer.simplifyTokenList();
|
tokenizer.simplifyTokenList();
|
||||||
|
|
||||||
// Assign variable ids
|
// Assign variable ids
|
||||||
tokenizer.setVarId();
|
tokenizer.setVarId();
|
||||||
|
|
||||||
// Fill function list
|
// Fill function list
|
||||||
tokenizer.fillFunctionList();
|
tokenizer.fillFunctionList();
|
||||||
|
|
||||||
// Clear the error buffer..
|
// Clear the error buffer..
|
||||||
errout.str("");
|
errout.str("");
|
||||||
|
|
||||||
// Check for buffer overruns..
|
// Check for buffer overruns..
|
||||||
Settings settings;
|
Settings settings;
|
||||||
settings._showAll = true;
|
settings._showAll = true;
|
||||||
CheckBufferOverrunClass checkBufferOverrun( &tokenizer, settings, this );
|
CheckBufferOverrunClass checkBufferOverrun( &tokenizer, settings, this );
|
||||||
checkBufferOverrun.CheckBufferOverrun();
|
checkBufferOverrun.CheckBufferOverrun();
|
||||||
}
|
}
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
TEST_CASE( noerr1 );
|
TEST_CASE( noerr1 );
|
||||||
TEST_CASE( noerr2 );
|
TEST_CASE( noerr2 );
|
||||||
TEST_CASE( noerr3 );
|
TEST_CASE( noerr3 );
|
||||||
TEST_CASE( noerr4 );
|
TEST_CASE( noerr4 );
|
||||||
|
|
||||||
TEST_CASE( array_index_1 );
|
TEST_CASE( array_index_1 );
|
||||||
TEST_CASE( array_index_2 );
|
TEST_CASE( array_index_2 );
|
||||||
TEST_CASE( array_index_3 );
|
TEST_CASE( array_index_3 );
|
||||||
TEST_CASE( array_index_4 );
|
TEST_CASE( array_index_4 );
|
||||||
TEST_CASE( array_index_5 );
|
TEST_CASE( array_index_5 );
|
||||||
TEST_CASE( array_index_6 );
|
TEST_CASE( array_index_6 );
|
||||||
TEST_CASE( array_index_7 );
|
TEST_CASE( array_index_7 );
|
||||||
TEST_CASE( array_index_8 );
|
TEST_CASE( array_index_8 );
|
||||||
TEST_CASE( array_index_9 );
|
TEST_CASE( array_index_9 );
|
||||||
TEST_CASE( array_index_10 );
|
TEST_CASE( array_index_10 );
|
||||||
TEST_CASE( array_index_11 );
|
TEST_CASE( array_index_11 );
|
||||||
TEST_CASE( array_index_12 );
|
TEST_CASE( array_index_12 );
|
||||||
|
|
||||||
TEST_CASE( buffer_overrun_1 );
|
TEST_CASE( buffer_overrun_1 );
|
||||||
TEST_CASE( buffer_overrun_2 );
|
TEST_CASE( buffer_overrun_2 );
|
||||||
|
|
||||||
TEST_CASE( varid1 );
|
TEST_CASE( varid1 );
|
||||||
TEST_CASE( varid2 );
|
TEST_CASE( varid2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void noerr1()
|
void noerr1()
|
||||||
{
|
{
|
||||||
check( "void f()\n"
|
check( "void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" if (ab)\n"
|
" if (ab)\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" char str[50];\n"
|
" char str[50];\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" if (ab)\n"
|
" if (ab)\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" char str[50];\n"
|
" char str[50];\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void noerr2()
|
void noerr2()
|
||||||
{
|
{
|
||||||
check( "void f1(char *str)\n"
|
check( "void f1(char *str)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" strcpy(buf,str);\n"
|
" strcpy(buf,str);\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"void f2(char *str)\n"
|
"void f2(char *str)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" strcat(buf,str);\n"
|
" strcat(buf,str);\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"void f3(char *str)\n"
|
"void f3(char *str)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" sprintf(buf,\"%s\",str);\n"
|
" sprintf(buf,\"%s\",str);\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"void f4(const char str[])\n"
|
"void f4(const char str[])\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" strcpy(buf, str);\n"
|
" strcpy(buf, str);\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void noerr3()
|
void noerr3()
|
||||||
{
|
{
|
||||||
check( "static void f()\n"
|
check( "static void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" char data[1];\n"
|
" char data[1];\n"
|
||||||
" return abc.data[1];\n"
|
" return abc.data[1];\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void noerr4()
|
void noerr4()
|
||||||
{
|
{
|
||||||
// The memory isn't read or written and therefore there is no error.
|
// The memory isn't read or written and therefore there is no error.
|
||||||
check( "static void f()\n"
|
check( "static void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" char data[100];\n"
|
" char data[100];\n"
|
||||||
" const char *p = &data[100];\n"
|
" const char *p = &data[100];\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void array_index_1()
|
void array_index_1()
|
||||||
{
|
{
|
||||||
check("void f()\n"
|
check("void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" char str[0x10];\n"
|
" char str[0x10];\n"
|
||||||
" str[15] = 0;\n"
|
" str[15] = 0;\n"
|
||||||
" str[16] = 0;\n"
|
" str[16] = 0;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:5]: Array index out of bounds\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:5]: Array index out of bounds\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void array_index_2()
|
void array_index_2()
|
||||||
{
|
{
|
||||||
check("void f()\n"
|
check("void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" char *str = new char[0x10];\n"
|
" char *str = new char[0x10];\n"
|
||||||
" str[15] = 0;\n"
|
" str[15] = 0;\n"
|
||||||
" str[16] = 0;\n"
|
" str[16] = 0;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:5]: Array index out of bounds\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:5]: Array index out of bounds\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void array_index_3()
|
void array_index_3()
|
||||||
{
|
{
|
||||||
check( "void f()\n"
|
check( "void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int val[50];\n"
|
" int val[50];\n"
|
||||||
" for (i = 0; i < 100; i++)\n"
|
" for (i = 0; i < 100; i++)\n"
|
||||||
" sum += val[i];\n"
|
" sum += val[i];\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:5]: Buffer overrun\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:5]: Buffer overrun\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void array_index_4()
|
void array_index_4()
|
||||||
{
|
{
|
||||||
check( "const int SIZE = 10;\n"
|
check( "const int SIZE = 10;\n"
|
||||||
"void f()\n"
|
"void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int i[SIZE];\n"
|
" int i[SIZE];\n"
|
||||||
" i[SIZE] = 0;\n"
|
" i[SIZE] = 0;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:5]: Array index out of bounds\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:5]: Array index out of bounds\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void array_index_5()
|
void array_index_5()
|
||||||
{
|
{
|
||||||
check( "void f()\n"
|
check( "void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int i[10];\n"
|
" int i[10];\n"
|
||||||
" i[ sizeof(i) - 1 ] = 0;\n"
|
" i[ sizeof(i) - 1 ] = 0;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:4]: Array index out of bounds\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:4]: Array index out of bounds\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void array_index_6()
|
void array_index_6()
|
||||||
{
|
{
|
||||||
check( "struct ABC\n"
|
check( "struct ABC\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" char str[10];\n"
|
" char str[10];\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"\n"
|
"\n"
|
||||||
"static void f()\n"
|
"static void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" struct ABC abc;\n"
|
" struct ABC abc;\n"
|
||||||
" abc.str[10] = 0;\n"
|
" abc.str[10] = 0;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:9]: Array index out of bounds\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:9]: Array index out of bounds\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void array_index_7()
|
void array_index_7()
|
||||||
{
|
{
|
||||||
check( "struct ABC\n"
|
check( "struct ABC\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" char str[10];\n"
|
" char str[10];\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"\n"
|
"\n"
|
||||||
"static void f(ABC *abc)\n"
|
"static void f(ABC *abc)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" abc->str[10] = 0;\n"
|
" abc->str[10] = 0;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:8]: Array index out of bounds\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:8]: Array index out of bounds\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void array_index_8()
|
void array_index_8()
|
||||||
{
|
{
|
||||||
check( "const int SIZE = 10;\n"
|
check( "const int SIZE = 10;\n"
|
||||||
"\n"
|
"\n"
|
||||||
"struct ABC\n"
|
"struct ABC\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" char str[SIZE];\n"
|
" char str[SIZE];\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"\n"
|
"\n"
|
||||||
"static void f()\n"
|
"static void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" struct ABC abc;\n"
|
" struct ABC abc;\n"
|
||||||
" abc.str[SIZE] = 0;\n"
|
" abc.str[SIZE] = 0;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:11]: Array index out of bounds\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:11]: Array index out of bounds\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void array_index_9()
|
void array_index_9()
|
||||||
{
|
{
|
||||||
check( "static void memclr( char *data )\n"
|
check( "static void memclr( char *data )\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" data[10] = 0;\n"
|
" data[10] = 0;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n"
|
||||||
"static void f()\n"
|
"static void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" char str[5];\n"
|
" char str[5];\n"
|
||||||
" memclr( str ); // ERROR\n"
|
" memclr( str ); // ERROR\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:9] -> [test.cpp:3]: Array index out of bounds\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:9] -> [test.cpp:3]: Array index out of bounds\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void array_index_10()
|
void array_index_10()
|
||||||
{
|
{
|
||||||
check( "struct ABC\n"
|
check( "struct ABC\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" char str[10];\n"
|
" char str[10];\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"\n"
|
"\n"
|
||||||
"static void memclr( char *data )\n"
|
"static void memclr( char *data )\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" data[10] = 0;\n"
|
" data[10] = 0;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n"
|
||||||
"static void f(ABC *abc)\n"
|
"static void f(ABC *abc)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" memclr(abc->str);\n"
|
" memclr(abc->str);\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:13] -> [test.cpp:8]: Array index out of bounds\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:13] -> [test.cpp:8]: Array index out of bounds\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void array_index_11()
|
void array_index_11()
|
||||||
{
|
{
|
||||||
check( "class ABC\n"
|
check( "class ABC\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" ABC();\n"
|
" ABC();\n"
|
||||||
" char *str[10];\n"
|
" char *str[10];\n"
|
||||||
" struct ABC *next;"
|
" struct ABC *next;"
|
||||||
"};\n"
|
"};\n"
|
||||||
"\n"
|
"\n"
|
||||||
"static void f()\n"
|
"static void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" for ( ABC *abc = abc1; abc; abc = abc->next() )\n"
|
" for ( ABC *abc = abc1; abc; abc = abc->next() )\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" abc->str[10] = 0;\n"
|
" abc->str[10] = 0;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:12]: Array index out of bounds\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:12]: Array index out of bounds\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void array_index_12()
|
void array_index_12()
|
||||||
{
|
{
|
||||||
check( "class Fred\n"
|
check( "class Fred\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"private:\n"
|
"private:\n"
|
||||||
" char str[10];\n"
|
" char str[10];\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" Fred();\n"
|
" Fred();\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"Fred::Fred()\n"
|
"Fred::Fred()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" str[10] = 0;\n"
|
" str[10] = 0;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
std::string err( errout.str() );
|
std::string err( errout.str() );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:10]: Array index out of bounds\n"), err );
|
ASSERT_EQUALS( std::string("[test.cpp:10]: Array index out of bounds\n"), err );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void buffer_overrun_1()
|
void buffer_overrun_1()
|
||||||
{
|
{
|
||||||
check( "void f()\n"
|
check( "void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" char str[3];\n"
|
" char str[3];\n"
|
||||||
" strcpy(str, \"abc\");\n"
|
" strcpy(str, \"abc\");\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:4]: Buffer overrun\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:4]: Buffer overrun\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void buffer_overrun_2()
|
void buffer_overrun_2()
|
||||||
{
|
{
|
||||||
check( "struct ABC\n"
|
check( "struct ABC\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" char str[5];\n"
|
" char str[5];\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"\n"
|
"\n"
|
||||||
"static void f(ABC *abc)\n"
|
"static void f(ABC *abc)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" strcpy( abc->str, \"abcdef\" );\n"
|
" strcpy( abc->str, \"abcdef\" );\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:8]: Buffer overrun\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:8]: Buffer overrun\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void varid1()
|
void varid1()
|
||||||
{
|
{
|
||||||
check( "void foo()\n"
|
check( "void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" char str[10];\n"
|
" char str[10];\n"
|
||||||
" if (str[0])\n"
|
" if (str[0])\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" char str[50];\n"
|
" char str[50];\n"
|
||||||
" str[30] = 0;\n"
|
" str[30] = 0;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void varid2()
|
void varid2()
|
||||||
{
|
{
|
||||||
check( "void foo()\n"
|
check( "void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" char str[10];\n"
|
" char str[10];\n"
|
||||||
" if (str[0])\n"
|
" if (str[0])\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" char str[50];\n"
|
" char str[50];\n"
|
||||||
" memset(str,0,50);\n"
|
" memset(str,0,50);\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST( TestBufferOverrun )
|
REGISTER_TEST( TestBufferOverrun )
|
||||||
|
|
||||||
|
|
||||||
|
|
210
testcharvar.cpp
210
testcharvar.cpp
|
@ -1,105 +1,105 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#define UNIT_TESTING
|
#define UNIT_TESTING
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
#include "checkother.h"
|
#include "checkother.h"
|
||||||
#include "testsuite.h"
|
#include "testsuite.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
extern std::ostringstream errout;
|
extern std::ostringstream errout;
|
||||||
|
|
||||||
class TestCharVar : public TestFixture
|
class TestCharVar : public TestFixture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TestCharVar() : TestFixture("TestCharVar")
|
TestCharVar() : TestFixture("TestCharVar")
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
TEST_CASE( array_index );
|
TEST_CASE( array_index );
|
||||||
TEST_CASE( bitop1 );
|
TEST_CASE( bitop1 );
|
||||||
TEST_CASE( bitop2 );
|
TEST_CASE( bitop2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void check( const char code[] )
|
void check( const char code[] )
|
||||||
{
|
{
|
||||||
// Tokenize..
|
// Tokenize..
|
||||||
Tokenizer tokenizer;
|
Tokenizer tokenizer;
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
tokenizer.tokenize( istr, "test.cpp" );
|
tokenizer.tokenize( istr, "test.cpp" );
|
||||||
|
|
||||||
// Clear the error buffer..
|
// Clear the error buffer..
|
||||||
errout.str("");
|
errout.str("");
|
||||||
|
|
||||||
// Check char variable usage..
|
// Check char variable usage..
|
||||||
CheckOther checkOther( &tokenizer, this );
|
CheckOther checkOther( &tokenizer, this );
|
||||||
checkOther.CheckCharVariable();
|
checkOther.CheckCharVariable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void array_index()
|
void array_index()
|
||||||
{
|
{
|
||||||
check( "void foo()\n"
|
check( "void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" unsigned char ch = 0x80;\n"
|
" unsigned char ch = 0x80;\n"
|
||||||
" buf[ch] = 0;\n"
|
" buf[ch] = 0;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
|
|
||||||
check( "void foo()\n"
|
check( "void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" char ch = 0x80;\n"
|
" char ch = 0x80;\n"
|
||||||
" buf[ch] = 0;\n"
|
" buf[ch] = 0;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:4]: Warning - using char variable as array index\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:4]: Warning - using char variable as array index\n"), errout.str() );
|
||||||
|
|
||||||
check( "void foo(char ch)\n"
|
check( "void foo(char ch)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" buf[ch] = 0;\n"
|
" buf[ch] = 0;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:3]: Warning - using char variable as array index\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:3]: Warning - using char variable as array index\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void bitop1()
|
void bitop1()
|
||||||
{
|
{
|
||||||
check( "void foo()\n"
|
check( "void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" char ch;\n"
|
" char ch;\n"
|
||||||
" result = a | ch;\n"
|
" result = a | ch;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:4]: Warning - using char variable in bit operation\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:4]: Warning - using char variable in bit operation\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void bitop2()
|
void bitop2()
|
||||||
{
|
{
|
||||||
check( "void foo()\n"
|
check( "void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" char ch;\n"
|
" char ch;\n"
|
||||||
" func(&ch);\n"
|
" func(&ch);\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST( TestCharVar )
|
REGISTER_TEST( TestCharVar )
|
||||||
|
|
||||||
|
|
230
testclass.cpp
230
testclass.cpp
|
@ -1,115 +1,115 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define UNIT_TESTING
|
#define UNIT_TESTING
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
#include "checkclass.h"
|
#include "checkclass.h"
|
||||||
#include "testsuite.h"
|
#include "testsuite.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
extern std::ostringstream errout;
|
extern std::ostringstream errout;
|
||||||
|
|
||||||
class TestClass : public TestFixture
|
class TestClass : public TestFixture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TestClass() : TestFixture("TestClass")
|
TestClass() : TestFixture("TestClass")
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
TEST_CASE( virtualDestructor1 ); // Base class not found => no error
|
TEST_CASE( virtualDestructor1 ); // Base class not found => no error
|
||||||
TEST_CASE( virtualDestructor2 ); // Base class doesn't have a destructor
|
TEST_CASE( virtualDestructor2 ); // Base class doesn't have a destructor
|
||||||
TEST_CASE( virtualDestructor3 ); // Base class has a destructor, but it's not virtual
|
TEST_CASE( virtualDestructor3 ); // Base class has a destructor, but it's not virtual
|
||||||
TEST_CASE( virtualDestructor4 ); // Derived class doesn't have a destructor => no error
|
TEST_CASE( virtualDestructor4 ); // Derived class doesn't have a destructor => no error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that base classes have virtual destructors
|
// Check that base classes have virtual destructors
|
||||||
void checkVirtualDestructor(const char code[])
|
void checkVirtualDestructor(const char code[])
|
||||||
{
|
{
|
||||||
// Tokenize..
|
// Tokenize..
|
||||||
Tokenizer tokenizer;
|
Tokenizer tokenizer;
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
tokenizer.tokenize( istr, "test.cpp" );
|
tokenizer.tokenize( istr, "test.cpp" );
|
||||||
tokenizer.simplifyTokenList();
|
tokenizer.simplifyTokenList();
|
||||||
|
|
||||||
// Clear the error log
|
// Clear the error log
|
||||||
errout.str("");
|
errout.str("");
|
||||||
|
|
||||||
// Check..
|
// Check..
|
||||||
Settings settings;
|
Settings settings;
|
||||||
CheckClass checkClass( &tokenizer, settings, this );
|
CheckClass checkClass( &tokenizer, settings, this );
|
||||||
checkClass.virtualDestructor();
|
checkClass.virtualDestructor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void virtualDestructor1()
|
void virtualDestructor1()
|
||||||
{
|
{
|
||||||
// Base class not found
|
// Base class not found
|
||||||
|
|
||||||
checkVirtualDestructor("class Derived : public Base { };");
|
checkVirtualDestructor("class Derived : public Base { };");
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
|
|
||||||
checkVirtualDestructor("class Derived : Base { };");
|
checkVirtualDestructor("class Derived : Base { };");
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void virtualDestructor2()
|
void virtualDestructor2()
|
||||||
{
|
{
|
||||||
// Base class doesn't have a destructor
|
// Base class doesn't have a destructor
|
||||||
|
|
||||||
checkVirtualDestructor("class Base { };\n"
|
checkVirtualDestructor("class Base { };\n"
|
||||||
"class Derived : public Base { public: ~Derived() { (void)11; } };");
|
"class Derived : public Base { public: ~Derived() { (void)11; } };");
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:1]: Base class Base doesn't have a virtual destructor\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:1]: Base class Base doesn't have a virtual destructor\n"), errout.str() );
|
||||||
|
|
||||||
checkVirtualDestructor("class Base { };\n"
|
checkVirtualDestructor("class Base { };\n"
|
||||||
"class Derived : Base { public: ~Derived() { (void)11; } };");
|
"class Derived : Base { public: ~Derived() { (void)11; } };");
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void virtualDestructor3()
|
void virtualDestructor3()
|
||||||
{
|
{
|
||||||
// Base class has a destructor, but it's not virtual
|
// Base class has a destructor, but it's not virtual
|
||||||
|
|
||||||
checkVirtualDestructor("class Base { public: ~Base(); };\n"
|
checkVirtualDestructor("class Base { public: ~Base(); };\n"
|
||||||
"class Derived : public Base { public: ~Derived() { (void)11; } };");
|
"class Derived : public Base { public: ~Derived() { (void)11; } };");
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:1]: The destructor for the base class Base is not virtual\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:1]: The destructor for the base class Base is not virtual\n"), errout.str() );
|
||||||
|
|
||||||
checkVirtualDestructor("class Base { public: ~Base(); };\n"
|
checkVirtualDestructor("class Base { public: ~Base(); };\n"
|
||||||
"class Derived : private Fred, public Base { public: ~Derived() { (void)11; } };");
|
"class Derived : private Fred, public Base { public: ~Derived() { (void)11; } };");
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:1]: The destructor for the base class Base is not virtual\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:1]: The destructor for the base class Base is not virtual\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void virtualDestructor4()
|
void virtualDestructor4()
|
||||||
{
|
{
|
||||||
// Derived class doesn't have a destructor => no error
|
// Derived class doesn't have a destructor => no error
|
||||||
|
|
||||||
checkVirtualDestructor("class Base { public: ~Base(); };\n"
|
checkVirtualDestructor("class Base { public: ~Base(); };\n"
|
||||||
"class Derived : public Base { };");
|
"class Derived : public Base { };");
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
|
|
||||||
checkVirtualDestructor("class Base { public: ~Base(); };\n"
|
checkVirtualDestructor("class Base { public: ~Base(); };\n"
|
||||||
"class Derived : private Fred, public Base { };");
|
"class Derived : private Fred, public Base { };");
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST( TestClass )
|
REGISTER_TEST( TestClass )
|
||||||
|
|
|
@ -1,326 +1,326 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define UNIT_TESTING
|
#define UNIT_TESTING
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
#include "checkclass.h"
|
#include "checkclass.h"
|
||||||
#include "testsuite.h"
|
#include "testsuite.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
extern std::ostringstream errout;
|
extern std::ostringstream errout;
|
||||||
|
|
||||||
class TestConstructors : public TestFixture
|
class TestConstructors : public TestFixture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TestConstructors() : TestFixture("TestConstructors")
|
TestConstructors() : TestFixture("TestConstructors")
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
||||||
void check( const char code[] )
|
void check( const char code[] )
|
||||||
{
|
{
|
||||||
// Tokenize..
|
// Tokenize..
|
||||||
Tokenizer tokenizer;
|
Tokenizer tokenizer;
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
tokenizer.tokenize( istr, "test.cpp" );
|
tokenizer.tokenize( istr, "test.cpp" );
|
||||||
tokenizer.simplifyTokenList();
|
tokenizer.simplifyTokenList();
|
||||||
|
|
||||||
// Clear the error buffer..
|
// Clear the error buffer..
|
||||||
errout.str("");
|
errout.str("");
|
||||||
|
|
||||||
// Check class constructors..
|
// Check class constructors..
|
||||||
Settings settings;
|
Settings settings;
|
||||||
settings._checkCodingStyle = true;
|
settings._checkCodingStyle = true;
|
||||||
CheckClass checkClass( &tokenizer, settings, this );
|
CheckClass checkClass( &tokenizer, settings, this );
|
||||||
checkClass.CheckConstructors();
|
checkClass.CheckConstructors();
|
||||||
}
|
}
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
TEST_CASE( simple1 );
|
TEST_CASE( simple1 );
|
||||||
TEST_CASE( simple2 );
|
TEST_CASE( simple2 );
|
||||||
TEST_CASE( simple3 );
|
TEST_CASE( simple3 );
|
||||||
TEST_CASE( simple4 );
|
TEST_CASE( simple4 );
|
||||||
|
|
||||||
TEST_CASE( initvar_with_this ); // BUG 2190300
|
TEST_CASE( initvar_with_this ); // BUG 2190300
|
||||||
TEST_CASE( initvar_if ); // BUG 2190290
|
TEST_CASE( initvar_if ); // BUG 2190290
|
||||||
TEST_CASE( initvar_operator_eq1 ); // BUG 2190376
|
TEST_CASE( initvar_operator_eq1 ); // BUG 2190376
|
||||||
TEST_CASE( initvar_operator_eq2 ); // BUG 2190376
|
TEST_CASE( initvar_operator_eq2 ); // BUG 2190376
|
||||||
TEST_CASE( initvar_operator_eq3 );
|
TEST_CASE( initvar_operator_eq3 );
|
||||||
TEST_CASE( initvar_same_classname ); // BUG 2208157
|
TEST_CASE( initvar_same_classname ); // BUG 2208157
|
||||||
TEST_CASE( initvar_chained_assign ); // BUG 2270433
|
TEST_CASE( initvar_chained_assign ); // BUG 2270433
|
||||||
TEST_CASE( initvar_2constructors ); // BUG 2270353
|
TEST_CASE( initvar_2constructors ); // BUG 2270353
|
||||||
|
|
||||||
TEST_CASE( initvar_private_constructor ); // BUG 2354171 - private constructor
|
TEST_CASE( initvar_private_constructor ); // BUG 2354171 - private constructor
|
||||||
|
|
||||||
TEST_CASE( initvar_destructor ); // No variables need to be initialized in a destructor
|
TEST_CASE( initvar_destructor ); // No variables need to be initialized in a destructor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void simple1()
|
void simple1()
|
||||||
{
|
{
|
||||||
check( "class Fred\n"
|
check( "class Fred\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" int i;\n"
|
" int i;\n"
|
||||||
"};\n" );
|
"};\n" );
|
||||||
std::string actual( errout.str() );
|
std::string actual( errout.str() );
|
||||||
std::string expected( "[test.cpp:1] The class 'Fred' has no constructor\n" );
|
std::string expected( "[test.cpp:1] The class 'Fred' has no constructor\n" );
|
||||||
ASSERT_EQUALS( expected, actual );
|
ASSERT_EQUALS( expected, actual );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void simple2()
|
void simple2()
|
||||||
{
|
{
|
||||||
check( "class Fred\n"
|
check( "class Fred\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" Fred() { }\n"
|
" Fred() { }\n"
|
||||||
" int i;\n"
|
" int i;\n"
|
||||||
"};\n" );
|
"};\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:4] Uninitialized member variable 'Fred::i'\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:4] Uninitialized member variable 'Fred::i'\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void simple3()
|
void simple3()
|
||||||
{
|
{
|
||||||
check( "class Fred\n"
|
check( "class Fred\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" Fred();\n"
|
" Fred();\n"
|
||||||
" int i;\n"
|
" int i;\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"Fred::Fred()\n"
|
"Fred::Fred()\n"
|
||||||
"{ }\n" );
|
"{ }\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:7] Uninitialized member variable 'Fred::i'\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:7] Uninitialized member variable 'Fred::i'\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void simple4()
|
void simple4()
|
||||||
{
|
{
|
||||||
check( "class Fred\n"
|
check( "class Fred\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" Fred();\n"
|
" Fred();\n"
|
||||||
" Fred(int _i);\n"
|
" Fred(int _i);\n"
|
||||||
" int i;\n"
|
" int i;\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"Fred::Fred()\n"
|
"Fred::Fred()\n"
|
||||||
"{ }\n"
|
"{ }\n"
|
||||||
"Fred::Fred(int _i)\n"
|
"Fred::Fred(int _i)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" i = _i;\n"
|
" i = _i;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:8] Uninitialized member variable 'Fred::i'\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:8] Uninitialized member variable 'Fred::i'\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void initvar_with_this()
|
void initvar_with_this()
|
||||||
{
|
{
|
||||||
check( "class Fred\n"
|
check( "class Fred\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" Fred()\n"
|
" Fred()\n"
|
||||||
" { this->i = 0; }\n"
|
" { this->i = 0; }\n"
|
||||||
" int i;\n"
|
" int i;\n"
|
||||||
"};\n" );
|
"};\n" );
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void initvar_if()
|
void initvar_if()
|
||||||
{
|
{
|
||||||
check( "class Fred\n"
|
check( "class Fred\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" Fred()\n"
|
" Fred()\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" if (true)\n"
|
" if (true)\n"
|
||||||
" i = 0;\n"
|
" i = 0;\n"
|
||||||
" else\n"
|
" else\n"
|
||||||
" i = 1;\n"
|
" i = 1;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" int i;\n"
|
" int i;\n"
|
||||||
"};\n" );
|
"};\n" );
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void initvar_operator_eq1()
|
void initvar_operator_eq1()
|
||||||
{
|
{
|
||||||
// Bug 2190376 - False positive, Uninitialized member variable with operator=
|
// Bug 2190376 - False positive, Uninitialized member variable with operator=
|
||||||
|
|
||||||
check( "class Fred\n"
|
check( "class Fred\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"private:\n"
|
"private:\n"
|
||||||
" int i;\n"
|
" int i;\n"
|
||||||
"\n"
|
"\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" Fred()\n"
|
" Fred()\n"
|
||||||
" { i = 0; }\n"
|
" { i = 0; }\n"
|
||||||
"\n"
|
"\n"
|
||||||
" Fred(const Fred &fred)\n"
|
" Fred(const Fred &fred)\n"
|
||||||
" { *this = fred; }\n"
|
" { *this = fred; }\n"
|
||||||
"\n"
|
"\n"
|
||||||
" const Fred & operator=(const Fred &fred)\n"
|
" const Fred & operator=(const Fred &fred)\n"
|
||||||
" { i = fred.i; return *this; }\n"
|
" { i = fred.i; return *this; }\n"
|
||||||
"};\n" );
|
"};\n" );
|
||||||
|
|
||||||
std::string err( errout.str() );
|
std::string err( errout.str() );
|
||||||
ASSERT_EQUALS( std::string(""), err );
|
ASSERT_EQUALS( std::string(""), err );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void initvar_operator_eq2()
|
void initvar_operator_eq2()
|
||||||
{
|
{
|
||||||
check( "class Fred\n"
|
check( "class Fred\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" Fred() { i = 0; }\n"
|
" Fred() { i = 0; }\n"
|
||||||
" void operator=() { }\n"
|
" void operator=() { }\n"
|
||||||
" int i;\n"
|
" int i;\n"
|
||||||
"};\n" );
|
"};\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:5] Uninitialized member variable 'Fred::i'\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:5] Uninitialized member variable 'Fred::i'\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void initvar_operator_eq3()
|
void initvar_operator_eq3()
|
||||||
{
|
{
|
||||||
check( "class Fred\n"
|
check( "class Fred\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" Fred() { Init(); }\n"
|
" Fred() { Init(); }\n"
|
||||||
" void operator=() { Init(); }\n"
|
" void operator=() { Init(); }\n"
|
||||||
"private:\n"
|
"private:\n"
|
||||||
" Init() { i = 0; }\n"
|
" Init() { i = 0; }\n"
|
||||||
" int i;\n"
|
" int i;\n"
|
||||||
"};\n" );
|
"};\n" );
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void initvar_same_classname()
|
void initvar_same_classname()
|
||||||
{
|
{
|
||||||
// Bug 2208157 - False positive: Uninitialized variable, same class name
|
// Bug 2208157 - False positive: Uninitialized variable, same class name
|
||||||
|
|
||||||
check( "void func1()\n"
|
check( "void func1()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" class Fred\n"
|
" class Fred\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" int a;\n"
|
" int a;\n"
|
||||||
" Fred() { a = 0; }\n"
|
" Fred() { a = 0; }\n"
|
||||||
" };\n"
|
" };\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n"
|
||||||
"void func2()\n"
|
"void func2()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" class Fred\n"
|
" class Fred\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" int b;\n"
|
" int b;\n"
|
||||||
" Fred() { b = 0; }\n"
|
" Fred() { b = 0; }\n"
|
||||||
" };\n"
|
" };\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
|
|
||||||
std::string err( errout.str() );
|
std::string err( errout.str() );
|
||||||
ASSERT_EQUALS( std::string(""), err );
|
ASSERT_EQUALS( std::string(""), err );
|
||||||
}
|
}
|
||||||
|
|
||||||
void initvar_chained_assign()
|
void initvar_chained_assign()
|
||||||
{
|
{
|
||||||
// Bug 2270433 - Uninitialized variable false positive on chained assigns
|
// Bug 2270433 - Uninitialized variable false positive on chained assigns
|
||||||
|
|
||||||
check( "class c\n"
|
check( "class c\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" c();\n"
|
" c();\n"
|
||||||
"\n"
|
"\n"
|
||||||
" int m_iMyInt1;\n"
|
" int m_iMyInt1;\n"
|
||||||
" int m_iMyInt2;\n"
|
" int m_iMyInt2;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n"
|
||||||
"c::c()\n"
|
"c::c()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" m_iMyInt1 = m_iMyInt2 = 0;\n"
|
" m_iMyInt1 = m_iMyInt2 = 0;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
|
|
||||||
std::string err( errout.str() );
|
std::string err( errout.str() );
|
||||||
ASSERT_EQUALS( std::string(""), err );
|
ASSERT_EQUALS( std::string(""), err );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void initvar_2constructors()
|
void initvar_2constructors()
|
||||||
{
|
{
|
||||||
check( "class c\n"
|
check( "class c\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" c();\n"
|
" c();\n"
|
||||||
" c(bool b);"
|
" c(bool b);"
|
||||||
"\n"
|
"\n"
|
||||||
" void InitInt();\n"
|
" void InitInt();\n"
|
||||||
"\n"
|
"\n"
|
||||||
" int m_iMyInt;\n"
|
" int m_iMyInt;\n"
|
||||||
" int m_bMyBool;\n"
|
" int m_bMyBool;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n"
|
||||||
"c::c()\n"
|
"c::c()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" m_bMyBool = false;\n"
|
" m_bMyBool = false;\n"
|
||||||
" InitInt();"
|
" InitInt();"
|
||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n"
|
||||||
"c::c(bool b)\n"
|
"c::c(bool b)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" m_bMyBool = b;\n"
|
" m_bMyBool = b;\n"
|
||||||
" InitInt();\n"
|
" InitInt();\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n"
|
||||||
"void c::InitInt()\n"
|
"void c::InitInt()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" m_iMyInt = 0;\n"
|
" m_iMyInt = 0;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
|
|
||||||
std::string err( errout.str() );
|
std::string err( errout.str() );
|
||||||
ASSERT_EQUALS( std::string(""), err );
|
ASSERT_EQUALS( std::string(""), err );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void initvar_private_constructor()
|
void initvar_private_constructor()
|
||||||
{
|
{
|
||||||
check( "class Fred\n"
|
check( "class Fred\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"private:\n"
|
"private:\n"
|
||||||
" int var;\n"
|
" int var;\n"
|
||||||
" Fred();\n"
|
" Fred();\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"Fred::Fred()\n"
|
"Fred::Fred()\n"
|
||||||
"{ }" );
|
"{ }" );
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void initvar_destructor()
|
void initvar_destructor()
|
||||||
{
|
{
|
||||||
check( "class Fred\n"
|
check( "class Fred\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"private:\n"
|
"private:\n"
|
||||||
" int var;\n"
|
" int var;\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" Fred() : var(0) {}\n"
|
" Fred() : var(0) {}\n"
|
||||||
" ~Fred() {}\n"
|
" ~Fred() {}\n"
|
||||||
"};\n" );
|
"};\n" );
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST( TestConstructors )
|
REGISTER_TEST( TestConstructors )
|
||||||
|
|
300
testdivision.cpp
300
testdivision.cpp
|
@ -1,150 +1,150 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// Check for dangerous division..
|
// Check for dangerous division..
|
||||||
// such as "svar / uvar". Treating "svar" as unsigned data is not good
|
// such as "svar / uvar". Treating "svar" as unsigned data is not good
|
||||||
|
|
||||||
|
|
||||||
#define UNIT_TESTING
|
#define UNIT_TESTING
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
#include "checkother.h"
|
#include "checkother.h"
|
||||||
#include "testsuite.h"
|
#include "testsuite.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
extern std::ostringstream errout;
|
extern std::ostringstream errout;
|
||||||
|
|
||||||
class TestDivision : public TestFixture
|
class TestDivision : public TestFixture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TestDivision() : TestFixture("TestDivision")
|
TestDivision() : TestFixture("TestDivision")
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void check( const char code[] )
|
void check( const char code[] )
|
||||||
{
|
{
|
||||||
// Tokenize..
|
// Tokenize..
|
||||||
Tokenizer tokenizer;
|
Tokenizer tokenizer;
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
tokenizer.tokenize( istr, "test.cpp" );
|
tokenizer.tokenize( istr, "test.cpp" );
|
||||||
|
|
||||||
// Clear the error buffer..
|
// Clear the error buffer..
|
||||||
errout.str("");
|
errout.str("");
|
||||||
|
|
||||||
// Check for unsigned divisions..
|
// Check for unsigned divisions..
|
||||||
CheckOther checkOther( &tokenizer, this );
|
CheckOther checkOther( &tokenizer, this );
|
||||||
checkOther.CheckUnsignedDivision();
|
checkOther.CheckUnsignedDivision();
|
||||||
}
|
}
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
TEST_CASE( division1 );
|
TEST_CASE( division1 );
|
||||||
TEST_CASE( division2 );
|
TEST_CASE( division2 );
|
||||||
TEST_CASE( division3 );
|
TEST_CASE( division3 );
|
||||||
TEST_CASE( division4 );
|
TEST_CASE( division4 );
|
||||||
TEST_CASE( division5 );
|
TEST_CASE( division5 );
|
||||||
TEST_CASE( division6 );
|
TEST_CASE( division6 );
|
||||||
TEST_CASE( division7 );
|
TEST_CASE( division7 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void division1()
|
void division1()
|
||||||
{
|
{
|
||||||
check( "void f()\n"
|
check( "void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int ivar = -2;\n"
|
" int ivar = -2;\n"
|
||||||
" unsigned int uvar = 2;\n"
|
" unsigned int uvar = 2;\n"
|
||||||
" return ivar / uvar;\n"
|
" return ivar / uvar;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:5]: Warning: Division with signed and unsigned operators\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:5]: Warning: Division with signed and unsigned operators\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void division2()
|
void division2()
|
||||||
{
|
{
|
||||||
check( "void f()\n"
|
check( "void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int ivar = -2;\n"
|
" int ivar = -2;\n"
|
||||||
" unsigned int uvar = 2;\n"
|
" unsigned int uvar = 2;\n"
|
||||||
" return uvar / ivar;\n"
|
" return uvar / ivar;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:5]: Warning: Division with signed and unsigned operators\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:5]: Warning: Division with signed and unsigned operators\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void division3()
|
void division3()
|
||||||
{
|
{
|
||||||
check( "typedef int s32;\n"
|
check( "typedef int s32;\n"
|
||||||
"typedef unsigned int u32;\n"
|
"typedef unsigned int u32;\n"
|
||||||
"void f()\n"
|
"void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" s32 ivar = -2;\n"
|
" s32 ivar = -2;\n"
|
||||||
" u32 uvar = 2;\n"
|
" u32 uvar = 2;\n"
|
||||||
" return uvar / ivar;\n"
|
" return uvar / ivar;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:7]: Warning: Division with signed and unsigned operators\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:7]: Warning: Division with signed and unsigned operators\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void division4()
|
void division4()
|
||||||
{
|
{
|
||||||
check( "void f1()\n"
|
check( "void f1()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int i1;\n"
|
" int i1;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n"
|
||||||
"void f2(unsigned int i1)\n"
|
"void f2(unsigned int i1)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" unsigned int i2;\n"
|
" unsigned int i2;\n"
|
||||||
" result = i2 / i1;\n"
|
" result = i2 / i1;\n"
|
||||||
);
|
);
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void division5()
|
void division5()
|
||||||
{
|
{
|
||||||
check( "#define USER_HASH (16)\n"
|
check( "#define USER_HASH (16)\n"
|
||||||
"void foo()\n"
|
"void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" unsigned int val = 32;\n"
|
" unsigned int val = 32;\n"
|
||||||
" val = val / USER_HASH;\n"
|
" val = val / USER_HASH;\n"
|
||||||
);
|
);
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void division6()
|
void division6()
|
||||||
{
|
{
|
||||||
check( "void foo()\n"
|
check( "void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" unsigned int val = 32;\n"
|
" unsigned int val = 32;\n"
|
||||||
" int i = val / -2;\n"
|
" int i = val / -2;\n"
|
||||||
);
|
);
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:4]: Unsigned division. The result will be wrong.\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:4]: Unsigned division. The result will be wrong.\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void division7()
|
void division7()
|
||||||
{
|
{
|
||||||
check( "void foo()\n"
|
check( "void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" unsigned int val = 32;\n"
|
" unsigned int val = 32;\n"
|
||||||
" int i = -96 / val;\n"
|
" int i = -96 / val;\n"
|
||||||
);
|
);
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:4]: Unsigned division. The result will be wrong.\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:4]: Unsigned division. The result will be wrong.\n"), errout.str() );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST( TestDivision )
|
REGISTER_TEST( TestDivision )
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,53 +1,53 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2008 Daniel Marjamäki and Reijo Tomperi
|
* Copyright (C) 2008 Daniel Marjamäki and Reijo Tomperi
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "testsuite.h"
|
#include "testsuite.h"
|
||||||
#include "filelister.h"
|
#include "filelister.h"
|
||||||
|
|
||||||
class TestFileLister : public TestFixture
|
class TestFileLister : public TestFixture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TestFileLister() : TestFixture("TestFileLister")
|
TestFileLister() : TestFixture("TestFileLister")
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
TEST_CASE( simplify_path );
|
TEST_CASE( simplify_path );
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplify_path()
|
void simplify_path()
|
||||||
{
|
{
|
||||||
ASSERT_EQUALS( std::string( "index.h" ), FileLister::simplifyPath( "index.h" ) );
|
ASSERT_EQUALS( std::string( "index.h" ), FileLister::simplifyPath( "index.h" ) );
|
||||||
ASSERT_EQUALS( std::string( "/index.h" ), FileLister::simplifyPath( "/index.h" ) );
|
ASSERT_EQUALS( std::string( "/index.h" ), FileLister::simplifyPath( "/index.h" ) );
|
||||||
ASSERT_EQUALS( std::string( "/path/" ), FileLister::simplifyPath( "/path/" ) );
|
ASSERT_EQUALS( std::string( "/path/" ), FileLister::simplifyPath( "/path/" ) );
|
||||||
ASSERT_EQUALS( std::string( "/" ), FileLister::simplifyPath( "/" ) );
|
ASSERT_EQUALS( std::string( "/" ), FileLister::simplifyPath( "/" ) );
|
||||||
ASSERT_EQUALS( std::string( "./index.h" ), FileLister::simplifyPath( "./index.h" ) );
|
ASSERT_EQUALS( std::string( "./index.h" ), FileLister::simplifyPath( "./index.h" ) );
|
||||||
ASSERT_EQUALS( std::string( "../index.h" ), FileLister::simplifyPath( "../index.h" ) );
|
ASSERT_EQUALS( std::string( "../index.h" ), FileLister::simplifyPath( "../index.h" ) );
|
||||||
ASSERT_EQUALS( std::string( "/index.h" ), FileLister::simplifyPath( "/path/../index.h" ) );
|
ASSERT_EQUALS( std::string( "/index.h" ), FileLister::simplifyPath( "/path/../index.h" ) );
|
||||||
ASSERT_EQUALS( std::string( "/index.h" ), FileLister::simplifyPath( "/path/../other/../index.h" ) );
|
ASSERT_EQUALS( std::string( "/index.h" ), FileLister::simplifyPath( "/path/../other/../index.h" ) );
|
||||||
ASSERT_EQUALS( std::string( "/index.h" ), FileLister::simplifyPath( "/path/../other///././../index.h" ) );
|
ASSERT_EQUALS( std::string( "/index.h" ), FileLister::simplifyPath( "/path/../other///././../index.h" ) );
|
||||||
ASSERT_EQUALS( std::string( "../path/index.h" ), FileLister::simplifyPath( "../path/other/../index.h" ) );
|
ASSERT_EQUALS( std::string( "../path/index.h" ), FileLister::simplifyPath( "../path/other/../index.h" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST( TestFileLister )
|
REGISTER_TEST( TestFileLister )
|
||||||
|
|
|
@ -1,105 +1,105 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#define UNIT_TESTING
|
#define UNIT_TESTING
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
#include "testsuite.h"
|
#include "testsuite.h"
|
||||||
#include "checkfunctionusage.h"
|
#include "checkfunctionusage.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
extern std::ostringstream errout;
|
extern std::ostringstream errout;
|
||||||
|
|
||||||
class TestFunctionUsage : public TestFixture
|
class TestFunctionUsage : public TestFixture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TestFunctionUsage() : TestFixture("TestFunctionUsage")
|
TestFunctionUsage() : TestFixture("TestFunctionUsage")
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
TEST_CASE( incondition );
|
TEST_CASE( incondition );
|
||||||
TEST_CASE( return1 );
|
TEST_CASE( return1 );
|
||||||
TEST_CASE( callback1 );
|
TEST_CASE( callback1 );
|
||||||
TEST_CASE( else1 );
|
TEST_CASE( else1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void check( const char code[] )
|
void check( const char code[] )
|
||||||
{
|
{
|
||||||
// Tokenize..
|
// Tokenize..
|
||||||
Tokenizer tokenizer;
|
Tokenizer tokenizer;
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
tokenizer.tokenize( istr, "test.cpp" );
|
tokenizer.tokenize( istr, "test.cpp" );
|
||||||
|
|
||||||
// Clear the error buffer..
|
// Clear the error buffer..
|
||||||
errout.str("");
|
errout.str("");
|
||||||
|
|
||||||
// Check for unused functions..
|
// Check for unused functions..
|
||||||
CheckFunctionUsage checkFunctionUsage(this);
|
CheckFunctionUsage checkFunctionUsage(this);
|
||||||
checkFunctionUsage.parseTokens( tokenizer );
|
checkFunctionUsage.parseTokens( tokenizer );
|
||||||
checkFunctionUsage.check();
|
checkFunctionUsage.check();
|
||||||
}
|
}
|
||||||
|
|
||||||
void incondition()
|
void incondition()
|
||||||
{
|
{
|
||||||
check( "int f1()\n"
|
check( "int f1()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" if (f1())\n"
|
" if (f1())\n"
|
||||||
" { }\n"
|
" { }\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
std::string err( errout.str() );
|
std::string err( errout.str() );
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void return1()
|
void return1()
|
||||||
{
|
{
|
||||||
check( "int f1()\n"
|
check( "int f1()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" return f1();\n"
|
" return f1();\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
std::string err( errout.str() );
|
std::string err( errout.str() );
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void callback1()
|
void callback1()
|
||||||
{
|
{
|
||||||
check( "void f1()\n"
|
check( "void f1()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" void (*f)() = cond ? f1 : NULL;\n"
|
" void (*f)() = cond ? f1 : NULL;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
std::string err( errout.str() );
|
std::string err( errout.str() );
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void else1()
|
void else1()
|
||||||
{
|
{
|
||||||
check( "void f1()\n"
|
check( "void f1()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" if (cond) ;\n"
|
" if (cond) ;\n"
|
||||||
" else f1();\n"
|
" else f1();\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
std::string err( errout.str() );
|
std::string err( errout.str() );
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST( TestFunctionUsage )
|
REGISTER_TEST( TestFunctionUsage )
|
||||||
|
|
||||||
|
|
|
@ -1,91 +1,91 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Check for unused variables..
|
// Check for unused variables..
|
||||||
|
|
||||||
#define UNIT_TESTING
|
#define UNIT_TESTING
|
||||||
#include "testsuite.h"
|
#include "testsuite.h"
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
#include "checkother.h"
|
#include "checkother.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
extern std::ostringstream errout;
|
extern std::ostringstream errout;
|
||||||
|
|
||||||
class TestIncompleteStatement : public TestFixture
|
class TestIncompleteStatement : public TestFixture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TestIncompleteStatement() : TestFixture("TestIncompleteStatement")
|
TestIncompleteStatement() : TestFixture("TestIncompleteStatement")
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void check( const char code[] )
|
void check( const char code[] )
|
||||||
{
|
{
|
||||||
// Tokenize..
|
// Tokenize..
|
||||||
Tokenizer tokenizer;
|
Tokenizer tokenizer;
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
tokenizer.tokenize( istr, "test.cpp" );
|
tokenizer.tokenize( istr, "test.cpp" );
|
||||||
tokenizer.simplifyTokenList();
|
tokenizer.simplifyTokenList();
|
||||||
|
|
||||||
// Clear the error buffer..
|
// Clear the error buffer..
|
||||||
errout.str("");
|
errout.str("");
|
||||||
|
|
||||||
// Check for unused variables..
|
// Check for unused variables..
|
||||||
CheckOther checkOther( &tokenizer, this );
|
CheckOther checkOther( &tokenizer, this );
|
||||||
checkOther.CheckIncompleteStatement();
|
checkOther.CheckIncompleteStatement();
|
||||||
}
|
}
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
TEST_CASE( test1 );
|
TEST_CASE( test1 );
|
||||||
TEST_CASE( test2 );
|
TEST_CASE( test2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void test1()
|
void test1()
|
||||||
{
|
{
|
||||||
check( "void foo()\n"
|
check( "void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" const char def[] =\n"
|
" const char def[] =\n"
|
||||||
"#ifdef ABC\n"
|
"#ifdef ABC\n"
|
||||||
" \"abc\";\n"
|
" \"abc\";\n"
|
||||||
"#else\n"
|
"#else\n"
|
||||||
" \"not abc\";\n"
|
" \"not abc\";\n"
|
||||||
"#endif\n"
|
"#endif\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
|
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void test2()
|
void test2()
|
||||||
{
|
{
|
||||||
// Todo: remove the ';' before the string
|
// Todo: remove the ';' before the string
|
||||||
|
|
||||||
check( "void foo()\n"
|
check( "void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" ;\"abc\";\n"
|
" ;\"abc\";\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
|
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:3]: Redundant code: Found a statement that begins with string constant\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:3]: Redundant code: Found a statement that begins with string constant\n"), errout.str() );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST( TestIncompleteStatement )
|
REGISTER_TEST( TestIncompleteStatement )
|
||||||
|
|
||||||
|
|
||||||
|
|
2452
testmemleak.cpp
2452
testmemleak.cpp
File diff suppressed because it is too large
Load Diff
|
@ -1,446 +1,446 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// The preprocessor that c++check uses is a bit special. Instead of generating
|
// The preprocessor that c++check uses is a bit special. Instead of generating
|
||||||
// the code for a known configuration, it generates the code for each configuration.
|
// the code for a known configuration, it generates the code for each configuration.
|
||||||
|
|
||||||
|
|
||||||
#include "testsuite.h"
|
#include "testsuite.h"
|
||||||
#include "preprocessor.h"
|
#include "preprocessor.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class TestPreprocessor : public TestFixture
|
class TestPreprocessor : public TestFixture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TestPreprocessor() : TestFixture("TestPreprocessor")
|
TestPreprocessor() : TestFixture("TestPreprocessor")
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
// Just read the code into a string. Perform simple cleanup of the code
|
// Just read the code into a string. Perform simple cleanup of the code
|
||||||
TEST_CASE(readCode);
|
TEST_CASE(readCode);
|
||||||
|
|
||||||
// The bug that started the whole work with the new preprocessor
|
// The bug that started the whole work with the new preprocessor
|
||||||
TEST_CASE( Bug2190219 );
|
TEST_CASE( Bug2190219 );
|
||||||
|
|
||||||
TEST_CASE( test1 );
|
TEST_CASE( test1 );
|
||||||
TEST_CASE( test2 );
|
TEST_CASE( test2 );
|
||||||
TEST_CASE( test3 );
|
TEST_CASE( test3 );
|
||||||
TEST_CASE( test4 );
|
TEST_CASE( test4 );
|
||||||
TEST_CASE( test5 );
|
TEST_CASE( test5 );
|
||||||
|
|
||||||
TEST_CASE( comments1 );
|
TEST_CASE( comments1 );
|
||||||
|
|
||||||
TEST_CASE( if0 );
|
TEST_CASE( if0 );
|
||||||
TEST_CASE( if1 );
|
TEST_CASE( if1 );
|
||||||
|
|
||||||
TEST_CASE( elif );
|
TEST_CASE( elif );
|
||||||
|
|
||||||
TEST_CASE( include1 );
|
TEST_CASE( include1 );
|
||||||
|
|
||||||
TEST_CASE( if_cond1 );
|
TEST_CASE( if_cond1 );
|
||||||
|
|
||||||
TEST_CASE( multiline );
|
TEST_CASE( multiline );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void readCode()
|
void readCode()
|
||||||
{
|
{
|
||||||
const char code[] = " \t a //\n"
|
const char code[] = " \t a //\n"
|
||||||
" #aa\t /* remove this */\tb \r\n";
|
" #aa\t /* remove this */\tb \r\n";
|
||||||
Preprocessor p;
|
Preprocessor p;
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
std::string codestr( p.read(istr,"") );
|
std::string codestr( p.read(istr,"") );
|
||||||
ASSERT_EQUALS( "a \n#aa b \n", codestr );
|
ASSERT_EQUALS( "a \n#aa b \n", codestr );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool cmpmaps(const std::map<std::string, std::string> &m1, const std::map<std::string, std::string> &m2)
|
bool cmpmaps(const std::map<std::string, std::string> &m1, const std::map<std::string, std::string> &m2)
|
||||||
{
|
{
|
||||||
// Begin by checking the sizes
|
// Begin by checking the sizes
|
||||||
if ( m1.size() != m2.size() )
|
if ( m1.size() != m2.size() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Check each item in the maps..
|
// Check each item in the maps..
|
||||||
for ( std::map<std::string,std::string>::const_iterator it1 = m1.begin(); it1 != m1.end(); ++it1 )
|
for ( std::map<std::string,std::string>::const_iterator it1 = m1.begin(); it1 != m1.end(); ++it1 )
|
||||||
{
|
{
|
||||||
std::string s1 = it1->first;
|
std::string s1 = it1->first;
|
||||||
std::map<std::string,std::string>::const_iterator it2 = m2.find(s1);
|
std::map<std::string,std::string>::const_iterator it2 = m2.find(s1);
|
||||||
if ( it2 == m2.end() )
|
if ( it2 == m2.end() )
|
||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::string s1 = it1->second;
|
std::string s1 = it1->second;
|
||||||
std::string s2 = it2->second;
|
std::string s2 = it2->second;
|
||||||
if ( s1 != s2 )
|
if ( s1 != s2 )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No diffs were found
|
// No diffs were found
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Bug2190219()
|
void Bug2190219()
|
||||||
{
|
{
|
||||||
const char filedata[] = "int main()\n"
|
const char filedata[] = "int main()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"#ifdef __cplusplus\n"
|
"#ifdef __cplusplus\n"
|
||||||
" int* flags = new int[10];\n"
|
" int* flags = new int[10];\n"
|
||||||
"#else\n"
|
"#else\n"
|
||||||
" int* flags = (int*)malloc((10)*sizeof(int));\n"
|
" int* flags = (int*)malloc((10)*sizeof(int));\n"
|
||||||
"#endif\n"
|
"#endif\n"
|
||||||
"\n"
|
"\n"
|
||||||
"#ifdef __cplusplus\n"
|
"#ifdef __cplusplus\n"
|
||||||
" delete [] flags;\n"
|
" delete [] flags;\n"
|
||||||
"#else\n"
|
"#else\n"
|
||||||
" free(flags);\n"
|
" free(flags);\n"
|
||||||
"#endif\n"
|
"#endif\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
// Expected result..
|
// Expected result..
|
||||||
std::map<std::string, std::string> expected;
|
std::map<std::string, std::string> expected;
|
||||||
expected[""] = "int main()\n"
|
expected[""] = "int main()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"\n"
|
"\n"
|
||||||
"\n"
|
"\n"
|
||||||
"\n"
|
"\n"
|
||||||
"int* flags = (int*)malloc((10)*sizeof(int));\n"
|
"int* flags = (int*)malloc((10)*sizeof(int));\n"
|
||||||
"\n"
|
"\n"
|
||||||
"\n"
|
"\n"
|
||||||
"\n"
|
"\n"
|
||||||
"\n"
|
"\n"
|
||||||
"\n"
|
"\n"
|
||||||
"free(flags);\n"
|
"free(flags);\n"
|
||||||
"\n"
|
"\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
expected["__cplusplus"] = "int main()\n"
|
expected["__cplusplus"] = "int main()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"\n"
|
"\n"
|
||||||
"int* flags = new int[10];\n"
|
"int* flags = new int[10];\n"
|
||||||
"\n"
|
"\n"
|
||||||
"\n"
|
"\n"
|
||||||
"\n"
|
"\n"
|
||||||
"\n"
|
"\n"
|
||||||
"\n"
|
"\n"
|
||||||
"delete [] flags;\n"
|
"delete [] flags;\n"
|
||||||
"\n"
|
"\n"
|
||||||
"\n"
|
"\n"
|
||||||
"\n"
|
"\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
// Preprocess => actual result..
|
// Preprocess => actual result..
|
||||||
std::istringstream istr(filedata);
|
std::istringstream istr(filedata);
|
||||||
std::map<std::string, std::string> actual;
|
std::map<std::string, std::string> actual;
|
||||||
Preprocessor preprocessor;
|
Preprocessor preprocessor;
|
||||||
preprocessor.preprocess( istr, actual, "" );
|
preprocessor.preprocess( istr, actual, "" );
|
||||||
|
|
||||||
// Compare results..
|
// Compare results..
|
||||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void test1()
|
void test1()
|
||||||
{
|
{
|
||||||
const char filedata[] = "#ifdef WIN32 \n"
|
const char filedata[] = "#ifdef WIN32 \n"
|
||||||
" abcdef\n"
|
" abcdef\n"
|
||||||
"#else \n"
|
"#else \n"
|
||||||
" qwerty\n"
|
" qwerty\n"
|
||||||
"#endif \n";
|
"#endif \n";
|
||||||
|
|
||||||
// Expected result..
|
// Expected result..
|
||||||
std::map<std::string, std::string> expected;
|
std::map<std::string, std::string> expected;
|
||||||
expected[""] = "\n\n\nqwerty\n\n";
|
expected[""] = "\n\n\nqwerty\n\n";
|
||||||
expected["WIN32"] = "\nabcdef\n\n\n\n";
|
expected["WIN32"] = "\nabcdef\n\n\n\n";
|
||||||
|
|
||||||
// Preprocess => actual result..
|
// Preprocess => actual result..
|
||||||
std::istringstream istr(filedata);
|
std::istringstream istr(filedata);
|
||||||
std::map<std::string, std::string> actual;
|
std::map<std::string, std::string> actual;
|
||||||
Preprocessor preprocessor;
|
Preprocessor preprocessor;
|
||||||
preprocessor.preprocess( istr, actual, "" );
|
preprocessor.preprocess( istr, actual, "" );
|
||||||
|
|
||||||
// Compare results..
|
// Compare results..
|
||||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
void test2()
|
void test2()
|
||||||
{
|
{
|
||||||
const char filedata[] = "# ifndef WIN32\n"
|
const char filedata[] = "# ifndef WIN32\n"
|
||||||
" \" # ifdef WIN32\" // a comment\n"
|
" \" # ifdef WIN32\" // a comment\n"
|
||||||
" # else \n"
|
" # else \n"
|
||||||
" qwerty\n"
|
" qwerty\n"
|
||||||
" # endif \n";
|
" # endif \n";
|
||||||
|
|
||||||
// Expected result..
|
// Expected result..
|
||||||
std::map<std::string, std::string> expected;
|
std::map<std::string, std::string> expected;
|
||||||
expected["WIN32"] = "\n\n\nqwerty\n\n";
|
expected["WIN32"] = "\n\n\nqwerty\n\n";
|
||||||
expected[""] = "\n\" # ifdef WIN32\"\n\n\n\n";
|
expected[""] = "\n\" # ifdef WIN32\"\n\n\n\n";
|
||||||
|
|
||||||
// Preprocess => actual result..
|
// Preprocess => actual result..
|
||||||
std::istringstream istr(filedata);
|
std::istringstream istr(filedata);
|
||||||
std::map<std::string, std::string> actual;
|
std::map<std::string, std::string> actual;
|
||||||
Preprocessor preprocessor;
|
Preprocessor preprocessor;
|
||||||
preprocessor.preprocess( istr, actual, "" );
|
preprocessor.preprocess( istr, actual, "" );
|
||||||
|
|
||||||
// Compare results..
|
// Compare results..
|
||||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
void test3()
|
void test3()
|
||||||
{
|
{
|
||||||
const char filedata[] = "#ifdef ABC\n"
|
const char filedata[] = "#ifdef ABC\n"
|
||||||
"a\n"
|
"a\n"
|
||||||
"#ifdef DEF\n"
|
"#ifdef DEF\n"
|
||||||
"b\n"
|
"b\n"
|
||||||
"#endif\n"
|
"#endif\n"
|
||||||
"c\n"
|
"c\n"
|
||||||
"#endif\n";
|
"#endif\n";
|
||||||
|
|
||||||
// Expected result..
|
// Expected result..
|
||||||
std::map<std::string, std::string> expected;
|
std::map<std::string, std::string> expected;
|
||||||
expected[""] = "\n\n\n\n\n\n\n";
|
expected[""] = "\n\n\n\n\n\n\n";
|
||||||
expected["ABC"] = "\na\n\n\n\nc\n\n";
|
expected["ABC"] = "\na\n\n\n\nc\n\n";
|
||||||
expected["ABC;DEF"] = "\na\n\nb\n\nc\n\n";
|
expected["ABC;DEF"] = "\na\n\nb\n\nc\n\n";
|
||||||
|
|
||||||
// Preprocess => actual result..
|
// Preprocess => actual result..
|
||||||
std::istringstream istr(filedata);
|
std::istringstream istr(filedata);
|
||||||
std::map<std::string, std::string> actual;
|
std::map<std::string, std::string> actual;
|
||||||
Preprocessor preprocessor;
|
Preprocessor preprocessor;
|
||||||
preprocessor.preprocess( istr, actual, "" );
|
preprocessor.preprocess( istr, actual, "" );
|
||||||
|
|
||||||
// Compare results..
|
// Compare results..
|
||||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
void test4()
|
void test4()
|
||||||
{
|
{
|
||||||
const char filedata[] = "#ifdef ABC\n"
|
const char filedata[] = "#ifdef ABC\n"
|
||||||
"A\n"
|
"A\n"
|
||||||
"#endif\t\n"
|
"#endif\t\n"
|
||||||
"#ifdef ABC\n"
|
"#ifdef ABC\n"
|
||||||
"A\n"
|
"A\n"
|
||||||
"#endif\n";
|
"#endif\n";
|
||||||
|
|
||||||
// Expected result..
|
// Expected result..
|
||||||
std::map<std::string, std::string> expected;
|
std::map<std::string, std::string> expected;
|
||||||
expected[""] = "\n\n\n\n\n\n";
|
expected[""] = "\n\n\n\n\n\n";
|
||||||
expected["ABC"] = "\nA\n\n\nA\n\n";
|
expected["ABC"] = "\nA\n\n\nA\n\n";
|
||||||
|
|
||||||
// Preprocess => actual result..
|
// Preprocess => actual result..
|
||||||
std::istringstream istr(filedata);
|
std::istringstream istr(filedata);
|
||||||
std::map<std::string, std::string> actual;
|
std::map<std::string, std::string> actual;
|
||||||
Preprocessor preprocessor;
|
Preprocessor preprocessor;
|
||||||
preprocessor.preprocess( istr, actual, "" );
|
preprocessor.preprocess( istr, actual, "" );
|
||||||
|
|
||||||
// Compare results..
|
// Compare results..
|
||||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
void test5()
|
void test5()
|
||||||
{
|
{
|
||||||
const char filedata[] = "#ifdef ABC\n"
|
const char filedata[] = "#ifdef ABC\n"
|
||||||
"A\n"
|
"A\n"
|
||||||
"#else\n"
|
"#else\n"
|
||||||
"B\n"
|
"B\n"
|
||||||
"#ifdef DEF\n"
|
"#ifdef DEF\n"
|
||||||
"C\n"
|
"C\n"
|
||||||
"#endif\n"
|
"#endif\n"
|
||||||
"#endif\n";
|
"#endif\n";
|
||||||
|
|
||||||
// Expected result..
|
// Expected result..
|
||||||
std::map<std::string, std::string> expected;
|
std::map<std::string, std::string> expected;
|
||||||
expected[""] = "\n\n\nB\n\n\n\n\n";
|
expected[""] = "\n\n\nB\n\n\n\n\n";
|
||||||
expected["ABC"] = "\nA\n\n\n\n\n\n\n";
|
expected["ABC"] = "\nA\n\n\n\n\n\n\n";
|
||||||
expected["DEF"] = "\n\n\nB\n\nC\n\n\n";
|
expected["DEF"] = "\n\n\nB\n\nC\n\n\n";
|
||||||
|
|
||||||
// Preprocess => actual result..
|
// Preprocess => actual result..
|
||||||
std::istringstream istr(filedata);
|
std::istringstream istr(filedata);
|
||||||
std::map<std::string, std::string> actual;
|
std::map<std::string, std::string> actual;
|
||||||
Preprocessor preprocessor;
|
Preprocessor preprocessor;
|
||||||
preprocessor.preprocess( istr, actual, "" );
|
preprocessor.preprocess( istr, actual, "" );
|
||||||
|
|
||||||
// Compare results..
|
// Compare results..
|
||||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void comments1()
|
void comments1()
|
||||||
{
|
{
|
||||||
const char filedata[] = "/*\n"
|
const char filedata[] = "/*\n"
|
||||||
"#ifdef WIN32\n"
|
"#ifdef WIN32\n"
|
||||||
"#endif\n"
|
"#endif\n"
|
||||||
"*/\n";
|
"*/\n";
|
||||||
|
|
||||||
// Expected result..
|
// Expected result..
|
||||||
std::map<std::string, std::string> expected;
|
std::map<std::string, std::string> expected;
|
||||||
expected[""] = "\n\n\n\n";
|
expected[""] = "\n\n\n\n";
|
||||||
|
|
||||||
// Preprocess => actual result..
|
// Preprocess => actual result..
|
||||||
std::istringstream istr(filedata);
|
std::istringstream istr(filedata);
|
||||||
std::map<std::string, std::string> actual;
|
std::map<std::string, std::string> actual;
|
||||||
Preprocessor preprocessor;
|
Preprocessor preprocessor;
|
||||||
preprocessor.preprocess( istr, actual, "" );
|
preprocessor.preprocess( istr, actual, "" );
|
||||||
|
|
||||||
// Compare results..
|
// Compare results..
|
||||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void if0()
|
void if0()
|
||||||
{
|
{
|
||||||
const char filedata[] = " # if /* comment */ 0 // comment\n"
|
const char filedata[] = " # if /* comment */ 0 // comment\n"
|
||||||
"#ifdef WIN32\n"
|
"#ifdef WIN32\n"
|
||||||
"#endif\n"
|
"#endif\n"
|
||||||
"#endif\n";
|
"#endif\n";
|
||||||
|
|
||||||
// Expected result..
|
// Expected result..
|
||||||
std::map<std::string, std::string> expected;
|
std::map<std::string, std::string> expected;
|
||||||
expected[""] = "\n\n\n\n";
|
expected[""] = "\n\n\n\n";
|
||||||
|
|
||||||
// Preprocess => actual result..
|
// Preprocess => actual result..
|
||||||
std::istringstream istr(filedata);
|
std::istringstream istr(filedata);
|
||||||
std::map<std::string, std::string> actual;
|
std::map<std::string, std::string> actual;
|
||||||
Preprocessor preprocessor;
|
Preprocessor preprocessor;
|
||||||
preprocessor.preprocess( istr, actual, "" );
|
preprocessor.preprocess( istr, actual, "" );
|
||||||
|
|
||||||
// Compare results..
|
// Compare results..
|
||||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
void if1()
|
void if1()
|
||||||
{
|
{
|
||||||
const char filedata[] = " # if /* comment */ 1 // comment\n"
|
const char filedata[] = " # if /* comment */ 1 // comment\n"
|
||||||
"ABC\n"
|
"ABC\n"
|
||||||
" # endif \n";
|
" # endif \n";
|
||||||
|
|
||||||
// Expected result..
|
// Expected result..
|
||||||
std::map<std::string, std::string> expected;
|
std::map<std::string, std::string> expected;
|
||||||
expected[""] = "\nABC\n\n";
|
expected[""] = "\nABC\n\n";
|
||||||
|
|
||||||
// Preprocess => actual result..
|
// Preprocess => actual result..
|
||||||
std::istringstream istr(filedata);
|
std::istringstream istr(filedata);
|
||||||
std::map<std::string, std::string> actual;
|
std::map<std::string, std::string> actual;
|
||||||
Preprocessor preprocessor;
|
Preprocessor preprocessor;
|
||||||
preprocessor.preprocess( istr, actual, "" );
|
preprocessor.preprocess( istr, actual, "" );
|
||||||
|
|
||||||
// Compare results..
|
// Compare results..
|
||||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void elif()
|
void elif()
|
||||||
{
|
{
|
||||||
const char filedata[] = "#if DEF1\n"
|
const char filedata[] = "#if DEF1\n"
|
||||||
"ABC\n"
|
"ABC\n"
|
||||||
"#elif DEF2\n"
|
"#elif DEF2\n"
|
||||||
"DEF\n"
|
"DEF\n"
|
||||||
"#endif\n";
|
"#endif\n";
|
||||||
|
|
||||||
// Expected result..
|
// Expected result..
|
||||||
std::map<std::string, std::string> expected;
|
std::map<std::string, std::string> expected;
|
||||||
expected[""] = "\n\n\n\n\n";
|
expected[""] = "\n\n\n\n\n";
|
||||||
expected["DEF1"] = "\nABC\n\n\n\n";
|
expected["DEF1"] = "\nABC\n\n\n\n";
|
||||||
expected["DEF2"] = "\n\n\nDEF\n\n";
|
expected["DEF2"] = "\n\n\nDEF\n\n";
|
||||||
|
|
||||||
// Preprocess => actual result..
|
// Preprocess => actual result..
|
||||||
std::istringstream istr(filedata);
|
std::istringstream istr(filedata);
|
||||||
std::map<std::string, std::string> actual;
|
std::map<std::string, std::string> actual;
|
||||||
Preprocessor preprocessor;
|
Preprocessor preprocessor;
|
||||||
preprocessor.preprocess( istr, actual, "" );
|
preprocessor.preprocess( istr, actual, "" );
|
||||||
|
|
||||||
// Compare results..
|
// Compare results..
|
||||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void include1()
|
void include1()
|
||||||
{
|
{
|
||||||
const char filedata[] = " # include \"abcd.h\" // abcd\n";
|
const char filedata[] = " # include \"abcd.h\" // abcd\n";
|
||||||
|
|
||||||
// Expected result..
|
// Expected result..
|
||||||
std::map<std::string, std::string> expected;
|
std::map<std::string, std::string> expected;
|
||||||
expected[""] = "#include \"abcd.h\"\n";
|
expected[""] = "#include \"abcd.h\"\n";
|
||||||
|
|
||||||
// Preprocess => actual result..
|
// Preprocess => actual result..
|
||||||
std::istringstream istr(filedata);
|
std::istringstream istr(filedata);
|
||||||
std::map<std::string, std::string> actual;
|
std::map<std::string, std::string> actual;
|
||||||
Preprocessor preprocessor;
|
Preprocessor preprocessor;
|
||||||
preprocessor.preprocess( istr, actual, "" );
|
preprocessor.preprocess( istr, actual, "" );
|
||||||
|
|
||||||
// Compare results..
|
// Compare results..
|
||||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void if_cond1()
|
void if_cond1()
|
||||||
{
|
{
|
||||||
const char filedata[] = "#if LIBVER>100\n"
|
const char filedata[] = "#if LIBVER>100\n"
|
||||||
" A\n"
|
" A\n"
|
||||||
"#else\n"
|
"#else\n"
|
||||||
" B\n"
|
" B\n"
|
||||||
"#endif\n";
|
"#endif\n";
|
||||||
|
|
||||||
std::map<std::string, std::string> expected;
|
std::map<std::string, std::string> expected;
|
||||||
expected[""] = "\n\n\nB\n\n";
|
expected[""] = "\n\n\nB\n\n";
|
||||||
expected["LIBVER>100"] = "\nA\n\n\n\n";
|
expected["LIBVER>100"] = "\nA\n\n\n\n";
|
||||||
|
|
||||||
// Preprocess => actual result..
|
// Preprocess => actual result..
|
||||||
std::istringstream istr(filedata);
|
std::istringstream istr(filedata);
|
||||||
std::map<std::string, std::string> actual;
|
std::map<std::string, std::string> actual;
|
||||||
Preprocessor preprocessor;
|
Preprocessor preprocessor;
|
||||||
preprocessor.preprocess( istr, actual, "" );
|
preprocessor.preprocess( istr, actual, "" );
|
||||||
|
|
||||||
// Compare results..
|
// Compare results..
|
||||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void multiline()
|
void multiline()
|
||||||
{
|
{
|
||||||
const char filedata[] = "#define str \"abc\" \\ \n"
|
const char filedata[] = "#define str \"abc\" \\ \n"
|
||||||
" \"def\" \\ \n"
|
" \"def\" \\ \n"
|
||||||
" \"ghi\" \n";
|
" \"ghi\" \n";
|
||||||
|
|
||||||
std::map<std::string, std::string> expected;
|
std::map<std::string, std::string> expected;
|
||||||
expected[""] = "#define str \"abc\" \"def\" \"ghi\"\n\n\n";
|
expected[""] = "#define str \"abc\" \"def\" \"ghi\"\n\n\n";
|
||||||
|
|
||||||
// Preprocess => actual result..
|
// Preprocess => actual result..
|
||||||
std::istringstream istr(filedata);
|
std::istringstream istr(filedata);
|
||||||
std::map<std::string, std::string> actual;
|
std::map<std::string, std::string> actual;
|
||||||
Preprocessor preprocessor;
|
Preprocessor preprocessor;
|
||||||
preprocessor.preprocess( istr, actual, "" );
|
preprocessor.preprocess( istr, actual, "" );
|
||||||
|
|
||||||
// Compare results..
|
// Compare results..
|
||||||
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
ASSERT_EQUALS( true, cmpmaps(actual, expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST( TestPreprocessor )
|
REGISTER_TEST( TestPreprocessor )
|
||||||
|
|
|
@ -1,87 +1,87 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// Check for dangerous division..
|
// Check for dangerous division..
|
||||||
// such as "svar / uvar". Treating "svar" as unsigned data is not good
|
// such as "svar / uvar". Treating "svar" as unsigned data is not good
|
||||||
|
|
||||||
|
|
||||||
#define UNIT_TESTING
|
#define UNIT_TESTING
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
#include "checkother.h"
|
#include "checkother.h"
|
||||||
#include "testsuite.h"
|
#include "testsuite.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
extern std::ostringstream errout;
|
extern std::ostringstream errout;
|
||||||
|
|
||||||
class TestRedundantIf : public TestFixture
|
class TestRedundantIf : public TestFixture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TestRedundantIf() : TestFixture("TestRedundantIf")
|
TestRedundantIf() : TestFixture("TestRedundantIf")
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void check( const char code[] )
|
void check( const char code[] )
|
||||||
{
|
{
|
||||||
// Tokenize..
|
// Tokenize..
|
||||||
Tokenizer tokenizer;
|
Tokenizer tokenizer;
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
tokenizer.tokenize( istr, "test.cpp" );
|
tokenizer.tokenize( istr, "test.cpp" );
|
||||||
|
|
||||||
// Clear the error buffer..
|
// Clear the error buffer..
|
||||||
errout.str("");
|
errout.str("");
|
||||||
|
|
||||||
// Check for redundant condition..
|
// Check for redundant condition..
|
||||||
CheckOther checkOther( &tokenizer, this );
|
CheckOther checkOther( &tokenizer, this );
|
||||||
checkOther.redundantCondition2();
|
checkOther.redundantCondition2();
|
||||||
}
|
}
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
TEST_CASE( remove1 );
|
TEST_CASE( remove1 );
|
||||||
TEST_CASE( remove2 );
|
TEST_CASE( remove2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove1()
|
void remove1()
|
||||||
{
|
{
|
||||||
check( "void f()\n"
|
check( "void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" if (haystack.find(needle) != haystack.end())\n"
|
" if (haystack.find(needle) != haystack.end())\n"
|
||||||
" haystack.remove(needle);"
|
" haystack.remove(needle);"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:3]: Redundant condition found. The remove function in the STL will not do anything if element doesn't exist\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:3]: Redundant condition found. The remove function in the STL will not do anything if element doesn't exist\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove2()
|
void remove2()
|
||||||
{
|
{
|
||||||
check( "void f()\n"
|
check( "void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" if (haystack.find(needle) != haystack.end())\n"
|
" if (haystack.find(needle) != haystack.end())\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" haystack.remove(needle);\n"
|
" haystack.remove(needle);\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:3]: Redundant condition found. The remove function in the STL will not do anything if element doesn't exist\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:3]: Redundant condition found. The remove function in the STL will not do anything if element doesn't exist\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST( TestRedundantIf )
|
REGISTER_TEST( TestRedundantIf )
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "testsuite.h"
|
#include "testsuite.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
int main(int argc, const char *argv[])
|
int main(int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
TestFixture::runTests( (argc==2) ? argv[1] : NULL );
|
TestFixture::runTests( (argc==2) ? argv[1] : NULL );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,73 +1,73 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "testsuite.h"
|
#include "testsuite.h"
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
extern std::ostringstream errout;
|
extern std::ostringstream errout;
|
||||||
|
|
||||||
class TestSimplifyTokens : public TestFixture
|
class TestSimplifyTokens : public TestFixture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TestSimplifyTokens() : TestFixture("TestSimplifyTokens")
|
TestSimplifyTokens() : TestFixture("TestSimplifyTokens")
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
TEST_CASE( cast0 );
|
TEST_CASE( cast0 );
|
||||||
TEST_CASE( sizeof1 );
|
TEST_CASE( sizeof1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string tok(const char code[])
|
std::string tok(const char code[])
|
||||||
{
|
{
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
Tokenizer tokenizer;
|
Tokenizer tokenizer;
|
||||||
tokenizer.tokenize( istr, "test.cpp" );
|
tokenizer.tokenize( istr, "test.cpp" );
|
||||||
tokenizer.simplifyTokenList();
|
tokenizer.simplifyTokenList();
|
||||||
|
|
||||||
std::string ret;
|
std::string ret;
|
||||||
for ( const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next() )
|
for ( const TOKEN *tok = tokenizer.tokens(); tok; tok = tok->next() )
|
||||||
{
|
{
|
||||||
ret += tok->str() + " ";
|
ret += tok->str() + " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cast0()
|
void cast0()
|
||||||
{
|
{
|
||||||
const char code1[] = " if ( p == (char *)0 ) ";
|
const char code1[] = " if ( p == (char *)0 ) ";
|
||||||
const char code2[] = " if ( p == 0 ) ";
|
const char code2[] = " if ( p == 0 ) ";
|
||||||
ASSERT_EQUALS( tok(code1), tok(code2) );
|
ASSERT_EQUALS( tok(code1), tok(code2) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void sizeof1()
|
void sizeof1()
|
||||||
{
|
{
|
||||||
const char code1[] = " struct ABC *abc = malloc(sizeof(*abc)); ";
|
const char code1[] = " struct ABC *abc = malloc(sizeof(*abc)); ";
|
||||||
const char code2[] = " struct ABC *abc = malloc(100); ";
|
const char code2[] = " struct ABC *abc = malloc(100); ";
|
||||||
ASSERT_EQUALS( tok(code1), tok(code2) );
|
ASSERT_EQUALS( tok(code1), tok(code2) );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST( TestSimplifyTokens )
|
REGISTER_TEST( TestSimplifyTokens )
|
||||||
|
|
332
testsuite.cpp
332
testsuite.cpp
|
@ -1,178 +1,178 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "testsuite.h"
|
#include "testsuite.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
std::ostringstream errout;
|
std::ostringstream errout;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TestRegistry
|
* TestRegistry
|
||||||
**/
|
**/
|
||||||
|
|
||||||
class TestRegistry
|
class TestRegistry
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::list<TestFixture *> _tests;
|
std::list<TestFixture *> _tests;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static TestRegistry &theInstance()
|
static TestRegistry &theInstance()
|
||||||
{
|
{
|
||||||
static TestRegistry testreg;
|
static TestRegistry testreg;
|
||||||
return testreg;
|
return testreg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addTest( TestFixture *t )
|
void addTest( TestFixture *t )
|
||||||
{
|
{
|
||||||
_tests.push_back( t );
|
_tests.push_back( t );
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::list<TestFixture *> &tests() const
|
const std::list<TestFixture *> &tests() const
|
||||||
{
|
{
|
||||||
return _tests;
|
return _tests;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TestFixture
|
* TestFixture
|
||||||
**/
|
**/
|
||||||
|
|
||||||
std::ostringstream TestFixture::errmsg;
|
std::ostringstream TestFixture::errmsg;
|
||||||
unsigned int TestFixture::countTests;
|
unsigned int TestFixture::countTests;
|
||||||
|
|
||||||
TestFixture::TestFixture(const std::string &_name) : classname(_name)
|
TestFixture::TestFixture(const std::string &_name) : classname(_name)
|
||||||
{
|
{
|
||||||
TestRegistry::theInstance().addTest(this);
|
TestRegistry::theInstance().addTest(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool TestFixture::runTest(const char testname[])
|
bool TestFixture::runTest(const char testname[])
|
||||||
{
|
{
|
||||||
if ( testToRun.empty() || testToRun == testname )
|
if ( testToRun.empty() || testToRun == testname )
|
||||||
{
|
{
|
||||||
countTests++;
|
countTests++;
|
||||||
std::cout << classname << "::" << testname << "\n";
|
std::cout << classname << "::" << testname << "\n";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string writestr( const std::string &str )
|
static std::string writestr( const std::string &str )
|
||||||
{
|
{
|
||||||
std::ostringstream ostr;
|
std::ostringstream ostr;
|
||||||
ostr << "\"";
|
ostr << "\"";
|
||||||
for (unsigned int i = 0; i < str.length(); ++i)
|
for (unsigned int i = 0; i < str.length(); ++i)
|
||||||
{
|
{
|
||||||
char ch = str[i];
|
char ch = str[i];
|
||||||
if ( ch == '\n' )
|
if ( ch == '\n' )
|
||||||
ostr << "\\n";
|
ostr << "\\n";
|
||||||
else if ( ch == '\t' )
|
else if ( ch == '\t' )
|
||||||
ostr << "\\t";
|
ostr << "\\t";
|
||||||
else if ( ch == '\"' )
|
else if ( ch == '\"' )
|
||||||
ostr << "\\\"";
|
ostr << "\\\"";
|
||||||
else
|
else
|
||||||
ostr << std::string(1, ch);
|
ostr << std::string(1, ch);
|
||||||
}
|
}
|
||||||
ostr << "\"";
|
ostr << "\"";
|
||||||
return ostr.str();
|
return ostr.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestFixture::assertEquals(const char *filename, int linenr, const std::string &expected, const std::string &actual)
|
void TestFixture::assertEquals(const char *filename, int linenr, const std::string &expected, const std::string &actual)
|
||||||
{
|
{
|
||||||
if ( expected != actual )
|
if ( expected != actual )
|
||||||
{
|
{
|
||||||
errmsg << "Assertion failed in " << filename << " at line " << linenr << std::endl
|
errmsg << "Assertion failed in " << filename << " at line " << linenr << std::endl
|
||||||
<< "Expected:" << std::endl
|
<< "Expected:" << std::endl
|
||||||
<< writestr(expected) << std::endl
|
<< writestr(expected) << std::endl
|
||||||
<< "Actual:" << std::endl
|
<< "Actual:" << std::endl
|
||||||
<< writestr(actual) << std::endl;
|
<< writestr(actual) << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestFixture::assertEquals(const char *filename, int linenr, unsigned int expected, unsigned int actual)
|
void TestFixture::assertEquals(const char *filename, int linenr, unsigned int expected, unsigned int actual)
|
||||||
{
|
{
|
||||||
std::ostringstream ostr1;
|
std::ostringstream ostr1;
|
||||||
ostr1 << expected;
|
ostr1 << expected;
|
||||||
std::ostringstream ostr2;
|
std::ostringstream ostr2;
|
||||||
ostr2 << actual;
|
ostr2 << actual;
|
||||||
assertEquals( filename, linenr, ostr1.str(), ostr2.str() );
|
assertEquals( filename, linenr, ostr1.str(), ostr2.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestFixture::printTests()
|
void TestFixture::printTests()
|
||||||
{
|
{
|
||||||
const std::list<TestFixture *> &tests = TestRegistry::theInstance().tests();
|
const std::list<TestFixture *> &tests = TestRegistry::theInstance().tests();
|
||||||
|
|
||||||
for ( std::list<TestFixture *>::const_iterator it = tests.begin(); it != tests.end(); ++it )
|
for ( std::list<TestFixture *>::const_iterator it = tests.begin(); it != tests.end(); ++it )
|
||||||
{
|
{
|
||||||
std::cout << (*it)->classname << std::endl;
|
std::cout << (*it)->classname << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestFixture::run(const std::string &str)
|
void TestFixture::run(const std::string &str)
|
||||||
{
|
{
|
||||||
testToRun = str;
|
testToRun = str;
|
||||||
run();
|
run();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestFixture::runTests(const char cmd[])
|
void TestFixture::runTests(const char cmd[])
|
||||||
{
|
{
|
||||||
std::string classname(cmd ? cmd : "");
|
std::string classname(cmd ? cmd : "");
|
||||||
std::string testname("");
|
std::string testname("");
|
||||||
if ( classname.find("::") != std::string::npos )
|
if ( classname.find("::") != std::string::npos )
|
||||||
{
|
{
|
||||||
testname = classname.substr( classname.find("::") + 2 );
|
testname = classname.substr( classname.find("::") + 2 );
|
||||||
classname.erase( classname.find("::") );
|
classname.erase( classname.find("::") );
|
||||||
}
|
}
|
||||||
|
|
||||||
countTests = 0;
|
countTests = 0;
|
||||||
errmsg.str("");
|
errmsg.str("");
|
||||||
|
|
||||||
const std::list<TestFixture *> &tests = TestRegistry::theInstance().tests();
|
const std::list<TestFixture *> &tests = TestRegistry::theInstance().tests();
|
||||||
|
|
||||||
for ( std::list<TestFixture *>::const_iterator it = tests.begin(); it != tests.end(); ++it )
|
for ( std::list<TestFixture *>::const_iterator it = tests.begin(); it != tests.end(); ++it )
|
||||||
{
|
{
|
||||||
if ( classname.empty() || (*it)->classname == classname )
|
if ( classname.empty() || (*it)->classname == classname )
|
||||||
{
|
{
|
||||||
(*it)->run(testname);
|
(*it)->run(testname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "\n\nTesting Complete\nNumber of tests: " << countTests << "\n";
|
std::cout << "\n\nTesting Complete\nNumber of tests: " << countTests << "\n";
|
||||||
|
|
||||||
std::cerr << errmsg.str();
|
std::cerr << errmsg.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TestFixture::reportErr( const std::string &errmsg)
|
void TestFixture::reportErr( const std::string &errmsg)
|
||||||
{
|
{
|
||||||
errout << errmsg << std::endl;
|
errout << errmsg << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestFixture::reportOut( const std::string &outmsg)
|
void TestFixture::reportOut( const std::string &outmsg)
|
||||||
{
|
{
|
||||||
// These can probably be ignored
|
// These can probably be ignored
|
||||||
}
|
}
|
||||||
|
|
116
testsuite.h
116
testsuite.h
|
@ -1,61 +1,61 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "errorlogger.h"
|
#include "errorlogger.h"
|
||||||
|
|
||||||
class TOKEN;
|
class TOKEN;
|
||||||
|
|
||||||
class TestFixture : public ErrorLogger
|
class TestFixture : public ErrorLogger
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
static std::ostringstream errmsg;
|
static std::ostringstream errmsg;
|
||||||
static unsigned int countTests;
|
static unsigned int countTests;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::string classname;
|
std::string classname;
|
||||||
std::string testToRun;
|
std::string testToRun;
|
||||||
|
|
||||||
virtual void run() = 0;
|
virtual void run() = 0;
|
||||||
|
|
||||||
bool runTest(const char testname[]);
|
bool runTest(const char testname[]);
|
||||||
void assertEquals(const char *filename, int linenr, const std::string &expected, const std::string &actual);
|
void assertEquals(const char *filename, int linenr, const std::string &expected, const std::string &actual);
|
||||||
void assertEquals(const char *filename, int linenr, unsigned int expected, unsigned int actual);
|
void assertEquals(const char *filename, int linenr, unsigned int expected, unsigned int actual);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void reportErr( const std::string &errmsg);
|
virtual void reportErr( const std::string &errmsg);
|
||||||
|
|
||||||
virtual void reportOut( const std::string &outmsg);
|
virtual void reportOut( const std::string &outmsg);
|
||||||
|
|
||||||
void run(const std::string &str);
|
void run(const std::string &str);
|
||||||
|
|
||||||
TestFixture(const std::string &_name);
|
TestFixture(const std::string &_name);
|
||||||
virtual ~TestFixture() { }
|
virtual ~TestFixture() { }
|
||||||
|
|
||||||
static void printTests();
|
static void printTests();
|
||||||
static void runTests(const char cmd[]);
|
static void runTests(const char cmd[]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#define TEST_CASE( NAME ) if ( runTest(#NAME) ) NAME ();
|
#define TEST_CASE( NAME ) if ( runTest(#NAME) ) NAME ();
|
||||||
#define ASSERT_EQUALS( EXPECTED , ACTUAL ) assertEquals(__FILE__, __LINE__, EXPECTED, ACTUAL)
|
#define ASSERT_EQUALS( EXPECTED , ACTUAL ) assertEquals(__FILE__, __LINE__, EXPECTED, ACTUAL)
|
||||||
#define REGISTER_TEST( CLASSNAME ) namespace { CLASSNAME instance; }
|
#define REGISTER_TEST( CLASSNAME ) namespace { CLASSNAME instance; }
|
||||||
|
|
||||||
|
|
122
testtoken.cpp
122
testtoken.cpp
|
@ -1,61 +1,61 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2008 Daniel Marjamäki and Reijo Tomperi
|
* Copyright (C) 2008 Daniel Marjamäki and Reijo Tomperi
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "testsuite.h"
|
#include "testsuite.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
|
|
||||||
extern std::ostringstream errout;
|
extern std::ostringstream errout;
|
||||||
class TestTOKEN : public TestFixture
|
class TestTOKEN : public TestFixture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TestTOKEN() : TestFixture("TestTOKEN")
|
TestTOKEN() : TestFixture("TestTOKEN")
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
TEST_CASE( nextprevious );
|
TEST_CASE( nextprevious );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nextprevious()
|
void nextprevious()
|
||||||
{
|
{
|
||||||
TOKEN *token = new TOKEN;
|
TOKEN *token = new TOKEN;
|
||||||
token->setstr( "1" );
|
token->setstr( "1" );
|
||||||
token->insertToken( "2" );
|
token->insertToken( "2" );
|
||||||
token->next()->insertToken( "3" );
|
token->next()->insertToken( "3" );
|
||||||
TOKEN *last = token->next()->next();
|
TOKEN *last = token->next()->next();
|
||||||
ASSERT_EQUALS( token->str(), "1" );
|
ASSERT_EQUALS( token->str(), "1" );
|
||||||
ASSERT_EQUALS( token->next()->str(), "2" );
|
ASSERT_EQUALS( token->next()->str(), "2" );
|
||||||
ASSERT_EQUALS( token->next()->next()->str(), "3" );
|
ASSERT_EQUALS( token->next()->next()->str(), "3" );
|
||||||
if( last->next() )
|
if( last->next() )
|
||||||
ASSERT_EQUALS( "Null was expected", "" );
|
ASSERT_EQUALS( "Null was expected", "" );
|
||||||
|
|
||||||
ASSERT_EQUALS( last->str(), "3" );
|
ASSERT_EQUALS( last->str(), "3" );
|
||||||
ASSERT_EQUALS( last->previous()->str(), "2" );
|
ASSERT_EQUALS( last->previous()->str(), "2" );
|
||||||
ASSERT_EQUALS( last->previous()->previous()->str(), "1" );
|
ASSERT_EQUALS( last->previous()->previous()->str(), "1" );
|
||||||
if( token->previous() )
|
if( token->previous() )
|
||||||
ASSERT_EQUALS( "Null was expected", "" );
|
ASSERT_EQUALS( "Null was expected", "" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST( TestTOKEN )
|
REGISTER_TEST( TestTOKEN )
|
||||||
|
|
1012
testtokenize.cpp
1012
testtokenize.cpp
File diff suppressed because it is too large
Load Diff
|
@ -1,120 +1,120 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#define UNIT_TESTING
|
#define UNIT_TESTING
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
#include "checkclass.h"
|
#include "checkclass.h"
|
||||||
#include "testsuite.h"
|
#include "testsuite.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
extern std::ostringstream errout;
|
extern std::ostringstream errout;
|
||||||
|
|
||||||
class TestUnusedPrivateFunction : public TestFixture
|
class TestUnusedPrivateFunction : public TestFixture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TestUnusedPrivateFunction() : TestFixture("TestUnusedPrivateFunction")
|
TestUnusedPrivateFunction() : TestFixture("TestUnusedPrivateFunction")
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
TEST_CASE( test1 );
|
TEST_CASE( test1 );
|
||||||
|
|
||||||
// [ 2236547 ] False positive --style unused function, called via pointer
|
// [ 2236547 ] False positive --style unused function, called via pointer
|
||||||
TEST_CASE( func_pointer );
|
TEST_CASE( func_pointer );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void check( const char code[] )
|
void check( const char code[] )
|
||||||
{
|
{
|
||||||
// Tokenize..
|
// Tokenize..
|
||||||
Tokenizer tokenizer;
|
Tokenizer tokenizer;
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
tokenizer.tokenize( istr, "test.cpp" );
|
tokenizer.tokenize( istr, "test.cpp" );
|
||||||
|
|
||||||
// Clear the error buffer..
|
// Clear the error buffer..
|
||||||
errout.str("");
|
errout.str("");
|
||||||
|
|
||||||
// Check for unused private functions..
|
// Check for unused private functions..
|
||||||
Settings settings;
|
Settings settings;
|
||||||
settings._checkCodingStyle = true;
|
settings._checkCodingStyle = true;
|
||||||
CheckClass checkClass( &tokenizer, settings, this );
|
CheckClass checkClass( &tokenizer, settings, this );
|
||||||
checkClass.CheckUnusedPrivateFunctions();
|
checkClass.CheckUnusedPrivateFunctions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void test1()
|
void test1()
|
||||||
{
|
{
|
||||||
check( "class Fred\n"
|
check( "class Fred\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"private:\n"
|
"private:\n"
|
||||||
" unsigned int f();\n"
|
" unsigned int f();\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" Fred();\n"
|
" Fred();\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Fred::Fred()\n"
|
"Fred::Fred()\n"
|
||||||
"{ }\n"
|
"{ }\n"
|
||||||
"\n"
|
"\n"
|
||||||
"unsigned int Fred::f()\n"
|
"unsigned int Fred::f()\n"
|
||||||
"{ }\n" );
|
"{ }\n" );
|
||||||
|
|
||||||
ASSERT_EQUALS( std::string("Class 'Fred', unused private function: 'f'\n"), errout.str() );
|
ASSERT_EQUALS( std::string("Class 'Fred', unused private function: 'f'\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void func_pointer()
|
void func_pointer()
|
||||||
{
|
{
|
||||||
check( "class Fred\n"
|
check( "class Fred\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"private:\n"
|
"private:\n"
|
||||||
" typedef void (*testfp)();\n"
|
" typedef void (*testfp)();\n"
|
||||||
"\n"
|
"\n"
|
||||||
" testfp get()\n"
|
" testfp get()\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" return test;\n"
|
" return test;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"\n"
|
"\n"
|
||||||
" static void test()\n"
|
" static void test()\n"
|
||||||
" { }\n"
|
" { }\n"
|
||||||
"\n"
|
"\n"
|
||||||
"public:\n"
|
"public:\n"
|
||||||
" Fred();\n"
|
" Fred();\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Fred::Fred()\n"
|
"Fred::Fred()\n"
|
||||||
"{}\n" );
|
"{}\n" );
|
||||||
|
|
||||||
std::string str( errout.str() );
|
std::string str( errout.str() );
|
||||||
|
|
||||||
ASSERT_EQUALS( std::string("Class 'Fred', unused private function: 'get'\n"), str );
|
ASSERT_EQUALS( std::string("Class 'Fred', unused private function: 'get'\n"), str );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST( TestUnusedPrivateFunction )
|
REGISTER_TEST( TestUnusedPrivateFunction )
|
||||||
|
|
||||||
|
|
|
@ -1,184 +1,184 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Check for unused variables..
|
// Check for unused variables..
|
||||||
|
|
||||||
#define UNIT_TESTING
|
#define UNIT_TESTING
|
||||||
#include "testsuite.h"
|
#include "testsuite.h"
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
#include "checkother.h"
|
#include "checkother.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
extern std::ostringstream errout;
|
extern std::ostringstream errout;
|
||||||
|
|
||||||
class TestUnusedVar : public TestFixture
|
class TestUnusedVar : public TestFixture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TestUnusedVar() : TestFixture("TestUnusedVar")
|
TestUnusedVar() : TestFixture("TestUnusedVar")
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void check( const char code[] )
|
void check( const char code[] )
|
||||||
{
|
{
|
||||||
// Tokenize..
|
// Tokenize..
|
||||||
Tokenizer tokenizer;
|
Tokenizer tokenizer;
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
tokenizer.tokenize( istr, "test.cpp" );
|
tokenizer.tokenize( istr, "test.cpp" );
|
||||||
tokenizer.simplifyTokenList();
|
tokenizer.simplifyTokenList();
|
||||||
|
|
||||||
// Clear the error buffer..
|
// Clear the error buffer..
|
||||||
errout.str("");
|
errout.str("");
|
||||||
|
|
||||||
// Check for unused variables..
|
// Check for unused variables..
|
||||||
CheckOther checkOther( &tokenizer, this );
|
CheckOther checkOther( &tokenizer, this );
|
||||||
checkOther.CheckStructMemberUsage();
|
checkOther.CheckStructMemberUsage();
|
||||||
}
|
}
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
TEST_CASE( structmember1 );
|
TEST_CASE( structmember1 );
|
||||||
TEST_CASE( structmember2 );
|
TEST_CASE( structmember2 );
|
||||||
TEST_CASE( structmember3 );
|
TEST_CASE( structmember3 );
|
||||||
|
|
||||||
TEST_CASE( localvar1 );
|
TEST_CASE( localvar1 );
|
||||||
TEST_CASE( localvar2 );
|
TEST_CASE( localvar2 );
|
||||||
TEST_CASE( localvar3 );
|
TEST_CASE( localvar3 );
|
||||||
TEST_CASE( localvar4 );
|
TEST_CASE( localvar4 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void structmember1()
|
void structmember1()
|
||||||
{
|
{
|
||||||
check( "struct abc\n"
|
check( "struct abc\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int a;\n"
|
" int a;\n"
|
||||||
" int b;\n"
|
" int b;\n"
|
||||||
" int c;\n"
|
" int c;\n"
|
||||||
"};\n" );
|
"};\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:2]: struct member 'abc::a' is never read\n"
|
ASSERT_EQUALS( std::string("[test.cpp:2]: struct member 'abc::a' is never read\n"
|
||||||
"[test.cpp:3]: struct member 'abc::b' is never read\n"
|
"[test.cpp:3]: struct member 'abc::b' is never read\n"
|
||||||
"[test.cpp:4]: struct member 'abc::c' is never read\n"), errout.str() );
|
"[test.cpp:4]: struct member 'abc::c' is never read\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void structmember2()
|
void structmember2()
|
||||||
{
|
{
|
||||||
check( "struct ABC\n"
|
check( "struct ABC\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int a;\n"
|
" int a;\n"
|
||||||
" int b;\n"
|
" int b;\n"
|
||||||
" int c;\n"
|
" int c;\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"\n"
|
"\n"
|
||||||
"void foo()\n"
|
"void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" struct ABC abc;\n"
|
" struct ABC abc;\n"
|
||||||
" int a = abc.a;\n"
|
" int a = abc.a;\n"
|
||||||
" int b = abc.b;\n"
|
" int b = abc.b;\n"
|
||||||
" int c = abc.c;\n"
|
" int c = abc.c;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void structmember3()
|
void structmember3()
|
||||||
{
|
{
|
||||||
check( "struct ABC\n"
|
check( "struct ABC\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int a;\n"
|
" int a;\n"
|
||||||
" int b;\n"
|
" int b;\n"
|
||||||
" int c;\n"
|
" int c;\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"\n"
|
"\n"
|
||||||
"static struct ABC abc[] = { {1, 2, 3} };\n"
|
"static struct ABC abc[] = { {1, 2, 3} };\n"
|
||||||
"\n"
|
"\n"
|
||||||
"void foo()\n"
|
"void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int a = abc[0].a;\n"
|
" int a = abc[0].a;\n"
|
||||||
" int b = abc[0].b;\n"
|
" int b = abc[0].b;\n"
|
||||||
" int c = abc[0].c;\n"
|
" int c = abc[0].c;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void functionVariableUsage( const char code[] )
|
void functionVariableUsage( const char code[] )
|
||||||
{
|
{
|
||||||
// Tokenize..
|
// Tokenize..
|
||||||
Tokenizer tokenizer;
|
Tokenizer tokenizer;
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
tokenizer.tokenize( istr, "test.cpp" );
|
tokenizer.tokenize( istr, "test.cpp" );
|
||||||
tokenizer.simplifyTokenList();
|
tokenizer.simplifyTokenList();
|
||||||
|
|
||||||
// Clear the error buffer..
|
// Clear the error buffer..
|
||||||
errout.str("");
|
errout.str("");
|
||||||
|
|
||||||
// Check for unused variables..
|
// Check for unused variables..
|
||||||
CheckOther checkOther( &tokenizer, this );
|
CheckOther checkOther( &tokenizer, this );
|
||||||
checkOther.functionVariableUsage();
|
checkOther.functionVariableUsage();
|
||||||
}
|
}
|
||||||
|
|
||||||
void localvar1()
|
void localvar1()
|
||||||
{
|
{
|
||||||
functionVariableUsage( "void foo()\n"
|
functionVariableUsage( "void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int i = 0;\n"
|
" int i = 0;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:2]: Variable 'i' is assigned a value that is never used\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:2]: Variable 'i' is assigned a value that is never used\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void localvar2()
|
void localvar2()
|
||||||
{
|
{
|
||||||
functionVariableUsage( "void foo()\n"
|
functionVariableUsage( "void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int i;\n"
|
" int i;\n"
|
||||||
" return i;\n"
|
" return i;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:2]: Variable 'i' is not assigned a value\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:2]: Variable 'i' is not assigned a value\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void localvar3()
|
void localvar3()
|
||||||
{
|
{
|
||||||
functionVariableUsage( "void foo()\n"
|
functionVariableUsage( "void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int i;\n"
|
" int i;\n"
|
||||||
" if ( abc )\n"
|
" if ( abc )\n"
|
||||||
" ;\n"
|
" ;\n"
|
||||||
" else i = 0;\n"
|
" else i = 0;\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string("[test.cpp:2]: Variable 'i' is assigned a value that is never used\n"), errout.str() );
|
ASSERT_EQUALS( std::string("[test.cpp:2]: Variable 'i' is assigned a value that is never used\n"), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void localvar4()
|
void localvar4()
|
||||||
{
|
{
|
||||||
functionVariableUsage( "void foo()\n"
|
functionVariableUsage( "void foo()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" int i = 0;\n"
|
" int i = 0;\n"
|
||||||
" f(i);\n"
|
" f(i);\n"
|
||||||
"}\n" );
|
"}\n" );
|
||||||
ASSERT_EQUALS( std::string(""), errout.str() );
|
ASSERT_EQUALS( std::string(""), errout.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST( TestUnusedVar )
|
REGISTER_TEST( TestUnusedVar )
|
||||||
|
|
||||||
|
|
||||||
|
|
860
token.cpp
860
token.cpp
|
@ -1,436 +1,436 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi
|
* Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#ifdef __BORLANDC__
|
#ifdef __BORLANDC__
|
||||||
#include <ctype.h> // isalpha, isdigit
|
#include <ctype.h> // isalpha, isdigit
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TOKEN::TOKEN()
|
TOKEN::TOKEN()
|
||||||
{
|
{
|
||||||
_fileIndex = 0;
|
_fileIndex = 0;
|
||||||
_cstr = 0;
|
_cstr = 0;
|
||||||
_str = "";
|
_str = "";
|
||||||
_linenr = 0;
|
_linenr = 0;
|
||||||
_next = 0;
|
_next = 0;
|
||||||
_previous = 0;
|
_previous = 0;
|
||||||
_varId = 0;
|
_varId = 0;
|
||||||
_isName = false;
|
_isName = false;
|
||||||
_isNumber = false;
|
_isNumber = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
TOKEN::~TOKEN()
|
TOKEN::~TOKEN()
|
||||||
{
|
{
|
||||||
std::free(_cstr);
|
std::free(_cstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TOKEN::setstr( const char s[] )
|
void TOKEN::setstr( const char s[] )
|
||||||
{
|
{
|
||||||
_str = s;
|
_str = s;
|
||||||
std::free(_cstr);
|
std::free(_cstr);
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
_cstr = strdup(s);
|
_cstr = strdup(s);
|
||||||
#else
|
#else
|
||||||
_cstr = _strdup(s);
|
_cstr = _strdup(s);
|
||||||
#endif
|
#endif
|
||||||
_isName = bool(_str[0]=='_' || isalpha(_str[0]));
|
_isName = bool(_str[0]=='_' || isalpha(_str[0]));
|
||||||
_isNumber = bool(isdigit(_str[0]) != 0);
|
_isNumber = bool(isdigit(_str[0]) != 0);
|
||||||
_varId = 0;
|
_varId = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TOKEN::combineWithNext(const char str1[], const char str2[])
|
void TOKEN::combineWithNext(const char str1[], const char str2[])
|
||||||
{
|
{
|
||||||
if (!(_next))
|
if (!(_next))
|
||||||
return;
|
return;
|
||||||
if (_str!=str1 || _next->_str!=str2)
|
if (_str!=str1 || _next->_str!=str2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::string newstr(std::string(str1) + std::string(str2));
|
std::string newstr(std::string(str1) + std::string(str2));
|
||||||
setstr( newstr.c_str() );
|
setstr( newstr.c_str() );
|
||||||
deleteNext();
|
deleteNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TOKEN::deleteNext()
|
void TOKEN::deleteNext()
|
||||||
{
|
{
|
||||||
TOKEN *n = _next;
|
TOKEN *n = _next;
|
||||||
_next = n->next();
|
_next = n->next();
|
||||||
delete n;
|
delete n;
|
||||||
if (_next)
|
if (_next)
|
||||||
_next->previous(this);
|
_next->previous(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const TOKEN *TOKEN::tokAt(int index) const
|
const TOKEN *TOKEN::tokAt(int index) const
|
||||||
{
|
{
|
||||||
const TOKEN *tok = this;
|
const TOKEN *tok = this;
|
||||||
while (index>0 && tok)
|
while (index>0 && tok)
|
||||||
{
|
{
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
index--;
|
index--;
|
||||||
}
|
}
|
||||||
return tok;
|
return tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *TOKEN::strAt(int index) const
|
const char *TOKEN::strAt(int index) const
|
||||||
{
|
{
|
||||||
const TOKEN *tok = this->tokAt(index);
|
const TOKEN *tok = this->tokAt(index);
|
||||||
return tok ? tok->_cstr : "";
|
return tok ? tok->_cstr : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
int TOKEN::multiCompare( const char *needle, const char *haystack )
|
int TOKEN::multiCompare( const char *needle, const char *haystack )
|
||||||
{
|
{
|
||||||
bool emptyStringFound = false;
|
bool emptyStringFound = false;
|
||||||
bool findNextOr = false;
|
bool findNextOr = false;
|
||||||
const char *haystackPointer = haystack;
|
const char *haystackPointer = haystack;
|
||||||
for( ; *needle; ++needle )
|
for( ; *needle; ++needle )
|
||||||
{
|
{
|
||||||
if( *needle == '|' )
|
if( *needle == '|' )
|
||||||
{
|
{
|
||||||
// If needle and haystack are both at the end, we have a match.
|
// If needle and haystack are both at the end, we have a match.
|
||||||
if( *haystackPointer == 0 )
|
if( *haystackPointer == 0 )
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
haystackPointer = haystack;
|
haystackPointer = haystack;
|
||||||
if( findNextOr )
|
if( findNextOr )
|
||||||
findNextOr = false;
|
findNextOr = false;
|
||||||
else
|
else
|
||||||
emptyStringFound = true;
|
emptyStringFound = true;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( findNextOr )
|
if( findNextOr )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// If haystack and needle don't share the same character, reset
|
// If haystack and needle don't share the same character, reset
|
||||||
// haystackpointer and find next '|' character.
|
// haystackpointer and find next '|' character.
|
||||||
if( *haystackPointer != *needle )
|
if( *haystackPointer != *needle )
|
||||||
{
|
{
|
||||||
haystackPointer = haystack;
|
haystackPointer = haystack;
|
||||||
findNextOr = true;
|
findNextOr = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// All characters in haystack and needle have matched this far
|
// All characters in haystack and needle have matched this far
|
||||||
haystackPointer++;
|
haystackPointer++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If both needle and haystack are at the end, then we have a match.
|
// If both needle and haystack are at the end, then we have a match.
|
||||||
if( *haystackPointer == 0 )
|
if( *haystackPointer == 0 )
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
// If empty string was found or if last character in needle was '|'
|
// If empty string was found or if last character in needle was '|'
|
||||||
if( emptyStringFound || findNextOr == false )
|
if( emptyStringFound || findNextOr == false )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TOKEN::Match(const TOKEN *tok, const char pattern[], const char *varname1[], const char *varname2[], unsigned int varid)
|
bool TOKEN::Match(const TOKEN *tok, const char pattern[], const char *varname1[], const char *varname2[], unsigned int varid)
|
||||||
{
|
{
|
||||||
const char *p = pattern;
|
const char *p = pattern;
|
||||||
while ( *p )
|
while ( *p )
|
||||||
{
|
{
|
||||||
// Skip spaces in pattern..
|
// Skip spaces in pattern..
|
||||||
while ( *p == ' ' )
|
while ( *p == ' ' )
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
if (!tok)
|
if (!tok)
|
||||||
{
|
{
|
||||||
// If we have no tokens, pattern "!!else" should return true
|
// If we have no tokens, pattern "!!else" should return true
|
||||||
if( isNotPattern( p ) )
|
if( isNotPattern( p ) )
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract token from pattern..
|
// Extract token from pattern..
|
||||||
// TODO: Refactor this so there can't be buffer overflows
|
// TODO: Refactor this so there can't be buffer overflows
|
||||||
char str[500];
|
char str[500];
|
||||||
char *s = str;
|
char *s = str;
|
||||||
while (*p && *p!=' ')
|
while (*p && *p!=' ')
|
||||||
{
|
{
|
||||||
*s = *p;
|
*s = *p;
|
||||||
s++;
|
s++;
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
*s = 0;
|
*s = 0;
|
||||||
|
|
||||||
// No token => Success!
|
// No token => Success!
|
||||||
if (str[0] == 0)
|
if (str[0] == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
bool useVar1;
|
bool useVar1;
|
||||||
// Any symbolname..
|
// Any symbolname..
|
||||||
if (strcmp(str,"%var%")==0 || strcmp(str,"%type%")==0)
|
if (strcmp(str,"%var%")==0 || strcmp(str,"%type%")==0)
|
||||||
{
|
{
|
||||||
if (!tok->isName())
|
if (!tok->isName())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accept any token
|
// Accept any token
|
||||||
else if (strcmp(str,"%any%")==0 )
|
else if (strcmp(str,"%any%")==0 )
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Variable name..
|
// Variable name..
|
||||||
else if ((useVar1 = (strcmp(str,"%var1%")==0)) || strcmp(str,"%var2%")==0)
|
else if ((useVar1 = (strcmp(str,"%var1%")==0)) || strcmp(str,"%var2%")==0)
|
||||||
{
|
{
|
||||||
const char **varname = useVar1 ? varname1 : varname2;
|
const char **varname = useVar1 ? varname1 : varname2;
|
||||||
|
|
||||||
if ( ! varname )
|
if ( ! varname )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (tok->_str != varname[0])
|
if (tok->_str != varname[0])
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for ( int i = 1; varname[i]; i++ )
|
for ( int i = 1; varname[i]; i++ )
|
||||||
{
|
{
|
||||||
if ( !(tok->tokAt(2)) )
|
if ( !(tok->tokAt(2)) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ( strcmp(tok->strAt( 1), ".") )
|
if ( strcmp(tok->strAt( 1), ".") )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ( strcmp(tok->strAt( 2), varname[i]) )
|
if ( strcmp(tok->strAt( 2), varname[i]) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
tok = tok->tokAt(2);
|
tok = tok->tokAt(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (strcmp(str,"%varid%")==0)
|
else if (strcmp(str,"%varid%")==0)
|
||||||
{
|
{
|
||||||
if ( tok->varId() != varid )
|
if ( tok->varId() != varid )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (strcmp(str,"%num%")==0)
|
else if (strcmp(str,"%num%")==0)
|
||||||
{
|
{
|
||||||
if ( ! tok->isNumber() )
|
if ( ! tok->isNumber() )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
else if (strcmp(str,"%str%")==0)
|
else if (strcmp(str,"%str%")==0)
|
||||||
{
|
{
|
||||||
if ( tok->_str[0] != '\"' )
|
if ( tok->_str[0] != '\"' )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// [.. => search for a one-character token..
|
// [.. => search for a one-character token..
|
||||||
else if (str[0]=='[' && strchr(str, ']') && tok->_str[1] == 0)
|
else if (str[0]=='[' && strchr(str, ']') && tok->_str[1] == 0)
|
||||||
{
|
{
|
||||||
*strrchr(str, ']') = 0;
|
*strrchr(str, ']') = 0;
|
||||||
if ( strchr( str + 1, tok->_str[0] ) == 0 )
|
if ( strchr( str + 1, tok->_str[0] ) == 0 )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse multi options, such as void|int|char (accept token which is one of these 3)
|
// Parse multi options, such as void|int|char (accept token which is one of these 3)
|
||||||
else if ( strchr(str, '|') && strlen( str ) > 2 )
|
else if ( strchr(str, '|') && strlen( str ) > 2 )
|
||||||
{
|
{
|
||||||
int res = multiCompare( str, tok->_cstr );
|
int res = multiCompare( str, tok->_cstr );
|
||||||
if( res == 0 )
|
if( res == 0 )
|
||||||
{
|
{
|
||||||
// Empty alternative matches, use the same token on next round
|
// Empty alternative matches, use the same token on next round
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if( res == -1 )
|
else if( res == -1 )
|
||||||
{
|
{
|
||||||
// No match
|
// No match
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse "not" options. Token can be anything except the given one
|
// Parse "not" options. Token can be anything except the given one
|
||||||
else if( isNotPattern( str ) )
|
else if( isNotPattern( str ) )
|
||||||
{
|
{
|
||||||
if( strcmp( tok->aaaa(), &(str[2]) ) == 0 )
|
if( strcmp( tok->aaaa(), &(str[2]) ) == 0 )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (str != tok->_str)
|
else if (str != tok->_str)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The end of the pattern has been reached and nothing wrong has been found
|
// The end of the pattern has been reached and nothing wrong has been found
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TOKEN::isNotPattern( const char *pattern )
|
bool TOKEN::isNotPattern( const char *pattern )
|
||||||
{
|
{
|
||||||
if( pattern && strlen(pattern) > 2 && pattern[0] == '!' && pattern[1] == '!' )
|
if( pattern && strlen(pattern) > 2 && pattern[0] == '!' && pattern[1] == '!' )
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TOKEN::isName() const
|
bool TOKEN::isName() const
|
||||||
{
|
{
|
||||||
return _isName;
|
return _isName;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TOKEN::isNumber() const
|
bool TOKEN::isNumber() const
|
||||||
{
|
{
|
||||||
return _isNumber;
|
return _isNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TOKEN::isStandardType() const
|
bool TOKEN::isStandardType() const
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
const char *type[] = {"bool","char","short","int","long","float","double",0};
|
const char *type[] = {"bool","char","short","int","long","float","double",0};
|
||||||
for (int i = 0; type[i]; i++)
|
for (int i = 0; type[i]; i++)
|
||||||
ret |= (_str == type[i]);
|
ret |= (_str == type[i]);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
const TOKEN *TOKEN::findmatch(const TOKEN *tok, const char pattern[], const char *varname1[], const char *varname2[])
|
const TOKEN *TOKEN::findmatch(const TOKEN *tok, const char pattern[], const char *varname1[], const char *varname2[])
|
||||||
{
|
{
|
||||||
for ( ; tok; tok = tok->next())
|
for ( ; tok; tok = tok->next())
|
||||||
{
|
{
|
||||||
if ( TOKEN::Match(tok, pattern, varname1, varname2) )
|
if ( TOKEN::Match(tok, pattern, varname1, varname2) )
|
||||||
return tok;
|
return tok;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TOKEN *TOKEN::findtoken(const TOKEN *tok1, const char *tokenstr[])
|
const TOKEN *TOKEN::findtoken(const TOKEN *tok1, const char *tokenstr[])
|
||||||
{
|
{
|
||||||
for (const TOKEN *ret = tok1; ret; ret = ret->next())
|
for (const TOKEN *ret = tok1; ret; ret = ret->next())
|
||||||
{
|
{
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
const TOKEN *tok = ret;
|
const TOKEN *tok = ret;
|
||||||
while (tokenstr[i])
|
while (tokenstr[i])
|
||||||
{
|
{
|
||||||
if (!tok)
|
if (!tok)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (*(tokenstr[i]) && (tokenstr[i] != tok->_str))
|
if (*(tokenstr[i]) && (tokenstr[i] != tok->_str))
|
||||||
break;
|
break;
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (!tokenstr[i])
|
if (!tokenstr[i])
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int TOKEN::varId() const
|
unsigned int TOKEN::varId() const
|
||||||
{
|
{
|
||||||
return _varId;
|
return _varId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TOKEN::varId( unsigned int id )
|
void TOKEN::varId( unsigned int id )
|
||||||
{
|
{
|
||||||
_varId = id;
|
_varId = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
TOKEN *TOKEN::next() const
|
TOKEN *TOKEN::next() const
|
||||||
{
|
{
|
||||||
return _next;
|
return _next;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TOKEN::next( TOKEN *next )
|
void TOKEN::next( TOKEN *next )
|
||||||
{
|
{
|
||||||
_next = next;
|
_next = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
TOKEN *TOKEN::previous() const
|
TOKEN *TOKEN::previous() const
|
||||||
{
|
{
|
||||||
return _previous;
|
return _previous;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TOKEN::previous( TOKEN *previous )
|
void TOKEN::previous( TOKEN *previous )
|
||||||
{
|
{
|
||||||
_previous = previous;
|
_previous = previous;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TOKEN::insertToken( const char str[] )
|
void TOKEN::insertToken( const char str[] )
|
||||||
{
|
{
|
||||||
TOKEN *newToken = new TOKEN;
|
TOKEN *newToken = new TOKEN;
|
||||||
newToken->setstr( str );
|
newToken->setstr( str );
|
||||||
newToken->_linenr = _linenr;
|
newToken->_linenr = _linenr;
|
||||||
newToken->_fileIndex = _fileIndex;
|
newToken->_fileIndex = _fileIndex;
|
||||||
if( this->next() )
|
if( this->next() )
|
||||||
{
|
{
|
||||||
newToken->next( this->next() );
|
newToken->next( this->next() );
|
||||||
newToken->next()->previous( newToken );
|
newToken->next()->previous( newToken );
|
||||||
}
|
}
|
||||||
|
|
||||||
this->next( newToken );
|
this->next( newToken );
|
||||||
newToken->previous( this );
|
newToken->previous( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
void TOKEN::eraseTokens( TOKEN *begin, const TOKEN *end )
|
void TOKEN::eraseTokens( TOKEN *begin, const TOKEN *end )
|
||||||
{
|
{
|
||||||
if ( ! begin )
|
if ( ! begin )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while ( begin->next() && begin->next() != end )
|
while ( begin->next() && begin->next() != end )
|
||||||
{
|
{
|
||||||
begin->deleteNext();
|
begin->deleteNext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int TOKEN::fileIndex() const
|
unsigned int TOKEN::fileIndex() const
|
||||||
{
|
{
|
||||||
return _fileIndex;
|
return _fileIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TOKEN::fileIndex( unsigned int fileIndex )
|
void TOKEN::fileIndex( unsigned int fileIndex )
|
||||||
{
|
{
|
||||||
_fileIndex = fileIndex;
|
_fileIndex = fileIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int TOKEN::linenr() const
|
unsigned int TOKEN::linenr() const
|
||||||
{
|
{
|
||||||
return _linenr;
|
return _linenr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TOKEN::linenr( unsigned int linenr )
|
void TOKEN::linenr( unsigned int linenr )
|
||||||
{
|
{
|
||||||
_linenr = linenr;
|
_linenr = linenr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TOKEN::printOut( const char *title ) const
|
void TOKEN::printOut( const char *title ) const
|
||||||
{
|
{
|
||||||
std::cout << std::endl << "###";
|
std::cout << std::endl << "###";
|
||||||
if ( title )
|
if ( title )
|
||||||
std::cout << " " << title << " ";
|
std::cout << " " << title << " ";
|
||||||
else
|
else
|
||||||
std::cout << "########";
|
std::cout << "########";
|
||||||
|
|
||||||
std::cout << "###" << std::endl;
|
std::cout << "###" << std::endl;
|
||||||
for( const TOKEN *t = this; t; t = t->next() )
|
for( const TOKEN *t = this; t; t = t->next() )
|
||||||
{
|
{
|
||||||
std::cout << t->linenr() << ": " << t->str();
|
std::cout << t->linenr() << ": " << t->str();
|
||||||
if ( t->varId() )
|
if ( t->varId() )
|
||||||
std::cout << " ("<< t->varId() <<")";
|
std::cout << " ("<< t->varId() <<")";
|
||||||
|
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
366
token.h
366
token.h
|
@ -1,183 +1,183 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi
|
* Copyright (C) 2007-2008 Daniel Marjamäki and Reijo Tomperi
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TOKEN_H
|
#ifndef TOKEN_H
|
||||||
#define TOKEN_H
|
#define TOKEN_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class TOKEN
|
class TOKEN
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TOKEN();
|
TOKEN();
|
||||||
~TOKEN();
|
~TOKEN();
|
||||||
void setstr( const char s[] );
|
void setstr( const char s[] );
|
||||||
|
|
||||||
const std::string &str() const
|
const std::string &str() const
|
||||||
{ return _str; }
|
{ return _str; }
|
||||||
|
|
||||||
const char *aaaa() const
|
const char *aaaa() const
|
||||||
{ return _cstr; }
|
{ return _cstr; }
|
||||||
|
|
||||||
char aaaa0() const
|
char aaaa0() const
|
||||||
{ return _cstr[0]; }
|
{ return _cstr[0]; }
|
||||||
|
|
||||||
char aaaa1() const
|
char aaaa1() const
|
||||||
{ return _cstr[1]; }
|
{ return _cstr[1]; }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Combine two tokens that belong to each other.
|
* Combine two tokens that belong to each other.
|
||||||
* Ex: "<" and "=" may become "<="
|
* Ex: "<" and "=" may become "<="
|
||||||
*/
|
*/
|
||||||
void combineWithNext(const char str1[], const char str2[]);
|
void combineWithNext(const char str1[], const char str2[]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unlink and delete next token.
|
* Unlink and delete next token.
|
||||||
*/
|
*/
|
||||||
void deleteNext();
|
void deleteNext();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns token in given index, related to this token.
|
* Returns token in given index, related to this token.
|
||||||
* For example index 1 would return next token, and 2
|
* For example index 1 would return next token, and 2
|
||||||
* would return next from that one.
|
* would return next from that one.
|
||||||
*/
|
*/
|
||||||
const TOKEN *tokAt(int index) const;
|
const TOKEN *tokAt(int index) const;
|
||||||
|
|
||||||
const char *strAt(int index) const;
|
const char *strAt(int index) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Match given token (or list of tokens) to a pattern list.
|
* Match given token (or list of tokens) to a pattern list.
|
||||||
*
|
*
|
||||||
* Possible patterns
|
* Possible patterns
|
||||||
* "%any%" any token
|
* "%any%" any token
|
||||||
* "%var%" any token which is a name or type e.g. "hello" or "int"
|
* "%var%" any token which is a name or type e.g. "hello" or "int"
|
||||||
* "%num%" Any numeric token, e.g. "23"
|
* "%num%" Any numeric token, e.g. "23"
|
||||||
* "%str%" Any token starting with "-character (C-string).
|
* "%str%" Any token starting with "-character (C-string).
|
||||||
* "%var1%" Match with parameter varname1
|
* "%var1%" Match with parameter varname1
|
||||||
* "%var2%" Match with parameter varname2
|
* "%var2%" Match with parameter varname2
|
||||||
* "%varid%" Match with parameter varid
|
* "%varid%" Match with parameter varid
|
||||||
* "[abc]" Any of the characters 'a' or 'b' or 'c'
|
* "[abc]" Any of the characters 'a' or 'b' or 'c'
|
||||||
* "int|void|char" Any of the strings, int, void or char
|
* "int|void|char" Any of the strings, int, void or char
|
||||||
* "int|void|char|" Any of the strings, int, void or char or empty string
|
* "int|void|char|" Any of the strings, int, void or char or empty string
|
||||||
* "!!else" No tokens or any token that is not "else".
|
* "!!else" No tokens or any token that is not "else".
|
||||||
* "someRandomText" If token contains "someRandomText".
|
* "someRandomText" If token contains "someRandomText".
|
||||||
*
|
*
|
||||||
* The patterns can be also combined to compare to multiple tokens at once
|
* The patterns can be also combined to compare to multiple tokens at once
|
||||||
* by separating tokens with a space, e.g.
|
* by separating tokens with a space, e.g.
|
||||||
* ") const|void {" will return true if first token is ')' next token is either
|
* ") const|void {" will return true if first token is ')' next token is either
|
||||||
* "const" or "void" and token after that is '{'. If even one of the tokens does not
|
* "const" or "void" and token after that is '{'. If even one of the tokens does not
|
||||||
* match its pattern, false is returned.
|
* match its pattern, false is returned.
|
||||||
*
|
*
|
||||||
* @param tok List of tokens to be compared to the pattern
|
* @param tok List of tokens to be compared to the pattern
|
||||||
* @param pattern The pattern where tokens are compared, e.g. "const"
|
* @param pattern The pattern where tokens are compared, e.g. "const"
|
||||||
* or ") const|volatile| {".
|
* or ") const|volatile| {".
|
||||||
* @param varname1 Used with pattern "%var1%" and "%var2%"
|
* @param varname1 Used with pattern "%var1%" and "%var2%"
|
||||||
* @param varname2 Used with pattern "%var1%" and "%var2%"
|
* @param varname2 Used with pattern "%var1%" and "%var2%"
|
||||||
* @return true if given token matches with given pattern
|
* @return true if given token matches with given pattern
|
||||||
* false if given token does not match with given pattern
|
* false if given token does not match with given pattern
|
||||||
*/
|
*/
|
||||||
static bool Match(const TOKEN *tok, const char pattern[], const char *varname1[]=0, const char *varname2[]=0, unsigned int varid=0);
|
static bool Match(const TOKEN *tok, const char pattern[], const char *varname1[]=0, const char *varname2[]=0, unsigned int varid=0);
|
||||||
|
|
||||||
bool isName() const;
|
bool isName() const;
|
||||||
bool isNumber() const;
|
bool isNumber() const;
|
||||||
bool isStandardType() const;
|
bool isStandardType() const;
|
||||||
static const TOKEN *findmatch(const TOKEN *tok, const char pattern[], const char *varname1[]=0, const char *varname2[]=0);
|
static const TOKEN *findmatch(const TOKEN *tok, const char pattern[], const char *varname1[]=0, const char *varname2[]=0);
|
||||||
static const TOKEN *findtoken(const TOKEN *tok1, const char *tokenstr[]);
|
static const TOKEN *findtoken(const TOKEN *tok1, const char *tokenstr[]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Needle is build from multiple alternatives. If one of
|
* Needle is build from multiple alternatives. If one of
|
||||||
* them is equal to haystack, return value is 1. If there
|
* them is equal to haystack, return value is 1. If there
|
||||||
* are no matches, but one alternative to needle is empty
|
* are no matches, but one alternative to needle is empty
|
||||||
* string, return value is 0. If needle was not found, return
|
* string, return value is 0. If needle was not found, return
|
||||||
* value is -1.
|
* value is -1.
|
||||||
*
|
*
|
||||||
* @param needle e.g. "one|two" or "|one|two"
|
* @param needle e.g. "one|two" or "|one|two"
|
||||||
* @param haystack e.g. "one", "two" or "invalid"
|
* @param haystack e.g. "one", "two" or "invalid"
|
||||||
* @return 1 if needle is found from the haystack
|
* @return 1 if needle is found from the haystack
|
||||||
* 0 if needle was empty string
|
* 0 if needle was empty string
|
||||||
* -1 if needle was not found
|
* -1 if needle was not found
|
||||||
*/
|
*/
|
||||||
static int multiCompare( const char *needle, const char *haystack );
|
static int multiCompare( const char *needle, const char *haystack );
|
||||||
|
|
||||||
|
|
||||||
unsigned int linenr() const;
|
unsigned int linenr() const;
|
||||||
void linenr( unsigned int linenr );
|
void linenr( unsigned int linenr );
|
||||||
|
|
||||||
unsigned int fileIndex() const;
|
unsigned int fileIndex() const;
|
||||||
void fileIndex( unsigned int fileIndex );
|
void fileIndex( unsigned int fileIndex );
|
||||||
|
|
||||||
TOKEN *next() const;
|
TOKEN *next() const;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete tokens between begin and end. E.g. if begin = 1
|
* Delete tokens between begin and end. E.g. if begin = 1
|
||||||
* and end = 5, tokens 2,3 and 4 would be erased.
|
* and end = 5, tokens 2,3 and 4 would be erased.
|
||||||
*
|
*
|
||||||
* @param begin Tokens after this will be erased.
|
* @param begin Tokens after this will be erased.
|
||||||
* @param end Tokens before this will be erased.
|
* @param end Tokens before this will be erased.
|
||||||
*/
|
*/
|
||||||
static void eraseTokens( TOKEN *begin, const TOKEN *end );
|
static void eraseTokens( TOKEN *begin, const TOKEN *end );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert new token after this token. This function will handle
|
* Insert new token after this token. This function will handle
|
||||||
* relations between next and previous token also.
|
* relations between next and previous token also.
|
||||||
* @param str String for the new token.
|
* @param str String for the new token.
|
||||||
*/
|
*/
|
||||||
void insertToken( const char str[] );
|
void insertToken( const char str[] );
|
||||||
|
|
||||||
TOKEN *previous() const;
|
TOKEN *previous() const;
|
||||||
|
|
||||||
|
|
||||||
unsigned int varId() const;
|
unsigned int varId() const;
|
||||||
void varId( unsigned int id );
|
void varId( unsigned int id );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For debugging purposes, prints token and all tokens
|
* For debugging purposes, prints token and all tokens
|
||||||
* followed by it.
|
* followed by it.
|
||||||
* @param title Title for the printout or use default parameter or 0
|
* @param title Title for the printout or use default parameter or 0
|
||||||
* for no title.
|
* for no title.
|
||||||
*/
|
*/
|
||||||
void printOut( const char *title = 0 ) const;
|
void printOut( const char *title = 0 ) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void next( TOKEN *next );
|
void next( TOKEN *next );
|
||||||
void previous( TOKEN *previous );
|
void previous( TOKEN *previous );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if pattern is e.g. "!!else".
|
* Return true if pattern is e.g. "!!else".
|
||||||
* See Match() for more info.
|
* See Match() for more info.
|
||||||
*
|
*
|
||||||
* @param pattern Pattern to match, e.g. "if ; !!else"
|
* @param pattern Pattern to match, e.g. "if ; !!else"
|
||||||
* @return true if pattern starts with "!!" and contains 3
|
* @return true if pattern starts with "!!" and contains 3
|
||||||
* or more characters.
|
* or more characters.
|
||||||
*/
|
*/
|
||||||
static bool isNotPattern( const char *pattern );
|
static bool isNotPattern( const char *pattern );
|
||||||
|
|
||||||
std::string _str;
|
std::string _str;
|
||||||
char * _cstr;
|
char * _cstr;
|
||||||
bool _isName;
|
bool _isName;
|
||||||
bool _isNumber;
|
bool _isNumber;
|
||||||
unsigned int _varId;
|
unsigned int _varId;
|
||||||
TOKEN *_next;
|
TOKEN *_next;
|
||||||
TOKEN *_previous;
|
TOKEN *_previous;
|
||||||
unsigned int _fileIndex;
|
unsigned int _fileIndex;
|
||||||
unsigned int _linenr;
|
unsigned int _linenr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TOKEN_H
|
#endif // TOKEN_H
|
||||||
|
|
2838
tokenize.cpp
2838
tokenize.cpp
File diff suppressed because it is too large
Load Diff
278
tokenize.h
278
tokenize.h
|
@ -1,139 +1,139 @@
|
||||||
/*
|
/*
|
||||||
* c++check - c/c++ syntax checking
|
* c++check - c/c++ syntax checking
|
||||||
* Copyright (C) 2007 Daniel Marjamäki
|
* Copyright (C) 2007 Daniel Marjamäki
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/
|
* along with this program. If not, see <http://www.gnu.org/licenses/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#ifndef tokenizeH
|
#ifndef tokenizeH
|
||||||
#define tokenizeH
|
#define tokenizeH
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "errorlogger.h"
|
#include "errorlogger.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
|
|
||||||
class Tokenizer
|
class Tokenizer
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// Deallocate lists..
|
// Deallocate lists..
|
||||||
void DeallocateTokens();
|
void DeallocateTokens();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function for "tokenize". This recursively parses into included header files.
|
* Helper function for "tokenize". This recursively parses into included header files.
|
||||||
*/
|
*/
|
||||||
void tokenizeCode(std::istream &code, const unsigned int FileIndex=0);
|
void tokenizeCode(std::istream &code, const unsigned int FileIndex=0);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Tokenizer();
|
Tokenizer();
|
||||||
~Tokenizer();
|
~Tokenizer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tokenize code
|
* Tokenize code
|
||||||
* @param code input stream for code
|
* @param code input stream for code
|
||||||
* @param FileName The filename
|
* @param FileName The filename
|
||||||
*/
|
*/
|
||||||
void tokenize(std::istream &code, const char FileName[]);
|
void tokenize(std::istream &code, const char FileName[]);
|
||||||
|
|
||||||
/** Set variable id */
|
/** Set variable id */
|
||||||
void setVarId();
|
void setVarId();
|
||||||
|
|
||||||
/** Simplify tokenlist */
|
/** Simplify tokenlist */
|
||||||
void simplifyTokenList();
|
void simplifyTokenList();
|
||||||
|
|
||||||
|
|
||||||
// Helper functions for handling the tokens list..
|
// Helper functions for handling the tokens list..
|
||||||
|
|
||||||
static void deleteTokens(TOKEN *tok);
|
static void deleteTokens(TOKEN *tok);
|
||||||
static const char *getParameterName( const TOKEN *ftok, int par );
|
static const char *getParameterName( const TOKEN *ftok, int par );
|
||||||
|
|
||||||
static bool SameFileName( const char fname1[], const char fname2[] );
|
static bool SameFileName( const char fname1[], const char fname2[] );
|
||||||
|
|
||||||
|
|
||||||
std::string fileLine( const TOKEN *tok ) const;
|
std::string fileLine( const TOKEN *tok ) const;
|
||||||
|
|
||||||
// Return size.
|
// Return size.
|
||||||
int SizeOfType(const char type[]) const;
|
int SizeOfType(const char type[]) const;
|
||||||
|
|
||||||
void initTokens();
|
void initTokens();
|
||||||
|
|
||||||
const std::vector<std::string> *getFiles() const;
|
const std::vector<std::string> *getFiles() const;
|
||||||
|
|
||||||
void fillFunctionList();
|
void fillFunctionList();
|
||||||
const TOKEN *GetFunctionTokenByName( const char funcname[] ) const;
|
const TOKEN *GetFunctionTokenByName( const char funcname[] ) const;
|
||||||
const TOKEN *tokens() const;
|
const TOKEN *tokens() const;
|
||||||
|
|
||||||
|
|
||||||
#ifndef UNIT_TESTING
|
#ifndef UNIT_TESTING
|
||||||
private:
|
private:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct DefineSymbol
|
struct DefineSymbol
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
char *value;
|
char *value;
|
||||||
struct DefineSymbol *next;
|
struct DefineSymbol *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Define(const char Name[], const char Value[]);
|
void Define(const char Name[], const char Value[]);
|
||||||
|
|
||||||
void addtoken(const char str[], const unsigned int lineno, const unsigned int fileno);
|
void addtoken(const char str[], const unsigned int lineno, const unsigned int fileno);
|
||||||
|
|
||||||
/** Simplify conditions
|
/** Simplify conditions
|
||||||
* @return true if something is modified
|
* @return true if something is modified
|
||||||
* false if nothing is done.
|
* false if nothing is done.
|
||||||
*/
|
*/
|
||||||
bool simplifyConditions();
|
bool simplifyConditions();
|
||||||
|
|
||||||
/** Simplify casts
|
/** Simplify casts
|
||||||
* @return true if something is modified
|
* @return true if something is modified
|
||||||
* false if nothing is done.
|
* false if nothing is done.
|
||||||
*/
|
*/
|
||||||
bool simplifyCasts();
|
bool simplifyCasts();
|
||||||
|
|
||||||
/** Simplify function calls - constant return value
|
/** Simplify function calls - constant return value
|
||||||
* @return true if something is modified
|
* @return true if something is modified
|
||||||
* false if nothing is done.
|
* false if nothing is done.
|
||||||
*/
|
*/
|
||||||
bool simplifyFunctionReturn();
|
bool simplifyFunctionReturn();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simplify function that replaces a variable with its value in cases
|
* A simplify function that replaces a variable with its value in cases
|
||||||
* when the value is known. e.g. "x=10; if(x)" => "x=10;if(10)"
|
* when the value is known. e.g. "x=10; if(x)" => "x=10;if(10)"
|
||||||
*
|
*
|
||||||
* @param token The token list to check and modify.
|
* @param token The token list to check and modify.
|
||||||
* @return true if modifications to token-list are done.
|
* @return true if modifications to token-list are done.
|
||||||
* false if no modifications are done.
|
* false if no modifications are done.
|
||||||
*/
|
*/
|
||||||
bool simplifyKnownVariables();
|
bool simplifyKnownVariables();
|
||||||
|
|
||||||
TOKEN *_gettok(TOKEN *tok, int index);
|
TOKEN *_gettok(TOKEN *tok, int index);
|
||||||
|
|
||||||
void InsertTokens(TOKEN *dest, TOKEN *src, unsigned int n);
|
void InsertTokens(TOKEN *dest, TOKEN *src, unsigned int n);
|
||||||
|
|
||||||
TOKEN *_tokensBack;
|
TOKEN *_tokensBack;
|
||||||
std::map<std::string, unsigned int> _typeSize;
|
std::map<std::string, unsigned int> _typeSize;
|
||||||
std::vector<const TOKEN *> _functionList;
|
std::vector<const TOKEN *> _functionList;
|
||||||
std::vector<std::string> _files;
|
std::vector<std::string> _files;
|
||||||
struct DefineSymbol * _dsymlist;
|
struct DefineSymbol * _dsymlist;
|
||||||
TOKEN *_tokens;
|
TOKEN *_tokens;
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue