2012-01-01 21:55:05 +01:00
|
|
|
/*
|
|
|
|
* Cppcheck - A tool for static C/C++ code analysis
|
2018-10-13 18:20:31 +02:00
|
|
|
* Copyright (C) 2007-2018 Cppcheck team.
|
2012-01-01 21:55:05 +01:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2017-05-27 04:33:47 +02:00
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <ctime>
|
2012-01-02 22:05:27 +01:00
|
|
|
#include <list>
|
2017-05-27 04:33:47 +02:00
|
|
|
#include <set>
|
2012-01-02 21:53:13 +01:00
|
|
|
#include <string>
|
2012-01-03 22:35:06 +01:00
|
|
|
#include <vector>
|
2012-01-01 21:55:05 +01:00
|
|
|
|
2012-05-06 10:38:55 +02:00
|
|
|
class ErrorLogger;
|
2012-01-09 20:33:11 +01:00
|
|
|
class Settings;
|
2017-05-27 04:33:47 +02:00
|
|
|
class Token;
|
2018-09-01 11:26:10 +02:00
|
|
|
class Tokenizer;
|
2017-05-27 04:33:47 +02:00
|
|
|
class TokenList;
|
2012-01-01 21:55:05 +01:00
|
|
|
|
|
|
|
/// @addtogroup Core
|
|
|
|
/// @{
|
|
|
|
|
|
|
|
/** @brief Simplify templates from the preprocessed and partially simplified code. */
|
2012-06-10 14:19:09 +02:00
|
|
|
class CPPCHECKLIB TemplateSimplifier {
|
2012-04-23 20:45:36 +02:00
|
|
|
public:
|
2018-09-01 11:26:10 +02:00
|
|
|
TemplateSimplifier(TokenList &tokenlist, const Settings *settings, ErrorLogger *errorLogger);
|
|
|
|
~TemplateSimplifier();
|
2012-01-01 21:55:05 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
2018-09-01 11:26:10 +02:00
|
|
|
void cleanupAfterSimplify();
|
2012-01-02 21:37:32 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
*/
|
2018-09-01 11:26:10 +02:00
|
|
|
void checkComplicatedSyntaxErrorsInTemplates();
|
2012-01-02 21:43:38 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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);
|
2012-01-02 21:46:43 +01:00
|
|
|
|
2017-12-26 10:55:18 +01:00
|
|
|
/**
|
|
|
|
* Token and its full scopename
|
|
|
|
*/
|
|
|
|
struct TokenAndName {
|
2018-09-01 11:26:10 +02:00
|
|
|
TokenAndName(Token *tok, const std::string &s, const std::string &n);
|
2018-09-14 14:16:34 +02:00
|
|
|
bool operator == (const TokenAndName & rhs) const {
|
|
|
|
return token == rhs.token && scope == rhs.scope && name == rhs.name;
|
|
|
|
}
|
2017-12-26 10:55:18 +01:00
|
|
|
Token *token;
|
2017-12-30 09:00:19 +01:00
|
|
|
std::string scope;
|
2017-12-26 10:55:18 +01:00
|
|
|
std::string name;
|
|
|
|
};
|
|
|
|
|
2012-01-02 22:05:27 +01:00
|
|
|
/**
|
2018-09-01 11:26:10 +02:00
|
|
|
* 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
|
2012-01-02 22:05:27 +01:00
|
|
|
*/
|
2018-09-01 11:26:10 +02:00
|
|
|
static bool instantiateMatch(const Token *instance, const std::size_t numberOfArguments, const char patternAfter[]);
|
2012-01-02 22:05:27 +01:00
|
|
|
|
|
|
|
/**
|
2018-09-01 11:26:10 +02:00
|
|
|
* Match template declaration/instantiation
|
|
|
|
* @param tok The ">" token e.g. before "class"
|
2018-10-24 14:38:59 +02:00
|
|
|
* @param forward declaration or forward declaration
|
2018-09-01 11:26:10 +02:00
|
|
|
* @return -1 to bail out or positive integer to identity the position
|
|
|
|
* of the template name.
|
2012-01-02 22:05:27 +01:00
|
|
|
*/
|
2018-10-24 14:38:59 +02:00
|
|
|
static int getTemplateNamePosition(const Token *tok, bool forward = false);
|
2012-01-03 22:35:06 +01:00
|
|
|
|
|
|
|
/**
|
2018-09-01 11:26:10 +02:00
|
|
|
* Simplify templates
|
|
|
|
* @param maxtime time when the simplification should be stopped
|
|
|
|
* @param codeWithTemplates output parameter that is set if code contains templates
|
2012-01-03 22:35:06 +01:00
|
|
|
*/
|
2018-09-01 11:26:10 +02:00
|
|
|
void simplifyTemplates(
|
|
|
|
const std::time_t maxtime,
|
|
|
|
bool &codeWithTemplates);
|
2012-01-03 22:35:06 +01:00
|
|
|
|
2017-12-29 22:47:07 +01:00
|
|
|
/**
|
2018-09-01 11:26:10 +02:00
|
|
|
* 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.
|
2017-12-29 22:47:07 +01:00
|
|
|
*/
|
2018-10-14 16:57:07 +02:00
|
|
|
static bool simplifyNumericCalculations(Token *tok);
|
2017-12-29 22:47:07 +01:00
|
|
|
|
2012-01-03 22:35:06 +01:00
|
|
|
/**
|
2018-09-01 11:26:10 +02:00
|
|
|
* 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.
|
2012-01-03 22:35:06 +01:00
|
|
|
*/
|
2018-09-01 11:26:10 +02:00
|
|
|
bool simplifyCalculations();
|
2012-01-03 22:35:06 +01:00
|
|
|
|
2018-09-01 11:26:10 +02:00
|
|
|
private:
|
2012-01-03 22:49:50 +01:00
|
|
|
/**
|
2018-09-01 11:26:10 +02:00
|
|
|
* Get template declarations
|
2018-11-10 16:41:14 +01:00
|
|
|
* @return true if code has templates.
|
2012-01-03 22:49:50 +01:00
|
|
|
*/
|
2018-11-10 16:41:14 +01:00
|
|
|
bool getTemplateDeclarations();
|
2012-01-05 21:45:19 +01:00
|
|
|
|
2017-12-26 22:34:39 +01:00
|
|
|
/**
|
2018-09-01 11:26:10 +02:00
|
|
|
* Get template instantiations
|
2017-12-26 22:34:39 +01:00
|
|
|
*/
|
2018-09-01 11:26:10 +02:00
|
|
|
void getTemplateInstantiations();
|
2012-01-09 20:33:11 +01:00
|
|
|
|
2018-10-24 14:38:59 +02:00
|
|
|
/**
|
|
|
|
* Fix forward declared default argument values by copying them
|
|
|
|
* when they are not present in the declaration.
|
|
|
|
*/
|
|
|
|
void fixForwardDeclaredDefaultArgumentValues();
|
|
|
|
|
2014-11-01 22:07:24 +01:00
|
|
|
/**
|
2018-09-01 11:26:10 +02:00
|
|
|
* simplify template instantiations (use default argument values)
|
2014-11-01 22:07:24 +01:00
|
|
|
*/
|
2018-09-01 11:26:10 +02:00
|
|
|
void useDefaultArgumentValues();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* simplify template aliases
|
|
|
|
*/
|
|
|
|
void simplifyTemplateAliases();
|
2014-11-01 22:07:24 +01:00
|
|
|
|
2012-01-09 20:33:11 +01:00
|
|
|
/**
|
2013-02-10 07:43:09 +01:00
|
|
|
* Simplify templates : expand all instantiations for a template
|
2012-01-09 20:33:11 +01:00
|
|
|
* @todo It seems that inner templates should be instantiated recursively
|
2017-12-26 10:55:18 +01:00
|
|
|
* @param templateDeclaration template declaration
|
2017-12-30 22:14:48 +01:00
|
|
|
* @param specializations template specializations (list each template name token)
|
2016-02-12 12:05:32 +01:00
|
|
|
* @param maxtime time when the simplification will stop
|
2012-01-09 20:33:11 +01:00
|
|
|
* @param expandedtemplates all templates that has been expanded so far. The full names are stored.
|
2012-07-29 16:01:05 +02:00
|
|
|
* @return true if the template was instantiated
|
2012-01-09 20:33:11 +01:00
|
|
|
*/
|
2018-09-01 11:26:10 +02:00
|
|
|
bool simplifyTemplateInstantiations(
|
2017-12-26 10:55:18 +01:00
|
|
|
const TokenAndName &templateDeclaration,
|
2017-12-30 22:14:48 +01:00
|
|
|
const std::list<const Token *> &specializations,
|
2016-02-12 12:05:32 +01:00
|
|
|
const std::time_t maxtime,
|
2012-01-09 20:33:11 +01:00
|
|
|
std::set<std::string> &expandedtemplates);
|
|
|
|
|
2018-11-05 19:55:21 +01:00
|
|
|
/**
|
|
|
|
* Simplify templates : add namespace to template name
|
|
|
|
* @param templateDeclaration template declaration
|
|
|
|
* @param tok place to insert namespace
|
|
|
|
*/
|
|
|
|
void addNamespace(const TokenAndName &templateDeclaration, const Token *tok);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Simplify templates : check if namespace already present
|
|
|
|
* @param templateDeclaration template declaration
|
|
|
|
* @param tok place to start looking for namespace
|
|
|
|
* @return true if namespace already present
|
|
|
|
*/
|
|
|
|
bool alreadyHasNamespace(const TokenAndName &templateDeclaration, const Token *tok) const;
|
|
|
|
|
2018-09-01 11:26:10 +02:00
|
|
|
/**
|
|
|
|
* Expand a template. Create "expanded" class/function at end of tokenlist.
|
2018-10-26 14:20:13 +02:00
|
|
|
* @param templateDeclaration Template declaration information
|
|
|
|
* @param templateDeclarationToken Template declaration token
|
|
|
|
* @param templateInstantiation Full name of template
|
2018-09-01 11:26:10 +02:00
|
|
|
* @param typeParametersInDeclaration The type parameters of the template
|
|
|
|
* @param newName New name of class/function.
|
2018-10-14 16:57:07 +02:00
|
|
|
* @param copy copy or expand in place
|
2018-09-01 11:26:10 +02:00
|
|
|
*/
|
|
|
|
void expandTemplate(
|
2018-10-26 14:20:13 +02:00
|
|
|
const TokenAndName &templateDeclaration,
|
2018-09-01 11:26:10 +02:00
|
|
|
const Token *templateDeclarationToken,
|
2018-10-26 14:20:13 +02:00
|
|
|
const TokenAndName &templateInstantiation,
|
2018-09-01 11:26:10 +02:00
|
|
|
const std::vector<const Token *> &typeParametersInDeclaration,
|
|
|
|
const std::string &newName,
|
2018-10-14 16:57:07 +02:00
|
|
|
bool copy);
|
2018-09-01 11:26:10 +02:00
|
|
|
|
2017-06-08 00:16:43 +02:00
|
|
|
/**
|
|
|
|
* Replace all matching template usages 'Foo < int >' => 'Foo<int>'
|
|
|
|
* @param instantiationToken Template instantiation token
|
2017-12-26 10:55:18 +01:00
|
|
|
* @param templateName full template name with scope info
|
2017-12-26 22:34:39 +01:00
|
|
|
* @param typeStringsUsedInTemplateInstantiation template parameters. list of token strings.
|
2017-06-08 00:16:43 +02:00
|
|
|
* @param newName The new type name
|
|
|
|
*/
|
2018-09-01 11:26:10 +02:00
|
|
|
void replaceTemplateUsage(Token *const instantiationToken,
|
|
|
|
const std::string &templateName,
|
|
|
|
const std::list<std::string> &typeStringsUsedInTemplateInstantiation,
|
2018-10-14 16:57:07 +02:00
|
|
|
const std::string &newName);
|
2012-08-20 18:10:32 +02:00
|
|
|
|
|
|
|
/**
|
2018-09-01 11:26:10 +02:00
|
|
|
* @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
|
2012-01-09 20:33:11 +01:00
|
|
|
*/
|
2018-10-14 16:57:07 +02:00
|
|
|
static const Token * getTemplateParametersInDeclaration(
|
2018-09-01 11:26:10 +02:00
|
|
|
const Token * tok,
|
|
|
|
std::vector<const Token *> & typeParametersInDeclaration);
|
2012-07-29 16:01:05 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove a specific "template < ..." template class/function
|
|
|
|
*/
|
2018-09-01 11:26:10 +02:00
|
|
|
bool removeTemplate(Token *tok);
|
2012-07-29 16:01:05 +02:00
|
|
|
|
2015-06-23 20:53:57 +02:00
|
|
|
/** Syntax error */
|
|
|
|
static void syntaxError(const Token *tok);
|
|
|
|
|
2018-10-14 16:57:07 +02:00
|
|
|
static bool matchSpecialization(
|
2018-09-01 11:26:10 +02:00
|
|
|
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
|
|
|
|
*/
|
2018-10-14 16:57:07 +02:00
|
|
|
static void deleteToken(Token *tok);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the new token name.
|
|
|
|
* @param tok name token
|
|
|
|
* @param &typeStringsUsedInTemplateInstantiation type strings use in template instantiation
|
|
|
|
* @return new token name
|
|
|
|
*/
|
|
|
|
std::string getNewName(
|
|
|
|
Token *tok2,
|
|
|
|
std::list<std::string> &typeStringsUsedInTemplateInstantiation);
|
2018-09-01 11:26:10 +02:00
|
|
|
|
|
|
|
TokenList &mTokenList;
|
|
|
|
const Settings *mSettings;
|
|
|
|
ErrorLogger *mErrorLogger;
|
|
|
|
|
|
|
|
std::list<TokenAndName> mTemplateDeclarations;
|
2018-11-10 16:41:14 +01:00
|
|
|
std::list<TokenAndName> mTemplateForwardDeclarations;
|
2018-09-01 11:26:10 +02:00
|
|
|
std::list<TokenAndName> mTemplateInstantiations;
|
|
|
|
std::list<TokenAndName> mInstantiatedTemplates;
|
2018-09-14 14:16:34 +02:00
|
|
|
std::list<TokenAndName> mMemberFunctionsToDelete;
|
2018-10-14 16:57:07 +02:00
|
|
|
std::vector<Token *> mTypesUsedInTemplateInstantiation;
|
2012-01-01 21:55:05 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/// @}
|
|
|
|
//---------------------------------------------------------------------------
|
2013-09-04 20:59:49 +02:00
|
|
|
#endif // templatesimplifierH
|