Skip to content

Commit 7adfb6e

Browse files
committed
Add variable and type information to tokens for C array range based for loops.
1 parent f8dd6ee commit 7adfb6e

2 files changed

Lines changed: 74 additions & 9 deletions

File tree

lib/symboldatabase.cpp

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4566,20 +4566,27 @@ void SymbolDatabase::setValueType(Token *tok, const ValueType &valuetype)
45664566
// range for loop, auto
45674567
if (vt2 &&
45684568
parent->str() == ":" &&
4569-
Token::Match(parent->astParent(), "( const| auto *| %var% :") &&
4569+
Token::Match(parent->astParent(), "( const| auto *|&| %var% :") &&
45704570
!parent->previous()->valueType() &&
45714571
Token::simpleMatch(parent->astParent()->astOperand1(), "for")) {
4572-
bool isconst = Token::simpleMatch(parent->astParent()->next(), "const");
4572+
const bool isconst = Token::simpleMatch(parent->astParent()->next(), "const");
45734573
Token * const autoToken = const_cast<Token *>(parent->astParent()->tokAt(isconst ? 2 : 1));
45744574
if (vt2->pointer) {
4575-
ValueType vt(*vt2);
4576-
vt.pointer--;
4577-
if (isconst)
4578-
vt.constness |= 1;
4579-
setValueType(autoToken, vt);
4575+
ValueType autovt(*vt2);
4576+
autovt.pointer--;
4577+
autovt.constness = 0;
4578+
setValueType(autoToken, autovt);
45804579
setAutoTokenProperties(autoToken);
4581-
setValueType(parent->previous(), vt);
4582-
const_cast<Variable *>(parent->previous()->variable())->setFlags(vt);
4580+
ValueType varvt(*vt2);
4581+
varvt.pointer--;
4582+
if (isconst)
4583+
varvt.constness |= 1;
4584+
setValueType(parent->previous(), varvt);
4585+
const_cast<Variable *>(parent->previous()->variable())->setFlags(varvt);
4586+
if (vt2->typeScope && vt2->typeScope->definedType) {
4587+
const_cast<Variable *>(parent->previous()->variable())->type(vt2->typeScope->definedType);
4588+
autoToken->type(vt2->typeScope->definedType);
4589+
}
45834590
} else if (vt2->container) {
45844591
// TODO: Determine exact type of RHS
45854592
const Token *typeStart = parent->astOperand2();

test/testsymboldatabase.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4614,6 +4614,64 @@ class TestSymbolDatabase: public TestFixture {
46144614
ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E");
46154615
}
46164616

4617+
void auto4() {
4618+
GET_SYMBOL_DB("struct S { int i; };\n"
4619+
"int foo() {\n"
4620+
" S array[10];\n"
4621+
" for (auto a : array)\n"
4622+
" a.i = 0;\n"
4623+
" for (auto & b : array)\n"
4624+
" b.i = 1;\n"
4625+
" for (const auto & c : array)\n"
4626+
" auto ci = c.i;\n"
4627+
" for (auto * d : array)\n"
4628+
" d->i = 0;\n"
4629+
" for (const auto * e : array)\n"
4630+
" auto ei = e->i;\n"
4631+
" return array[0].i;\n"
4632+
"}");
4633+
const Token *autotok = Token::findsimplematch(tokenizer.tokens(), "auto a");
4634+
ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
4635+
ASSERT(db && autotok && autotok->type() && autotok->type()->name() == "S");
4636+
4637+
autotok = Token::findsimplematch(autotok->next(), "auto & b");
4638+
ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
4639+
ASSERT(db && autotok && autotok->type() && autotok->type()->name() == "S");
4640+
4641+
autotok = Token::findsimplematch(autotok->next(), "auto & c");
4642+
ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
4643+
ASSERT(db && autotok && autotok->type() && autotok->type()->name() == "S");
4644+
4645+
autotok = Token::findsimplematch(autotok->next(), "auto * d");
4646+
ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
4647+
ASSERT(db && autotok && autotok->type() && autotok->type()->name() == "S");
4648+
4649+
autotok = Token::findsimplematch(autotok->next(), "auto * e");
4650+
ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
4651+
ASSERT(db && autotok && autotok->type() && autotok->type()->name() == "S");
4652+
4653+
vartok = Token::findsimplematch(tokenizer.tokens(), "a :");
4654+
ASSERT(db && vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
4655+
ASSERT(db && vartok && vartok->variable() && !vartok->variable()->isReference() && !vartok->variable()->isPointer());
4656+
ASSERT(db && vartok && vartok->variable() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
4657+
4658+
vartok = Token::findsimplematch(vartok->next(), "b :");
4659+
ASSERT(db && vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
4660+
ASSERT(db && vartok && vartok->variable() && vartok->variable()->isReference() && !vartok->variable()->isPointer() && !vartok->variable()->isConst());
4661+
4662+
vartok = Token::findsimplematch(vartok->next(), "c :");
4663+
ASSERT(db && vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
4664+
ASSERT(db && vartok && vartok->variable() && vartok->variable()->isReference() && !vartok->variable()->isPointer() && vartok->variable()->isConst());
4665+
4666+
vartok = Token::findsimplematch(vartok->next(), "d :");
4667+
ASSERT(db && vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
4668+
ASSERT(db && vartok && vartok->variable() && !vartok->variable()->isReference() && vartok->variable()->isPointer() && !vartok->variable()->isConst());
4669+
4670+
vartok = Token::findsimplematch(vartok->next(), "e :");
4671+
ASSERT(db && vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
4672+
ASSERT(db && vartok && vartok->variable() && !vartok->variable()->isReference() && vartok->variable()->isPointer() && vartok->variable()->isConst());
4673+
}
4674+
46174675
};
46184676

46194677
REGISTER_TEST(TestSymbolDatabase)

0 commit comments

Comments
 (0)