diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 911dd9902..1211505fe 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -79,6 +79,17 @@ static const Token * isFunctionHead(const Token *tok, const std::string &endsWit } return nullptr; } + +static bool isClassStructUnionStart(const Token * tok) +{ + if (tok->str() != "{") + return false; + const Token * tok2 = tok->previous(); + while (tok2 && !Token::Match(tok2, "class|struct|union|{|;")) + tok2 = tok2->previous(); + return Token::Match(tok2, "class|struct|union"); +} + //--------------------------------------------------------------------------- Tokenizer::Tokenizer() : @@ -2590,14 +2601,14 @@ void Tokenizer::setVarId() scopeInfo.push(variableId); } else if (tok->str() == "{") { // parse anonymous unions as part of the current scope - if (!(tok->strAt(-1) == "union" && Token::simpleMatch(tok->link(), "} ;")) && - !(initlist && Token::Match(tok->previous(), "%name%|>|>>") && Token::Match(tok->link(), "} ,|{"))) { + if (!(initlist && Token::Match(tok->previous(), "%name%|>|>>") && Token::Match(tok->link(), "} ,|{"))) { bool isExecutable; if (tok->strAt(-1) == ")" || Token::Match(tok->tokAt(-2), ") %type%") || (initlist && tok->strAt(-1) == "}")) { isExecutable = true; } else { - isExecutable = (initlist || tok->strAt(-1) == "else"); + isExecutable = ((scopeStack.top().isExecutable || initlist || tok->strAt(-1) == "else") && + !isClassStructUnionStart(tok)); scopeInfo.push(variableId); } initlist = false; diff --git a/test/testvarid.cpp b/test/testvarid.cpp index e68a220a4..9a31ef0a1 100644 --- a/test/testvarid.cpp +++ b/test/testvarid.cpp @@ -85,6 +85,7 @@ private: TEST_CASE(varid54); // hang TEST_CASE(varid55); // #5868: Function::addArgument with varid 0 for argument named the same as a typedef TEST_CASE(varid56); // function with a throw() + TEST_CASE(varid57); // #6636: new scope by {} TEST_CASE(varid_cpp_keywords_in_c_code); TEST_CASE(varid_cpp_keywords_in_c_code2); // #5373: varid=0 for argument called "delete" TEST_CASE(varidFunctionCall1); @@ -991,6 +992,37 @@ private: ASSERT_EQUALS(expected3, tokenize(code3, false, "test.cpp")); } + void varid57() { // #6636: new scope by {} + const char code1[] = "void SmoothPath() {\n" + " {\n" // new scope + " float dfx = (p2p0.x > 0.0f)?\n" + " ((n0->xmax() * SQUARE_SIZE) - p0.x):\n" + " ((n0->xmin() * SQUARE_SIZE) - p0.x);\n" + " float tx = dfx / dx;\n" + " if (hEdge) {\n" + " }\n" + " if (vEdge) {\n" + " pi.z = tx;\n" + " }\n" + " }\n" + "}\n"; + const char expected1[] = "\n\n##file 0\n" + "1: void SmoothPath ( ) {\n" + "2:\n" + "3: float dfx@1 ; dfx@1 = ( p2p0 . x > 0.0f ) ?\n" + "4: ( ( n0 . xmax ( ) * SQUARE_SIZE ) - p0 . x ) :\n" + "5: ( ( n0 . xmin ( ) * SQUARE_SIZE ) - p0 . x ) ;\n" + "6: float tx@2 ; tx@2 = dfx@1 / dx ;\n" + "7: if ( hEdge ) {\n" + "8: }\n" + "9: if ( vEdge ) {\n" + "10: pi . z = tx@2 ;\n" + "11: }\n" + "12:\n" + "13: }\n"; + ASSERT_EQUALS(expected1, tokenize(code1, false, "test.cpp")); + } + void varid_cpp_keywords_in_c_code() { const char code[] = "void f() {\n" " delete d;\n"