Skip to content

Commit c9f09fc

Browse files
IOBYTERobert Reif
andauthored
small template simplifier fixes (danmar#3168)
* small template simplifier optimization * don't look for template parameter name in default values * fix cppcheck warning * add test for TemplateSimplifier::getTemplateParametersInDeclaration() Also removed TemplateSimplifier::getTemplateParametersInDeclaration() return value since it wasn't used. * added another test Co-authored-by: Robert Reif <reif@FX6840>
1 parent b1eaa30 commit c9f09fc

File tree

3 files changed

+57
-12
lines changed

3 files changed

+57
-12
lines changed

lib/templatesimplifier.cpp

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,7 +1650,7 @@ void TemplateSimplifier::expandTemplate(
16501650
std::stack<Token *> brackets1; // holds "(" and "{" tokens
16511651
bool pointerType = false;
16521652
Token * const dst1 = dst->previous();
1653-
for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype].token();
1653+
for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype];
16541654
typetok && (typeindentlevel > 0 || !Token::Match(typetok, ",|>"));
16551655
typetok = typetok->next()) {
16561656
if (typeindentlevel == 0 && typetok->str() == "*")
@@ -1896,7 +1896,7 @@ void TemplateSimplifier::expandTemplate(
18961896
if (itype < typeParametersInDeclaration.size()) {
18971897
unsigned int typeindentlevel = 0;
18981898
std::stack<Token *> brackets1; // holds "(" and "{" tokens
1899-
for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype].token();
1899+
for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype];
19001900
typetok && (typeindentlevel>0 || !Token::Match(typetok, ",|>"));
19011901
typetok = typetok->next()) {
19021902
if (!Token::simpleMatch(typetok, "...")) {
@@ -2003,7 +2003,7 @@ void TemplateSimplifier::expandTemplate(
20032003
std::stack<Token *> brackets1; // holds "(" and "{" tokens
20042004
Token * const beforeTypeToken = mTokenList.back();
20052005
bool pointerType = false;
2006-
for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype].token();
2006+
for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype];
20072007
typetok && (typeindentlevel > 0 || !Token::Match(typetok, ",|>"));
20082008
typetok = typetok->next()) {
20092009
if (typeindentlevel == 0 && typetok->str() == "*")
@@ -2817,25 +2817,38 @@ bool TemplateSimplifier::simplifyCalculations(Token* frontToken, Token *backToke
28172817
return ret;
28182818
}
28192819

2820-
const Token * TemplateSimplifier::getTemplateParametersInDeclaration(
2820+
void TemplateSimplifier::getTemplateParametersInDeclaration(
28212821
const Token * tok,
28222822
std::vector<const Token *> & typeParametersInDeclaration)
28232823
{
28242824
assert(tok->strAt(-1) == "<");
28252825

28262826
typeParametersInDeclaration.clear();
28272827
const Token *end = tok->previous()->findClosingBracket();
2828+
bool inDefaultValue = false;
28282829
for (; tok && tok!= end; tok = tok->next()) {
28292830
if (Token::simpleMatch(tok, "template <")) {
28302831
const Token *closing = tok->next()->findClosingBracket();
28312832
if (closing)
28322833
tok = closing->next();
28332834
} else if (tok->link() && Token::Match(tok, "{|(|["))
28342835
tok = tok->link();
2835-
else if (Token::Match(tok, "%name% ,|>|="))
2836-
typeParametersInDeclaration.push_back(tok);
2836+
else if (Token::Match(tok, "%name% ,|>|=")) {
2837+
if (!inDefaultValue) {
2838+
typeParametersInDeclaration.push_back(tok);
2839+
if (tok->strAt(1) == "=")
2840+
inDefaultValue = true;
2841+
}
2842+
} else if (inDefaultValue) {
2843+
if (tok->str() == ",")
2844+
inDefaultValue = false;
2845+
else if (tok->str() == "<") {
2846+
const Token *closing = tok->findClosingBracket();
2847+
if (closing)
2848+
tok = closing;
2849+
}
2850+
}
28372851
}
2838-
return tok;
28392852
}
28402853

28412854
bool TemplateSimplifier::matchSpecialization(
@@ -2909,7 +2922,7 @@ std::string TemplateSimplifier::getNewName(
29092922
else if (indentlevel > 0 && Token::Match(tok3, "> [,>]"))
29102923
--indentlevel;
29112924
if (indentlevel == 0 && Token::Match(tok3->previous(), "[<,]")) {
2912-
mTypesUsedInTemplateInstantiation.emplace_back(tok3, "");
2925+
mTypesUsedInTemplateInstantiation.push_back(tok3);
29132926
}
29142927
if (tok3->str() == "(")
29152928
++indentlevel;

lib/templatesimplifier.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ class TokenList;
4343

4444
/** @brief Simplify templates from the preprocessed and partially simplified code. */
4545
class CPPCHECKLIB TemplateSimplifier {
46+
friend class TestSimplifyTemplate;
47+
4648
public:
4749
explicit TemplateSimplifier(Tokenizer *tokenizer);
4850
~TemplateSimplifier();
@@ -437,10 +439,8 @@ class CPPCHECKLIB TemplateSimplifier {
437439
* ^ tok
438440
* @param typeParametersInDeclaration template < typename T, typename S >
439441
* ^ [0] ^ [1]
440-
* @return template < typename T, typename S >
441-
* ^ return
442442
*/
443-
static const Token * getTemplateParametersInDeclaration(
443+
static void getTemplateParametersInDeclaration(
444444
const Token * tok,
445445
std::vector<const Token *> & typeParametersInDeclaration);
446446

@@ -501,7 +501,7 @@ class CPPCHECKLIB TemplateSimplifier {
501501
std::list<TokenAndName> mInstantiatedTemplates;
502502
std::list<TokenAndName> mMemberFunctionsToDelete;
503503
std::vector<TokenAndName> mExplicitInstantiationsToDelete;
504-
std::vector<TokenAndName> mTypesUsedInTemplateInstantiation;
504+
std::vector<const Token *> mTypesUsedInTemplateInstantiation;
505505
std::unordered_map<const Token*, int> mTemplateNamePos;
506506
};
507507

test/testsimplifytemplate.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,8 @@ class TestSimplifyTemplate : public TestFixture {
243243

244244
TEST_CASE(findTemplateDeclarationEnd);
245245

246+
TEST_CASE(getTemplateParametersInDeclaration);
247+
246248
TEST_CASE(expandSpecialized1);
247249
TEST_CASE(expandSpecialized2);
248250
TEST_CASE(expandSpecialized3); // #8671
@@ -5206,6 +5208,36 @@ class TestSimplifyTemplate : public TestFixture {
52065208
ASSERT(findTemplateDeclarationEndHelper("template <typename... f, c<h<e<typename f::d...>>::g>> void i(){} int x;", "} int x ;"));
52075209
}
52085210

5211+
// Helper function to unit test TemplateSimplifier::getTemplateParametersInDeclaration
5212+
bool getTemplateParametersInDeclarationHelper(const char code[], const std::vector<std::string> & params) {
5213+
Tokenizer tokenizer(&settings, this);
5214+
5215+
std::istringstream istr(code);
5216+
tokenizer.createTokens(istr, "test.cpp");
5217+
tokenizer.createLinks();
5218+
tokenizer.splitTemplateRightAngleBrackets(false);
5219+
5220+
std::vector<const Token *> typeParametersInDeclaration;
5221+
TemplateSimplifier::getTemplateParametersInDeclaration(tokenizer.tokens()->tokAt(2), typeParametersInDeclaration);
5222+
5223+
if (params.size() != typeParametersInDeclaration.size())
5224+
return false;
5225+
5226+
for (size_t i = 0; i < typeParametersInDeclaration.size(); ++i) {
5227+
if (typeParametersInDeclaration[i]->str() != params[i])
5228+
return false;
5229+
}
5230+
return true;
5231+
}
5232+
5233+
void getTemplateParametersInDeclaration() {
5234+
ASSERT(getTemplateParametersInDeclarationHelper("template<typename T> class Fred {};", std::vector<std::string>{"T"}));
5235+
ASSERT(getTemplateParametersInDeclarationHelper("template<typename T=int> class Fred {};", std::vector<std::string>{"T"}));
5236+
ASSERT(getTemplateParametersInDeclarationHelper("template<typename T,typename U> class Fred {};", std::vector<std::string>{"T","U"}));
5237+
ASSERT(getTemplateParametersInDeclarationHelper("template<typename T,typename U=int> class Fred {};", std::vector<std::string>{"T","U"}));
5238+
ASSERT(getTemplateParametersInDeclarationHelper("template<typename T=int,typename U=int> class Fred {};", std::vector<std::string>{"T","U"}));
5239+
}
5240+
52095241
void expandSpecialized1() {
52105242
ASSERT_EQUALS("class A<int> { } ;", tok("template<> class A<int> {};"));
52115243
ASSERT_EQUALS("class A<int> : public B { } ;", tok("template<> class A<int> : public B {};"));

0 commit comments

Comments
 (0)