Skip to content

Commit af9fb50

Browse files
authored
Fix #13873 (Tokenizer: do not simplify 'using' in function declaration/definition for function name) (danmar#7537)
1 parent 5147b19 commit af9fb50

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

lib/tokenize.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2650,6 +2650,22 @@ namespace {
26502650
return false;
26512651
}
26522652

2653+
if (Token::Match(tok1, "%name% (") && TokenList::isFunctionHead(tok1->next(), "{;:")) {
2654+
if (Token::Match(tok1->previous(), "%name%") && !tok1->previous()->isControlFlowKeyword())
2655+
return false;
2656+
if (Token::Match(tok1->previous(), ">|>>") && tok1->linkAt(-1))
2657+
return false;
2658+
if (Token::Match(tok1->previous(), "*|&|&&")) {
2659+
const Token* prev = tok1->previous();
2660+
while (Token::Match(prev, "%name%|*|&|&&|::") && !prev->isControlFlowKeyword())
2661+
prev = prev->previous();
2662+
if (Token::Match(prev, ">|>>") && tok1->linkAt(-1))
2663+
return false;
2664+
if (Token::Match(prev, "[;{}] %name%"))
2665+
return false;
2666+
}
2667+
}
2668+
26532669
// get qualification
26542670
std::string qualification;
26552671
const Token* tok2 = tok1;
@@ -3027,6 +3043,8 @@ bool Tokenizer::simplifyUsing()
30273043
}
30283044
}
30293045

3046+
bool isTypedefInfoAdded = false; // TODO should we add a separate mUsingInfo?
3047+
30303048
std::string scope1 = currentScope1->fullName;
30313049
bool skip = false; // don't erase type aliases we can't parse
30323050
Token *enumOpenBrace = nullptr;
@@ -3097,6 +3115,18 @@ bool Tokenizer::simplifyUsing()
30973115
} else if (!usingMatch(nameToken, scope, tok1, scope1, currentScope1, nullptr))
30983116
continue;
30993117

3118+
if (!isTypedefInfoAdded && Token::Match(tok1, "%name% (")) {
3119+
isTypedefInfoAdded = true;
3120+
TypedefInfo usingInfo;
3121+
usingInfo.name = name;
3122+
usingInfo.filename = list.file(nameToken);
3123+
usingInfo.lineNumber = nameToken->linenr();
3124+
usingInfo.column = nameToken->column();
3125+
usingInfo.used = true;
3126+
usingInfo.isFunctionPointer = false;
3127+
mTypedefInfo.push_back(std::move(usingInfo));
3128+
}
3129+
31003130
const auto nReplace = tokDistance(start, usingEnd);
31013131
if (nReplace > maxReplacementTokens) {
31023132
simplifyUsingError(usingStart, usingEnd);

test/testsimplifyusing.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ class TestSimplifyUsing : public TestFixture {
9191
TEST_CASE(simplifyUsing10173);
9292
TEST_CASE(simplifyUsing10335);
9393
TEST_CASE(simplifyUsing10720);
94+
TEST_CASE(simplifyUsing13873); // function declaration
9495

9596
TEST_CASE(scopeInfo1);
9697
TEST_CASE(scopeInfo2);
@@ -1586,6 +1587,20 @@ class TestSimplifyUsing : public TestFixture {
15861587
TODO_ASSERT(startsWith(errout_str(), "[test.cpp:6]: (debug) Failed to parse 'using C = S < S < S < int"));
15871588
}
15881589

1590+
void simplifyUsing13873() { // function declaration
1591+
const char code1[] = "using NS1::f;\n"
1592+
"namespace NS1 { void f(); }\n";
1593+
ASSERT_EQUALS("namespace NS1 { void f ( ) ; }", tok(code1));
1594+
1595+
const char code2[] = "using NS1::f;\n"
1596+
"void bar() { f(); }\n";
1597+
ASSERT_EQUALS("void bar ( ) { NS1 :: f ( ) ; }", tok(code2));
1598+
1599+
const char code3[] = "using NS1::f;\n"
1600+
"namespace NS1 { void* f(); }\n";
1601+
ASSERT_EQUALS("namespace NS1 { void * f ( ) ; }", tok(code3));
1602+
}
1603+
15891604
void scopeInfo1() {
15901605
const char code[] = "struct A {\n"
15911606
" enum class Mode { UNKNOWN, ENABLED, NONE, };\n"

0 commit comments

Comments
 (0)