* Fix #5766 (FP: typedef array throws off parser) * Fix travis build.
This commit is contained in:
parent
26ff750848
commit
4710d80a40
|
@ -1533,15 +1533,34 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// function returning function pointer? '... ( ... %name% ( ... ))( ... ) {'
|
// function returning function pointer? '... ( ... %name% ( ... ))( ... ) {'
|
||||||
|
// function returning reference to array '... ( & %name% ( ... ))[ ... ] {'
|
||||||
if (tok->str() == "(" && tok->strAt(1) != "*" &&
|
if (tok->str() == "(" && tok->strAt(1) != "*" &&
|
||||||
tok->link()->previous()->str() == ")") {
|
(tok->link()->previous()->str() == ")" || Token::simpleMatch(tok->link()->tokAt(-2), ") const"))) {
|
||||||
const Token* tok2 = tok->link()->next();
|
const Token* tok2 = tok->link()->next();
|
||||||
if (tok2 && tok2->str() == "(" && Token::Match(tok2->link()->next(), "{|;|const|=")) {
|
if (tok2 && tok2->str() == "(" && Token::Match(tok2->link()->next(), "{|;|const|=")) {
|
||||||
const Token* argStartTok = tok->link()->previous()->link();
|
const Token* argStartTok;
|
||||||
|
if (tok->link()->previous()->str() == "const")
|
||||||
|
argStartTok = tok->link()->linkAt(-2);
|
||||||
|
else
|
||||||
|
argStartTok = tok->link()->linkAt(-1);
|
||||||
*funcStart = argStartTok->previous();
|
*funcStart = argStartTok->previous();
|
||||||
*argStart = argStartTok;
|
*argStart = argStartTok;
|
||||||
*declEnd = Token::findmatch(tok2->link()->next(), "{|;");
|
*declEnd = Token::findmatch(tok2->link()->next(), "{|;");
|
||||||
return true;
|
return true;
|
||||||
|
} else if (tok2 && tok2->str() == "[") {
|
||||||
|
while (tok2 && tok2->str() == "[")
|
||||||
|
tok2 = tok2->link()->next();
|
||||||
|
if (Token::Match(tok2, "{|;|const|=")) {
|
||||||
|
const Token* argStartTok;
|
||||||
|
if (tok->link()->previous()->str() == "const")
|
||||||
|
argStartTok = tok->link()->linkAt(-2);
|
||||||
|
else
|
||||||
|
argStartTok = tok->link()->linkAt(-1);
|
||||||
|
*funcStart = argStartTok->previous();
|
||||||
|
*argStart = argStartTok;
|
||||||
|
*declEnd = Token::findmatch(tok2, "{|;");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,10 +91,14 @@ const Token * Tokenizer::isFunctionHead(const Token *tok, const std::string &end
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (tok->str() == "(")
|
if (tok->str() == "(")
|
||||||
tok = tok->link();
|
tok = tok->link();
|
||||||
if (Token::Match(tok, ") [;{]")) {
|
if (Token::Match(tok, ") )| ;|{|[")) {
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
if (tok->isName())
|
if (tok->isName())
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
|
if (tok->str() == ")")
|
||||||
|
tok = tok->next();
|
||||||
|
while (tok && tok->str() == "[")
|
||||||
|
tok = tok->link()->next();
|
||||||
return (endsWith.find(tok->str()) != std::string::npos) ? tok : nullptr;
|
return (endsWith.find(tok->str()) != std::string::npos) ? tok : nullptr;
|
||||||
}
|
}
|
||||||
if (cpp && tok->str() == ")") {
|
if (cpp && tok->str() == ")") {
|
||||||
|
@ -102,6 +106,10 @@ const Token * Tokenizer::isFunctionHead(const Token *tok, const std::string &end
|
||||||
while (Token::Match(tok, "const|noexcept|override|volatile|&|&& !!(") ||
|
while (Token::Match(tok, "const|noexcept|override|volatile|&|&& !!(") ||
|
||||||
(Token::Match(tok, "%name% !!(") && tok->isUpperCaseName()))
|
(Token::Match(tok, "%name% !!(") && tok->isUpperCaseName()))
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
|
if (tok && tok->str() == ")")
|
||||||
|
tok = tok->next();
|
||||||
|
while (tok && tok->str() == "[")
|
||||||
|
tok = tok->link()->next();
|
||||||
if (Token::Match(tok, "throw|noexcept ("))
|
if (Token::Match(tok, "throw|noexcept ("))
|
||||||
tok = tok->linkAt(1)->next();
|
tok = tok->linkAt(1)->next();
|
||||||
if (Token::Match(tok, "%name% (") && tok->isUpperCaseName())
|
if (Token::Match(tok, "%name% (") && tok->isUpperCaseName())
|
||||||
|
@ -1035,8 +1043,13 @@ void Tokenizer::simplifyTypedef()
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for member functions
|
// check for member functions
|
||||||
else if (isCPP() && Token::Match(tok2, ") const| {")) {
|
else if (isCPP() && Token::Match(tok2, ")|] const| {")) {
|
||||||
const Token *func = tok2->link()->previous();
|
const Token *temp = tok2;
|
||||||
|
while (temp->str() == "]")
|
||||||
|
temp = temp->link()->previous();
|
||||||
|
const Token *func = temp->link()->previous();
|
||||||
|
if (temp->str() != ")")
|
||||||
|
continue;
|
||||||
if (!func || !func->previous()) // Ticket #4239
|
if (!func || !func->previous()) // Ticket #4239
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -1107,7 +1120,6 @@ void Tokenizer::simplifyTypedef()
|
||||||
// check for typedef that can be substituted
|
// check for typedef that can be substituted
|
||||||
else if (Token::simpleMatch(tok2, pattern.c_str()) ||
|
else if (Token::simpleMatch(tok2, pattern.c_str()) ||
|
||||||
(inMemberFunc && tok2->str() == typeName->str())) {
|
(inMemberFunc && tok2->str() == typeName->str())) {
|
||||||
|
|
||||||
// member function class variables don't need qualification
|
// member function class variables don't need qualification
|
||||||
if (!(inMemberFunc && tok2->str() == typeName->str()) && pattern.find("::") != std::string::npos) { // has a "something ::"
|
if (!(inMemberFunc && tok2->str() == typeName->str()) && pattern.find("::") != std::string::npos) { // has a "something ::"
|
||||||
Token *start = tok2;
|
Token *start = tok2;
|
||||||
|
@ -1517,6 +1529,17 @@ void Tokenizer::simplifyTypedef()
|
||||||
if (!tok2)
|
if (!tok2)
|
||||||
syntaxError(nullptr);
|
syntaxError(nullptr);
|
||||||
|
|
||||||
|
while (tok2->strAt(1) == "::")
|
||||||
|
tok2 = tok2->tokAt(2);
|
||||||
|
|
||||||
|
// skip over function parameters
|
||||||
|
if (tok2->strAt(1) == "(") {
|
||||||
|
tok2 = tok2->linkAt(1);
|
||||||
|
|
||||||
|
if (tok2->strAt(1) == "const")
|
||||||
|
tok2 = tok2->next();
|
||||||
|
}
|
||||||
|
|
||||||
tok2->insertToken(")");
|
tok2->insertToken(")");
|
||||||
tok2 = tok2->next();
|
tok2 = tok2->next();
|
||||||
Token::createMutualLinks(tok2, tok3);
|
Token::createMutualLinks(tok2, tok3);
|
||||||
|
@ -1533,8 +1556,6 @@ void Tokenizer::simplifyTypedef()
|
||||||
if (!tok2->next())
|
if (!tok2->next())
|
||||||
syntaxError(tok2);
|
syntaxError(tok2);
|
||||||
|
|
||||||
tok2 = tok2->next();
|
|
||||||
|
|
||||||
if (tok2->str() == "=") {
|
if (tok2->str() == "=") {
|
||||||
if (!tok2->next())
|
if (!tok2->next())
|
||||||
syntaxError(tok2);
|
syntaxError(tok2);
|
||||||
|
|
|
@ -187,6 +187,7 @@ private:
|
||||||
TEST_CASE(constructors_crash1); // ticket #5641
|
TEST_CASE(constructors_crash1); // ticket #5641
|
||||||
TEST_CASE(classWithOperatorInName);// ticket #2827
|
TEST_CASE(classWithOperatorInName);// ticket #2827
|
||||||
TEST_CASE(templateConstructor); // ticket #7942
|
TEST_CASE(templateConstructor); // ticket #7942
|
||||||
|
TEST_CASE(typedefArray); // ticket #5766
|
||||||
|
|
||||||
TEST_CASE(uninitAssignmentWithOperator); // ticket #7429
|
TEST_CASE(uninitAssignmentWithOperator); // ticket #7429
|
||||||
TEST_CASE(uninitCompoundAssignment); // ticket #7429
|
TEST_CASE(uninitCompoundAssignment); // ticket #7429
|
||||||
|
@ -3397,6 +3398,16 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void typedefArray() { // ticket #5766
|
||||||
|
check("typedef float rvec[3];\n"
|
||||||
|
"class SelectionPosition {\n"
|
||||||
|
"public:\n"
|
||||||
|
" SelectionPosition() {}\n"
|
||||||
|
" const rvec &x() const;\n"
|
||||||
|
"};");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void uninitAssignmentWithOperator() {
|
void uninitAssignmentWithOperator() {
|
||||||
check("struct C {\n"
|
check("struct C {\n"
|
||||||
" int x;\n"
|
" int x;\n"
|
||||||
|
|
|
@ -158,6 +158,7 @@ private:
|
||||||
TEST_CASE(simplifyTypedef118); // ticket #5749
|
TEST_CASE(simplifyTypedef118); // ticket #5749
|
||||||
TEST_CASE(simplifyTypedef119); // ticket #7541
|
TEST_CASE(simplifyTypedef119); // ticket #7541
|
||||||
TEST_CASE(simplifyTypedef120); // ticket #8357
|
TEST_CASE(simplifyTypedef120); // ticket #8357
|
||||||
|
TEST_CASE(simplifyTypedef121); // ticket #5766
|
||||||
|
|
||||||
TEST_CASE(simplifyTypedefFunction1);
|
TEST_CASE(simplifyTypedefFunction1);
|
||||||
TEST_CASE(simplifyTypedefFunction2); // ticket #1685
|
TEST_CASE(simplifyTypedefFunction2); // ticket #1685
|
||||||
|
@ -2454,6 +2455,43 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void simplifyTypedef121() { // #5766
|
||||||
|
const char code[] = "typedef float vec3[3];\n"
|
||||||
|
"typedef float mat3x3[3][3];\n"
|
||||||
|
"vec3 v3;\n"
|
||||||
|
"mat3x3 m3x3;\n"
|
||||||
|
"const vec3 &gv() { return v3; }\n"
|
||||||
|
"const mat3x3 &gm() { return m3x3; }\n"
|
||||||
|
"class Fred {\n"
|
||||||
|
"public:\n"
|
||||||
|
" vec3 &v();\n"
|
||||||
|
" mat3x3 &m();\n"
|
||||||
|
" const vec3 &vc() const;\n"
|
||||||
|
" const mat3x3 &mc() const;\n"
|
||||||
|
"};\n"
|
||||||
|
"vec3 & Fred::v() { return v3; }\n"
|
||||||
|
"mat3x3 & Fred::m() { return m3x3; }\n"
|
||||||
|
"const vec3 & Fred::vc() const { return v3; }\n"
|
||||||
|
"const mat3x3 & Fred::mc() const { return m3x3; }";
|
||||||
|
const char exp [] = "float v3 [ 3 ] ; "
|
||||||
|
"float m3x3 [ 3 ] [ 3 ] ; "
|
||||||
|
"const float ( & gv ( ) ) [ 3 ] { return v3 ; } "
|
||||||
|
"const float ( & gm ( ) ) [ 3 ] [ 3 ] { return m3x3 ; } "
|
||||||
|
"class Fred { "
|
||||||
|
"public: "
|
||||||
|
"float ( & v ( ) ) [ 3 ] ; "
|
||||||
|
"float ( & m ( ) ) [ 3 ] [ 3 ] ; "
|
||||||
|
"const float ( & vc ( ) const ) [ 3 ] ; "
|
||||||
|
"const float ( & mc ( ) const ) [ 3 ] [ 3 ] ; "
|
||||||
|
"} ; "
|
||||||
|
"float ( & Fred :: v ( ) ) [ 3 ] { return v3 ; } "
|
||||||
|
"float ( & Fred :: m ( ) ) [ 3 ] [ 3 ] { return m3x3 ; } "
|
||||||
|
"const float ( & Fred :: vc ( ) const ) [ 3 ] { return v3 ; } "
|
||||||
|
"const float ( & Fred :: mc ( ) const ) [ 3 ] [ 3 ] { return m3x3 ; }";
|
||||||
|
ASSERT_EQUALS(exp, tok(code, false));
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void simplifyTypedefFunction1() {
|
void simplifyTypedefFunction1() {
|
||||||
{
|
{
|
||||||
const char code[] = "typedef void (*my_func)();\n"
|
const char code[] = "typedef void (*my_func)();\n"
|
||||||
|
|
Loading…
Reference in New Issue