Skip to content

Commit da91ce2

Browse files
IOBYTEdanmar
authored andcommitted
Fixed danmar#6183 (TemplateSimplifier: Does not handle methods) (danmar#1546)
* Fixed danmar#6183 (TemplateSimplifier: Does not handle methods) * Fix function lookup.
1 parent e4677ae commit da91ce2

File tree

4 files changed

+294
-41
lines changed

4 files changed

+294
-41
lines changed

lib/templatesimplifier.cpp

Lines changed: 106 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,9 @@ bool TemplateSimplifier::getTemplateDeclarations()
497497
tok2 = tok2->link();
498498
else if (tok2->str() == ")")
499499
break;
500+
// skip decltype(...)
501+
else if (Token::Match(tok2, "decltype ("))
502+
tok2 = tok2->linkAt(1);
500503
// Declaration => add to mTemplateForwardDeclarations
501504
else if (tok2->str() == ";") {
502505
const int namepos = getTemplateNamePosition(parmEnd, true);
@@ -891,17 +894,24 @@ bool TemplateSimplifier::getTemplateNamePositionTemplateFunction(const Token *to
891894
while (tok && tok->next()) {
892895
if (Token::Match(tok->next(), ";|{"))
893896
return false;
894-
else if (Token::Match(tok->next(), "%type% <")) {
897+
// skip decltype(...)
898+
else if (Token::Match(tok, "decltype (")) {
899+
const Token * end = tok->linkAt(1);
900+
while (tok && tok != end) {
901+
tok = tok->next();
902+
namepos++;
903+
}
904+
} else if (Token::Match(tok->next(), "%type% <")) {
895905
const Token *closing = tok->tokAt(2)->findClosingBracket();
896906
if (closing) {
897-
if (closing->strAt(1) == "(" && mTokenizer->isFunctionHead(closing->tokAt(2), ";|{|:"))
907+
if (closing->strAt(1) == "(" && Tokenizer::isFunctionHead(closing->next(), ";|{|:", true))
898908
return true;
899909
while (tok && tok->next() && tok->next() != closing) {
900910
tok = tok->next();
901911
namepos++;
902912
}
903913
}
904-
} else if (Token::Match(tok->next(), "%type% (") && mTokenizer->isFunctionHead(tok->tokAt(2), ";|{|:")) {
914+
} else if (Token::Match(tok->next(), "%type% (") && Tokenizer::isFunctionHead(tok->tokAt(2), ";|{|:", true)) {
905915
return true;
906916
}
907917
tok = tok->next();
@@ -984,15 +994,19 @@ void TemplateSimplifier::expandTemplate(
984994
const Token *endOfTemplateDefinition = nullptr;
985995
const Token * const templateDeclarationNameToken = templateDeclarationToken->tokAt(getTemplateNamePosition(templateDeclarationToken));
986996
const bool isClass = Token::Match(templateDeclarationToken->next(), "class|struct|union %name% <|{|:");
987-
const bool isFunction = templateDeclarationNameToken->strAt(1) == "(";
997+
const bool isFunction = templateDeclarationNameToken->strAt(1) == "(" ||
998+
(templateDeclarationNameToken->strAt(1) == "<" && templateDeclarationNameToken->next()->findClosingBracket()->strAt(1) == "(");
999+
const bool isSpecialization = Token::Match(templateDeclaration.token, "template < >");
9881000

9891001
// add forward declarations
9901002
if (copy && isClass) {
9911003
templateDeclaration.token->insertToken(templateDeclarationToken->strAt(1), "", true);
9921004
templateDeclaration.token->insertToken(newName, "", true);
9931005
templateDeclaration.token->insertToken(";", "", true);
994-
} else if (copy && isFunction) {
1006+
} else if (isFunction && (copy || (!copy && isSpecialization))) {
9951007
Token * dst = templateDeclaration.token;
1008+
bool isStatic = false;
1009+
std::string scope;
9961010
Token * start;
9971011
Token * end;
9981012
auto it = mTemplateForwardDeclarationsMap.find(dst);
@@ -1003,8 +1017,21 @@ void TemplateSimplifier::expandTemplate(
10031017
start = temp1->next();
10041018
end = temp2->linkAt(1)->next();
10051019
} else {
1020+
auto it2 = mTemplateUserSpecializationMap.find(dst);
1021+
if (it2 != mTemplateUserSpecializationMap.end()) {
1022+
dst = it2->second;
1023+
isStatic = dst->next()->findClosingBracket()->strAt(1) == "static";
1024+
const Token * temp = templateDeclarationNameToken;
1025+
while (Token::Match(temp->tokAt(-2), "%name% ::")) {
1026+
scope.insert(0, temp->strAt(-2) + " :: ");
1027+
temp = temp->tokAt(-2);
1028+
}
1029+
}
10061030
start = templateDeclarationToken->next();
1007-
end = templateDeclarationNameToken->linkAt(1)->next();
1031+
if (templateDeclarationNameToken->strAt(1) == "(")
1032+
end = templateDeclarationNameToken->linkAt(1)->next();
1033+
else
1034+
end = templateDeclarationNameToken->next()->findClosingBracket()->linkAt(1)->next();
10081035
}
10091036
unsigned int typeindentlevel = 0;
10101037
while (!(typeindentlevel == 0 && Token::Match(end, ";|{|:"))) {
@@ -1015,6 +1042,9 @@ void TemplateSimplifier::expandTemplate(
10151042
end = end->next();
10161043
}
10171044

1045+
if (isStatic)
1046+
dst->insertToken("static", "", true);
1047+
10181048
std::map<const Token *, Token *> links;
10191049
while (start && start != end) {
10201050
unsigned int itype = 0;
@@ -1041,7 +1071,11 @@ void TemplateSimplifier::expandTemplate(
10411071
dst->previous()->isLong(typetok->isLong());
10421072
}
10431073
} else {
1044-
if (start->str() == templateDeclarationNameToken->str()) {
1074+
if (isSpecialization && !copy && !scope.empty() && Token::Match(start, (scope + templateDeclarationNameToken->str()).c_str())) {
1075+
// skip scope
1076+
while (start->strAt(1) != templateDeclarationNameToken->str())
1077+
start = start->next();
1078+
} else if (start->str() == templateDeclarationNameToken->str()) {
10451079
dst->insertToken(newName, "", true);
10461080
if (start->strAt(1) == "<")
10471081
start = start->next()->findClosingBracket();
@@ -1133,6 +1167,8 @@ void TemplateSimplifier::expandTemplate(
11331167
// Start of template..
11341168
if (tok3 == templateDeclarationToken) {
11351169
tok3 = tok3->next();
1170+
if (tok3->str() == "static")
1171+
tok3 = tok3->next();
11361172
}
11371173

11381174
// member function implemented outside class definition
@@ -1907,23 +1943,12 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
19071943
return false;
19081944

19091945
// already simplified
1910-
if (!Token::Match(startToken, "%name% <"))
1946+
if (!Token::Match(tok2, "%name% <"))
19111947
return false;
19121948

1913-
if (templateDeclaration.scope.empty()) {
1914-
if (startToken->str() != templateDeclaration.name)
1915-
return false;
1916-
} else {
1917-
std::string name = templateDeclaration.scope + " :: " + startToken->str();
1918-
if (name != templateDeclaration.name)
1919-
return false;
1920-
}
1921-
1922-
if (!matchSpecialization(tok->tokAt(namepos), startToken, specializations))
1949+
if (!matchSpecialization(tok->tokAt(namepos), tok2, specializations))
19231950
return false;
19241951

1925-
tok2 = startToken;
1926-
19271952
// New type..
19281953
mTypesUsedInTemplateInstantiation.clear();
19291954
std::list<std::string> typeStringsUsedInTemplateInstantiation;
@@ -2051,6 +2076,61 @@ void TemplateSimplifier::replaceTemplateUsage(
20512076
}
20522077
}
20532078

2079+
static std::string getPathName(const TemplateSimplifier::TokenAndName & decl)
2080+
{
2081+
std::string name = decl.scope;
2082+
if (!name.empty())
2083+
name += " :: ";
2084+
if (decl.nameToken->strAt(-1) == "::") {
2085+
const Token * start = decl.nameToken;
2086+
2087+
while (Token::Match(start->tokAt(-2), "%name% ::"))
2088+
start = start->tokAt(-2);
2089+
2090+
while (start != decl.nameToken) {
2091+
name += (start->str() + " ");
2092+
start = start->next();
2093+
}
2094+
}
2095+
name += decl.name;
2096+
return name;
2097+
}
2098+
2099+
void TemplateSimplifier::getUserDefinedSpecializations()
2100+
{
2101+
// try to locate a matching declaration for each user defined specialization
2102+
for (auto & spec : mTemplateDeclarations) {
2103+
if (Token::Match(spec.token, "template < >")) {
2104+
std::string specName = getPathName(spec);
2105+
2106+
bool found = false;
2107+
for (auto & decl : mTemplateDeclarations) {
2108+
if (Token::Match(decl.token, "template < >"))
2109+
continue;
2110+
std::string declName = getPathName(decl);
2111+
2112+
// make sure the scopes and names match
2113+
if (specName == declName) {
2114+
// @todo make sure function parameters also match
2115+
mTemplateUserSpecializationMap[spec.token] = decl.token;
2116+
}
2117+
}
2118+
2119+
if (!found) {
2120+
for (auto & decl : mTemplateForwardDeclarations) {
2121+
std::string declName = getPathName(decl);
2122+
2123+
// make sure the scopes and names match
2124+
if (specName == declName) {
2125+
// @todo make sure function parameters also match
2126+
mTemplateUserSpecializationMap[spec.token] = decl.token;
2127+
}
2128+
}
2129+
}
2130+
}
2131+
}
2132+
}
2133+
20542134
void TemplateSimplifier::fixForwardDeclaredDefaultArgumentValues()
20552135
{
20562136
// try to locate a matching declaration for each forward declaration
@@ -2066,26 +2146,8 @@ void TemplateSimplifier::fixForwardDeclaredDefaultArgumentValues()
20662146

20672147
// make sure the number of arguments match
20682148
if (params1.size() == params2.size()) {
2069-
std::string declName = decl.scope;
2070-
if (!declName.empty())
2071-
declName += " :: ";
2072-
if (decl.nameToken->strAt(-1) == "::") {
2073-
const Token * start = decl.nameToken;
2074-
2075-
while (Token::Match(start->tokAt(-2), "%name% ::"))
2076-
start = start->tokAt(-2);
2077-
2078-
while (start != decl.nameToken) {
2079-
declName += (start->str() + " ");
2080-
start = start->next();
2081-
}
2082-
}
2083-
declName += decl.name;
2084-
2085-
std::string forwardDeclName = forwardDecl.scope;
2086-
if (!forwardDeclName.empty())
2087-
forwardDeclName += " :: ";
2088-
forwardDeclName += forwardDecl.name;
2149+
std::string declName = getPathName(decl);
2150+
std::string forwardDeclName = getPathName(forwardDecl);
20892151

20902152
// make sure the scopes and names match
20912153
if (forwardDeclName == declName) {
@@ -2124,6 +2186,7 @@ void TemplateSimplifier::simplifyTemplates(
21242186
mTemplateDeclarations.clear();
21252187
mTemplateForwardDeclarations.clear();
21262188
mTemplateForwardDeclarationsMap.clear();
2189+
mTemplateUserSpecializationMap.clear();
21272190
mTemplateInstantiations.clear();
21282191
mInstantiatedTemplates.clear();
21292192
mExplicitInstantiationsToDelete.clear();
@@ -2157,6 +2220,9 @@ void TemplateSimplifier::simplifyTemplates(
21572220
// Copy default argument values from forward declaration to declaration
21582221
fixForwardDeclaredDefaultArgumentValues();
21592222

2223+
// Locate user defined specializations.
2224+
getUserDefinedSpecializations();
2225+
21602226
// Locate possible instantiations of templates..
21612227
getTemplateInstantiations();
21622228

lib/templatesimplifier.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,12 @@ class CPPCHECKLIB TemplateSimplifier {
156156
*/
157157
void useDefaultArgumentValues();
158158

159+
/**
160+
* Try to locate a matching declaration for each user defined
161+
* specialization.
162+
*/
163+
void getUserDefinedSpecializations();
164+
159165
/**
160166
* simplify template aliases
161167
*/
@@ -278,6 +284,7 @@ class CPPCHECKLIB TemplateSimplifier {
278284
std::list<TokenAndName> mTemplateDeclarations;
279285
std::list<TokenAndName> mTemplateForwardDeclarations;
280286
std::map<Token *, Token *> mTemplateForwardDeclarationsMap;
287+
std::map<Token *, Token *> mTemplateUserSpecializationMap;
281288
std::list<TokenAndName> mTemplateInstantiations;
282289
std::list<TokenAndName> mInstantiatedTemplates;
283290
std::list<TokenAndName> mMemberFunctionsToDelete;

0 commit comments

Comments
 (0)