* Fixed #8683 (Using deleted token with multiple template instantiations.) * Fixed #8321 (heap use after free: templatesimplifier) * Add a flag to Token indicating that it has a pointer to it. * Run dmake * Fix one source of list pointers to deleted tokens. Refactor TemplateSimplifier class to get access to template lists. Remove many function parameters now that they are class variables. Fix one source of list pointers to deleted tokens. Add tests with no output to catch crashes. * Run dmake again. * Make 2 more functions private. * Make requested changes. * Missed one change request. * Use TokenList rather than Tokenizer. * Move TokenAndName constructor to cpp file so token.h is not needed in header file.
242 lines
8.3 KiB
C++
242 lines
8.3 KiB
C++
/*
|
|
* Cppcheck - A tool for static C/C++ code analysis
|
|
* Copyright (C) 2007-2017 Cppcheck team.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
#ifndef templatesimplifierH
|
|
#define templatesimplifierH
|
|
//---------------------------------------------------------------------------
|
|
|
|
#include "config.h"
|
|
|
|
#include <ctime>
|
|
#include <list>
|
|
#include <set>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
class ErrorLogger;
|
|
class Settings;
|
|
class Token;
|
|
class Tokenizer;
|
|
class TokenList;
|
|
|
|
/// @addtogroup Core
|
|
/// @{
|
|
|
|
/** @brief Simplify templates from the preprocessed and partially simplified code. */
|
|
class CPPCHECKLIB TemplateSimplifier {
|
|
public:
|
|
TemplateSimplifier(TokenList &tokenlist, const Settings *settings, ErrorLogger *errorLogger);
|
|
~TemplateSimplifier();
|
|
|
|
/**
|
|
* Used after simplifyTemplates to perform a little cleanup.
|
|
* Sometimes the simplifyTemplates isn't fully successful and then
|
|
* there are function calls etc with "wrong" syntax.
|
|
*/
|
|
void cleanupAfterSimplify();
|
|
|
|
/**
|
|
*/
|
|
void checkComplicatedSyntaxErrorsInTemplates();
|
|
|
|
/**
|
|
* is the token pointing at a template parameters block
|
|
* < int , 3 > => yes
|
|
* \param tok start token that must point at "<"
|
|
* \return number of parameters (invalid parameters => 0)
|
|
*/
|
|
static unsigned int templateParameters(const Token *tok);
|
|
|
|
/**
|
|
* Token and its full scopename
|
|
*/
|
|
struct TokenAndName {
|
|
TokenAndName(Token *tok, const std::string &s, const std::string &n);
|
|
Token *token;
|
|
std::string scope;
|
|
std::string name;
|
|
};
|
|
|
|
/**
|
|
* Match template declaration/instantiation
|
|
* @param instance template instantiation
|
|
* @param numberOfArguments number of template arguments
|
|
* @param patternAfter pattern that must match the tokens after the ">"
|
|
* @return match => true
|
|
*/
|
|
static bool instantiateMatch(const Token *instance, const std::size_t numberOfArguments, const char patternAfter[]);
|
|
|
|
/**
|
|
* Match template declaration/instantiation
|
|
* @param tok The ">" token e.g. before "class"
|
|
* @return -1 to bail out or positive integer to identity the position
|
|
* of the template name.
|
|
*/
|
|
static int getTemplateNamePosition(const Token *tok);
|
|
|
|
/**
|
|
* Simplify templates
|
|
* @param maxtime time when the simplification should be stopped
|
|
* @param codeWithTemplates output parameter that is set if code contains templates
|
|
*/
|
|
void simplifyTemplates(
|
|
const std::time_t maxtime,
|
|
bool &codeWithTemplates);
|
|
|
|
/**
|
|
* Simplify constant calculations such as "1+2" => "3"
|
|
* @param tok start token
|
|
* @return true if modifications to token-list are done.
|
|
* false if no modifications are done.
|
|
*/
|
|
bool simplifyNumericCalculations(Token *tok);
|
|
|
|
/**
|
|
* Simplify constant calculations such as "1+2" => "3".
|
|
* This also performs simple cleanup of parentheses etc.
|
|
* @return true if modifications to token-list are done.
|
|
* false if no modifications are done.
|
|
*/
|
|
bool simplifyCalculations();
|
|
|
|
private:
|
|
/**
|
|
* Get template declarations
|
|
* @return list of template declarations
|
|
*/
|
|
std::list<TokenAndName> getTemplateDeclarations(bool &codeWithTemplates);
|
|
|
|
/**
|
|
* Get template instantiations
|
|
*/
|
|
void getTemplateInstantiations();
|
|
|
|
/**
|
|
* simplify template instantiations (use default argument values)
|
|
*/
|
|
void useDefaultArgumentValues();
|
|
|
|
/**
|
|
* simplify template aliases
|
|
*/
|
|
void simplifyTemplateAliases();
|
|
|
|
/**
|
|
* Simplify templates : expand all instantiations for a template
|
|
* @todo It seems that inner templates should be instantiated recursively
|
|
* @param templateDeclaration template declaration
|
|
* @param specializations template specializations (list each template name token)
|
|
* @param maxtime time when the simplification will stop
|
|
* @param expandedtemplates all templates that has been expanded so far. The full names are stored.
|
|
* @return true if the template was instantiated
|
|
*/
|
|
bool simplifyTemplateInstantiations(
|
|
const TokenAndName &templateDeclaration,
|
|
const std::list<const Token *> &specializations,
|
|
const std::time_t maxtime,
|
|
std::set<std::string> &expandedtemplates);
|
|
|
|
/**
|
|
* Expand a template. Create "expanded" class/function at end of tokenlist.
|
|
* @param fullName Full name of template
|
|
* @param typeParametersInDeclaration The type parameters of the template
|
|
* @param newName New name of class/function.
|
|
* @param typesUsedInTemplateInstantiation Type parameters in instantiation
|
|
*/
|
|
void expandTemplate(
|
|
const Token *templateDeclarationToken,
|
|
const std::string &fullName,
|
|
const std::vector<const Token *> &typeParametersInDeclaration,
|
|
const std::string &newName,
|
|
const std::vector<const Token *> &typesUsedInTemplateInstantiation);
|
|
|
|
/**
|
|
* Replace all matching template usages 'Foo < int >' => 'Foo<int>'
|
|
* @param instantiationToken Template instantiation token
|
|
* @param templateName full template name with scope info
|
|
* @param typeStringsUsedInTemplateInstantiation template parameters. list of token strings.
|
|
* @param newName The new type name
|
|
* @param typesUsedInTemplateInstantiation template instantiation parameters
|
|
*/
|
|
void replaceTemplateUsage(Token *const instantiationToken,
|
|
const std::string &templateName,
|
|
const std::list<std::string> &typeStringsUsedInTemplateInstantiation,
|
|
const std::string &newName,
|
|
const std::vector<const Token *> &typesUsedInTemplateInstantiation);
|
|
|
|
/**
|
|
* Expand specialized templates : "template<>.."
|
|
* @return names of expanded templates
|
|
*/
|
|
std::set<std::string> expandSpecialized();
|
|
|
|
/**
|
|
* @brief TemplateParametersInDeclaration
|
|
* @param tok template < typename T, typename S >
|
|
* ^ tok
|
|
* @param typeParametersInDeclaration template < typename T, typename S >
|
|
* ^ [0] ^ [1]
|
|
* @return template < typename T, typename S >
|
|
* ^ return
|
|
*/
|
|
const Token * getTemplateParametersInDeclaration(
|
|
const Token * tok,
|
|
std::vector<const Token *> & typeParametersInDeclaration);
|
|
|
|
/**
|
|
* Remove a specific "template < ..." template class/function
|
|
*/
|
|
bool removeTemplate(Token *tok);
|
|
|
|
/** Syntax error */
|
|
static void syntaxError(const Token *tok);
|
|
|
|
bool matchSpecialization(
|
|
const Token *templateDeclarationNameToken,
|
|
const Token *templateInstantiationNameToken,
|
|
const std::list<const Token *> & specializations);
|
|
|
|
/*
|
|
* Same as Token::eraseTokens() but tries to fix up lists with pointers to the deleted tokens.
|
|
* @param begin Tokens after this will be erased.
|
|
* @param end Tokens before this will be erased.
|
|
*/
|
|
void eraseTokens(Token *begin, const Token *end);
|
|
|
|
/**
|
|
* Delete specified token without invalidating pointer to following token.
|
|
* tok will be invalidated.
|
|
* @param tok token to delete
|
|
*/
|
|
void deleteToken(Token *tok);
|
|
|
|
TokenList &mTokenList;
|
|
const Settings *mSettings;
|
|
ErrorLogger *mErrorLogger;
|
|
|
|
std::list<TokenAndName> mTemplateDeclarations;
|
|
std::list<TokenAndName> mTemplateInstantiations;
|
|
std::list<TokenAndName> mInstantiatedTemplates;
|
|
};
|
|
|
|
/// @}
|
|
//---------------------------------------------------------------------------
|
|
#endif // templatesimplifierH
|