fix overloaded function lookup for explicit instantiations (#2929)
This commit is contained in:
parent
f250e06df7
commit
2bbc7abedc
|
@ -69,8 +69,15 @@ TemplateSimplifier::TokenAndName::TokenAndName(Token *token, const std::string &
|
|||
mFullName(mScope.empty() ? mName : (mScope + " :: " + mName)),
|
||||
mNameToken(nullptr), mParamEnd(nullptr), mFlags(0)
|
||||
{
|
||||
if (mToken)
|
||||
if (mToken) {
|
||||
if (mToken->strAt(1) == "<") {
|
||||
const Token *end = mToken->next()->findClosingBracket();
|
||||
if (end && end->strAt(1) == "(") {
|
||||
isFunction(true);
|
||||
}
|
||||
}
|
||||
mToken->templateSimplifierPointer(this);
|
||||
}
|
||||
}
|
||||
|
||||
TemplateSimplifier::TokenAndName::TokenAndName(Token *token, const std::string &scope, const Token *nameToken, const Token *paramEnd) :
|
||||
|
@ -749,7 +756,18 @@ void TemplateSimplifier::addInstantiation(Token *token, const std::string &scope
|
|||
|
||||
static void getFunctionArguments(const Token *nameToken, std::vector<const Token *> &args)
|
||||
{
|
||||
const Token *argToken = nameToken->tokAt(2);
|
||||
const Token *argToken;
|
||||
|
||||
if (nameToken->strAt(1) == "(")
|
||||
argToken = nameToken->tokAt(2);
|
||||
else if (nameToken->strAt(1) == "<") {
|
||||
const Token *end = nameToken->next()->findClosingBracket();
|
||||
if (end)
|
||||
argToken = end->tokAt(2);
|
||||
else
|
||||
return;
|
||||
} else
|
||||
return;
|
||||
|
||||
if (argToken->str() == ")")
|
||||
return;
|
||||
|
@ -3041,6 +3059,27 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
|||
continue;
|
||||
}
|
||||
|
||||
if (templateDeclaration.isFunction() && instantiation.isFunction()) {
|
||||
std::vector<const Token*> declFuncArgs;
|
||||
getFunctionArguments(templateDeclaration.nameToken(), declFuncArgs);
|
||||
std::vector<const Token*> instFuncParams;
|
||||
getFunctionArguments(instantiation.token(), instFuncParams);
|
||||
|
||||
if (declFuncArgs.size() != instFuncParams.size()) {
|
||||
// check for default arguments
|
||||
const Token* tok = templateDeclaration.nameToken()->tokAt(2);
|
||||
const Token* end = templateDeclaration.nameToken()->linkAt(1);
|
||||
size_t count = 0;
|
||||
for (; tok != end; tok = tok->next()) {
|
||||
if (tok->str() == "=")
|
||||
count++;
|
||||
}
|
||||
|
||||
if (instFuncParams.size() < (declFuncArgs.size() - count) || instFuncParams.size() > declFuncArgs.size())
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// A global function can't be called through a pointer.
|
||||
if (templateDeclaration.isFunction() && templateDeclaration.scope().empty() &&
|
||||
(instantiation.token()->strAt(-1) == "." ||
|
||||
|
@ -3300,7 +3339,26 @@ static bool specMatch(
|
|||
if (decl.isPartialSpecialization() || decl.isSpecialization() || decl.isAlias() || decl.isFriend())
|
||||
return false;
|
||||
|
||||
return spec.isSameFamily(decl);
|
||||
if (!spec.isSameFamily(decl))
|
||||
return false;
|
||||
|
||||
// make sure the scopes and names match
|
||||
if (spec.fullName() == decl.fullName()) {
|
||||
if (spec.isFunction()) {
|
||||
std::vector<const Token*> specArgs;
|
||||
std::vector<const Token*> declArgs;
|
||||
getFunctionArguments(spec.nameToken(), specArgs);
|
||||
getFunctionArguments(decl.nameToken(), declArgs);
|
||||
|
||||
if (specArgs.size() == declArgs.size()) {
|
||||
// @todo make sure function parameters also match
|
||||
return true;
|
||||
}
|
||||
} else
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void TemplateSimplifier::getSpecializations()
|
||||
|
@ -3310,26 +3368,18 @@ void TemplateSimplifier::getSpecializations()
|
|||
if (spec.isSpecialization()) {
|
||||
bool found = false;
|
||||
for (auto & decl : mTemplateDeclarations) {
|
||||
if (!specMatch(spec, decl))
|
||||
continue;
|
||||
|
||||
// make sure the scopes and names match
|
||||
if (spec.fullName() == decl.fullName()) {
|
||||
// @todo make sure function parameters also match
|
||||
if (specMatch(spec, decl)) {
|
||||
mTemplateSpecializationMap[spec.token()] = decl.token();
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
for (auto & decl : mTemplateForwardDeclarations) {
|
||||
if (!specMatch(spec, decl))
|
||||
continue;
|
||||
|
||||
// make sure the scopes and names match
|
||||
if (spec.fullName() == decl.fullName()) {
|
||||
// @todo make sure function parameters also match
|
||||
if (specMatch(spec, decl)) {
|
||||
mTemplateSpecializationMap[spec.token()] = decl.token();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3344,26 +3394,18 @@ void TemplateSimplifier::getPartialSpecializations()
|
|||
if (spec.isPartialSpecialization()) {
|
||||
bool found = false;
|
||||
for (auto & decl : mTemplateDeclarations) {
|
||||
if (!specMatch(spec, decl))
|
||||
continue;
|
||||
|
||||
// make sure the scopes and names match
|
||||
if (spec.fullName() == decl.fullName()) {
|
||||
// @todo make sure function parameters also match
|
||||
if (specMatch(spec, decl)) {
|
||||
mTemplatePartialSpecializationMap[spec.token()] = decl.token();
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
for (auto & decl : mTemplateForwardDeclarations) {
|
||||
if (!specMatch(spec, decl))
|
||||
continue;
|
||||
|
||||
// make sure the scopes and names match
|
||||
if (spec.fullName() == decl.fullName()) {
|
||||
// @todo make sure function parameters also match
|
||||
if (specMatch(spec, decl)) {
|
||||
mTemplatePartialSpecializationMap[spec.token()] = decl.token();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -202,6 +202,7 @@ private:
|
|||
TEST_CASE(template157); // #9854
|
||||
TEST_CASE(template158); // daca crash
|
||||
TEST_CASE(template159); // #9886
|
||||
TEST_CASE(template160);
|
||||
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)
|
||||
|
@ -1971,8 +1972,8 @@ private:
|
|||
void template87() {
|
||||
const char code[] = "template<typename T>\n"
|
||||
"T f1(T t) { return t; }\n"
|
||||
"template const char * f1<const char *>();\n"
|
||||
"template const char & f1<const char &>();";
|
||||
"template const char * f1<const char *>(const char *);\n"
|
||||
"template const char & f1<const char &>(const char &);";
|
||||
const char exp[] = "const char * f1<constchar*> ( const char * t ) ; "
|
||||
"const char & f1<constchar&> ( const char & t ) ; "
|
||||
"const char * f1<constchar*> ( const char * t ) { return t ; } "
|
||||
|
@ -4045,6 +4046,28 @@ private:
|
|||
ASSERT_EQUALS(exp, tok(code));
|
||||
}
|
||||
|
||||
void template160() {
|
||||
const char code[] = "struct Fred {\n"
|
||||
" template <typename T> static void foo() { }\n"
|
||||
" template <typename T> static void foo(T) { }\n"
|
||||
"};\n"
|
||||
"template void Fred::foo<char>();\n"
|
||||
"template <> void Fred::foo<bool>() { }\n"
|
||||
"template void Fred::foo<float>(float);\n"
|
||||
"template <> void Fred::foo<int>(int) { }";
|
||||
const char exp[] = "struct Fred { "
|
||||
"static void foo<bool> ( ) ; "
|
||||
"static void foo<char> ( ) ; "
|
||||
"static void foo<int> ( int ) ; "
|
||||
"static void foo<float> ( float ) ; "
|
||||
"} ; "
|
||||
"void Fred :: foo<bool> ( ) { } "
|
||||
"void Fred :: foo<int> ( int ) { } "
|
||||
"void Fred :: foo<float> ( float ) { } "
|
||||
"void Fred :: foo<char> ( ) { }";
|
||||
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