template simplifier: Add flag variable to cache information about dec… (#1569)

* template simplifier: Add flag variable to cache information about declarations.

Also fix some cppcheck warnings.

* Make variable const.
This commit is contained in:
IOBYTE 2019-01-07 00:55:22 -05:00 committed by Daniel Marjamäki
parent 286cb2fc2c
commit 07da4b4d37
2 changed files with 97 additions and 30 deletions

View File

@ -54,14 +54,26 @@ namespace {
}
TemplateSimplifier::TokenAndName::TokenAndName(Token *tok, const std::string &s, const std::string &n, const Token *nt, const Token *pe) :
token(tok), scope(s), name(n), nameToken(nt), paramEnd(pe)
token(tok), scope(s), name(n), nameToken(nt), paramEnd(pe), flags(0)
{
// only set flags for declaration
if (token && nameToken && paramEnd) {
isClass(Token::Match(paramEnd->next(), "class|struct|union %name% <|{|:"));
isFunction(nameToken->strAt(1) == "(" ||
(nameToken->strAt(1) == "<" && nameToken->next()->findClosingBracket()->strAt(1) == "("));
isVariable(Token::Match(nameToken->next(), "=|;") ||
(nameToken->strAt(1) == "<" && Token::Match(nameToken->next()->findClosingBracket()->next(), "=|;")));
isAlias(paramEnd->strAt(1) == "using");
isSpecialized(Token::Match(token, "template < >"));
}
if (token)
token->templateSimplifierPointer(this);
}
TemplateSimplifier::TokenAndName::TokenAndName(const TokenAndName& otherTok) :
token(otherTok.token), scope(otherTok.scope), name(otherTok.name), nameToken(otherTok.nameToken), paramEnd(otherTok.paramEnd)
token(otherTok.token), scope(otherTok.scope), name(otherTok.name),
nameToken(otherTok.nameToken), paramEnd(otherTok.paramEnd), flags(otherTok.flags)
{
if (token)
token->templateSimplifierPointer(this);
@ -983,7 +995,7 @@ void TemplateSimplifier::addNamespace(const TokenAndName &templateDeclaration, c
}
}
bool TemplateSimplifier::alreadyHasNamespace(const TokenAndName &templateDeclaration, const Token *tok) const
bool TemplateSimplifier::alreadyHasNamespace(const TokenAndName &templateDeclaration, const Token *tok)
{
std::string scope = templateDeclaration.scope;
@ -1012,17 +1024,16 @@ void TemplateSimplifier::expandTemplate(
const Token *endOfTemplateDefinition = nullptr;
const Token * const templateDeclarationNameToken = templateDeclaration.nameToken;
const Token * const templateDeclarationToken = templateDeclaration.paramEnd;
const bool isClass = Token::Match(templateDeclaration.paramEnd->next(), "class|struct|union %name% <|{|:");
const bool isFunction = templateDeclarationNameToken->strAt(1) == "(" ||
(templateDeclarationNameToken->strAt(1) == "<" && templateDeclarationNameToken->next()->findClosingBracket()->strAt(1) == "(");
const bool isSpecialization = Token::Match(templateDeclaration.token, "template < >");
const bool isClass = templateDeclaration.isClass();
const bool isFunction = templateDeclaration.isFunction();
const bool isSpecialization = templateDeclaration.isSpecialized();
// add forward declarations
if (copy && isClass) {
templateDeclaration.token->insertToken(templateDeclarationToken->strAt(1), "", true);
templateDeclaration.token->insertToken(newName, "", true);
templateDeclaration.token->insertToken(";", "", true);
} else if (isFunction && (copy || (!copy && isSpecialization))) {
} else if (isFunction && (copy || isSpecialization)) {
Token * dst = templateDeclaration.token;
bool isStatic = false;
std::string scope;
@ -1812,16 +1823,8 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
std::vector<const Token *> typeParametersInDeclaration;
getTemplateParametersInDeclaration(templateDeclaration.token->tokAt(2), typeParametersInDeclaration);
const bool printDebug = mSettings->debugwarnings;
const bool specialized = Token::simpleMatch(templateDeclaration.token, "template < >");
bool isfunc = false;
if (templateDeclaration.nameToken->strAt(1) == "(")
isfunc = true;
else if (templateDeclaration.nameToken->strAt(1) == "<") {
const Token *tok1 = templateDeclaration.nameToken->tokAt(1)->findClosingBracket();
if (tok1 && tok1->strAt(1) == "(")
isfunc = true;
}
const bool specialized = templateDeclaration.isSpecialized();
const bool isfunc = templateDeclaration.isFunction();
// locate template usage..
std::string::size_type numberOfTemplateInstantiations = mTemplateInstantiations.size();
@ -2098,12 +2101,12 @@ void TemplateSimplifier::getUserDefinedSpecializations()
{
// try to locate a matching declaration for each user defined specialization
for (auto & spec : mTemplateDeclarations) {
if (Token::Match(spec.token, "template < >")) {
if (spec.isSpecialized()) {
std::string specName = getPathName(spec);
bool found = false;
for (auto & decl : mTemplateDeclarations) {
if (Token::Match(decl.token, "template < >"))
if (decl.isSpecialized())
continue;
std::string declName = getPathName(decl);
@ -2111,6 +2114,7 @@ void TemplateSimplifier::getUserDefinedSpecializations()
if (specName == declName) {
// @todo make sure function parameters also match
mTemplateUserSpecializationMap[spec.token] = decl.token;
found = true;
}
}
@ -2258,7 +2262,7 @@ void TemplateSimplifier::simplifyTemplates(
break;
}
if (decl != mTemplateDeclarations.end()) {
if (Token::simpleMatch(it->token, "template < >")) {
if (it->isSpecialized()) {
// delete the "template < >"
Token * tok = it->token;
tok->deleteNext(2);
@ -2296,7 +2300,7 @@ void TemplateSimplifier::simplifyTemplates(
end = end->next();
if (start->previous())
start = start->previous();
if (end->next())
if (end && end->next())
end = end->next();
eraseTokens(start, end);
}

View File

@ -43,7 +43,7 @@ class TokenList;
/** @brief Simplify templates from the preprocessed and partially simplified code. */
class CPPCHECKLIB TemplateSimplifier {
public:
TemplateSimplifier(Tokenizer *tokenizer);
explicit TemplateSimplifier(Tokenizer *tokenizer);
~TemplateSimplifier();
/**
@ -74,13 +74,76 @@ public:
~TokenAndName();
bool operator == (const TokenAndName & rhs) const {
return token == rhs.token && scope == rhs.scope && name == rhs.name && nameToken == rhs.nameToken && paramEnd == rhs.paramEnd;;
return token == rhs.token && scope == rhs.scope && name == rhs.name &&
nameToken == rhs.nameToken && paramEnd == rhs.paramEnd && flags == rhs.flags;
}
Token *token;
std::string scope;
std::string name;
const Token *nameToken;
const Token *paramEnd;
unsigned int flags;
enum {
fIsClass = (1 << 0), // class template
fIsFunction = (1 << 1), // function template
fIsVariable = (1 << 2), // variable template
fIsAlias = (1 << 3), // alias template
fIsSpecialized = (1 << 4), // user specialized template
};
bool isClass() const {
return getFlag(fIsClass);
}
void isClass(bool state) {
setFlag(fIsClass, state);
}
bool isFunction() const {
return getFlag(fIsFunction);
}
void isFunction(bool state) {
setFlag(fIsFunction, state);
}
bool isVariable() const {
return getFlag(fIsVariable);
}
void isVariable(bool state) {
setFlag(fIsVariable, state);
}
bool isAlias() const {
return getFlag(fIsAlias);
}
void isAlias(bool state) {
setFlag(fIsAlias, state);
}
bool isSpecialized() const {
return getFlag(fIsSpecialized);
}
void isSpecialized(bool state) {
setFlag(fIsSpecialized, state);
}
/**
* Get specified flag state.
* @param flag flag to get state of
* @return true if flag set or false in flag not set
*/
bool getFlag(unsigned int flag) const {
return ((flags & flag) != 0);
}
/**
* Set specified flag state.
* @param flag flag to set state
* @param state new state of flag
*/
void setFlag(unsigned int flag, bool state) {
flags = state ? flags | flag : flags & ~flag;
}
};
/**
@ -99,7 +162,7 @@ public:
* @return -1 to bail out or positive integer to identity the position
* of the template name.
*/
int getTemplateNamePosition(const Token *tok, bool forward = false);
static int getTemplateNamePosition(const Token *tok, bool forward = false);
/**
* Get template name position
@ -107,7 +170,7 @@ public:
* @param namepos return offset to name
* @return true if name found, false if not
* */
bool getTemplateNamePositionTemplateFunction(const Token *tok, int &namepos);
static bool getTemplateNamePositionTemplateFunction(const Token *tok, int &namepos);
/**
* Simplify templates
@ -132,7 +195,7 @@ public:
* @return true if modifications to token-list are done.
* false if no modifications are done.
*/
bool simplifyCalculations(Token* tok = nullptr);
bool simplifyCalculations(Token* frontToken = nullptr);
private:
/**
@ -196,7 +259,7 @@ private:
* @param tok place to start looking for namespace
* @return true if namespace already present
*/
bool alreadyHasNamespace(const TokenAndName &templateDeclaration, const Token *tok) const;
static bool alreadyHasNamespace(const TokenAndName &templateDeclaration, const Token *tok);
/**
* Expand a template. Create "expanded" class/function at end of tokenlist.
@ -241,7 +304,7 @@ private:
/**
* Remove a specific "template < ..." template class/function
*/
bool removeTemplate(Token *tok);
static bool removeTemplate(Token *tok);
/** Syntax error */
static void syntaxError(const Token *tok);
@ -256,7 +319,7 @@ private:
* @param begin Tokens after this will be erased.
* @param end Tokens before this will be erased.
*/
void eraseTokens(Token *begin, const Token *end);
static void eraseTokens(Token *begin, const Token *end);
/**
* Delete specified token without invalidating pointer to following token.