From e8bbfdbfee609391da1294c6e8f6024f3a966fbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 19 Apr 2020 17:29:40 +0200 Subject: [PATCH] Fixed #9559 (Multiple checks to std::atomic are not redundant) --- lib/symboldatabase.cpp | 2 +- lib/valueflow.cpp | 2 ++ test/testsymboldatabase.cpp | 16 ++++++++++++++++ test/testvalueflow.cpp | 15 +++++++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index be5f9ca4c..7db4e888e 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1871,7 +1871,7 @@ void Variable::evaluate(const Settings* settings) setFlag(fIsStatic, true); else if (tok->str() == "extern") setFlag(fIsExtern, true); - else if (tok->str() == "volatile") + else if (tok->str() == "volatile" || Token::simpleMatch(tok, "std :: atomic <")) setFlag(fIsVolatile, true); else if (tok->str() == "mutable") setFlag(fIsMutable, true); diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 609d53dbd..79f869c7d 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -3928,6 +3928,8 @@ struct ValueFlowConditionHandler { Condition cond = parse(tok); if (!cond.vartok) continue; + if (cond.vartok->variable() && cond.vartok->variable()->isVolatile()) + continue; if (cond.true_values.empty() || cond.false_values.empty()) continue; diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 4952388fb..603f7050d 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -150,6 +150,7 @@ private: TEST_CASE(isVariablePointerToVolatilePointer); TEST_CASE(isVariablePointerToConstVolatilePointer); TEST_CASE(isVariableMultiplePointersAndQualifiers); + TEST_CASE(variableVolatile); TEST_CASE(VariableValueType1); TEST_CASE(VariableValueType2); @@ -1134,6 +1135,21 @@ private: ASSERT(false == v.isReference()); } + void variableVolatile() { + GET_SYMBOL_DB("std::atomic x;\n" + "volatile int y;\n"); + + const Token *x = Token::findsimplematch(tokenizer.tokens(), "x"); + ASSERT(x); + ASSERT(x->variable()); + ASSERT(x->variable()->isVolatile()); + + const Token *y = Token::findsimplematch(tokenizer.tokens(), "y"); + ASSERT(y); + ASSERT(y->variable()); + ASSERT(y->variable()->isVolatile()); + } + void arrayMemberVar1() { GET_SYMBOL_DB("struct Foo {\n" " int x;\n" diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 39a303822..6fc9e0914 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -2370,6 +2370,21 @@ private: "}\n"; ASSERT_EQUALS(false, testValueOfXKnown(code, 6U, 0)); ASSERT_EQUALS(true, testValueOfX(code, 6U, 0)); + + // volatile variable + code = "void foo(const volatile int &x) {\n" + " if (x==1) {\n" + " return x;\n" + " }" + "}"; + ASSERT_EQUALS(false, testValueOfXKnown(code, 3U, 1)); + + code = "void foo(const std::atomic &x) {\n" + " if (x==2) {\n" + " return x;\n" + " }" + "}"; + ASSERT_EQUALS(false, testValueOfXKnown(code, 3U, 2)); } void valueFlowAfterConditionExpr() {