Fixed #10100 (FP: shadowVariable clangimport)

This commit is contained in:
Daniel Marjamäki 2021-01-27 20:03:42 +01:00
parent 4e1ff86bb2
commit 203d6ebe5a
4 changed files with 105 additions and 0 deletions

View File

@ -249,6 +249,14 @@ namespace clangimport {
notFound(addr);
}
void replaceVarDecl(const Variable *from, Variable *to) {
for (auto &it: mDeclMap) {
Decl &decl = it.second;
if (decl.var == from)
decl.var = to;
}
}
void ref(const std::string &addr, Token *tok) {
auto it = mDeclMap.find(addr);
if (it != mDeclMap.end())
@ -632,6 +640,29 @@ Scope *clangimport::AstNode::createScope(TokenList *tokenList, Scope::ScopeType
scope->type = scopeType;
scope->classDef = def;
scope->check = nestedIn->check;
if (Token::Match(def, "if|for|while (")) {
std::map<const Variable *, const Variable *> replaceVar;
for (const Token *vartok = def->tokAt(2); vartok; vartok = vartok->next()) {
if (!vartok->variable())
continue;
if (vartok->variable()->nameToken() == vartok) {
const Variable *from = vartok->variable();
scope->varlist.emplace_back(*from, scope);
Variable *to = &scope->varlist.back();
replaceVar[from] = to;
mData->replaceVarDecl(from, to);
}
if (replaceVar.find(vartok->variable()) != replaceVar.end())
const_cast<Token *>(vartok)->variable(replaceVar[vartok->variable()]);
}
std::list<Variable> &varlist = const_cast<Scope *>(def->scope())->varlist;
for (std::list<Variable>::iterator var = varlist.begin(); var != varlist.end();) {
if (replaceVar.find(&(*var)) != replaceVar.end())
varlist.erase(var++);
else
var++;
}
}
scope->bodyStart = addtoken(tokenList, "{");
tokenList->back()->scope(scope);
mData->scopeAccessControl[scope] = scope->defaultAccess();

View File

@ -1886,6 +1886,38 @@ Variable::Variable(const Token *name_, const std::string &clangType, const Token
setFlag(fIsInit, true);
}
Variable::Variable(const Variable &var, const Scope *scope)
: mNameToken(var.mNameToken)
, mTypeStartToken(var.mTypeStartToken)
, mTypeEndToken(var.mTypeEndToken)
, mIndex(var.mIndex)
, mAccess(var.mAccess)
, mFlags(var.mFlags)
, mType(var.mType)
, mScope(scope ? scope : var.mScope)
, mValueType(nullptr)
, mDimensions(var.mDimensions)
{
if (var.mValueType)
mValueType = new ValueType(*var.mValueType);
}
Variable::Variable(const Variable &var)
: mNameToken(var.mNameToken)
, mTypeStartToken(var.mTypeStartToken)
, mTypeEndToken(var.mTypeEndToken)
, mIndex(var.mIndex)
, mAccess(var.mAccess)
, mFlags(var.mFlags)
, mType(var.mType)
, mScope(var.mScope)
, mValueType(nullptr)
, mDimensions(var.mDimensions)
{
if (var.mValueType)
mValueType = new ValueType(*var.mValueType);
}
Variable::~Variable()
{
delete mValueType;

View File

@ -240,6 +240,10 @@ public:
const Token *typeEnd, nonneg int index_, AccessControl access_,
const Type *type_, const Scope *scope_);
Variable(const Variable &var, const Scope *scope);
Variable(const Variable &var);
~Variable();
/**
@ -1236,6 +1240,21 @@ public:
containerTypeToken(nullptr),
originalTypeName(otn)
{}
ValueType(const ValueType &vt)
: sign(vt.sign)
, type(vt.type)
, bits(vt.bits)
, pointer(vt.pointer)
, constness(vt.constness)
, reference(vt.reference)
, typeScope(vt.typeScope)
, smartPointerType(vt.smartPointerType)
, smartPointerTypeToken(vt.smartPointerTypeToken)
, container(vt.container)
, containerTypeToken(vt.containerTypeToken)
, originalTypeName(vt.originalTypeName)
{}
static ValueType parseDecl(const Token *type, const Settings *settings);
static Type typeFromString(const std::string &typestr, bool longType);

View File

@ -119,6 +119,7 @@ private:
TEST_CASE(symbolDatabaseVariableRRef);
TEST_CASE(symbolDatabaseVariablePointerRef);
TEST_CASE(symbolDatabaseNodeType1);
TEST_CASE(symbolDatabaseForVariable);
TEST_CASE(valueFlow1);
TEST_CASE(valueFlow2);
@ -1210,6 +1211,28 @@ private:
ASSERT_EQUALS("signed long", tok->valueType()->str());
}
void symbolDatabaseForVariable() {
const char clang[] = "`-FunctionDecl 0x38f8bb0 <10100.c:2:1, line:4:1> line:2:6 f 'void (void)'\n"
" `-CompoundStmt 0x38f8d88 <col:14, line:4:1>\n"
" `-ForStmt 0x38f8d50 <line:3:5, col:26>\n"
" |-DeclStmt 0x38f8d28 <col:10, col:19>\n"
" | `-VarDecl 0x38f8ca8 <col:10, col:18> col:14 i 'int' cinit\n"
" | `-IntegerLiteral 0x38f8d08 <col:18> 'int' 0\n"
" |-<<<NULL>>>\n"
" |-<<<NULL>>>\n"
" |-<<<NULL>>>\n"
" `-CompoundStmt 0x38f8d40 <col:25, col:26>";
ASSERT_EQUALS("void f ( ) { for ( int i@1 = 0 ; ; ) { } }", parse(clang));
GET_SYMBOL_DB(clang);
const Token *tok = Token::findsimplematch(tokenizer.tokens(), "i");
ASSERT(!!tok);
ASSERT(!!tok->variable());
ASSERT_EQUALS(Scope::ScopeType::eFor, tok->variable()->scope()->type);
}
void valueFlow1() {
// struct S { int x; int buf[10]; } ; int sz = sizeof(struct S);
const char clang[] = "|-RecordDecl 0x2fc5a88 <1.c:1:1, line:4:1> line:1:8 struct S definition\n"