Fixed #7417 ("syntax error" in valid code containing explicitly specialised variable template) (#1604)
This commit is contained in:
parent
4b1544d33b
commit
1acbdde302
|
@ -77,13 +77,23 @@ TemplateSimplifier::TokenAndName::TokenAndName(Token *tok, const std::string &s,
|
||||||
{
|
{
|
||||||
// only set flags for declaration
|
// only set flags for declaration
|
||||||
if (token && nameToken && paramEnd) {
|
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::simpleMatch(token, "template < >"));
|
isSpecialized(Token::simpleMatch(token, "template < >"));
|
||||||
|
isAlias(paramEnd->strAt(1) == "using");
|
||||||
|
isClass(Token::Match(paramEnd->next(), "class|struct|union %name% <|{|:|;"));
|
||||||
|
const Token *tok1 = nameToken->next();
|
||||||
|
if (tok1->str() == "<")
|
||||||
|
tok1 = tok1->findClosingBracket()->next();
|
||||||
|
isFunction(tok1->str() == "(");
|
||||||
|
isVariable(!isClass() && Token::Match(tok1, "=|;"));
|
||||||
|
if (isVariable())
|
||||||
|
isForwardDeclaration(tok1->str() == ";");
|
||||||
|
else {
|
||||||
|
if (isFunction())
|
||||||
|
tok1 = tok1->link()->next();
|
||||||
|
tok1 = Token::findmatch(tok1, "{|;");
|
||||||
|
if (tok1)
|
||||||
|
isForwardDeclaration(tok1->str() == ";");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token)
|
if (token)
|
||||||
|
@ -565,19 +575,19 @@ bool TemplateSimplifier::getTemplateDeclarations()
|
||||||
// skip decltype(...)
|
// skip decltype(...)
|
||||||
else if (Token::simpleMatch(tok2, "decltype ("))
|
else if (Token::simpleMatch(tok2, "decltype ("))
|
||||||
tok2 = tok2->linkAt(1);
|
tok2 = tok2->linkAt(1);
|
||||||
// Declaration => add to mTemplateForwardDeclarations
|
else if (Token::Match(tok2, "{|=|;")) {
|
||||||
else if (tok2->str() == ";") {
|
const int namepos = getTemplateNamePosition(parmEnd);
|
||||||
const int namepos = getTemplateNamePosition(parmEnd, true);
|
if (namepos > 0) {
|
||||||
if (namepos > 0)
|
TokenAndName decl(tok, getScopeName(scopeInfo), parmEnd->tokAt(namepos), parmEnd);
|
||||||
mTemplateForwardDeclarations.emplace_back(tok, getScopeName(scopeInfo), parmEnd->tokAt(namepos), parmEnd);
|
if (decl.isForwardDeclaration()) {
|
||||||
break;
|
// Declaration => add to mTemplateForwardDeclarations
|
||||||
}
|
mTemplateForwardDeclarations.emplace_back(decl);
|
||||||
// Implementation => add to mTemplateDeclarations
|
} else {
|
||||||
else if (tok2->str() == "{") {
|
// Implementation => add to mTemplateDeclarations
|
||||||
const int namepos = getTemplateNamePosition(parmEnd, false);
|
mTemplateDeclarations.emplace_back(decl);
|
||||||
if (namepos > 0)
|
}
|
||||||
mTemplateDeclarations.emplace_back(tok, getScopeName(scopeInfo), parmEnd->tokAt(namepos), parmEnd);
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -600,6 +610,7 @@ void TemplateSimplifier::getTemplateInstantiations()
|
||||||
tok = tok->next()->findClosingBracket();
|
tok = tok->next()->findClosingBracket();
|
||||||
if (!tok)
|
if (!tok)
|
||||||
break;
|
break;
|
||||||
|
const bool isUsing = tok->strAt(1) == "using";
|
||||||
if (tok->strAt(-1) == "<") {
|
if (tok->strAt(-1) == "<") {
|
||||||
// Don't ignore user specialization but don't consider it an instantiation.
|
// Don't ignore user specialization but don't consider it an instantiation.
|
||||||
// Instantiations in return type, function parameters, and executable code
|
// Instantiations in return type, function parameters, and executable code
|
||||||
|
@ -614,6 +625,8 @@ void TemplateSimplifier::getTemplateInstantiations()
|
||||||
const Token *tok2 = Token::findmatch(tok, "{|;");
|
const Token *tok2 = Token::findmatch(tok, "{|;");
|
||||||
if (tok2 && tok2->str() == "{")
|
if (tok2 && tok2->str() == "{")
|
||||||
tok = tok2->link();
|
tok = tok2->link();
|
||||||
|
else if (!isUsing && tok2 && tok2->str() == ";")
|
||||||
|
tok = const_cast<Token *>(tok2);
|
||||||
}
|
}
|
||||||
} else if (Token::Match(tok->previous(), "(|{|}|;|=|>|<<|:|.|*|& %name% ::|<") ||
|
} else if (Token::Match(tok->previous(), "(|{|}|;|=|>|<<|:|.|*|& %name% ::|<") ||
|
||||||
Token::Match(tok->previous(), "%type% %name% ::|<") ||
|
Token::Match(tok->previous(), "%type% %name% ::|<") ||
|
||||||
|
@ -1003,13 +1016,39 @@ bool TemplateSimplifier::getTemplateNamePositionTemplateFunction(const Token *to
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TemplateSimplifier::getTemplateNamePosition(const Token *tok, bool forward)
|
bool TemplateSimplifier::getTemplateNamePositionTemplateVariable(const Token *tok, int &namepos)
|
||||||
|
{
|
||||||
|
namepos = 1;
|
||||||
|
while (tok && tok->next()) {
|
||||||
|
if (Token::Match(tok->next(), ";|{|(|using"))
|
||||||
|
return false;
|
||||||
|
else if (Token::Match(tok->next(), "%type% <")) {
|
||||||
|
const Token *closing = tok->tokAt(2)->findClosingBracket();
|
||||||
|
if (closing) {
|
||||||
|
if (Token::Match(closing->next(), "=|;"))
|
||||||
|
return true;
|
||||||
|
while (tok && tok->next() && tok->next() != closing) {
|
||||||
|
tok = tok->next();
|
||||||
|
namepos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (Token::Match(tok->next(), "%type% =|;")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
tok = tok->next();
|
||||||
|
namepos++;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TemplateSimplifier::getTemplateNamePosition(const Token *tok)
|
||||||
{
|
{
|
||||||
// get the position of the template name
|
// get the position of the template name
|
||||||
int namepos = 0;
|
int namepos = 0;
|
||||||
if ((forward && Token::Match(tok, "> class|struct|union %type% :|<|;")) ||
|
if (Token::Match(tok, "> class|struct|union %type% :|<|;|{"))
|
||||||
(!forward && Token::Match(tok, "> class|struct|union %type% {|:|<")))
|
|
||||||
namepos = 2;
|
namepos = 2;
|
||||||
|
else if (getTemplateNamePositionTemplateVariable(tok, namepos))
|
||||||
|
;
|
||||||
else if (!getTemplateNamePositionTemplateFunction(tok, namepos))
|
else if (!getTemplateNamePositionTemplateFunction(tok, namepos))
|
||||||
return -1; // Name not found
|
return -1; // Name not found
|
||||||
|
|
||||||
|
@ -1079,14 +1118,16 @@ void TemplateSimplifier::expandTemplate(
|
||||||
const bool isClass = templateDeclaration.isClass();
|
const bool isClass = templateDeclaration.isClass();
|
||||||
const bool isFunction = templateDeclaration.isFunction();
|
const bool isFunction = templateDeclaration.isFunction();
|
||||||
const bool isSpecialization = templateDeclaration.isSpecialized();
|
const bool isSpecialization = templateDeclaration.isSpecialized();
|
||||||
|
const bool isVariable = templateDeclaration.isVariable();
|
||||||
|
|
||||||
// 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 || isSpecialization)) {
|
} else if ((isFunction && (copy || isSpecialization)) || (isVariable && !isSpecialization)) {
|
||||||
Token * dst = templateDeclaration.token;
|
Token * dst = templateDeclaration.token;
|
||||||
|
Token * dstStart = dst->previous();
|
||||||
bool isStatic = false;
|
bool isStatic = false;
|
||||||
std::string scope;
|
std::string scope;
|
||||||
Token * start;
|
Token * start;
|
||||||
|
@ -1094,6 +1135,7 @@ void TemplateSimplifier::expandTemplate(
|
||||||
auto it = mTemplateForwardDeclarationsMap.find(dst);
|
auto it = mTemplateForwardDeclarationsMap.find(dst);
|
||||||
if (it != mTemplateForwardDeclarationsMap.end()) {
|
if (it != mTemplateForwardDeclarationsMap.end()) {
|
||||||
dst = it->second;
|
dst = it->second;
|
||||||
|
dstStart = dst->previous();
|
||||||
const Token * temp1 = dst->tokAt(1)->findClosingBracket();
|
const Token * temp1 = dst->tokAt(1)->findClosingBracket();
|
||||||
const Token * temp2 = temp1->tokAt(getTemplateNamePosition(temp1));
|
const Token * temp2 = temp1->tokAt(getTemplateNamePosition(temp1));
|
||||||
start = temp1->next();
|
start = temp1->next();
|
||||||
|
@ -1102,6 +1144,7 @@ void TemplateSimplifier::expandTemplate(
|
||||||
auto it2 = mTemplateUserSpecializationMap.find(dst);
|
auto it2 = mTemplateUserSpecializationMap.find(dst);
|
||||||
if (it2 != mTemplateUserSpecializationMap.end()) {
|
if (it2 != mTemplateUserSpecializationMap.end()) {
|
||||||
dst = it2->second;
|
dst = it2->second;
|
||||||
|
dstStart = dst->previous();
|
||||||
isStatic = dst->next()->findClosingBracket()->strAt(1) == "static";
|
isStatic = dst->next()->findClosingBracket()->strAt(1) == "static";
|
||||||
const Token * temp = templateDeclarationNameToken;
|
const Token * temp = templateDeclarationNameToken;
|
||||||
while (Token::Match(temp->tokAt(-2), "%name% ::")) {
|
while (Token::Match(temp->tokAt(-2), "%name% ::")) {
|
||||||
|
@ -1110,10 +1153,13 @@ void TemplateSimplifier::expandTemplate(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
start = templateDeclarationToken->next();
|
start = templateDeclarationToken->next();
|
||||||
if (templateDeclarationNameToken->strAt(1) == "(")
|
end = templateDeclarationNameToken->next();
|
||||||
end = templateDeclarationNameToken->linkAt(1)->next();
|
if (end->str() == "<")
|
||||||
else
|
end = end->findClosingBracket()->next();
|
||||||
end = templateDeclarationNameToken->next()->findClosingBracket()->linkAt(1)->next();
|
if (end->str() == "(")
|
||||||
|
end = end->link()->next();
|
||||||
|
else if (isVariable && end->str() == "=")
|
||||||
|
end = const_cast<Token *>(Token::findsimplematch(templateDeclarationNameToken, ";"));
|
||||||
}
|
}
|
||||||
unsigned int typeindentlevel = 0;
|
unsigned int typeindentlevel = 0;
|
||||||
while (!(typeindentlevel == 0 && Token::Match(end, ";|{|:"))) {
|
while (!(typeindentlevel == 0 && Token::Match(end, ";|{|:"))) {
|
||||||
|
@ -1128,7 +1174,10 @@ void TemplateSimplifier::expandTemplate(
|
||||||
dst->insertToken("static", "", true);
|
dst->insertToken("static", "", true);
|
||||||
|
|
||||||
std::map<const Token *, Token *> links;
|
std::map<const Token *, Token *> links;
|
||||||
|
bool inAssignment = false;
|
||||||
while (start && start != end) {
|
while (start && start != end) {
|
||||||
|
if (isVariable && start->str() == "=")
|
||||||
|
inAssignment = true;
|
||||||
unsigned int itype = 0;
|
unsigned int itype = 0;
|
||||||
while (itype < typeParametersInDeclaration.size() && typeParametersInDeclaration[itype]->str() != start->str())
|
while (itype < typeParametersInDeclaration.size() && typeParametersInDeclaration[itype]->str() != start->str())
|
||||||
++itype;
|
++itype;
|
||||||
|
@ -1158,9 +1207,12 @@ void TemplateSimplifier::expandTemplate(
|
||||||
while (start->strAt(1) != templateDeclarationNameToken->str())
|
while (start->strAt(1) != templateDeclarationNameToken->str())
|
||||||
start = start->next();
|
start = start->next();
|
||||||
} else if (start->str() == templateDeclarationNameToken->str()) {
|
} else if (start->str() == templateDeclarationNameToken->str()) {
|
||||||
dst->insertToken(newName, "", true);
|
if (start->strAt(1) != "<" || Token::Match(start, newName.c_str()) || !inAssignment) {
|
||||||
if (start->strAt(1) == "<")
|
dst->insertToken(newName, "", true);
|
||||||
start = start->next()->findClosingBracket();
|
if (start->strAt(1) == "<")
|
||||||
|
start = start->next()->findClosingBracket();
|
||||||
|
} else
|
||||||
|
dst->insertToken(start->str(), "", true);
|
||||||
} else {
|
} else {
|
||||||
// check if type is a template
|
// check if type is a template
|
||||||
if (start->strAt(1) == "<") {
|
if (start->strAt(1) == "<") {
|
||||||
|
@ -1210,6 +1262,9 @@ void TemplateSimplifier::expandTemplate(
|
||||||
start = start->next();
|
start = start->next();
|
||||||
}
|
}
|
||||||
dst->insertToken(";", "", true);
|
dst->insertToken(";", "", true);
|
||||||
|
|
||||||
|
if (isVariable)
|
||||||
|
simplifyCalculations(dstStart, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (copy && (isClass || isFunction)) {
|
if (copy && (isClass || isFunction)) {
|
||||||
|
@ -1597,13 +1652,13 @@ bool TemplateSimplifier::simplifyNumericCalculations(Token *tok)
|
||||||
|
|
||||||
// TODO: This is not the correct class for simplifyCalculations(), so it
|
// TODO: This is not the correct class for simplifyCalculations(), so it
|
||||||
// should be moved away.
|
// should be moved away.
|
||||||
bool TemplateSimplifier::simplifyCalculations(Token* frontToken)
|
bool TemplateSimplifier::simplifyCalculations(Token* frontToken, Token *backToken)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
if (!frontToken) {
|
if (!frontToken) {
|
||||||
frontToken = mTokenList.front();
|
frontToken = mTokenList.front();
|
||||||
}
|
}
|
||||||
for (Token *tok = frontToken; tok; tok = tok->next()) {
|
for (Token *tok = frontToken; tok != backToken; tok = tok->next()) {
|
||||||
// Remove parentheses around variable..
|
// Remove parentheses around variable..
|
||||||
// keep parentheses here: dynamic_cast<Fred *>(p);
|
// keep parentheses here: dynamic_cast<Fred *>(p);
|
||||||
// keep parentheses here: A operator * (int);
|
// keep parentheses here: A operator * (int);
|
||||||
|
@ -1894,6 +1949,7 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
const bool printDebug = mSettings->debugwarnings;
|
const bool printDebug = mSettings->debugwarnings;
|
||||||
const bool specialized = templateDeclaration.isSpecialized();
|
const bool specialized = templateDeclaration.isSpecialized();
|
||||||
const bool isfunc = templateDeclaration.isFunction();
|
const bool isfunc = templateDeclaration.isFunction();
|
||||||
|
const bool isVar = templateDeclaration.isVariable();
|
||||||
|
|
||||||
// locate template usage..
|
// locate template usage..
|
||||||
std::string::size_type numberOfTemplateInstantiations = mTemplateInstantiations.size();
|
std::string::size_type numberOfTemplateInstantiations = mTemplateInstantiations.size();
|
||||||
|
@ -1956,7 +2012,7 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Token::Match(startToken->previous(), ";|{|}|=|const") &&
|
if (Token::Match(startToken->previous(), ";|{|}|=|const") &&
|
||||||
(!specialized && !instantiateMatch(tok2, typeParametersInDeclaration.size(), isfunc ? "(" : "*|&| %name%")))
|
(!specialized && !instantiateMatch(tok2, typeParametersInDeclaration.size(), isfunc ? "(" : isVar ? ";|%op%" : "*|&| %name%")))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// New type..
|
// New type..
|
||||||
|
@ -1981,7 +2037,7 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
|
|
||||||
if (expandedtemplates.find(newFullName) == expandedtemplates.end()) {
|
if (expandedtemplates.find(newFullName) == expandedtemplates.end()) {
|
||||||
expandedtemplates.insert(newFullName);
|
expandedtemplates.insert(newFullName);
|
||||||
expandTemplate(templateDeclaration, instantiation, typeParametersInDeclaration, newName, !specialized);
|
expandTemplate(templateDeclaration, instantiation, typeParametersInDeclaration, newName, !specialized && !isVar);
|
||||||
instantiated = true;
|
instantiated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2019,7 +2075,7 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Token::Match(startToken->previous(), ";|{|}|=|const") &&
|
if (Token::Match(startToken->previous(), ";|{|}|=|const") &&
|
||||||
(!specialized && !instantiateMatch(tok2, typeParametersInDeclaration.size(), isfunc ? "(" : "*|&| %name%")))
|
(!specialized && !instantiateMatch(tok2, typeParametersInDeclaration.size(), isfunc ? "(" : isVar ? ";|%op%" : "*|&| %name%")))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// already simplified
|
// already simplified
|
||||||
|
@ -2049,7 +2105,7 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
|
|
||||||
if (expandedtemplates.find(newFullName) == expandedtemplates.end()) {
|
if (expandedtemplates.find(newFullName) == expandedtemplates.end()) {
|
||||||
expandedtemplates.insert(newFullName);
|
expandedtemplates.insert(newFullName);
|
||||||
expandTemplate(templateDeclaration, templateDeclaration, typeParametersInDeclaration, newName, false);
|
expandTemplate(templateDeclaration, templateDeclaration, typeParametersInDeclaration, newName, !specialized && !isVar);
|
||||||
instantiated = true;
|
instantiated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2304,6 +2360,8 @@ void TemplateSimplifier::printOut(const TokenAndName &tokenAndName, const std::s
|
||||||
std::cout << " isAlias";
|
std::cout << " isAlias";
|
||||||
if (tokenAndName.isSpecialized())
|
if (tokenAndName.isSpecialized())
|
||||||
std::cout << " isSpecialized";
|
std::cout << " isSpecialized";
|
||||||
|
if (tokenAndName.isForwardDeclaration())
|
||||||
|
std::cout << " isForwardDeclaration";
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
if (tokenAndName.token && !tokenAndName.paramEnd && tokenAndName.token->strAt(1) == "<") {
|
if (tokenAndName.token && !tokenAndName.paramEnd && tokenAndName.token->strAt(1) == "<") {
|
||||||
const Token *end = tokenAndName.token->next()->findClosingBracket();
|
const Token *end = tokenAndName.token->next()->findClosingBracket();
|
||||||
|
|
|
@ -99,11 +99,12 @@ public:
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
fIsClass = (1 << 0), // class template
|
fIsClass = (1 << 0), // class template
|
||||||
fIsFunction = (1 << 1), // function template
|
fIsFunction = (1 << 1), // function template
|
||||||
fIsVariable = (1 << 2), // variable template
|
fIsVariable = (1 << 2), // variable template
|
||||||
fIsAlias = (1 << 3), // alias template
|
fIsAlias = (1 << 3), // alias template
|
||||||
fIsSpecialized = (1 << 4), // user specialized template
|
fIsSpecialized = (1 << 4), // user specialized template
|
||||||
|
fIsForwardDeclaration = (1 << 5), // forward declaration
|
||||||
};
|
};
|
||||||
|
|
||||||
bool isClass() const {
|
bool isClass() const {
|
||||||
|
@ -141,6 +142,13 @@ public:
|
||||||
setFlag(fIsSpecialized, state);
|
setFlag(fIsSpecialized, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isForwardDeclaration() const {
|
||||||
|
return getFlag(fIsForwardDeclaration);
|
||||||
|
}
|
||||||
|
void isForwardDeclaration(bool state) {
|
||||||
|
setFlag(fIsForwardDeclaration, state);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get specified flag state.
|
* Get specified flag state.
|
||||||
* @param flag flag to get state of
|
* @param flag flag to get state of
|
||||||
|
@ -172,20 +180,27 @@ public:
|
||||||
/**
|
/**
|
||||||
* Match template declaration/instantiation
|
* Match template declaration/instantiation
|
||||||
* @param tok The ">" token e.g. before "class"
|
* @param tok The ">" token e.g. before "class"
|
||||||
* @param forward declaration or forward declaration
|
|
||||||
* @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.
|
||||||
*/
|
*/
|
||||||
static int getTemplateNamePosition(const Token *tok, bool forward = false);
|
static int getTemplateNamePosition(const Token *tok);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get template name position
|
* Get function template name position
|
||||||
* @param tok The ">" token e.g. before "class"
|
* @param tok The ">" token e.g. before "class"
|
||||||
* @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
|
||||||
* */
|
* */
|
||||||
static bool getTemplateNamePositionTemplateFunction(const Token *tok, int &namepos);
|
static bool getTemplateNamePositionTemplateFunction(const Token *tok, int &namepos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get variable template name position
|
||||||
|
* @param tok The ">" token
|
||||||
|
* @param namepos return offset to name
|
||||||
|
* @return true if name found, false if not
|
||||||
|
* */
|
||||||
|
static bool getTemplateNamePositionTemplateVariable(const Token *tok, int &namepos);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simplify templates
|
* Simplify templates
|
||||||
* @param maxtime time when the simplification should be stopped
|
* @param maxtime time when the simplification should be stopped
|
||||||
|
@ -209,7 +224,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* frontToken = nullptr);
|
bool simplifyCalculations(Token* frontToken = nullptr, Token *backToken = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1838,6 +1838,8 @@ void Tokenizer::combineOperators()
|
||||||
|
|
||||||
// combine +-*/ and =
|
// combine +-*/ and =
|
||||||
if (c2 == '=' && (std::strchr("+-*/%|^=!<>", c1))) {
|
if (c2 == '=' && (std::strchr("+-*/%|^=!<>", c1))) {
|
||||||
|
if (cpp && Token::Match(tok->tokAt(-2), "< %any% >"))
|
||||||
|
continue;
|
||||||
tok->str(tok->str() + c2);
|
tok->str(tok->str() + c2);
|
||||||
tok->deleteNext();
|
tok->deleteNext();
|
||||||
continue;
|
continue;
|
||||||
|
@ -1927,7 +1929,7 @@ void Tokenizer::concatenateNegativeNumberAndAnyPositive()
|
||||||
if (!Token::Match(tok, "?|:|,|(|[|{|return|case|sizeof|%op% +|-") || tok->tokType() == Token::eIncDecOp)
|
if (!Token::Match(tok, "?|:|,|(|[|{|return|case|sizeof|%op% +|-") || tok->tokType() == Token::eIncDecOp)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
while (tok->next() && tok->next()->str() == "+")
|
while (tok->str() != ">" && tok->next() && tok->next()->str() == "+")
|
||||||
tok->deleteNext();
|
tok->deleteNext();
|
||||||
|
|
||||||
if (Token::Match(tok->next(), "- %num%")) {
|
if (Token::Match(tok->next(), "- %num%")) {
|
||||||
|
|
|
@ -132,6 +132,8 @@ private:
|
||||||
TEST_CASE(template92);
|
TEST_CASE(template92);
|
||||||
TEST_CASE(template93); // crash
|
TEST_CASE(template93); // crash
|
||||||
TEST_CASE(template94); // #8927 crash
|
TEST_CASE(template94); // #8927 crash
|
||||||
|
TEST_CASE(template95); // #7417
|
||||||
|
TEST_CASE(template96); // #7854
|
||||||
TEST_CASE(template_specialization_1); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
|
TEST_CASE(template_specialization_1); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
|
||||||
TEST_CASE(template_specialization_2); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
|
TEST_CASE(template_specialization_2); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
|
||||||
TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template)
|
TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template)
|
||||||
|
@ -1905,6 +1907,49 @@ private:
|
||||||
ASSERT_EQUALS(exp, tok(code));
|
ASSERT_EQUALS(exp, tok(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void template95() { // #7417
|
||||||
|
const char code[] = "template <typename T>\n"
|
||||||
|
"T Value = 123;\n"
|
||||||
|
"template<>\n"
|
||||||
|
"int Value<int> = 456;\n"
|
||||||
|
"float f = Value<float>;\n"
|
||||||
|
"int i = Value<int>;";
|
||||||
|
const char exp[] = "float Value<float> ; Value<float> = 123 ; "
|
||||||
|
"int Value<int> ; Value<int> = 456 ; "
|
||||||
|
"float f ; f = Value<float> ; "
|
||||||
|
"int i ; i = Value<int> ;";
|
||||||
|
ASSERT_EQUALS(exp, tok(code));
|
||||||
|
}
|
||||||
|
|
||||||
|
void template96() { // #7854
|
||||||
|
const char code[] = "template<unsigned int n>\n"
|
||||||
|
" constexpr long fib = fib<n-1> + fib<n-2>;\n"
|
||||||
|
"template<>\n"
|
||||||
|
" constexpr long fib<0> = 0;\n"
|
||||||
|
"template<>\n"
|
||||||
|
" constexpr long fib<1> = 1;\n"
|
||||||
|
"long f0 = fib<0>;\n"
|
||||||
|
"long f1 = fib<1>;\n"
|
||||||
|
"long f2 = fib<2>;\n"
|
||||||
|
"long f3 = fib<3>;";
|
||||||
|
const char act[] = "const long fib<2> = fib < 1 > + fib < 0 > ; "
|
||||||
|
"const long fib<0> = 0 ; "
|
||||||
|
"const long fib<1> = 1 ; "
|
||||||
|
"long f0 ; f0 = fib<0> ; "
|
||||||
|
"long f1 ; f1 = fib<1> ; "
|
||||||
|
"long f2 ; f2 = fib<2> ; "
|
||||||
|
"long f3 ; f3 = fib < 3 > ;";
|
||||||
|
const char exp[] = "const long fib<3> = fib<2> + fib<1> ; "
|
||||||
|
"const long fib<2> = fib<1> + fib<0> ; "
|
||||||
|
"const long fib<0> = 0 ; "
|
||||||
|
"const long fib<1> = 1 ; "
|
||||||
|
"long f0 ; f0 = fib<0> ; "
|
||||||
|
"long f1 ; f1 = fib<1> ; "
|
||||||
|
"long f2 ; f2 = fib<2> ; "
|
||||||
|
"long f3 ; f3 = fib<3> ;";
|
||||||
|
TODO_ASSERT_EQUALS(exp, act, tok(code, false));
|
||||||
|
}
|
||||||
|
|
||||||
void template_specialization_1() { // #7868 - template specialization template <typename T> struct S<C<T>> {..};
|
void template_specialization_1() { // #7868 - template specialization template <typename T> struct S<C<T>> {..};
|
||||||
const char code[] = "template <typename T> struct C {};\n"
|
const char code[] = "template <typename T> struct C {};\n"
|
||||||
"template <typename T> struct S {a};\n"
|
"template <typename T> struct S {a};\n"
|
||||||
|
|
Loading…
Reference in New Issue