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)),
|
mFullName(mScope.empty() ? mName : (mScope + " :: " + mName)),
|
||||||
mNameToken(nullptr), mParamEnd(nullptr), mFlags(0)
|
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);
|
mToken->templateSimplifierPointer(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TemplateSimplifier::TokenAndName::TokenAndName(Token *token, const std::string &scope, const Token *nameToken, const Token *paramEnd) :
|
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)
|
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() == ")")
|
if (argToken->str() == ")")
|
||||||
return;
|
return;
|
||||||
|
@ -3041,6 +3059,27 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
||||||
continue;
|
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.
|
// A global function can't be called through a pointer.
|
||||||
if (templateDeclaration.isFunction() && templateDeclaration.scope().empty() &&
|
if (templateDeclaration.isFunction() && templateDeclaration.scope().empty() &&
|
||||||
(instantiation.token()->strAt(-1) == "." ||
|
(instantiation.token()->strAt(-1) == "." ||
|
||||||
|
@ -3300,7 +3339,26 @@ static bool specMatch(
|
||||||
if (decl.isPartialSpecialization() || decl.isSpecialization() || decl.isAlias() || decl.isFriend())
|
if (decl.isPartialSpecialization() || decl.isSpecialization() || decl.isAlias() || decl.isFriend())
|
||||||
return false;
|
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()
|
void TemplateSimplifier::getSpecializations()
|
||||||
|
@ -3310,26 +3368,18 @@ void TemplateSimplifier::getSpecializations()
|
||||||
if (spec.isSpecialization()) {
|
if (spec.isSpecialization()) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (auto & decl : mTemplateDeclarations) {
|
for (auto & decl : mTemplateDeclarations) {
|
||||||
if (!specMatch(spec, decl))
|
if (specMatch(spec, decl)) {
|
||||||
continue;
|
|
||||||
|
|
||||||
// make sure the scopes and names match
|
|
||||||
if (spec.fullName() == decl.fullName()) {
|
|
||||||
// @todo make sure function parameters also match
|
|
||||||
mTemplateSpecializationMap[spec.token()] = decl.token();
|
mTemplateSpecializationMap[spec.token()] = decl.token();
|
||||||
found = true;
|
found = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
for (auto & decl : mTemplateForwardDeclarations) {
|
for (auto & decl : mTemplateForwardDeclarations) {
|
||||||
if (!specMatch(spec, decl))
|
if (specMatch(spec, decl)) {
|
||||||
continue;
|
|
||||||
|
|
||||||
// make sure the scopes and names match
|
|
||||||
if (spec.fullName() == decl.fullName()) {
|
|
||||||
// @todo make sure function parameters also match
|
|
||||||
mTemplateSpecializationMap[spec.token()] = decl.token();
|
mTemplateSpecializationMap[spec.token()] = decl.token();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3344,26 +3394,18 @@ void TemplateSimplifier::getPartialSpecializations()
|
||||||
if (spec.isPartialSpecialization()) {
|
if (spec.isPartialSpecialization()) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (auto & decl : mTemplateDeclarations) {
|
for (auto & decl : mTemplateDeclarations) {
|
||||||
if (!specMatch(spec, decl))
|
if (specMatch(spec, decl)) {
|
||||||
continue;
|
|
||||||
|
|
||||||
// make sure the scopes and names match
|
|
||||||
if (spec.fullName() == decl.fullName()) {
|
|
||||||
// @todo make sure function parameters also match
|
|
||||||
mTemplatePartialSpecializationMap[spec.token()] = decl.token();
|
mTemplatePartialSpecializationMap[spec.token()] = decl.token();
|
||||||
found = true;
|
found = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
for (auto & decl : mTemplateForwardDeclarations) {
|
for (auto & decl : mTemplateForwardDeclarations) {
|
||||||
if (!specMatch(spec, decl))
|
if (specMatch(spec, decl)) {
|
||||||
continue;
|
|
||||||
|
|
||||||
// make sure the scopes and names match
|
|
||||||
if (spec.fullName() == decl.fullName()) {
|
|
||||||
// @todo make sure function parameters also match
|
|
||||||
mTemplatePartialSpecializationMap[spec.token()] = decl.token();
|
mTemplatePartialSpecializationMap[spec.token()] = decl.token();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,6 +202,7 @@ private:
|
||||||
TEST_CASE(template157); // #9854
|
TEST_CASE(template157); // #9854
|
||||||
TEST_CASE(template158); // daca crash
|
TEST_CASE(template158); // daca crash
|
||||||
TEST_CASE(template159); // #9886
|
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_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)
|
||||||
|
@ -1971,8 +1972,8 @@ private:
|
||||||
void template87() {
|
void template87() {
|
||||||
const char code[] = "template<typename T>\n"
|
const char code[] = "template<typename T>\n"
|
||||||
"T f1(T t) { return t; }\n"
|
"T f1(T t) { return t; }\n"
|
||||||
"template const char * f1<const char *>();\n"
|
"template const char * f1<const char *>(const char *);\n"
|
||||||
"template const char & f1<const char &>();";
|
"template const char & f1<const char &>(const char &);";
|
||||||
const char exp[] = "const char * f1<constchar*> ( const char * t ) ; "
|
const char exp[] = "const char * f1<constchar*> ( const char * t ) ; "
|
||||||
"const char & f1<constchar&> ( const char & t ) ; "
|
"const char & f1<constchar&> ( const char & t ) ; "
|
||||||
"const char * f1<constchar*> ( const char * t ) { return t ; } "
|
"const char * f1<constchar*> ( const char * t ) { return t ; } "
|
||||||
|
@ -4045,6 +4046,28 @@ private:
|
||||||
ASSERT_EQUALS(exp, tok(code));
|
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>> {..};
|
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