add support for template constructors (#2911)
This commit is contained in:
parent
22114e3266
commit
1ea89bcad8
|
@ -2102,7 +2102,11 @@ Function::Function(const Tokenizer *mTokenizer,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class constructor/destructor
|
// class constructor/destructor
|
||||||
else if (tokenDef->str() == scope->className && scope->type != Scope::ScopeType::eNamespace) {
|
else if (((tokenDef->str() == scope->className) ||
|
||||||
|
(tokenDef->str().substr(0, scope->className.size()) == scope->className &&
|
||||||
|
tokenDef->str().size() > scope->className.size() + 1 &&
|
||||||
|
tokenDef->str()[scope->className.size() + 1] == '<')) &&
|
||||||
|
scope->type != Scope::ScopeType::eNamespace) {
|
||||||
// destructor
|
// destructor
|
||||||
if (tokenDef->previous()->str() == "~")
|
if (tokenDef->previous()->str() == "~")
|
||||||
type = Function::eDestructor;
|
type = Function::eDestructor;
|
||||||
|
|
|
@ -673,15 +673,6 @@ bool TemplateSimplifier::removeTemplate(Token *tok)
|
||||||
if (tok2->str() == ">")
|
if (tok2->str() == ">")
|
||||||
countgt++;
|
countgt++;
|
||||||
|
|
||||||
// don't remove constructor
|
|
||||||
if (tok2->str() == "explicit" ||
|
|
||||||
(countgt == 1 && Token::Match(tok2->previous(), "> %type% (") &&
|
|
||||||
Tokenizer::startOfExecutableScope(tok2->linkAt(1)))) {
|
|
||||||
eraseTokens(tok, tok2);
|
|
||||||
deleteToken(tok);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tok2->str() == ";") {
|
if (tok2->str() == ";") {
|
||||||
tok2 = tok2->next();
|
tok2 = tok2->next();
|
||||||
eraseTokens(tok, tok2);
|
eraseTokens(tok, tok2);
|
||||||
|
@ -895,8 +886,9 @@ void TemplateSimplifier::getTemplateInstantiations()
|
||||||
// get all declarations with this name
|
// get all declarations with this name
|
||||||
for (auto pos = functionNameMap.lower_bound(tok->str());
|
for (auto pos = functionNameMap.lower_bound(tok->str());
|
||||||
pos != functionNameMap.upper_bound(tok->str()); ++pos) {
|
pos != functionNameMap.upper_bound(tok->str()); ++pos) {
|
||||||
// look for declaration with same qualification
|
// look for declaration with same qualification or constructor with same qualification
|
||||||
if (pos->second->fullName() == fullName) {
|
if (pos->second->fullName() == fullName ||
|
||||||
|
(pos->second->scope() == fullName && tok->str() == pos->second->name())) {
|
||||||
std::vector<const Token *> templateParams;
|
std::vector<const Token *> templateParams;
|
||||||
getTemplateParametersInDeclaration(pos->second->token()->tokAt(2), templateParams);
|
getTemplateParametersInDeclaration(pos->second->token()->tokAt(2), templateParams);
|
||||||
|
|
||||||
|
@ -1700,8 +1692,13 @@ void TemplateSimplifier::expandTemplate(
|
||||||
end = end->next();
|
end = end->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isStatic)
|
if (isStatic) {
|
||||||
dst->insertToken("static", "", true);
|
dst->insertToken("static", "", true);
|
||||||
|
if (start) {
|
||||||
|
dst->previous()->linenr(start->linenr());
|
||||||
|
dst->previous()->column(start->column());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::map<const Token *, Token *> links;
|
std::map<const Token *, Token *> links;
|
||||||
bool inAssignment = false;
|
bool inAssignment = false;
|
||||||
|
@ -1734,6 +1731,8 @@ void TemplateSimplifier::expandTemplate(
|
||||||
else if (typetok->str() == ")")
|
else if (typetok->str() == ")")
|
||||||
--typeindentlevel;
|
--typeindentlevel;
|
||||||
dst->insertToken(typetok->str(), typetok->originalName(), true);
|
dst->insertToken(typetok->str(), typetok->originalName(), true);
|
||||||
|
dst->previous()->linenr(start->linenr());
|
||||||
|
dst->previous()->column(start->column());
|
||||||
Token *previous = dst->previous();
|
Token *previous = dst->previous();
|
||||||
previous->isTemplateArg(true);
|
previous->isTemplateArg(true);
|
||||||
previous->isSigned(typetok->isSigned());
|
previous->isSigned(typetok->isSigned());
|
||||||
|
@ -1760,6 +1759,8 @@ void TemplateSimplifier::expandTemplate(
|
||||||
}
|
}
|
||||||
if (pointerType && Token::simpleMatch(dst1, "const")) {
|
if (pointerType && Token::simpleMatch(dst1, "const")) {
|
||||||
dst->insertToken("const", dst1->originalName(), true);
|
dst->insertToken("const", dst1->originalName(), true);
|
||||||
|
dst->previous()->linenr(start->linenr());
|
||||||
|
dst->previous()->column(start->column());
|
||||||
dst1->deleteThis();
|
dst1->deleteThis();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1772,10 +1773,14 @@ void TemplateSimplifier::expandTemplate(
|
||||||
(start->strAt(-1) == "." || Token::simpleMatch(start->tokAt(-2), ". template")))) {
|
(start->strAt(-1) == "." || Token::simpleMatch(start->tokAt(-2), ". template")))) {
|
||||||
if (start->strAt(1) != "<" || Token::Match(start, newName.c_str()) || !inAssignment) {
|
if (start->strAt(1) != "<" || Token::Match(start, newName.c_str()) || !inAssignment) {
|
||||||
dst->insertToken(newName, "", true);
|
dst->insertToken(newName, "", true);
|
||||||
|
dst->previous()->linenr(start->linenr());
|
||||||
|
dst->previous()->column(start->column());
|
||||||
if (start->strAt(1) == "<")
|
if (start->strAt(1) == "<")
|
||||||
start = start->next()->findClosingBracket();
|
start = start->next()->findClosingBracket();
|
||||||
} else {
|
} else {
|
||||||
dst->insertToken(start->str(), "", true);
|
dst->insertToken(start->str(), "", true);
|
||||||
|
dst->previous()->linenr(start->linenr());
|
||||||
|
dst->previous()->column(start->column());
|
||||||
newInstantiations.emplace_back(dst->previous(), templateDeclaration.scope());
|
newInstantiations.emplace_back(dst->previous(), templateDeclaration.scope());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1797,6 +1802,8 @@ void TemplateSimplifier::expandTemplate(
|
||||||
if (Token::simpleMatch(inst.token(), name.c_str(), name.size())) {
|
if (Token::simpleMatch(inst.token(), name.c_str(), name.size())) {
|
||||||
// use the instantiated name
|
// use the instantiated name
|
||||||
dst->insertToken(name, "", true);
|
dst->insertToken(name, "", true);
|
||||||
|
dst->previous()->linenr(start->linenr());
|
||||||
|
dst->previous()->column(start->column());
|
||||||
start = closing;
|
start = closing;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1805,12 +1812,16 @@ void TemplateSimplifier::expandTemplate(
|
||||||
// just copy the token if it wasn't instantiated
|
// just copy the token if it wasn't instantiated
|
||||||
if (start != closing) {
|
if (start != closing) {
|
||||||
dst->insertToken(start->str(), start->originalName(), true);
|
dst->insertToken(start->str(), start->originalName(), true);
|
||||||
|
dst->previous()->linenr(start->linenr());
|
||||||
|
dst->previous()->column(start->column());
|
||||||
dst->previous()->isSigned(start->isSigned());
|
dst->previous()->isSigned(start->isSigned());
|
||||||
dst->previous()->isUnsigned(start->isUnsigned());
|
dst->previous()->isUnsigned(start->isUnsigned());
|
||||||
dst->previous()->isLong(start->isLong());
|
dst->previous()->isLong(start->isLong());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dst->insertToken(start->str(), start->originalName(), true);
|
dst->insertToken(start->str(), start->originalName(), true);
|
||||||
|
dst->previous()->linenr(start->linenr());
|
||||||
|
dst->previous()->column(start->column());
|
||||||
dst->previous()->isSigned(start->isSigned());
|
dst->previous()->isSigned(start->isSigned());
|
||||||
dst->previous()->isUnsigned(start->isUnsigned());
|
dst->previous()->isUnsigned(start->isUnsigned());
|
||||||
dst->previous()->isLong(start->isLong());
|
dst->previous()->isLong(start->isLong());
|
||||||
|
@ -1833,6 +1844,8 @@ void TemplateSimplifier::expandTemplate(
|
||||||
start = start->next();
|
start = start->next();
|
||||||
}
|
}
|
||||||
dst->insertToken(";", "", true);
|
dst->insertToken(";", "", true);
|
||||||
|
dst->previous()->linenr(dst->tokAt(-2)->linenr());
|
||||||
|
dst->previous()->column(dst->tokAt(-2)->column() + 1);
|
||||||
|
|
||||||
if (isVariable || isFunction)
|
if (isVariable || isFunction)
|
||||||
simplifyTemplateArgs(dstStart, dst);
|
simplifyTemplateArgs(dstStart, dst);
|
||||||
|
@ -3038,7 +3051,9 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
if (!Token::Match(instantiation.token(), "%name% <"))
|
if (!Token::Match(instantiation.token(), "%name% <"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (instantiation.fullName() != templateDeclaration.fullName()) {
|
if (!((instantiation.fullName() == templateDeclaration.fullName()) ||
|
||||||
|
(instantiation.name() == templateDeclaration.name() &&
|
||||||
|
instantiation.fullName() == templateDeclaration.scope()))) {
|
||||||
// FIXME: fallback to not matching scopes until type deduction works
|
// FIXME: fallback to not matching scopes until type deduction works
|
||||||
|
|
||||||
// names must match
|
// names must match
|
||||||
|
|
|
@ -252,6 +252,7 @@ private:
|
||||||
TEST_CASE(templateTypeDeduction2);
|
TEST_CASE(templateTypeDeduction2);
|
||||||
TEST_CASE(templateTypeDeduction3);
|
TEST_CASE(templateTypeDeduction3);
|
||||||
TEST_CASE(templateTypeDeduction4); // #9983
|
TEST_CASE(templateTypeDeduction4); // #9983
|
||||||
|
TEST_CASE(templateTypeDeduction5);
|
||||||
|
|
||||||
TEST_CASE(simplifyTemplateArgs1);
|
TEST_CASE(simplifyTemplateArgs1);
|
||||||
TEST_CASE(simplifyTemplateArgs2);
|
TEST_CASE(simplifyTemplateArgs2);
|
||||||
|
@ -5374,6 +5375,73 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void templateTypeDeduction5() {
|
||||||
|
{
|
||||||
|
const char code[] = "class Fred {\n"
|
||||||
|
"public:\n"
|
||||||
|
" template <class T> Fred(T t) { }\n"
|
||||||
|
"};\n"
|
||||||
|
"Fred fred1 = Fred(0);\n"
|
||||||
|
"Fred fred2 = Fred(0.0);\n"
|
||||||
|
"Fred fred3 = Fred(\"zero\");\n"
|
||||||
|
"Fred fred4 = Fred(false);";
|
||||||
|
const char exp[] = "class Fred { "
|
||||||
|
"public: "
|
||||||
|
"Fred<int> ( int t ) ; "
|
||||||
|
"Fred<double> ( double t ) ; "
|
||||||
|
"Fred<constchar*> ( const char * t ) ; "
|
||||||
|
"Fred<bool> ( bool t ) ; "
|
||||||
|
"} ; "
|
||||||
|
"Fred fred1 ; fred1 = Fred<int> ( 0 ) ; "
|
||||||
|
"Fred fred2 ; fred2 = Fred<double> ( 0.0 ) ; "
|
||||||
|
"Fred fred3 ; fred3 = Fred<constchar*> ( \"zero\" ) ; "
|
||||||
|
"Fred fred4 ; fred4 = Fred<bool> ( false ) ; "
|
||||||
|
"Fred :: Fred<int> ( int t ) { } "
|
||||||
|
"Fred :: Fred<double> ( double t ) { } "
|
||||||
|
"Fred :: Fred<constchar*> ( const char * t ) { } "
|
||||||
|
"Fred :: Fred<bool> ( bool t ) { }";
|
||||||
|
ASSERT_EQUALS(exp, tok(code));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const char code[] = "namespace NS {\n"
|
||||||
|
"class Fred {\n"
|
||||||
|
"public:\n"
|
||||||
|
" template <class T> Fred(T t) { }\n"
|
||||||
|
"};\n"
|
||||||
|
"Fred fred1 = Fred(0);\n"
|
||||||
|
"Fred fred2 = Fred(0.0);\n"
|
||||||
|
"Fred fred3 = Fred(\"zero\");\n"
|
||||||
|
"Fred fred4 = Fred(false);\n"
|
||||||
|
"}\n"
|
||||||
|
"NS::Fred fred1 = NS::Fred(0);\n"
|
||||||
|
"NS::Fred fred2 = NS::Fred(0.0);\n"
|
||||||
|
"NS::Fred fred3 = NS::Fred(\"zero\");\n"
|
||||||
|
"NS::Fred fred4 = NS::Fred(false);\n";
|
||||||
|
const char exp[] = "namespace NS { "
|
||||||
|
"class Fred { "
|
||||||
|
"public: "
|
||||||
|
"Fred<int> ( int t ) ; "
|
||||||
|
"Fred<double> ( double t ) ; "
|
||||||
|
"Fred<constchar*> ( const char * t ) ; "
|
||||||
|
"Fred<bool> ( bool t ) ; "
|
||||||
|
"} ; "
|
||||||
|
"Fred fred1 ; fred1 = Fred<int> ( 0 ) ; "
|
||||||
|
"Fred fred2 ; fred2 = Fred<double> ( 0.0 ) ; "
|
||||||
|
"Fred fred3 ; fred3 = Fred<constchar*> ( \"zero\" ) ; "
|
||||||
|
"Fred fred4 ; fred4 = Fred<bool> ( false ) ; "
|
||||||
|
"} "
|
||||||
|
"NS :: Fred fred1 ; fred1 = NS :: Fred<int> ( 0 ) ; "
|
||||||
|
"NS :: Fred fred2 ; fred2 = NS :: Fred<double> ( 0.0 ) ; "
|
||||||
|
"NS :: Fred fred3 ; fred3 = NS :: Fred<constchar*> ( \"zero\" ) ; "
|
||||||
|
"NS :: Fred fred4 ; fred4 = NS :: Fred<bool> ( false ) ; "
|
||||||
|
"NS :: Fred :: Fred<int> ( int t ) { } "
|
||||||
|
"NS :: Fred :: Fred<double> ( double t ) { } "
|
||||||
|
"NS :: Fred :: Fred<constchar*> ( const char * t ) { } "
|
||||||
|
"NS :: Fred :: Fred<bool> ( bool t ) { }";
|
||||||
|
ASSERT_EQUALS(exp, tok(code));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void simplifyTemplateArgs1() {
|
void simplifyTemplateArgs1() {
|
||||||
ASSERT_EQUALS("foo<2> = 2 ; foo<2> ;", tok("template<int N> foo = N; foo < ( 2 ) >;"));
|
ASSERT_EQUALS("foo<2> = 2 ; foo<2> ;", tok("template<int N> foo = N; foo < ( 2 ) >;"));
|
||||||
ASSERT_EQUALS("foo<2> = 2 ; foo<2> ;", tok("template<int N> foo = N; foo < 1 + 1 >;"));
|
ASSERT_EQUALS("foo<2> = 2 ; foo<2> ;", tok("template<int N> foo = N; foo < 1 + 1 >;"));
|
||||||
|
|
|
@ -5292,7 +5292,6 @@ private:
|
||||||
" fn2<int>();\n"
|
" fn2<int>();\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
ASSERT_EQUALS("void fn2<int> ( int t = [ ] { return 1 ; } ( ) ) ;\n"
|
ASSERT_EQUALS("void fn2<int> ( int t = [ ] { return 1 ; } ( ) ) ;\n"
|
||||||
"\n"
|
|
||||||
"\n"
|
"\n"
|
||||||
"int main ( )\n"
|
"int main ( )\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
|
Loading…
Reference in New Issue