Skip to content

Commit b46125e

Browse files
authored
Fix #14095 (TemplateSimplifier: store location of template argument token) (#7775)
1 parent e3d2d90 commit b46125e

File tree

5 files changed

+70
-7
lines changed

5 files changed

+70
-7
lines changed

lib/templatesimplifier.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1766,7 +1766,7 @@ void TemplateSimplifier::expandTemplate(
17661766
dst->previous()->linenr(start->linenr());
17671767
dst->previous()->column(start->column());
17681768
Token *previous = dst->previous();
1769-
previous->isTemplateArg(true);
1769+
previous->templateArgFrom(typetok);
17701770
previous->isSigned(typetok->isSigned());
17711771
previous->isUnsigned(typetok->isUnsigned());
17721772
previous->isLong(typetok->isLong());
@@ -2016,7 +2016,7 @@ void TemplateSimplifier::expandTemplate(
20162016
Token::createMutualLinks(brackets1.top(), back);
20172017
brackets1.pop();
20182018
}
2019-
back->isTemplateArg(true);
2019+
back->templateArgFrom(typetok);
20202020
back->isUnsigned(typetok->isUnsigned());
20212021
back->isSigned(typetok->isSigned());
20222022
back->isLong(typetok->isLong());
@@ -2120,7 +2120,7 @@ void TemplateSimplifier::expandTemplate(
21202120
Token::createMutualLinks(par1, mTokenList.back());
21212121
mTokenList.addtoken(typetok, tok3);
21222122
for (Token* t = par1; t; t = t->next())
2123-
t->isTemplateArg(true);
2123+
t->templateArgFrom(typetok);
21242124
continue;
21252125
}
21262126
}
@@ -2174,7 +2174,7 @@ void TemplateSimplifier::expandTemplate(
21742174
brackets1.pop();
21752175
}
21762176
if (copy)
2177-
back->isTemplateArg(true);
2177+
back->templateArgFrom(typetok);
21782178
}
21792179
if (pointerType && Token::simpleMatch(beforeTypeToken, "const")) {
21802180
mTokenList.addtoken(beforeTypeToken);

lib/token.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2720,3 +2720,10 @@ Token* findLambdaEndScope(Token* tok)
27202720
const Token* findLambdaEndScope(const Token* tok) {
27212721
return findLambdaEndScope(const_cast<Token*>(tok));
27222722
}
2723+
2724+
void Token::templateArgFrom(const Token* fromToken) {
2725+
setFlag(fIsTemplateArg, fromToken != nullptr);
2726+
mImpl->mTemplateArgFileIndex = fromToken ? fromToken->mImpl->mFileIndex : -1;
2727+
mImpl->mTemplateArgLineNumber = fromToken ? fromToken->mImpl->mLineNumber : -1;
2728+
mImpl->mTemplateArgColumn = fromToken ? fromToken->mImpl->mColumn : -1;
2729+
}

lib/token.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ struct TokenImpl {
7070
nonneg int mColumn{};
7171
nonneg int mExprId{};
7272

73+
// original template argument location
74+
int mTemplateArgFileIndex{-1};
75+
int mTemplateArgLineNumber{-1};
76+
int mTemplateArgColumn{-1};
77+
7378
/**
7479
* A value from 0-100 that provides a rough idea about where in the token
7580
* list this token is located.
@@ -824,8 +829,15 @@ class CPPCHECKLIB Token {
824829
bool isTemplateArg() const {
825830
return getFlag(fIsTemplateArg);
826831
}
827-
void isTemplateArg(const bool value) {
828-
setFlag(fIsTemplateArg, value);
832+
void templateArgFrom(const Token* fromToken);
833+
int templateArgFileIndex() const {
834+
return mImpl->mTemplateArgFileIndex;
835+
}
836+
int templateArgLineNumber() const {
837+
return mImpl->mTemplateArgLineNumber;
838+
}
839+
int templateArgColumn() const {
840+
return mImpl->mTemplateArgColumn;
829841
}
830842

831843
const std::string& getMacroName() const {

lib/tokenize.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6079,8 +6079,12 @@ void Tokenizer::dump(std::ostream &out) const
60796079
outs += " externLang=\"C\"";
60806080
if (tok->isExpandedMacro())
60816081
outs += " macroName=\"" + tok->getMacroName() + "\"";
6082-
if (tok->isTemplateArg())
6082+
if (tok->isTemplateArg()) {
60836083
outs += " isTemplateArg=\"true\"";
6084+
outs += " templateArgFileIndex=\"" + std::to_string(tok->templateArgFileIndex()) + "\"";
6085+
outs += " templateArgLineNumber=\"" + std::to_string(tok->templateArgLineNumber()) + "\"";
6086+
outs += " templateArgColumn=\"" + std::to_string(tok->templateArgColumn()) + "\"";
6087+
}
60846088
if (tok->isRemovedVoidParameter())
60856089
outs += " isRemovedVoidParameter=\"true\"";
60866090
if (tok->isSplittedVarDeclComma())

test/testsimplifytemplate.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,8 @@ class TestSimplifyTemplate : public TestFixture {
314314
TEST_CASE(explicitBool2);
315315

316316
TEST_CASE(templateArgPreserveType); // #13882 - type of template argument
317+
318+
TEST_CASE(dumpTemplateArgFrom);
317319
}
318320

319321
struct CheckOptions
@@ -333,6 +335,20 @@ class TestSimplifyTemplate : public TestFixture {
333335
return tokenizer.tokens()->stringifyList(nullptr, true);
334336
}
335337

338+
#define dump(...) dump_(__FILE__, __LINE__, __VA_ARGS__)
339+
template<size_t size>
340+
std::string dump_(const char* file, int line, const char (&code)[size], const CheckOptions& options = make_default_obj()) {
341+
const Settings settings1 = settingsBuilder(settings).library("std.cfg").debugwarnings(options.debugwarnings).build();
342+
SimpleTokenizer tokenizer(settings1, *this);
343+
344+
ASSERT_LOC(tokenizer.tokenize(code), file, line);
345+
346+
std::ostringstream ostr;
347+
(tokenizer.dump)(ostr);
348+
349+
return ostr.str();
350+
}
351+
336352
void template1() {
337353
const char code[] = "template <class T> T f(T val) { T a; }\n"
338354
"f<int>(10);";
@@ -6623,6 +6639,30 @@ class TestSimplifyTemplate : public TestFixture {
66236639
"class Test<64> { uint32_t i ; i = ( uint32_t ) 64 ; } ;",
66246640
tok(code));
66256641
}
6642+
6643+
void dumpTemplateArgFrom() {
6644+
const char code[] = "template<class T> void foo(T t) {}\n"
6645+
"foo<int>(23);";
6646+
const std::string d = dump(code);
6647+
ASSERT(!d.empty());
6648+
6649+
// Assert that first 'int' token has templateArg location info
6650+
const std::string::size_type strpos1 = d.find(" str=\"int\" ");
6651+
ASSERT(strpos1 < d.size());
6652+
const std::string::size_type endpos1 = d.find('>', strpos1);
6653+
const std::string::size_type templateArgPos1 = d.find(" templateArgFileIndex=\"0\" templateArgLineNumber=\"2\" templateArgColumn=\"5\"");
6654+
ASSERT(templateArgPos1 > strpos1 && templateArgPos1 < endpos1);
6655+
6656+
// Assert that second 'int' token has templateArg location info
6657+
const std::string::size_type strpos2 = d.find(" str=\"int\" ", endpos1);
6658+
ASSERT(strpos2 < d.size());
6659+
const std::string::size_type endpos2 = d.find('>', strpos2);
6660+
const std::string::size_type templateArgPos2 = d.find(" templateArgFileIndex=\"0\" templateArgLineNumber=\"2\" templateArgColumn=\"5\"", endpos1);
6661+
ASSERT(templateArgPos2 > strpos2 && templateArgPos2 < endpos2);
6662+
6663+
// Assert there is no further unexpected templateArg location info
6664+
ASSERT(d.find(" templateArg", endpos2) == std::string::npos);
6665+
}
66266666
};
66276667

66286668
REGISTER_TEST(TestSimplifyTemplate)

0 commit comments

Comments
 (0)