Fixed #10100 (FP: shadowVariable clangimport)
This commit is contained in:
parent
4e1ff86bb2
commit
203d6ebe5a
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue