Support unknown THROW()-style macros in symboldatabase; Fixed #5056.

Simplified related code.
This commit is contained in:
PKEuS 2014-03-31 20:33:01 +02:00
parent 484483bd5d
commit 025850d961
2 changed files with 50 additions and 56 deletions

View File

@ -560,33 +560,19 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
// function? // function?
if (isFunction(tok, scope, &funcStart, &argStart)) { if (isFunction(tok, scope, &funcStart, &argStart)) {
// has body? bool retFuncPtr = Token::simpleMatch(argStart->link(), ") ) (");
if (Token::Match(argStart->link(), ") const| {|:")) { const Token* scopeBegin = argStart->link()->next();
Scope *old_scope = scope;
// class function if (retFuncPtr)
if (tok->previous() && tok->previous()->str() == "::") scopeBegin = scopeBegin->next()->link()->next();
addClassFunction(&scope, &tok, argStart); if (scopeBegin->isName()) { // Jump behind 'const' or unknown Macro
scopeBegin = scopeBegin->next();
// class destructor if (scopeBegin->link() && scopeBegin->str() == "(") // Jump behind unknown macro of type THROW(...)
else if (tok->previous() && tok->previous()->str() == "~" && scopeBegin = scopeBegin->link()->next();
tok->tokAt(-2) && tok->strAt(-2) == "::")
addClassFunction(&scope, &tok, argStart);
// regular function
else
addGlobalFunction(scope, tok, argStart, funcStart);
// syntax error
if (!scope) {
scope = old_scope;
break;
}
} }
// function returning function pointer with body // has body?
else if (Token::simpleMatch(argStart->link(), ") ) (") && if (scopeBegin->str() == "{" || scopeBegin->str() == ":") {
Token::Match(argStart->link()->linkAt(2), ") const| {")) {
tok = funcStart; tok = funcStart;
Scope *old_scope = scope; Scope *old_scope = scope;
@ -594,10 +580,15 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
if (tok->previous()->str() == "::") if (tok->previous()->str() == "::")
addClassFunction(&scope, &tok, argStart); addClassFunction(&scope, &tok, argStart);
// class destructor
else if (tok->previous()->str() == "~" &&
tok->strAt(-2) == "::")
addClassFunction(&scope, &tok, argStart);
// regular function // regular function
else { else {
Function* function = addGlobalFunction(scope, tok, argStart, funcStart); Function* function = addGlobalFunction(scope, tok, argStart, funcStart);
function->retFuncPtr = true; function->retFuncPtr = retFuncPtr;
} }
// syntax error? // syntax error?
@ -606,9 +597,8 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
break; break;
} }
} }
// function prototype?
// function prototype else if (scopeBegin->str() == ";") {
else if (Token::simpleMatch(argStart->link(), ") ;")) {
bool newFunc = true; // Is this function already in the database? bool newFunc = true; // Is this function already in the database?
for (std::list<Function>::const_iterator i = scope->functionList.begin(); i != scope->functionList.end(); ++i) { for (std::list<Function>::const_iterator i = scope->functionList.begin(); i != scope->functionList.end(); ++i) {
if (i->tokenDef->str() == tok->str() && Function::argsMatch(scope, i->argDef->next(), argStart->next(), "", 0)) { if (i->tokenDef->str() == tok->str() && Function::argsMatch(scope, i->argDef->next(), argStart->next(), "", 0)) {
@ -617,29 +607,13 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
} }
} }
// save function prototype in database
if (newFunc)
addGlobalFunctionDecl(scope, tok, argStart, funcStart);
tok = argStart->link()->next();
continue;
}
// function returning function pointer prototype
else if (Token::simpleMatch(argStart->link(), ") ) (") &&
Token::simpleMatch(argStart->link()->linkAt(2), ") ;")) {
bool newFunc = true; // Is this function already in the database?
for (std::list<Function>::const_iterator i = scope->functionList.begin(); i != scope->functionList.end(); ++i) {
if (i->tokenDef->str() == tok->str() && Function::argsMatch(scope, i->argDef, argStart, "", 0))
newFunc = false;
}
// save function prototype in database // save function prototype in database
if (newFunc) { if (newFunc) {
Function* func = addGlobalFunctionDecl(scope, tok, argStart, funcStart); Function* func = addGlobalFunctionDecl(scope, tok, argStart, funcStart);
func->retFuncPtr = true; func->retFuncPtr = retFuncPtr;
} }
tok = argStart->link()->linkAt(2)->next(); tok = scopeBegin;
continue; continue;
} }
} }
@ -1000,14 +974,17 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
else if (Token::Match(tok, "%var% (") && tok->previous() && else if (Token::Match(tok, "%var% (") && tok->previous() &&
(tok->previous()->isName() || tok->strAt(-1) == ">" || tok->strAt(-1) == "&" || tok->strAt(-1) == "*" || // Either a return type in front of tok (tok->previous()->isName() || tok->strAt(-1) == ">" || tok->strAt(-1) == "&" || tok->strAt(-1) == "*" || // Either a return type in front of tok
tok->strAt(-1) == "::" || tok->strAt(-1) == "~" || // or a scope qualifier in front of tok tok->strAt(-1) == "::" || tok->strAt(-1) == "~" || // or a scope qualifier in front of tok
outerScope->isClassOrStruct()) && // or a ctor/dtor outerScope->isClassOrStruct())) { // or a ctor/dtor
(Token::Match(tok->next()->link(), ") const| ;|{|=") || const Token* tok2 = tok->next()->link()->next();
(Token::Match(tok->next()->link(), ") %var% ;|{") && tok->next()->link()->next()->isUpperCaseName()) || if ((Token::Match(tok2, "const| ;|{|=") ||
Token::Match(tok->next()->link(), ") : ::| %var% (|::|<|{") || (Token::Match(tok2, "%var% ;|{") && tok2->isUpperCaseName()) ||
Token::Match(tok->next()->link(), ") = delete|default ;"))) { (Token::Match(tok2, "%var% (") && tok2->isUpperCaseName() && tok2->next()->link()->strAt(1) == "{") ||
*funcStart = tok; Token::Match(tok2, ": ::| %var% (|::|<|{") ||
*argStart = tok->next(); Token::Match(tok2, "= delete|default ;"))) {
return true; *funcStart = tok;
*argStart = tok->next();
return true;
}
} }
// template constructor? // template constructor?

