This commit is contained in:
parent
cb02628c7c
commit
503a5dd441
|
@ -985,7 +985,11 @@ void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration)
|
|||
// template parameters with default value has syntax such as:
|
||||
// x = y
|
||||
// this list will contain all the '=' tokens for such arguments
|
||||
std::list<Token *> eq;
|
||||
struct Default {
|
||||
Token *eq;
|
||||
Token *end;
|
||||
};
|
||||
std::list<Default> eq;
|
||||
// and this set the position of parameters with a default value
|
||||
std::set<std::size_t> defaultedArgPos;
|
||||
|
||||
|
@ -1012,9 +1016,11 @@ void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration)
|
|||
|
||||
// end of template parameters?
|
||||
if (tok->str() == ">") {
|
||||
if (templateParmDepth<2)
|
||||
if (templateParmDepth<2) {
|
||||
if (!eq.empty())
|
||||
eq.back().end = tok;
|
||||
break;
|
||||
else
|
||||
} else
|
||||
--templateParmDepth;
|
||||
}
|
||||
|
||||
|
@ -1023,13 +1029,16 @@ void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration)
|
|||
typeParameterNames[tok->strAt(1)] = templatepar - 1;
|
||||
|
||||
// next template parameter
|
||||
if (tok->str() == "," && (1 == templateParmDepth)) // Ticket #5823: Properly count parameters
|
||||
if (tok->str() == "," && (1 == templateParmDepth)) { // Ticket #5823: Properly count parameters
|
||||
if (!eq.empty())
|
||||
eq.back().end = tok;
|
||||
++templatepar;
|
||||
}
|
||||
|
||||
// default parameter value?
|
||||
else if (Token::Match(tok, "= !!>")) {
|
||||
if (defaultedArgPos.insert(templatepar).second) {
|
||||
eq.push_back(tok);
|
||||
eq.push_back(Default{tok, nullptr});
|
||||
} else {
|
||||
// Ticket #5605: Syntax error (two equal signs for the same parameter), bail out
|
||||
eq.clear();
|
||||
|
@ -1085,25 +1094,30 @@ void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration)
|
|||
|
||||
if (tok && tok->str() == ">") {
|
||||
tok = tok->previous();
|
||||
std::list<Token *>::const_iterator it = eq.begin();
|
||||
std::list<Default>::const_iterator it = eq.begin();
|
||||
for (std::size_t i = (templatepar - eq.size()); it != eq.end() && i < usedpar; ++i)
|
||||
++it;
|
||||
int count = 0;
|
||||
while (it != eq.end()) {
|
||||
int indentlevel = 0;
|
||||
// check for end
|
||||
if (!it->end) {
|
||||
if (mSettings->debugwarnings) {
|
||||
const std::list<const Token*> locationList(1, it->eq);
|
||||
const ErrorMessage errmsg(locationList, &mTokenizer->list,
|
||||
Severity::debug,
|
||||
"noparamend",
|
||||
"TemplateSimplifier couldn't find end of template parameter.",
|
||||
false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ((usedpar + count) && usedpar <= (instantiationArgs.size() + count)) {
|
||||
tok->insertToken(",");
|
||||
tok = tok->next();
|
||||
}
|
||||
const Token *from = (*it)->next();
|
||||
std::stack<Token *> links;
|
||||
while (from && (!links.empty() || indentlevel || !Token::Match(from, ",|>"))) {
|
||||
if (from->str() == "<" &&
|
||||
(from->strAt(1) == ">" || (from->previous()->isName() &&
|
||||
typeParameterNames.find(from->strAt(-1)) == typeParameterNames.end())))
|
||||
++indentlevel;
|
||||
else if (from->str() == ">" && (links.empty() || links.top()->str() == "<" || indentlevel))
|
||||
--indentlevel;
|
||||
for (const Token* from = it->eq->next(); from && from != it->end; from = from->next()) {
|
||||
auto entry = typeParameterNames.find(from->str());
|
||||
if (entry != typeParameterNames.end() && entry->second < instantiationArgs.size()) {
|
||||
for (const Token *tok1 : instantiationArgs[entry->second]) {
|
||||
|
@ -1128,7 +1142,6 @@ void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration)
|
|||
links.pop();
|
||||
}
|
||||
}
|
||||
from = from->next();
|
||||
}
|
||||
++it;
|
||||
count++;
|
||||
|
@ -1139,7 +1152,8 @@ void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration)
|
|||
simplifyTemplateArgs(instantiation.token()->next(), instantiationEnd);
|
||||
}
|
||||
|
||||
for (Token * const eqtok : eq) {
|
||||
for (const auto & entry : eq) {
|
||||
Token *const eqtok = entry.eq;
|
||||
Token *tok2;
|
||||
int indentlevel = 0;
|
||||
for (tok2 = eqtok->next(); tok2; tok2 = tok2->next()) {
|
||||
|
|
|
@ -208,6 +208,7 @@ private:
|
|||
TEST_CASE(template163); // #9685 syntax error
|
||||
TEST_CASE(template164); // #9394
|
||||
TEST_CASE(template165); // #10032 syntax error
|
||||
TEST_CASE(template166); // #10081 hang
|
||||
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_enum); // #6299 Syntax error in complex enum declaration (including template)
|
||||
|
@ -4178,6 +4179,16 @@ private:
|
|||
ASSERT_EQUALS(exp, tok(code));
|
||||
}
|
||||
|
||||
void template166() { // #10081 hang
|
||||
const char code[] = "template <typename T, size_t k = (T::s < 3) ? 0 : 3>\n"
|
||||
"void foo() {}\n"
|
||||
"foo<T>();";
|
||||
const char exp[] = "void foo<T,(T::s<3)?0:3> ( ) ; "
|
||||
"foo<T,(T::s<3)?0:3> ( ) ; "
|
||||
"void foo<T,(T::s<3)?0:3> ( ) { }";
|
||||
ASSERT_EQUALS(exp, tok(code));
|
||||
}
|
||||
|
||||
void template_specialization_1() { // #7868 - template specialization template <typename T> struct S<C<T>> {..};
|
||||
const char code[] = "template <typename T> struct C {};\n"
|
||||
"template <typename T> struct S {a};\n"
|
||||
|
|
Loading…
Reference in New Issue