* 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;
|
||||
|
||||
// function returning function pointer? '... ( ... %name% ( ... ))( ... ) {'
|
||||
// function returning reference to array '... ( & %name% ( ... ))[ ... ] {'
|
||||
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();
|
||||
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();
|
||||
*argStart = argStartTok;
|
||||
*declEnd = Token::findmatch(tok2->link()->next(), "{|;");
|
||||
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;
|
||||
if (tok->str() == "(")
|
||||
tok = tok->link();
|
||||
if (Token::Match(tok, ") [;{]")) {
|
||||
if (Token::Match(tok, ") )| ;|{|[")) {
|
||||
tok = tok->next();
|
||||
if (tok->isName())
|
||||
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;
|
||||
}
|
||||
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|&|&& !!(") ||
|
||||
(Token::Match(tok, "%name% !!(") && tok->isUpperCaseName()))
|
||||
tok = tok->next();
|
||||
if (tok && tok->str() == ")")
|
||||
tok = tok->next();
|
||||
while (tok && tok->str() == "[")
|
||||
tok = tok->link()->next();
|
||||
if (Token::Match(tok, "throw|noexcept ("))
|
||||
tok = tok->linkAt(1)->next();
|
||||
if (Token::Match(tok, "%name% (") && tok->isUpperCaseName())
|
||||
|
@ -1035,8 +1043,13 @@ void Tokenizer::simplifyTypedef()
|
|||
}
|
||||
|
||||
// check for member functions
|
||||
else if (isCPP() && Token::Match(tok2, ") const| {")) {
|
||||
const Token *func = tok2->link()->previous();
|
||||
else if (isCPP() && Token::Match(tok2, ")|] const| {")) {
|
||||
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
|
||||
continue;
|
||||
|
||||
|
@ -1107,7 +1120,6 @@ void Tokenizer::simplifyTypedef()
|
|||
// check for typedef that can be substituted
|
||||
else if (Token::simpleMatch(tok2, pattern.c_str()) ||
|
||||
(inMemberFunc && tok2->str() == typeName->str())) {
|
||||
|
||||
// member function class variables don't need qualification
|
||||
if (!(inMemberFunc && tok2->str() == typeName->str()) && pattern.find("::") != std::string::npos) { // has a "something ::"
|
||||
Token *start = tok2;
|
||||
|
@ -1517,6 +1529,17 @@ void Tokenizer::simplifyTypedef()
|
|||
if (!tok2)
|
||||
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 = tok2->next();
|
||||
Token::createMutualLinks(tok2, tok3);
|
||||
|
@ -1533,8 +1556,6 @@ void Tokenizer::simplifyTypedef()
|
|||
if (!tok2->next())
|
||||
syntaxError(tok2);
|
||||
|
||||
tok2 = tok2->next();
|
||||
|
||||
if (tok2->str() == "=") {
|
||||
if (!tok2->next())
|
||||
syntaxError(tok2);
|
||||
|
|
|
@ -187,6 +187,7 @@ private:
|
|||
TEST_CASE(constructors_crash1); // ticket #5641
|
||||
TEST_CASE(classWithOperatorInName);// ticket #2827
|
||||
TEST_CASE(templateConstructor); // ticket #7942
|
||||
TEST_CASE(typedefArray); // ticket #5766
|
||||
|
||||
TEST_CASE(uninitAssignmentWithOperator); // ticket #7429
|
||||
TEST_CASE(uninitCompoundAssignment); // ticket #7429
|
||||
|
@ -3397,6 +3398,16 @@ private:
|
|||
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() {
|
||||
check("struct C {\n"
|
||||
" int x;\n"
|
||||
|
|
|
@ -158,6 +158,7 @@ private:
|
|||
TEST_CASE(simplifyTypedef118); // ticket #5749
|
||||
TEST_CASE(simplifyTypedef119); // ticket #7541
|
||||
TEST_CASE(simplifyTypedef120); // ticket #8357
|
||||
TEST_CASE(simplifyTypedef121); // ticket #5766
|
||||
|
||||
TEST_CASE(simplifyTypedefFunction1);
|
||||
TEST_CASE(simplifyTypedefFunction2); // ticket #1685
|
||||
|
@ -2454,6 +2455,43 @@ private:
|
|||
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() {
|
||||
{
|
||||
const char code[] = "typedef void (*my_func)();\n"
|
||||
|
|
Loading…
Reference in New Issue