parent
96cf2b34fd
commit
77717f73fd
|
@ -1583,6 +1583,12 @@ bool TemplateSimplifier::alreadyHasNamespace(const TokenAndName &templateDeclara
|
|||
return Token::simpleMatch(tok->tokAt(offset), scope.c_str(), scope.size());
|
||||
}
|
||||
|
||||
struct newInstantiation {
|
||||
newInstantiation(Token* t, std::string s) : token(t), scope(std::move(s)) {}
|
||||
Token* token;
|
||||
std::string scope;
|
||||
};
|
||||
|
||||
void TemplateSimplifier::expandTemplate(
|
||||
const TokenAndName &templateDeclaration,
|
||||
const TokenAndName &templateInstantiation,
|
||||
|
@ -1599,11 +1605,7 @@ void TemplateSimplifier::expandTemplate(
|
|||
const bool isFunction = templateDeclaration.isFunction();
|
||||
const bool isSpecialization = templateDeclaration.isSpecialization();
|
||||
const bool isVariable = templateDeclaration.isVariable();
|
||||
struct newInstantiation {
|
||||
newInstantiation(Token *t, std::string s) : token(t), scope(std::move(s)) {}
|
||||
Token *token;
|
||||
std::string scope;
|
||||
};
|
||||
|
||||
std::vector<newInstantiation> newInstantiations;
|
||||
|
||||
// add forward declarations
|
||||
|
@ -2251,7 +2253,9 @@ void TemplateSimplifier::expandTemplate(
|
|||
|
||||
// add new instantiations
|
||||
for (const auto & inst : newInstantiations) {
|
||||
simplifyTemplateArgs(inst.token->tokAt(2), inst.token->next()->findClosingBracket());
|
||||
if (!inst.token)
|
||||
continue;
|
||||
simplifyTemplateArgs(inst.token->tokAt(2), inst.token->next()->findClosingBracket(), &newInstantiations);
|
||||
// only add recursive instantiation if its arguments are a constant expression
|
||||
if (templateDeclaration.name() != inst.token->str() ||
|
||||
(inst.token->tokAt(2)->isNumber() || inst.token->tokAt(2)->isStandardType()))
|
||||
|
@ -2409,7 +2413,17 @@ static Token *skipTernaryOp(Token *tok, const Token *backToken)
|
|||
return tok;
|
||||
}
|
||||
|
||||
void TemplateSimplifier::simplifyTemplateArgs(Token *start, const Token *end)
|
||||
static void invalidateInst(const Token* beg, const Token* end, std::vector<newInstantiation>* newInst) {
|
||||
if (!newInst)
|
||||
return;
|
||||
for (auto& inst : *newInst) {
|
||||
for (const Token* tok = beg; tok != end; tok = tok->next())
|
||||
if (inst.token == tok)
|
||||
inst.token = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void TemplateSimplifier::simplifyTemplateArgs(Token *start, const Token *end, std::vector<newInstantiation>* newInst)
|
||||
{
|
||||
// start could be erased so use the token before start if available
|
||||
Token * first = (start && start->previous()) ? start->previous() : mTokenList.front();
|
||||
|
@ -2517,6 +2531,7 @@ void TemplateSimplifier::simplifyTemplateArgs(Token *start, const Token *end)
|
|||
}
|
||||
|
||||
if (Token::Match(tok->next(), "false|0")) {
|
||||
invalidateInst(tok->next(), colon, newInst);
|
||||
// Use code after colon, remove code before it.
|
||||
Token::eraseTokens(tok, colon);
|
||||
|
||||
|
@ -2543,6 +2558,7 @@ void TemplateSimplifier::simplifyTemplateArgs(Token *start, const Token *end)
|
|||
else if (endTok->str() == ">" && !end)
|
||||
;
|
||||
else {
|
||||
invalidateInst(colon->tokAt(-1), endTok, newInst);
|
||||
Token::eraseTokens(colon->tokAt(-2), endTok);
|
||||
again = true;
|
||||
break;
|
||||
|
|
|
@ -37,6 +37,7 @@ class Settings;
|
|||
class Token;
|
||||
class Tokenizer;
|
||||
class TokenList;
|
||||
struct newInstantiation;
|
||||
|
||||
/// @addtogroup Core
|
||||
/// @{
|
||||
|
@ -333,7 +334,7 @@ public:
|
|||
* @param start first token of arguments
|
||||
* @param end token following last argument token
|
||||
*/
|
||||
void simplifyTemplateArgs(Token *start, const Token *end);
|
||||
void simplifyTemplateArgs(Token *start, const Token *end, std::vector<newInstantiation>* newInst = nullptr);
|
||||
|
||||
private:
|
||||
/**
|
||||
|
|
|
@ -278,6 +278,7 @@ private:
|
|||
|
||||
TEST_CASE(simplifyTemplateArgs1);
|
||||
TEST_CASE(simplifyTemplateArgs2);
|
||||
TEST_CASE(simplifyTemplateArgs3);
|
||||
|
||||
TEST_CASE(template_variadic_1); // #9144
|
||||
TEST_CASE(template_variadic_2); // #4349
|
||||
|
@ -6051,6 +6052,35 @@ private:
|
|||
ASSERT_EQUALS(expected, tok(code));
|
||||
}
|
||||
|
||||
void simplifyTemplateArgs3() { // #11418
|
||||
const char code[] = "template <class T> struct S {};\n"
|
||||
"template<typename T>\n"
|
||||
"T f() {}\n"
|
||||
"template<typename T, typename U>\n"
|
||||
"void g() {\n"
|
||||
" S<decltype(true ? f<T>() : f<U>())> s1;\n"
|
||||
" S<decltype(false ? f<T>() : f<U>())> s2;\n"
|
||||
"}\n"
|
||||
"void h() {\n"
|
||||
" g<int, char>();\n"
|
||||
"}\n";
|
||||
const char expected[] = "struct S<decltype((f<int>()))> ; "
|
||||
"struct S<decltype(f<char>())> ; "
|
||||
"int f<int> ( ) ; "
|
||||
"char f<char> ( ) ; "
|
||||
"void g<int,char> ( ) ; "
|
||||
"void h ( ) { g<int,char> ( ) ; } "
|
||||
"void g<int,char> ( ) { "
|
||||
"S<decltype((f<int>()))> s1 ; "
|
||||
"S<decltype(f<char>())> s2 ; "
|
||||
"} "
|
||||
"int f<int> ( ) { } "
|
||||
"char f<char> ( ) { } "
|
||||
"struct S<decltype((f<int>()))> { } ; "
|
||||
"struct S<decltype(f<char>())> { } ;";
|
||||
ASSERT_EQUALS(expected, tok(code));
|
||||
}
|
||||
|
||||
void template_variadic_1() { // #9144
|
||||
const char code[] = "template <typename...> struct e {};\n"
|
||||
"static_assert(sizeof(e<>) == sizeof(e<int,int>), \"\");";
|
||||
|
|
Loading…
Reference in New Issue