diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index c84177d6cc4..04a94ea31a5 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -856,7 +856,7 @@ void CheckMemoryLeakStructMember::checkStructVariable(const Variable* const vari else if (tok3->str() == "}") { if (indentlevel3 == 0) { - memoryLeak(tok3, variable->name() + "." + assignToks.first->str(), allocType); + memoryLeak(tok3, variable->name() + "." + tok2->strAt(2), allocType); break; } --indentlevel3; diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index 62f10b883b5..0252fdd5411 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -1667,7 +1667,8 @@ void CheckUninitVar::valueFlowUninit() const bool deref = CheckNullPointer::isPointerDeRef(tok, unknown, *mSettings); uninitderef = deref && v->indirect == 0; const bool isleaf = isLeafDot(tok) || uninitderef; - if (!isleaf && Token::Match(tok->astParent(), ". %name%") && (tok->astParent()->next()->varId() || tok->astParent()->next()->isEnumerator())) + if (!isleaf && Token::Match(tok->astParent(), ". %name%") && + (tok->astParent()->next()->variable() || tok->astParent()->next()->isEnumerator())) continue; } const ExprUsage usage = getExprUsage(tok, v->indirect, *mSettings); diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index e2226269162..e0e6ea7bc11 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -3546,8 +3546,17 @@ void Tokenizer::combineOperators() tok->deleteNext(); } } else if (tok->str() == "->") { - tok->str("."); - tok->originalName("->"); + // If the preceding sequence is "( & %name% )", replace it by "%name%" + Token* t = tok->tokAt(-4); + if (Token::Match(t, "( & %name% )") && !Token::simpleMatch(t->previous(), ">")) { + t->deleteThis(); + t->deleteThis(); + t->deleteNext(); + tok->str("."); + } else { + tok->str("."); + tok->originalName("->"); + } } } } diff --git a/test/cfg/bsd.c b/test/cfg/bsd.c index 6cd0363d26e..3cb39c14810 100644 --- a/test/cfg/bsd.c +++ b/test/cfg/bsd.c @@ -72,7 +72,7 @@ ssize_t nullPointer_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t o return pwritev(fd,iov,iovcnt,offset); } -// #9346 +// False negative: #9346 void uninitvar_timercmp(struct timeval t) { struct timeval uninit; diff --git a/test/cfg/posix.c b/test/cfg/posix.c index 8206885251d..af9f68ba4f0 100644 --- a/test/cfg/posix.c +++ b/test/cfg/posix.c @@ -1389,7 +1389,7 @@ void uninitvar_types(void) b + 1; struct dirent d; - // cppcheck-suppress constStatement - TODO: uninitvar + // cppcheck-suppress [uninitvar,constStatement] d.d_ino + 1; } diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 9a51e052d25..b2374752795 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -7632,6 +7632,22 @@ class TestUninitVar : public TestFixture { " S s{ d };\n" "}\n"); ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: d\n", errout_str()); + + valueFlowUninit("struct S { int x; int y; };\n" + "int f() {\n" + " S s;\n" + " s.x = 0;\n" + " return (&s)->x;\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); + + valueFlowUninit("struct S { int x; int y; };\n" + "int f() {\n" + " S s;\n" + " s.x = 0;\n" + " return (&s)->y;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: s.y\n", errout_str()); } void valueFlowUninitForLoop() diff --git a/test/testvarid.cpp b/test/testvarid.cpp index 7f1a4c40451..3d7626cb165 100644 --- a/test/testvarid.cpp +++ b/test/testvarid.cpp @@ -528,7 +528,7 @@ class TestVarID : public TestFixture { const char expected[] = "1: struct S { int i@1 ; } ;\n" "2: int f ( S s@2 ) {\n" - "3: return ( & s@2 ) . i@3 ;\n" + "3: return s@2 . i@3 ;\n" "4: }\n"; ASSERT_EQUALS(expected, actual);