From 6e3d5dc0d1d7a9d4a520b3185d66e35abcbd589e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 16 Jul 2016 20:21:31 +0200 Subject: [PATCH] Fixed #7580 (False positive when using logical operator keywords 'and', 'or') --- lib/tokenize.cpp | 36 +++++++++++++++++------------------- test/testtokenize.cpp | 11 +++++++++++ 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index ed544ae0d..a74883a17 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -6024,18 +6024,16 @@ void Tokenizer::simplifyVariableMultipleAssign() } // Binary operators simplification map -namespace { - const std::map cAlternativeTokens = make_container< std::map >() - << std::make_pair("and", "&&") - << std::make_pair("and_eq", "&=") - << std::make_pair("bitand", "&") - << std::make_pair("bitor", "|") - << std::make_pair("not_eq", "!=") - << std::make_pair("or", "||") - << std::make_pair("or_eq", "|=") - << std::make_pair("xor", "^") - << std::make_pair("xor_eq", "^=") ; -} +static const std::map cAlternativeTokens = make_container< std::map >() + << std::make_pair("and", "&&") + << std::make_pair("and_eq", "&=") + << std::make_pair("bitand", "&") + << std::make_pair("bitor", "|") + << std::make_pair("not_eq", "!=") + << std::make_pair("or", "||") + << std::make_pair("or_eq", "|=") + << std::make_pair("xor", "^") + << std::make_pair("xor_eq", "^=") ; // Simplify the C alternative tokens: // and => && @@ -6051,10 +6049,10 @@ namespace { // xor_eq => ^= bool Tokenizer::simplifyCAlternativeTokens() { - if (!isC()) - return false; + // In C these are optional macros (iso646.h). In C++ these are builtin keywords. + bool cpp = isCPP(); - /* For C code: executable scope level */ + /* executable scope level */ unsigned int executableScopeLevel = 0; bool ret = false; @@ -6076,15 +6074,15 @@ bool Tokenizer::simplifyCAlternativeTokens() const std::map::const_iterator cOpIt = cAlternativeTokens.find(tok->str()); if (cOpIt != cAlternativeTokens.end()) { - if (!Token::Match(tok->previous(), "%name%|%num%|%char%|)|]|> %name% %name%|%num%|%char%|%op%|(")) + if (!cpp && !Token::Match(tok->previous(), "%name%|%num%|%char%|)|]|> %name% %name%|%num%|%char%|%op%|(")) continue; tok->str(cOpIt->second); ret = true; } else if (Token::Match(tok, "not|compl")) { // Don't simplify 'not p;' (in case 'not' is a type) - if (!Token::Match(tok->next(), "%name%|(") || - Token::Match(tok->previous(), "[;{}]") || - (executableScopeLevel == 0U && tok->strAt(-1) == "(")) + if (!cpp && (!Token::Match(tok->next(), "%name%|(") || + Token::Match(tok->previous(), "[;{}]") || + (executableScopeLevel == 0U && tok->strAt(-1) == "("))) continue; tok->str((tok->str() == "not") ? "!" : "~"); ret = true; diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 46ca7df59..9393f519c 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -5662,19 +5662,30 @@ private: void simplifyCAlternativeTokens() { ASSERT_EQUALS("void f ( ) { if ( a && b ) { ; } }", tokenizeAndStringify("void f() { if (a and b); }", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( a && b ) { ; } }", tokenizeAndStringify("void f() { if (a and b); }", false, true, Settings::Native, "test.cpp")); ASSERT_EQUALS("void f ( ) { if ( a || b ) { ; } }", tokenizeAndStringify("void f() { if (a or b); }", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( a || b ) { ; } }", tokenizeAndStringify("void f() { if (a or b); }", false, true, Settings::Native, "test.cpp")); ASSERT_EQUALS("void f ( ) { if ( a & b ) { ; } }", tokenizeAndStringify("void f() { if (a bitand b); }", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( a & b ) { ; } }", tokenizeAndStringify("void f() { if (a bitand b); }", false, true, Settings::Native, "test.cpp")); ASSERT_EQUALS("void f ( ) { if ( a | b ) { ; } }", tokenizeAndStringify("void f() { if (a bitor b); }", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( a | b ) { ; } }", tokenizeAndStringify("void f() { if (a bitor b); }", false, true, Settings::Native, "test.cpp")); ASSERT_EQUALS("void f ( ) { if ( a ^ b ) { ; } }", tokenizeAndStringify("void f() { if (a xor b); }", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( a ^ b ) { ; } }", tokenizeAndStringify("void f() { if (a xor b); }", false, true, Settings::Native, "test.cpp")); ASSERT_EQUALS("void f ( ) { if ( ~ b ) { ; } }", tokenizeAndStringify("void f() { if (compl b); }", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( ~ b ) { ; } }", tokenizeAndStringify("void f() { if (compl b); }", false, true, Settings::Native, "test.cpp")); ASSERT_EQUALS("void f ( ) { if ( ! b ) { ; } }", tokenizeAndStringify("void f() { if (not b); }", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( ! b ) { ; } }", tokenizeAndStringify("void f() { if (not b); }", false, true, Settings::Native, "test.cpp")); ASSERT_EQUALS("void f ( ) { if ( a != b ) { ; } }", tokenizeAndStringify("void f() { if (a not_eq b); }", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( a != b ) { ; } }", tokenizeAndStringify("void f() { if (a not_eq b); }", false, true, Settings::Native, "test.cpp")); // #6201 ASSERT_EQUALS("void f ( ) { if ( ! c || ! memcmp ( a , b , s ) ) { ; } }", tokenizeAndStringify("void f() { if (!c or !memcmp(a, b, s)); }", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( ! c || ! memcmp ( a , b , s ) ) { ; } }", tokenizeAndStringify("void f() { if (!c or !memcmp(a, b, s)); }", false, true, Settings::Native, "test.cpp")); // #6029 ASSERT_EQUALS("void f ( ) { if ( ! b ) { } }", tokenizeAndStringify("void f() { if (not b){} }", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( ! b ) { } }", tokenizeAndStringify("void f() { if (not b){} }", false, true, Settings::Native, "test.cpp")); // #6207 ASSERT_EQUALS("void f ( ) { if ( not = x ) { } }", tokenizeAndStringify("void f() { if (not=x){} }", false, true, Settings::Native, "test.c")); + ASSERT_EQUALS("void f ( ) { if ( not = x ) { } }", tokenizeAndStringify("void f() { if (not=x){} }", false, true, Settings::Native, "test.cpp")); } void simplifyCalculations() {