Fix #5766 (FP: typedef array throws off parser) (#1052)

* Fix #5766 (FP: typedef array throws off parser)

* Fix travis build.
This commit is contained in:
IOBYTE 2018-01-24 03:51:22 -05:00 committed by amai2012
parent 26ff750848
commit 4710d80a40
4 changed files with 97 additions and 8 deletions

View File

@ -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;
}
} }
} }

View File

@ -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);

View File

@ -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"

View File

@ -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"