Changed heuristics to detect variable constructor initialization syntax (#6071)
This commit is contained in:
parent
96c5983409
commit
5d50e7e9ae
|
@ -2281,7 +2281,8 @@ static bool setVarIdParseDeclaration(const Token **tok, const std::map<std::stri
|
||||||
if (!tok2 || tok2->str() != "::")
|
if (!tok2 || tok2->str() != "::")
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
++typeCount;
|
if (tok2->str() != "void" || Token::Match(tok2, "void const| *|(")) // just "void" cannot be a variable type
|
||||||
|
++typeCount;
|
||||||
++singleNameCount;
|
++singleNameCount;
|
||||||
}
|
}
|
||||||
} else if ((TemplateSimplifier::templateParameters(tok2) > 0) ||
|
} else if ((TemplateSimplifier::templateParameters(tok2) > 0) ||
|
||||||
|
@ -2545,7 +2546,7 @@ void Tokenizer::setVarId()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tok == list.front() || Token::Match(tok, "[;{}]") ||
|
if (tok == list.front() || Token::Match(tok, "[;{}]") ||
|
||||||
(Token::Match(tok,"[(,]") && (!executableScope.top() || Token::simpleMatch(tok->link(), ") {"))) ||
|
(Token::Match(tok, "[(,]") && (!executableScope.top() || Token::simpleMatch(tok->link(), ") {"))) ||
|
||||||
(tok->isName() && tok->str().at(tok->str().length()-1U) == ':')) {
|
(tok->isName() && tok->str().at(tok->str().length()-1U) == ':')) {
|
||||||
|
|
||||||
// No variable declarations in sizeof
|
// No variable declarations in sizeof
|
||||||
|
@ -2570,45 +2571,45 @@ void Tokenizer::setVarId()
|
||||||
if (notstart.find(tok2->str()) != notstart.end())
|
if (notstart.find(tok2->str()) != notstart.end())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const bool decl = setVarIdParseDeclaration(&tok2, variableId, executableScope.top(), isCPP());
|
bool decl = setVarIdParseDeclaration(&tok2, variableId, executableScope.top(), isCPP());
|
||||||
|
if (decl) {
|
||||||
|
const Token* prev2 = tok2->previous();
|
||||||
|
if (Token::Match(prev2, "%type% [;[=,)]") && tok2->previous()->str() != "const")
|
||||||
|
;
|
||||||
|
else if (Token::Match(prev2, "%type% ( !!)") && Token::simpleMatch(tok2->link(), ") ;")) {
|
||||||
|
// In C++ , a variable can't be called operator+ or something like that.
|
||||||
|
if (isCPP() &&
|
||||||
|
prev2->str().size() >= 9 &&
|
||||||
|
prev2->str().compare(0, 8, "operator") == 0 &&
|
||||||
|
prev2->str()[8] != '_' &&
|
||||||
|
!std::isalnum(prev2->str()[8]))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (decl && Token::Match(tok2->previous(), "%type% [;[=,)]") && tok2->previous()->str() != "const") {
|
const Token *tok3 = tok2->next();
|
||||||
variableId[tok2->previous()->str()] = ++_varId;
|
if (!tok3->isStandardType() && tok3->str() != "void" && !Token::Match(tok3, "struct|union|class %type%") && tok3->str() != "." && !Token::Match(tok2->link()->previous(), "[&*]")) {
|
||||||
tok = tok2->previous();
|
if (!executableScope.top()) {
|
||||||
}
|
// Detecting initializations with () in non-executable scope is hard and often impossible to be done safely. Thus, only treat code as a variable that definitly is one.
|
||||||
|
decl = false;
|
||||||
else if (decl && Token::Match(tok2->previous(), "%type% ( !!)") && Token::simpleMatch(tok2->link(), ") ;")) {
|
for (; tok3; tok3 = tok3->nextArgument()) {
|
||||||
// In C++ , a variable can't be called operator+ or something like that.
|
if (tok3->isLiteral() || (tok3->isName() && (variableId.find(tok3->str()) != variableId.end())) || tok3->isOp() || (tok3->next()->isOp() && !Token::Match(tok3->next(), "*|&")) || notstart.find(tok3->str()) != notstart.end()) {
|
||||||
if (isCPP() &&
|
decl = true;
|
||||||
tok2->previous()->str().size() >= 9 &&
|
break;
|
||||||
tok2->previous()->str().compare(0, 8, "operator") == 0 &&
|
}
|
||||||
tok2->previous()->str()[8] != '_' &&
|
}
|
||||||
!std::isalnum(tok2->previous()->str()[8]))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const Token *tok3 = tok2->next();
|
|
||||||
if (!tok3->isStandardType() && tok3->str() != "void" && !Token::Match(tok3, "struct|union|class %type%") && tok3->str() != "." && !Token::Match(tok2->link()->previous(), "[&*]")) {
|
|
||||||
bool isDecl = true;
|
|
||||||
for (; tok3; tok3 = tok3->nextArgument()) {
|
|
||||||
if (tok3->strAt(-2) == "&" || tok3->strAt(-2) == "*" || (notstart.find(tok3->str()) == notstart.end() && setVarIdParseDeclaration(&tok3, variableId, executableScope.top(), isCPP()))) {
|
|
||||||
isDecl = false;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
if (isDecl) {
|
decl = false;
|
||||||
variableId[tok2->previous()->str()] = ++_varId;
|
} else if (isCPP() && Token::Match(prev2, "%type% {") && Token::simpleMatch(tok2->link(), "} ;")) { // C++11 initialization style
|
||||||
tok = tok2->previous();
|
if (Token::Match(prev2, "do|try|else"))
|
||||||
}
|
continue;
|
||||||
|
} else
|
||||||
|
decl = false;
|
||||||
|
|
||||||
|
if (decl) {
|
||||||
|
variableId[prev2->str()] = ++_varId;
|
||||||
|
tok = tok2->previous();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (decl && isCPP() && Token::Match(tok2->previous(), "%type% {") && Token::simpleMatch(tok2->link(), "} ;")) { // C++11 initialization style
|
|
||||||
if (Token::Match(tok2->previous(), "do|try|else"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
variableId[tok2->previous()->str()] = ++_varId;
|
|
||||||
tok = tok2->previous();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tok->isName()) {
|
if (tok->isName()) {
|
||||||
|
|
|
@ -4633,14 +4633,16 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void varid_in_class17() { // #6056 - Set no varid for member functions
|
void varid_in_class17() { // #6056 - Set no varid for member functions
|
||||||
const char code[] = "class Fred {\n"
|
const char code1[] = "class Fred {\n"
|
||||||
" int method_with_internal(X&);\n"
|
" int method_with_internal(X&);\n"
|
||||||
" int method_with_internal(X*);\n"
|
" int method_with_internal(X*);\n"
|
||||||
" int method_with_internal(int&);\n"
|
" int method_with_internal(int&);\n"
|
||||||
" int method_with_internal(A* b, X&);\n"
|
" int method_with_internal(A* b, X&);\n"
|
||||||
" int method_with_internal(X&, A* b);\n"
|
" int method_with_internal(X&, A* b);\n"
|
||||||
" int method_with_internal(const B &, int);\n"
|
" int method_with_internal(const B &, int);\n"
|
||||||
"};";
|
" void Set(BAR);\n"
|
||||||
|
" FOO Set(BAR);\n"
|
||||||
|
"};";
|
||||||
ASSERT_EQUALS("\n\n##file 0\n"
|
ASSERT_EQUALS("\n\n##file 0\n"
|
||||||
"1: class Fred {\n"
|
"1: class Fred {\n"
|
||||||
"2: int method_with_internal ( X & ) ;\n"
|
"2: int method_with_internal ( X & ) ;\n"
|
||||||
|
@ -4649,7 +4651,21 @@ private:
|
||||||
"5: int method_with_internal ( A * b@1 , X & ) ;\n"
|
"5: int method_with_internal ( A * b@1 , X & ) ;\n"
|
||||||
"6: int method_with_internal ( X & , A * b@2 ) ;\n"
|
"6: int method_with_internal ( X & , A * b@2 ) ;\n"
|
||||||
"7: int method_with_internal ( const B & , int ) ;\n"
|
"7: int method_with_internal ( const B & , int ) ;\n"
|
||||||
"8: } ;\n", tokenizeDebugListing(code, false, "test.cpp"));
|
"8: void Set ( BAR ) ;\n"
|
||||||
|
"9: FOO Set ( BAR ) ;\n"
|
||||||
|
"10: } ;\n", tokenizeDebugListing(code1, false, "test.cpp"));
|
||||||
|
|
||||||
|
const char code2[] = "int i;\n"
|
||||||
|
"SomeType someVar1(i, i);\n"
|
||||||
|
"SomeType someVar2(j, j);\n"
|
||||||
|
"SomeType someVar3(j, 1);\n"
|
||||||
|
"SomeType someVar4(new bar);";
|
||||||
|
ASSERT_EQUALS("\n\n##file 0\n"
|
||||||
|
"1: int i@1 ;\n"
|
||||||
|
"2: SomeType someVar1@2 ( i@1 , i@1 ) ;\n"
|
||||||
|
"3: SomeType someVar2 ( j , j ) ;\n" // This one could be a function
|
||||||
|
"4: SomeType someVar3@3 ( j , 1 ) ;\n"
|
||||||
|
"5: SomeType someVar4@4 ( new bar ) ;\n", tokenizeDebugListing(code2, false, "test.cpp"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void varid_initList() {
|
void varid_initList() {
|
||||||
|
@ -7297,12 +7313,12 @@ private:
|
||||||
void functionpointer6() {
|
void functionpointer6() {
|
||||||
const char code1[] = ";void (*fp(f))(int);";
|
const char code1[] = ";void (*fp(f))(int);";
|
||||||
const char expected1[] = "\n\n##file 0\n"
|
const char expected1[] = "\n\n##file 0\n"
|
||||||
"1: ; void * fp@1 ( f ) ;\n";
|
"1: ; void * fp ( f ) ;\n"; // No varId - it could be a function
|
||||||
ASSERT_EQUALS(expected1, tokenizeDebugListing(code1, false));
|
ASSERT_EQUALS(expected1, tokenizeDebugListing(code1, false));
|
||||||
|
|
||||||
const char code2[] = ";std::string (*fp(f))(int);";
|
const char code2[] = ";std::string (*fp(f))(int);";
|
||||||
const char expected2[] = "\n\n##file 0\n"
|
const char expected2[] = "\n\n##file 0\n"
|
||||||
"1: ; std :: string * fp@1 ( f ) ;\n";
|
"1: ; std :: string * fp ( f ) ;\n";
|
||||||
ASSERT_EQUALS(expected2, tokenizeDebugListing(code2, false));
|
ASSERT_EQUALS(expected2, tokenizeDebugListing(code2, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue