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

View File

@ -43,7 +43,7 @@ class TokenList;
/** @brief Simplify templates from the preprocessed and partially simplified code. */ /** @brief Simplify templates from the preprocessed and partially simplified code. */
class CPPCHECKLIB TemplateSimplifier { class CPPCHECKLIB TemplateSimplifier {
public: public:
TemplateSimplifier(Tokenizer *tokenizer); explicit TemplateSimplifier(Tokenizer *tokenizer);
~TemplateSimplifier(); ~TemplateSimplifier();
/** /**
@ -74,13 +74,76 @@ public:
~TokenAndName(); ~TokenAndName();
bool operator == (const TokenAndName & rhs) const { 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; Token *token;
std::string scope; std::string scope;
std::string name; std::string name;
const Token *nameToken; const Token *nameToken;
const Token *paramEnd; 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 * @return -1 to bail out or positive integer to identity the position
* of the template name. * 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 * Get template name position
@ -107,7 +170,7 @@ public:
* @param namepos return offset to name * @param namepos return offset to name
* @return true if name found, false if not * @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 * Simplify templates
@ -132,7 +195,7 @@ public:
* @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 simplifyCalculations(Token* tok = nullptr); bool simplifyCalculations(Token* frontToken = nullptr);
private: private:
/** /**
@ -196,7 +259,7 @@ private:
* @param tok place to start looking for namespace * @param tok place to start looking for namespace
* @return true if namespace already present * @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. * Expand a template. Create "expanded" class/function at end of tokenlist.
@ -241,7 +304,7 @@ private:
/** /**
* Remove a specific "template < ..." template class/function * Remove a specific "template < ..." template class/function
*/ */
bool removeTemplate(Token *tok); static bool removeTemplate(Token *tok);
/** Syntax error */ /** Syntax error */
static void syntaxError(const Token *tok); static void syntaxError(const Token *tok);
@ -256,7 +319,7 @@ private:
* @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 eraseTokens(Token *begin, const Token *end); static void eraseTokens(Token *begin, const Token *end);
/** /**
* Delete specified token without invalidating pointer to following token. * Delete specified token without invalidating pointer to following token.