Skip to content

Commit a4faec0

Browse files
authored
fix #13371: Tokenizer: handle typeof and __typeof (#7720)
1 parent fa0189b commit a4faec0

File tree

2 files changed

+49
-8
lines changed

2 files changed

+49
-8
lines changed

lib/tokenize.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4209,7 +4209,7 @@ void VariableMap::addVariable(const std::string& varname, bool globalNamespace)
42094209
it->second = ++mVarId;
42104210
}
42114211

4212-
static bool setVarIdParseDeclaration(Token*& tok, const VariableMap& variableMap, bool executableScope)
4212+
static bool setVarIdParseDeclaration(Token*& tok, const VariableMap& variableMap, bool executableScope, Standards::cstd_t cStandard)
42134213
{
42144214
const Token* const tok1 = tok;
42154215
Token* tok2 = tok;
@@ -4229,7 +4229,9 @@ static bool setVarIdParseDeclaration(Token*& tok, const VariableMap& variableMap
42294229
}
42304230
if (tok2->isCpp() && Token::Match(tok2, "namespace|public|private|protected"))
42314231
return false;
4232-
if (tok2->isCpp() && Token::simpleMatch(tok2, "decltype (")) {
4232+
bool isC23 = tok2->isC() && cStandard >= Standards::C23;
4233+
if (((tok2->isCpp() || isC23) && Token::Match(tok2, "decltype|typeof (")) ||
4234+
(tok2->isC() && Token::simpleMatch(tok2, "__typeof ("))) {
42334235
typeCount = 1;
42344236
tok2 = tok2->linkAt(1)->next();
42354237
continue;
@@ -4762,7 +4764,7 @@ void Tokenizer::setVarIdPass1()
47624764
}
47634765

47644766
try { /* Ticket #8151 */
4765-
decl = setVarIdParseDeclaration(tok2, variableMap, scopeStack.top().isExecutable);
4767+
decl = setVarIdParseDeclaration(tok2, variableMap, scopeStack.top().isExecutable, mSettings.standards.c);
47664768
} catch (const Token * errTok) {
47674769
syntaxError(errTok);
47684770
}
@@ -4782,11 +4784,19 @@ void Tokenizer::setVarIdPass1()
47824784
variableMap.map(true),
47834785
mTemplateVarIdUsage);
47844786
}
4785-
if (Token *declTypeTok = Token::findsimplematch(tok, "decltype (", tok2)) {
4786-
for (Token *declTok = declTypeTok->linkAt(1); declTok != declTypeTok; declTok = declTok->previous()) {
4787-
if (declTok->isName() && !Token::Match(declTok->previous(), "::|.") && variableMap.hasVariable(declTok->str()))
4788-
declTok->varId(variableMap.map(false).find(declTok->str())->second);
4789-
}
4787+
}
4788+
4789+
Token *declTypeTok = nullptr;
4790+
if (cpp || mSettings.standards.c >= Standards::C23) {
4791+
declTypeTok = Token::findmatch(tok, "decltype|typeof (", tok2);
4792+
} else {
4793+
declTypeTok = Token::findsimplematch(tok, "__typeof (");
4794+
}
4795+
4796+
if (declTypeTok) {
4797+
for (Token *declTok = declTypeTok->linkAt(1); declTok != declTypeTok; declTok = declTok->previous()) {
4798+
if (declTok->isName() && !Token::Match(declTok->previous(), "::|.") && variableMap.hasVariable(declTok->str()))
4799+
declTok->varId(variableMap.map(false).find(declTok->str())->second);
47904800
}
47914801
}
47924802

test/testvarid.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,11 @@ class TestVarID : public TestFixture {
240240
TEST_CASE(decltype1);
241241
TEST_CASE(decltype2);
242242

243+
TEST_CASE(typeof1);
244+
TEST_CASE(typeof2);
245+
TEST_CASE(typeof3);
246+
TEST_CASE(typeof4);
247+
243248
TEST_CASE(exprid1);
244249
TEST_CASE(exprid2);
245250
TEST_CASE(exprid3);
@@ -4188,6 +4193,32 @@ class TestVarID : public TestFixture {
41884193
ASSERT_EQUALS(expected, tokenize(code));
41894194
}
41904195

4196+
void typeof1() {
4197+
const char code[] = "int x; typeof(x) y;";
4198+
const char expected[] = "1: int x@1 ; typeof ( x@1 ) y@2 ;\n";
4199+
ASSERT_EQUALS(expected, tokenize(code));
4200+
}
4201+
4202+
void typeof2() {
4203+
const char code[] = "int x; typeof(x) *y;";
4204+
const char expected[] = "1: int x@1 ; typeof ( x@1 ) * y@2 ;\n";
4205+
ASSERT_EQUALS(expected, tokenize(code));
4206+
}
4207+
4208+
void typeof3() {
4209+
const char code[] = "int x; const typeof(x) *const y;";
4210+
const char expected[] = "1: int x@1 ; const typeof ( x@1 ) * const y@2 ;\n";
4211+
ASSERT_EQUALS(expected, tokenize(code));
4212+
}
4213+
4214+
void typeof4() {
4215+
const char code[] = "int x; __typeof(x) y;";
4216+
const char expected[] = "1: int x@1 ; __typeof ( x@1 ) y@2 ;\n";
4217+
TokenizeOptions options;
4218+
options.cpp = false;
4219+
ASSERT_EQUALS(expected, tokenize(code, options));
4220+
}
4221+
41914222
void exprid1() {
41924223
const std::string actual = tokenizeExpr(
41934224
"struct A {\n"

0 commit comments

Comments
 (0)