View File

@ -140,7 +140,8 @@ private:
TEST_CASE(testConstructors); TEST_CASE(testConstructors);
TEST_CASE(functionDeclarationTemplate); TEST_CASE(functionDeclarationTemplate);
TEST_CASE(functionDeclarations); TEST_CASE(functionDeclarations);
TEST_CASE(memberFunctionOfUnknownClassMacro); TEST_CASE(memberFunctionOfUnknownClassMacro1);
TEST_CASE(memberFunctionOfUnknownClassMacro2);
TEST_CASE(classWithFriend); TEST_CASE(classWithFriend);
@ -956,7 +957,7 @@ private:
} }
} }
void memberFunctionOfUnknownClassMacro() { void memberFunctionOfUnknownClassMacro1() {
GET_SYMBOL_DB("class ScVbaFormatCondition { OUString getServiceImplName() SAL_OVERRIDE; };\n" GET_SYMBOL_DB("class ScVbaFormatCondition { OUString getServiceImplName() SAL_OVERRIDE; };\n"
"void ScVbaValidation::getFormula1() {\n" "void ScVbaValidation::getFormula1() {\n"
" sal_uInt16 nFlags = 0;\n" " sal_uInt16 nFlags = 0;\n"
@ -972,6 +973,22 @@ private:
} }
} }
void memberFunctionOfUnknownClassMacro2() {
GET_SYMBOL_DB("class ScVbaFormatCondition { OUString getServiceImplName() THROW(whatever); };\n"
"void ScVbaValidation::getFormula1() {\n"
" sal_uInt16 nFlags = 0;\n"
" if (pDocSh && !getCellRangesForAddress(nFlags)) ;\n"
"}");
ASSERT(db && errout.str() == "");
if (db) {
const Scope *scope = db->findScopeByName("getFormula1");
ASSERT(scope != nullptr);
ASSERT(scope && scope->nestedIn == &db->scopeList.front());
}
}
void classWithFriend() { void classWithFriend() {
GET_SYMBOL_DB("class Foo {}; class Bar1 { friend class Foo; }; class Bar2 { friend Foo; };") GET_SYMBOL_DB("class Foo {}; class Bar1 { friend class Foo; }; class Bar2 { friend Foo; };")
// 3 scopes: Global, 3 classes // 3 scopes: Global, 3 classes