diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 1b6c51ed5..80f4414a3 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -6758,7 +6758,7 @@ bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsign if (isCPP() && Token::Match(tok3, (">> " + structname + " %varid%").c_str(), varid)) { // bailout for such code: ; std :: cin >> i ; const Token *prev = tok3->previous(); - while (prev && prev->str() != "return" && (prev->isName() || prev->str() == "::")) + while (prev && prev->str() != "return" && Token::Match(prev, "%var%|::|*")) prev = prev->previous(); if (Token::Match(prev, ";|{|}|>>")) break; diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index a3ead1317..1acaf0f9b 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -564,6 +564,18 @@ static void valueFlowAfterAssign(TokenList *tokenlist, ErrorLogger *errorLogger, break; } + // bailout: possible assignment using >> + if (Token::Match(tok2->previous(), ">> %var% >>|;")) { + const Token *parent = tok2->previous(); + while (Token::simpleMatch(parent,">>")) + parent = parent->astParent(); + if (!parent) { + if (settings->debugwarnings) + bailout(tokenlist, errorLogger, tok2, "Possible assignment of " + tok2->str() + " using >>"); + break; + } + } + // skip if variable is conditionally used in ?: expression if (const Token *parent = skipValueInConditionalExpression(tok2)) { if (settings->debugwarnings) diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 3595cb011..cfc6519f1 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -188,6 +188,7 @@ private: TEST_CASE(simplifyKnownVariables53); // references TEST_CASE(simplifyKnownVariables54); // #4913 'x' is not 0 after *--x=0; TEST_CASE(simplifyKnownVariables55); // pointer alias + TEST_CASE(simplifyKnownVariables56); // ticket #5301 - >> TEST_CASE(simplifyKnownVariablesIfEq1); // if (a==5) => a is 5 in the block TEST_CASE(simplifyKnownVariablesIfEq2); // if (a==5) { buf[a++] = 0; } TEST_CASE(simplifyKnownVariablesIfEq3); // #4708 - if (a==5) { buf[--a] = 0; } @@ -2888,6 +2889,11 @@ private: ASSERT_EQUALS("void f ( ) { int a ; if ( x > a ) { } }", tokenizeAndStringify("void f() { int a; int *p=&a; if (x>*p) {} }", true)); } + void simplifyKnownVariables56() { // ticket #5301 - >> + ASSERT_EQUALS("void f ( ) { int a ; a = 0 ; int b ; b = 0 ; * p >> a >> b ; return a / b ; }", + tokenizeAndStringify("void f() { int a=0,b=0; *p>>a>>b; return a/b; }", true)); + } + void simplifyKnownVariablesIfEq1() { const char code[] = "void f(int x) {\n" " if (x==5) {\n" diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index e1a287d86..ba1122e69 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -498,6 +498,13 @@ private: "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 2)); + code = "void f() {\n" + " static int x = 2;\n" + " a >> x;\n" + " return x;\n" + "}"; + ASSERT_EQUALS(false, testValueOfX(code, 4U, 2)); + // function code = "void f() {\n" " char *x = 0;\n"