51 std::string name = funcName;
52 const auto pos = name.find(
'<');
53 if (pos > 0 && pos != std::string::npos)
64 const char *
const FileName = tokenizer.
list.
getFiles().front().c_str();
73 if (!func || !func->
token)
92 const std::string& fileName = tokenizer.
list.
file(func->
token);
99 else if (usage.
filename != fileName) {
107 const Token *lambdaEndToken =
nullptr;
110 if (tok == lambdaEndToken)
111 lambdaEndToken =
nullptr;
112 else if (!lambdaEndToken && tok->
str() ==
"[")
124 while ((scope || start) && markupVarToken) {
134 else if (markupVarToken->
next()->
str() ==
"(") {
143 markupVarToken = markupVarToken->
next();
150 while (propToken && propToken->
str() !=
")") {
152 const Token* nextPropToken = propToken->
next();
153 const std::string& value = nextPropToken->
str();
161 const std::string& value = prevPropToken->
str();
167 propToken = propToken->
next();
171 if (doMarkup && settings.
library.
isimporter(FileName, tok->str()) && tok->next()) {
173 if (propToken->
next()) {
174 propToken = propToken->
next();
175 while (propToken && propToken->
str() !=
")") {
176 const std::string& value = propToken->
str();
177 if (!value.empty()) {
182 propToken = propToken->
next();
194 if (funcToken->
str()==
",") {
195 if (++index == argIndex)
199 value += funcToken->
str();
200 funcToken = funcToken->
next();
202 if (index == argIndex) {
203 value = value.substr(1, value.length() - 2);
210 const Token *funcname =
nullptr;
213 funcname =
Token::Match(tok,
"%name% (") ? tok :
nullptr;
214 else if ((lambdaEndToken || tok->
scope()->isExecutable()) &&
Token::Match(tok,
"%name% (")) {
218 }
else if (
Token::Match(tok,
"< %name%") && tok->link()) {
219 funcname = tok->
next();
221 funcname = funcname->
tokAt(2);
222 }
else if (tok->scope()->type != Scope::ScopeType::eEnum && (
Token::Match(tok,
"[;{}.,()[=+-/|!?:]") ||
Token::Match(tok,
"return|throw"))) {
223 funcname = tok->
next();
224 if (funcname && funcname->
str() ==
"&")
225 funcname = funcname->
next();
226 if (funcname && funcname->
str() ==
"::")
227 funcname = funcname->
next();
229 funcname = funcname->
tokAt(2);
241 if (ftok->
str() ==
"<")
283 const std::string operatorPrefix =
"operator";
284 if (funcName.compare(0, operatorPrefix.length(), operatorPrefix) != 0) {
289 if (funcName.length() == operatorPrefix.length()) {
293 const char firstOperatorChar = funcName[operatorPrefix.length()];
294 if (firstOperatorChar ==
'_') {
298 if (!std::isalnum(firstOperatorChar)) {
302 const std::vector<std::string> additionalOperators = {
303 "new",
"new[]",
"delete",
"delete[]"
307 return std::find(additionalOperators.cbegin(), additionalOperators.cend(), funcName.substr(operatorPrefix.length())) != additionalOperators.cend();
310 #define logChecker(id) \
312 const ErrorMessage errmsg({}, nullptr, Severity::internal, "logChecker", (id), CWE(0U), Certainty::normal); \
313 errorLogger.reportErr(errmsg); \
320 using ErrorParams = std::tuple<std::string, unsigned int, unsigned int, std::string>;
321 std::vector<ErrorParams> errors;
323 for (std::unordered_map<std::string, FunctionUsage>::const_iterator it =
mFunctions.cbegin(); it !=
mFunctions.cend(); ++it) {
332 std::string filename;
346 std::sort(errors.begin(), errors.end());
347 for (
const auto& e : errors)
348 unusedFunctionError(errorLogger, std::get<0>(e), std::get<1>(e), std::get<2>(e), std::get<3>(e));
349 return !errors.empty();
353 const std::string &filename,
unsigned int fileIndex,
unsigned int lineNumber,
354 const std::string &funcname)
356 std::list<ErrorMessage::FileLocation> locationList;
357 if (!filename.empty()) {
358 locationList.emplace_back(filename, lineNumber, 0);
359 locationList.back().fileIndex = fileIndex;
367 : functionName(f->name()), lineNumber(f->token->linenr())
372 std::ostringstream ret;
374 ret <<
" <functiondecl"
376 <<
" lineNumber=\"" << functionDecl.lineNumber <<
"\"/>\n";
386 Location() : lineNumber(0) {}
387 Location(std::string f,
const int l) : fileName(std::move(f)), lineNumber(l) {}
388 std::string fileName;
395 std::map<std::string, Location> decls;
396 std::set<std::string> calls;
398 const std::string filesTxt(buildDir +
"/files.txt");
399 std::ifstream fin(filesTxt.c_str());
400 std::string filesTxtLine;
401 while (std::getline(fin, filesTxtLine)) {
402 const std::string::size_type firstColon = filesTxtLine.find(
':');
403 if (firstColon == std::string::npos)
405 const std::string::size_type secondColon = filesTxtLine.find(
':', firstColon+1);
406 if (secondColon == std::string::npos)
408 const std::string xmlfile = buildDir +
'/' + filesTxtLine.substr(0,firstColon);
409 const std::string sourcefile = filesTxtLine.substr(secondColon+1);
411 tinyxml2::XMLDocument doc;
412 const tinyxml2::XMLError
error = doc.LoadFile(xmlfile.c_str());
413 if (
error != tinyxml2::XML_SUCCESS)
416 const tinyxml2::XMLElement *
const rootNode = doc.FirstChildElement();
417 if (rootNode ==
nullptr)
420 for (
const tinyxml2::XMLElement *e = rootNode->FirstChildElement(); e; e = e->NextSiblingElement()) {
421 if (std::strcmp(e->Name(),
"FileInfo") != 0)
423 const char *checkattr = e->Attribute(
"check");
424 if (checkattr ==
nullptr || std::strcmp(checkattr,
"CheckUnusedFunctions") != 0)
426 for (
const tinyxml2::XMLElement *e2 = e->FirstChildElement(); e2; e2 = e2->NextSiblingElement()) {
427 const char* functionName = e2->Attribute(
"functionName");
428 if (functionName ==
nullptr)
430 if (std::strcmp(e2->Name(),
"functioncall") == 0) {
431 calls.insert(functionName);
434 if (std::strcmp(e2->Name(),
"functiondecl") == 0) {
435 const char* lineNumber = e2->Attribute(
"lineNumber");
438 decls[functionName] = Location(sourcefile, strToInt<int>(lineNumber));
445 for (std::map<std::string, Location>::const_iterator decl = decls.cbegin(); decl != decls.cend(); ++decl) {
452 const Location &loc = decl->second;
460 for (
const auto& entry :
check.mFunctions)
466 usage.
fileIndex = entry.second.fileIndex;
468 usage.
filename = entry.second.filename;
const Token * findLambdaEndToken(const Token *first)
find lambda function end token
static bool isOperatorFunction(const std::string &funcName)
static const CWE CWE561(561U)
static std::string stripTemplateParameters(const std::string &funcName)
FunctionDecl(const Function *f)
Check for functions never called.
std::unordered_map< std::string, FunctionUsage > mFunctions
void parseTokens(const Tokenizer &tokenizer, const Settings &settings)
static void unusedFunctionError(ErrorLogger &errorLogger, const std::string &filename, unsigned int fileIndex, unsigned int lineNumber, const std::string &funcname)
static void analyseWholeProgram(const Settings &settings, ErrorLogger &errorLogger, const std::string &buildDir)
std::list< FunctionDecl > mFunctionDecl
void updateFunctionData(const CheckUnusedFunctions &check)
std::string analyzerInfo() const
bool check(const Settings &settings, ErrorLogger &errorLogger) const
std::set< std::string > mFunctionCalls
This is an interface, which the class responsible of error logging should implement.
virtual void reportErr(const ErrorMessage &msg)=0
Information about found errors and warnings is directed here.
static std::string toxml(const std::string &str)
Convert XML-sensitive characters into XML entities.
Wrapper for error messages, provided by reportErr()
const std::string & name() const
bool isAttributeConstructor() const
Type type
constructor, destructor, ...
const Token * token
function name token in implementation
bool isAttributeDestructor() const
bool isexecutableblock(const std::string &file, const std::string &token) const
bool isexportedsuffix(const std::string &prefix, const std::string &token) const
bool isexporter(const std::string &prefix) const
const std::string & blockstart(const std::string &file) const
bool isentrypoint(const std::string &func) const
const std::string & blockend(const std::string &file) const
bool isreflection(const std::string &token) const
bool iskeyword(const std::string &file, const std::string &keyword) const
bool markupFile(const std::string &path) const
bool isimporter(const std::string &file, const std::string &importer) const
bool isexportedprefix(const std::string &prefix, const std::string &token) const
int blockstartoffset(const std::string &file) const
int reflectionArgument(const std::string &token) const
Function * function
function info for this function
This is just a container for general settings so that we don't need to pass individual values to func...
std::vector< const Scope * > functionScopes
Fast access to function scopes.
const std::string & file(const Token *tok) const
get filename for given token
const std::vector< std::string > & getFiles() const
Get filenames (the sourcefile + the files it include).
The token list that the TokenList generates is a linked-list of this class.
static bool Match(const Token *tok, const char pattern[], nonneg int varid=0)
Match given token (or list of tokens) to a pattern list.
const Token * tokAt(int index) const
void scope(const Scope *s)
Associate this token with given scope.
void link(Token *linkToToken)
Create link to given token.
const Token * linkAt(int index) const
nonneg int linenr() const
bool isStandardType() const
static bool simpleMatch(const Token *tok, const char(&pattern)[count])
Match given token (or list of tokens) to a pattern list.
nonneg int fileIndex() const
The main purpose is to tokenize the source code.
const Token * tokens() const
TokenList list
Token list: stores all tokens.
const SymbolDatabase * getSymbolDatabase() const
static const std::string emptyString
@ error
Programming error.