Support unknown THROW()-style macros in symboldatabase; Fixed #5056.
Simplified related code.
This commit is contained in:
parent
484483bd5d
commit
025850d961
|
@ -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?
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue