Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions lib/templatesimplifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1766,7 +1766,7 @@ void TemplateSimplifier::expandTemplate(
dst->previous()->linenr(start->linenr());
dst->previous()->column(start->column());
Token *previous = dst->previous();
previous->isTemplateArg(true);
previous->templateArgFrom(typetok);
previous->isSigned(typetok->isSigned());
previous->isUnsigned(typetok->isUnsigned());
previous->isLong(typetok->isLong());
Expand Down Expand Up @@ -2016,7 +2016,7 @@ void TemplateSimplifier::expandTemplate(
Token::createMutualLinks(brackets1.top(), back);
brackets1.pop();
}
back->isTemplateArg(true);
back->templateArgFrom(typetok);
back->isUnsigned(typetok->isUnsigned());
back->isSigned(typetok->isSigned());
back->isLong(typetok->isLong());
Expand Down Expand Up @@ -2120,7 +2120,7 @@ void TemplateSimplifier::expandTemplate(
Token::createMutualLinks(par1, mTokenList.back());
mTokenList.addtoken(typetok, tok3);
for (Token* t = par1; t; t = t->next())
t->isTemplateArg(true);
t->templateArgFrom(typetok);
continue;
}
}
Expand Down Expand Up @@ -2174,7 +2174,7 @@ void TemplateSimplifier::expandTemplate(
brackets1.pop();
}
if (copy)
back->isTemplateArg(true);
back->templateArgFrom(typetok);
}
if (pointerType && Token::simpleMatch(beforeTypeToken, "const")) {
mTokenList.addtoken(beforeTypeToken);
Expand Down
7 changes: 7 additions & 0 deletions lib/token.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2720,3 +2720,10 @@ Token* findLambdaEndScope(Token* tok)
const Token* findLambdaEndScope(const Token* tok) {
return findLambdaEndScope(const_cast<Token*>(tok));
}

void Token::templateArgFrom(const Token* fromToken) {
setFlag(fIsTemplateArg, fromToken != nullptr);
mImpl->mTemplateArgFileIndex = fromToken ? fromToken->mImpl->mFileIndex : -1;
mImpl->mTemplateArgLineNumber = fromToken ? fromToken->mImpl->mLineNumber : -1;
mImpl->mTemplateArgColumn = fromToken ? fromToken->mImpl->mColumn : -1;
}
16 changes: 14 additions & 2 deletions lib/token.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ struct TokenImpl {
nonneg int mColumn{};
nonneg int mExprId{};

// original template argument location
int mTemplateArgFileIndex{-1};
int mTemplateArgLineNumber{-1};
int mTemplateArgColumn{-1};

/**
* A value from 0-100 that provides a rough idea about where in the token
* list this token is located.
Expand Down Expand Up @@ -824,8 +829,15 @@ class CPPCHECKLIB Token {
bool isTemplateArg() const {
return getFlag(fIsTemplateArg);
}
void isTemplateArg(const bool value) {
setFlag(fIsTemplateArg, value);
void templateArgFrom(const Token* fromToken);
int templateArgFileIndex() const {
return mImpl->mTemplateArgFileIndex;
}
int templateArgLineNumber() const {
return mImpl->mTemplateArgLineNumber;
}
int templateArgColumn() const {
return mImpl->mTemplateArgColumn;
}

const std::string& getMacroName() const {
Expand Down
6 changes: 5 additions & 1 deletion lib/tokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6079,8 +6079,12 @@ void Tokenizer::dump(std::ostream &out) const
outs += " externLang=\"C\"";
if (tok->isExpandedMacro())
outs += " macroName=\"" + tok->getMacroName() + "\"";
if (tok->isTemplateArg())
if (tok->isTemplateArg()) {
outs += " isTemplateArg=\"true\"";
outs += " templateArgFileIndex=\"" + std::to_string(tok->templateArgFileIndex()) + "\"";
outs += " templateArgLineNumber=\"" + std::to_string(tok->templateArgLineNumber()) + "\"";
outs += " templateArgColumn=\"" + std::to_string(tok->templateArgColumn()) + "\"";
}
if (tok->isRemovedVoidParameter())
outs += " isRemovedVoidParameter=\"true\"";
if (tok->isSplittedVarDeclComma())
Expand Down
40 changes: 40 additions & 0 deletions test/testsimplifytemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,8 @@ class TestSimplifyTemplate : public TestFixture {
TEST_CASE(explicitBool2);

TEST_CASE(templateArgPreserveType); // #13882 - type of template argument

TEST_CASE(dumpTemplateArgFrom);
}

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

#define dump(...) dump_(__FILE__, __LINE__, __VA_ARGS__)
template<size_t size>
std::string dump_(const char* file, int line, const char (&code)[size], const CheckOptions& options = make_default_obj()) {
const Settings settings1 = settingsBuilder(settings).library("std.cfg").debugwarnings(options.debugwarnings).build();
SimpleTokenizer tokenizer(settings1, *this);

ASSERT_LOC(tokenizer.tokenize(code), file, line);

std::ostringstream ostr;
(tokenizer.dump)(ostr);

return ostr.str();
}

void template1() {
const char code[] = "template <class T> T f(T val) { T a; }\n"
"f<int>(10);";
Expand Down Expand Up @@ -6623,6 +6639,30 @@ class TestSimplifyTemplate : public TestFixture {
"class Test<64> { uint32_t i ; i = ( uint32_t ) 64 ; } ;",
tok(code));
}

void dumpTemplateArgFrom() {
const char code[] = "template<class T> void foo(T t) {}\n"
"foo<int>(23);";
const std::string d = dump(code);
ASSERT(!d.empty());

// Assert that first 'int' token has templateArg location info
const std::string::size_type strpos1 = d.find(" str=\"int\" ");
ASSERT(strpos1 < d.size());
const std::string::size_type endpos1 = d.find('>', strpos1);
const std::string::size_type templateArgPos1 = d.find(" templateArgFileIndex=\"0\" templateArgLineNumber=\"2\" templateArgColumn=\"5\"");
ASSERT(templateArgPos1 > strpos1 && templateArgPos1 < endpos1);

// Assert that second 'int' token has templateArg location info
const std::string::size_type strpos2 = d.find(" str=\"int\" ", endpos1);
ASSERT(strpos2 < d.size());
const std::string::size_type endpos2 = d.find('>', strpos2);
const std::string::size_type templateArgPos2 = d.find(" templateArgFileIndex=\"0\" templateArgLineNumber=\"2\" templateArgColumn=\"5\"", endpos1);
ASSERT(templateArgPos2 > strpos2 && templateArgPos2 < endpos2);

// Assert there is no further unexpected templateArg location info
ASSERT(d.find(" templateArg", endpos2) == std::string::npos);
}
};

REGISTER_TEST(TestSimplifyTemplate)