From ba1c24ee659ee07a4a898d4a40aa167684fd9bf2 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Thu, 8 Jan 2015 05:45:31 +0100 Subject: [PATCH] Fixed #6422 (symbol database: put function flags into a single flag variable) --- lib/check64bit.cpp | 2 +- lib/checkassert.cpp | 2 +- lib/checkbufferoverrun.cpp | 2 +- lib/checkclass.cpp | 58 ++++++------- lib/checkcondition.cpp | 2 +- lib/checkexceptionsafety.cpp | 12 +-- lib/checkmemoryleak.cpp | 8 +- lib/checknullpointer.cpp | 4 +- lib/checkother.cpp | 10 +-- lib/checkuninitvar.cpp | 4 +- lib/symboldatabase.cpp | 144 +++++++++++++++++++------------ lib/symboldatabase.h | 160 +++++++++++++++++++++++++++++------ test/testsymboldatabase.cpp | 74 +++++++++++----- 13 files changed, 328 insertions(+), 154 deletions(-) diff --git a/lib/check64bit.cpp b/lib/check64bit.cpp index 0031ce550..f418a8e21 100644 --- a/lib/check64bit.cpp +++ b/lib/check64bit.cpp @@ -53,7 +53,7 @@ void Check64BitPortability::pointerassignment() const std::size_t functions = symbolDatabase->functionScopes.size(); for (std::size_t i = 0; i < functions; ++i) { const Scope * scope = symbolDatabase->functionScopes[i]; - if (scope->function == 0 || !scope->function->hasBody) // We only look for functions with a body + if (scope->function == 0 || !scope->function->hasBody()) // We only look for functions with a body continue; bool retPointer = false; diff --git a/lib/checkassert.cpp b/lib/checkassert.cpp index a1592d730..4b876d4c3 100644 --- a/lib/checkassert.cpp +++ b/lib/checkassert.cpp @@ -47,7 +47,7 @@ void CheckAssert::assertWithSideEffects() if (tmp->type() == Token::eFunction) { const Function* f = tmp->function(); - if (f->nestedIn->isClassOrStruct() && !f->isStatic && !f->isConst) + if (f->nestedIn->isClassOrStruct() && !f->isStatic() && !f->isConst()) sideEffectInAssertError(tmp, f->name()); // Non-const member function called else { const Scope* scope = f->functionScope; diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index ef4e757ec..9807d3e1b 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -367,7 +367,7 @@ void CheckBufferOverrun::checkFunctionParameter(const Token &ftok, unsigned int else if (arrayInfo.num().size() == 1) { const Function* const func = ftok.function(); - if (func && func->hasBody) { + if (func && func->hasBody()) { // Get corresponding parameter.. const Variable* const parameter = func->getArgumentVar(par-1); diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index c514d800a..e2545ffc3 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -56,7 +56,7 @@ namespace { inline bool isPureWithoutBody(Function const & func) { - return func.isPure && !func.hasBody; + return func.isPure() && !func.hasBody(); } } @@ -120,8 +120,8 @@ void CheckClass::constructors() std::vector usage(scope->varlist.size()); for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) { - if (!func->hasBody || !(func->isConstructor() || - func->type == Function::eOperatorEqual)) + if (!func->hasBody() || !(func->isConstructor() || + func->type == Function::eOperatorEqual)) continue; // Mark all variables not used @@ -143,7 +143,7 @@ void CheckClass::constructors() if (usage[count].assign || usage[count].init || var->isStatic()) continue; - if (var->isConst() && func->isOperator) // We can't set const members in assignment operator + if (var->isConst() && func->isOperator()) // We can't set const members in assignment operator continue; // Check if this is a class constructor @@ -456,7 +456,7 @@ void CheckClass::initializeVarList(const Function &func, std::listhasBody) { + if (member->hasBody()) { // initialize variable use list using member function callstack.push_back(member); initializeVarList(*member, callstack, scope, usage); @@ -584,7 +584,7 @@ void CheckClass::initializeVarList(const Function &func, std::listhasBody) { + if (member->hasBody()) { // initialize variable use list using member function callstack.push_back(member); initializeVarList(*member, callstack, scope, usage); @@ -626,7 +626,7 @@ void CheckClass::initializeVarList(const Function &func, std::listhasBody) { + if (member->hasBody()) { // initialize variable use list using member function callstack.push_back(member); initializeVarList(*member, callstack, scope, usage); @@ -864,7 +864,7 @@ void CheckClass::privateFunctions() std::list privateFuncs; for (std::list::const_iterator func = scope->functionList.begin(); func != scope->functionList.end(); ++func) { // Get private functions.. - if (func->type == Function::eFunction && func->access == Private && !func->isOperator) // TODO: There are smarter ways to check private operator usage + if (func->type == Function::eFunction && func->access == Private && !func->isOperator()) // TODO: There are smarter ways to check private operator usage privateFuncs.push_back(&*func); } @@ -1019,7 +1019,7 @@ void CheckClass::checkMemsetType(const Scope *start, const Token *tok, const Sco std::list::const_iterator func; for (func = type->functionList.begin(); func != type->functionList.end(); ++func) { - if (func->isVirtual) { + if (func->isVirtual()) { if (allocation) mallocOnClassError(tok, tok->str(), type->classDef, "virtual method"); else @@ -1119,7 +1119,7 @@ void CheckClass::operatorEq() for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) { if (func->type == Function::eOperatorEqual && func->access == Public) { // skip "deleted" functions - cannot be called anyway - if (func->isDelete) + if (func->isDelete()) continue; // use definition for check so we don't have to deal with qualification if (!(Token::Match(func->retDef, "%type% &") && func->retDef->str() == scope->className)) { @@ -1160,7 +1160,7 @@ void CheckClass::operatorEqRetRefThis() std::list::const_iterator func; for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) { - if (func->type == Function::eOperatorEqual && func->hasBody) { + if (func->type == Function::eOperatorEqual && func->hasBody()) { // make sure return signature is correct if (Token::Match(func->retDef, "%type% &") && func->retDef->str() == scope->className) { checkReturnPtrThis(&(*scope), &(*func), func->functionScope->classStart, func->functionScope->classEnd); @@ -1196,13 +1196,13 @@ void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, co // check if it is a member function for (it = scope->functionList.begin(); it != scope->functionList.end(); ++it) { // check for a regular function with the same name and a body - if (it->type == Function::eFunction && it->hasBody && + if (it->type == Function::eFunction && it->hasBody() && it->token->str() == tok->next()->str()) { // check for the proper return type if (it->tokenDef->previous()->str() == "&" && it->tokenDef->strAt(-2) == scope->className) { // make sure it's not a const function - if (!it->isConst) { + if (!it->isConst()) { /** @todo make sure argument types match */ // avoid endless recursions if (analyzedFunctions.find(&*it) == analyzedFunctions.end()) { @@ -1265,7 +1265,7 @@ void CheckClass::operatorEqToSelf() std::list::const_iterator func; for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) { - if (func->type == Function::eOperatorEqual && func->hasBody) { + if (func->type == Function::eOperatorEqual && func->hasBody()) { // make sure that the operator takes an object of the same type as *this, otherwise we can't detect self-assignment checks if (func->argumentList.empty()) continue; @@ -1381,10 +1381,10 @@ void CheckClass::virtualDestructor() if (scope->definedType->derivedFrom.empty()) { if (_settings->inconclusive) { const Function *destructor = scope->getDestructor(); - if (destructor && !destructor->isVirtual) { + if (destructor && !destructor->isVirtual()) { std::list::const_iterator func; for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) { - if (func->isVirtual) { + if (func->isVirtual()) { inconclusive_errors.push_back(destructor); break; } @@ -1398,7 +1398,7 @@ void CheckClass::virtualDestructor() const Function *destructor = scope->getDestructor(); // Check for destructor with implementation - if (!destructor || !destructor->hasBody) + if (!destructor || !destructor->hasBody()) continue; // Empty destructor @@ -1477,7 +1477,7 @@ void CheckClass::virtualDestructor() if (found != inconclusive_errors.end()) inconclusive_errors.erase(found); } - } else if (!base_destructor->isVirtual) { + } else if (!base_destructor->isVirtual()) { // TODO: This is just a temporary fix, better solution is needed. // Skip situations where base class has base classes of its own, because // some of the base classes might have virtual destructor. @@ -1564,7 +1564,7 @@ void CheckClass::checkConst() for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) { // does the function have a body? - if (func->type == Function::eFunction && func->hasBody && !func->isFriend && !func->isStatic && !func->isVirtual) { + if (func->type == Function::eFunction && func->hasBody() && !func->isFriend() && !func->isStatic() && !func->isVirtual()) { // get last token of return type const Token *previous = func->tokenDef->previous(); @@ -1586,7 +1586,7 @@ void CheckClass::checkConst() if (!foundConst) continue; - } else if (func->isOperator && Token::Match(previous, ";|{|}|public:|private:|protected:")) { // Operator without return type: conversion operator + } else if (func->isOperator() && Token::Match(previous, ";|{|}|public:|private:|protected:")) { // Operator without return type: conversion operator const std::string& opName = func->tokenDef->str(); if (opName.compare(8, 5, "const") != 0 && opName[opName.size()-1] == '&') continue; @@ -1621,11 +1621,11 @@ void CheckClass::checkConst() else if (func->tokenDef->str() == "[") functionName += "]"; - if (!func->isConst || (!memberAccessed && !func->isOperator)) { - if (func->isInline) - checkConstError(func->token, classname, functionName, !memberAccessed && !func->isOperator); + if (!func->isConst() || (!memberAccessed && !func->isOperator())) { + if (func->isInline()) + checkConstError(func->token, classname, functionName, !memberAccessed && !func->isOperator()); else // not inline - checkConstError2(func->token, func->tokenDef, classname, functionName, !memberAccessed && !func->isOperator); + checkConstError2(func->token, func->tokenDef, classname, functionName, !memberAccessed && !func->isOperator()); } } } @@ -1688,7 +1688,7 @@ bool CheckClass::isMemberVar(const Scope *scope, const Token *tok) const bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok) const { if (tok->function() && tok->function()->nestedIn == scope) - return !tok->function()->isStatic; + return !tok->function()->isStatic(); // not found in this class if (!scope->definedType->derivedFrom.empty()) { @@ -1711,7 +1711,7 @@ bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok) const bool CheckClass::isConstMemberFunc(const Scope *scope, const Token *tok) const { if (tok->function() && tok->function()->nestedIn == scope) - return tok->function()->isConst; + return tok->function()->isConst(); // not found in this class if (!scope->definedType->derivedFrom.empty()) { @@ -1919,7 +1919,7 @@ void CheckClass::initializerListOrder() // iterate through all member functions looking for constructors for (func = info->functionList.begin(); func != info->functionList.end(); ++func) { - if ((func->isConstructor()) && func->hasBody) { + if ((func->isConstructor()) && func->hasBody()) { // check for initializer list const Token *tok = func->arg->link()->next(); @@ -2015,7 +2015,7 @@ void CheckClass::checkPureVirtualFunctionCall() std::map > callsPureVirtualFunctionMap; for (std::size_t i = 0; i < functions; ++i) { const Scope * scope = symbolDatabase->functionScopes[i]; - if (scope->function == 0 || !scope->function->hasBody || + if (scope->function == 0 || !scope->function->hasBody() || !(scope->function->isConstructor() || scope->function->isDestructor())) continue; @@ -2041,7 +2041,7 @@ const std::list & CheckClass::callsPureVirtualFunction(const Func callsPureVirtualFunctionMap.insert(std::pair >(&function, std::list())); std::list & pureFunctionCalls = found.first->second; if (found.second) { - if (function.hasBody) { + if (function.hasBody()) { for (const Token *tok = function.arg->link(); tok && tok != function.functionScope->classEnd; tok = tok->next()) { diff --git a/lib/checkcondition.cpp b/lib/checkcondition.cpp index dd9ae329c..2a12f07cc 100644 --- a/lib/checkcondition.cpp +++ b/lib/checkcondition.cpp @@ -429,7 +429,7 @@ void CheckCondition::oppositeInnerCondition() if (tok->variable() && Token::Match(tok, "%var% . %var% (") && !tok->variable()->isConst() && - !(tok->tokAt(2)->function() && tok->tokAt(2)->function()->isConst)) + !(tok->tokAt(2)->function() && tok->tokAt(2)->function()->isConst())) break; if (Token::Match(tok->previous(), "[(,] %var% [,)]")) { // is variable unchanged? default is false.. diff --git a/lib/checkexceptionsafety.cpp b/lib/checkexceptionsafety.cpp index cc6829ae1..b26b8aaf1 100644 --- a/lib/checkexceptionsafety.cpp +++ b/lib/checkexceptionsafety.cpp @@ -206,9 +206,9 @@ static const Token * functionThrowsRecursive(const Function * function, std::set } else if (tok->function()) { const Function * called = tok->function(); // check if called function has an exception specification - if (called->isThrow && called->throwArg) { + if (called->isThrow() && called->throwArg) { return tok; - } else if (called->isNoExcept && called->noexceptArg && + } else if (called->isNoExcept() && called->noexceptArg && called->noexceptArg->str() != "true") { return tok; } else if (functionThrowsRecursive(called, recursive)) { @@ -244,7 +244,7 @@ void CheckExceptionSafety::nothrowThrows() continue; // check noexcept functions - if (function->isNoExcept && + if (function->isNoExcept() && (!function->noexceptArg || function->noexceptArg->str() == "true")) { const Token *throws = functionThrows(function); if (throws) @@ -252,7 +252,7 @@ void CheckExceptionSafety::nothrowThrows() } // check throw() functions - else if (function->isThrow && !function->throwArg) { + else if (function->isThrow() && !function->throwArg) { const Token *throws = functionThrows(function); if (throws) nothrowThrowError(throws); @@ -288,7 +288,7 @@ void CheckExceptionSafety::unhandledExceptionSpecification() for (std::size_t i = 0; i < functions; ++i) { const Scope * scope = symbolDatabase->functionScopes[i]; // only check functions without exception epecification - if (scope->function && !scope->function->isThrow && + if (scope->function && !scope->function->isThrow() && scope->className != "main" && scope->className != "wmain" && scope->className != "_tmain" && scope->className != "WinMain") { for (const Token *tok = scope->function->functionScope->classStart->next(); @@ -298,7 +298,7 @@ void CheckExceptionSafety::unhandledExceptionSpecification() } else if (tok->function()) { const Function * called = tok->function(); // check if called function has an exception specification - if (called->isThrow && called->throwArg) { + if (called->isThrow() && called->throwArg) { unhandledExceptionSpecificationError(tok, called->tokenDef, scope->function->name()); break; } diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 33c360018..969e7cfac 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -397,7 +397,7 @@ void CheckMemoryLeak::mismatchAllocDealloc(const std::list &calls CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Function* func, std::list *callstack) const { - if (!func || !func->hasBody) + if (!func || !func->hasBody()) return No; // Get return pointer.. @@ -597,7 +597,7 @@ const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::listfunction(); - if (!func || !func->hasBody) + if (!func || !func->hasBody()) return 0; Token *ftok = getcode(func->functionScope->classStart->next(), callstack, 0, alloctype, dealloctype, false, 1); @@ -2317,7 +2317,7 @@ void CheckMemoryLeakInClass::variable(const Scope *scope, const Token *tokVarnam for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) { const bool constructor = func->isConstructor(); const bool destructor = func->isDestructor(); - if (!func->hasBody) { + if (!func->hasBody()) { if (destructor) { // implementation for destructor is not seen => assume it deallocates all variables properly deallocInDestructor = true; Dealloc = CheckMemoryLeak::Many; @@ -2445,7 +2445,7 @@ void CheckMemoryLeakInClass::checkPublicFunctions(const Scope *scope, const Toke for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) { if ((func->type == Function::eFunction || func->type == Function::eOperatorEqual) && - func->access == Public && func->hasBody) { + func->access == Public && func->hasBody()) { const Token *tok2 = func->token; while (tok2->str() != "{") tok2 = tok2->next(); diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index e73508cfa..3ffb3e5e0 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -379,7 +379,7 @@ void CheckNullPointer::nullConstantDereference() const std::size_t functions = symbolDatabase->functionScopes.size(); for (std::size_t i = 0; i < functions; ++i) { const Scope * scope = symbolDatabase->functionScopes[i]; - if (scope->function == 0 || !scope->function->hasBody) // We only look for functions with a body + if (scope->function == 0 || !scope->function->hasBody()) // We only look for functions with a body continue; const Token *tok = scope->classStart; @@ -484,7 +484,7 @@ void CheckNullPointer::nullPointerDefaultArgument() const std::size_t functions = symbolDatabase->functionScopes.size(); for (std::size_t i = 0; i < functions; ++i) { const Scope * scope = symbolDatabase->functionScopes[i]; - if (scope->function == 0 || !scope->function->hasBody) // We only look for functions with a body + if (scope->function == 0 || !scope->function->hasBody()) // We only look for functions with a body continue; // Scan the argument list for default arguments that are pointers and diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 0a6da02c6..92dd9be0d 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -66,7 +66,7 @@ static bool isConstExpression(const Token *tok, const std::set &con if (tok->isName() && tok->next()->str() == "(") { if (!tok->function() && !Token::Match(tok->previous(), ".|::") && constFunctions.find(tok->str()) == constFunctions.end()) return false; - else if (tok->function() && !tok->function()->isConst) + else if (tok->function() && !tok->function()->isConst()) return false; } if (tok->type() == Token::eIncDecOp) @@ -96,7 +96,7 @@ bool isSameExpression(const Token *tok1, const Token *tok2, const std::setisName() && tok1->next()->str() == "(") { if (!tok1->function() && !Token::Match(tok1->previous(), ".|::") && constFunctions.find(tok1->str()) == constFunctions.end() && !tok1->isAttributeConst() && !tok1->isAttributePure()) return false; - else if (tok1->function() && !tok1->function()->isConst && !tok1->function()->isAttributeConst() && !tok1->function()->isAttributePure()) + else if (tok1->function() && !tok1->function()->isConst() && !tok1->function()->isAttributeConst() && !tok1->function()->isAttributePure()) return false; } // templates/casts @@ -105,7 +105,7 @@ bool isSameExpression(const Token *tok1, const Token *tok2, const std::set return false if (Token::simpleMatch(tok1->next()->link(), "> (") && - !(tok1->function() && tok1->function()->isConst) && + !(tok1->function() && tok1->function()->isConst()) && tok1->str() != "dynamic_cast") return false; @@ -700,7 +700,7 @@ void CheckOther::checkRedundantAssignment() } } else if (scope->type == Scope::eSwitch) { // Avoid false positives if noreturn function is called in switch const Function* const func = tok->function(); - if (!func || !func->hasBody) { + if (!func || !func->hasBody()) { varAssignments.clear(); memAssignments.clear(); continue; @@ -2252,7 +2252,7 @@ void CheckOther::doubleCloseDirError(const Token *tok, const std::string &varnam namespace { bool notconst(const Function* func) { - return !func->isConst; + return !func->isConst(); } void getConstFunctions(const SymbolDatabase *symbolDatabase, std::list &constFunctions) diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index c51dcaffb..ff9ed6bbe 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -508,7 +508,7 @@ private: if (tok.next()->str() == ".") { if (Token::Match(&tok, "%var% . %var% (")) { const Function *function = tok.tokAt(2)->function(); - if (function && function->isStatic) + if (function && function->isStatic()) return &tok; } if (use_dead_pointer(checks, &tok)) { @@ -1809,7 +1809,7 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, bool all if (pointer && Token::Match(vartok, "%var% . %var% (")) { const Function *function = vartok->tokAt(2)->function(); - return (!function || !function->isStatic); + return (!function || !function->isStatic()); } if (cpp && Token::Match(vartok->next(), "<<|>>")) { diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index b6e3b6879..39387d7f8 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -335,7 +335,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti // operator function if (function.tokenDef->str().find("operator") == 0) { - function.isOperator = true; + function.isOperator(true); // 'operator =' is special if (function.tokenDef->str() == "operator=") @@ -374,7 +374,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti function.type = Function::eConstructor; if (function.tokenDef->previous()->str() == "explicit") - function.isExplicit = true; + function.isExplicit(true); } const Token *tok1 = tok; @@ -383,19 +383,19 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti while (tok1->previous() && !Token::Match(tok1->previous(), ";|}|{|public:|protected:|private:")) { // virtual function if (tok1->previous()->str() == "virtual") { - function.isVirtual = true; + function.isVirtual(true); break; } // static function else if (tok1->previous()->str() == "static") { - function.isStatic = true; + function.isStatic(true); break; } // friend function else if (tok1->previous()->str() == "friend") { - function.isFriend = true; + function.isFriend(true); break; } @@ -415,7 +415,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti // const function if (end->next()->str() == "const") - function.isConst = true; + function.isConst(true); // count the number of constructors if (function.isConstructor()) @@ -439,9 +439,9 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti // default or delete else if (Token::Match(end, ") = default|delete ;")) { if (end->strAt(2) == "default") - function.isDefault = true; + function.isDefault(true); else - function.isDelete = true; + function.isDelete(true); tok = end->tokAt(3); @@ -453,7 +453,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti // const noexcept; // const noexcept = 0; else if (Token::Match(end, ") const| noexcept ;|=")) { - function.isNoExcept = true; + function.isNoExcept(true); if (end->next()->str() == "const") tok = end->tokAt(3); @@ -461,7 +461,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti tok = end->tokAt(2); if (Token::Match(tok, "= %any% ;")) { - function.isPure = true; + function.isPure(true); tok = tok->tokAt(2); } @@ -481,10 +481,10 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti else tok = end->tokAt(2); - function.isNoExcept = tok->strAt(1) != "false"; + function.isNoExcept(tok->strAt(1) != "false"); if (Token::Match(tok->link()->next(), "= %any% ;")) { - function.isPure = true; + function.isPure(true); tok = tok->tokAt(2); } @@ -498,7 +498,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti else if (Token::Match(end, ") const| throw (") && (end->next()->str() == "const" ? Token::Match(end->linkAt(3), ") ;|=") : Token::Match(end->linkAt(2), ") ;|="))) { - function.isThrow = true; + function.isThrow(true); if (end->next()->str() == "const") { if (end->strAt(4) != ")") @@ -511,7 +511,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti } if (Token::Match(tok, "= %any% ;")) { - function.isPure = true; + function.isPure(true); tok = tok->tokAt(2); } @@ -520,7 +520,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti // pure virtual function else if (Token::Match(end, ") const| = %any% ;")) { - function.isPure = true; + function.isPure(true); if (end->next()->str() == "const") tok = end->tokAt(4); @@ -538,8 +538,8 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti // inline function else { - function.isInline = true; - function.hasBody = true; + function.isInline(true); + function.hasBody(true); if (Token::Match(end, ") const| noexcept")) { int arg = 2; @@ -550,7 +550,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti if (end->strAt(arg) == "(") function.noexceptArg = end->tokAt(arg + 1); - function.isNoExcept = true; + function.isNoExcept(true); } else if (Token::Match(end, ") const| throw (")) { int arg = 3; @@ -560,7 +560,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti if (end->strAt(arg) != ")") function.throwArg = end->tokAt(arg); - function.isThrow = true; + function.isThrow(true); } // find start of function '{' @@ -657,8 +657,10 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti else { Function* function = addGlobalFunction(scope, tok, argStart, funcStart); - if (!function) + if (!function) { _tokenizer->syntaxError(tok); + continue; + } // global functions can't be const but we have tests that are if (Token::Match(argStart->link(), ") const| noexcept")) { @@ -670,7 +672,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti if (argStart->link()->strAt(arg) == "(") function->noexceptArg = argStart->link()->tokAt(arg + 1); - function->isNoExcept = true; + function->isNoExcept(true); } else if (Token::Match(argStart->link(), ") const| throw (")) { int arg = 3; @@ -680,7 +682,26 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti if (argStart->link()->strAt(arg) != ")") function->throwArg = argStart->link()->tokAt(arg); - function->isThrow = true; + function->isThrow(true); + } + + const Token *tok1 = tok->previous(); + + // look for end of previous statement + while (tok1 && !Token::Match(tok1, ";|}|{")) { + // static function + if (tok1->str() == "static") { + function->isStaticLocal(true); + break; + } + + // extern function + else if (tok1->str() == "extern") { + function->isExtern(true); + break; + } + + tok1 = tok1->previous(); } } @@ -711,7 +732,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti if (argStart->link()->strAt(arg) == "(") func->noexceptArg = argStart->link()->tokAt(arg + 1); - func->isNoExcept = true; + func->isNoExcept(true); } else if (Token::Match(argStart->link(), ") const| throw (")) { int arg = 3; @@ -721,7 +742,20 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti if (argStart->link()->strAt(arg) != ")") func->throwArg = argStart->link()->tokAt(arg); - func->isThrow = true; + func->isThrow(true); + } + + const Token *tok1 = tok->previous(); + + // look for end of previous statement + while (tok1 && !Token::Match(tok1, ";|}|{")) { + // extern function + if (tok1->str() == "extern") { + func->isExtern(true); + break; + } + + tok1 = tok1->previous(); } } @@ -1548,7 +1582,7 @@ Function* SymbolDatabase::addGlobalFunction(Scope*& scope, const Token*& tok, co function->arg = argStart; function->token = funcStart; - function->hasBody = true; + function->hasBody(true); addNewFunction(&scope, &tok); @@ -1573,8 +1607,8 @@ Function* SymbolDatabase::addGlobalFunctionDecl(Scope*& scope, const Token *tok, // save the function name location function.tokenDef = funcStart; - function.isInline = false; - function.hasBody = false; + function.isInline(false); + function.hasBody(false); function.type = Function::eFunction; function.nestedIn = scope; @@ -1585,7 +1619,7 @@ Function* SymbolDatabase::addGlobalFunctionDecl(Scope*& scope, const Token *tok, tok1 = tok1->previous(); // find the return type - while (tok1 && Token::Match(tok1->next(), "static|const")) + while (tok1 && Token::Match(tok1, "static|extern|const")) tok1 = tok1->next(); if (tok1) @@ -1642,8 +1676,8 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To if (it2->scope) { Function * func = findFunctionInScope(tok1, it2->scope); if (func) { - if (!func->hasBody) { - func->hasBody = true; + if (!func->hasBody()) { + func->hasBody(true); func->token = *tok; func->arg = argStart; addNewFunction(scope, tok); @@ -1699,22 +1733,22 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To if (match) { for (std::multimap::iterator it = scope1->functionMap.find((*tok)->str()); it != scope1->functionMap.end() && it->first == (*tok)->str(); ++it) { Function * func = const_cast(it->second); - if (!func->hasBody) { + if (!func->hasBody()) { if (Function::argsMatch(scope1, func->argDef, (*tok)->next(), path, path_length)) { if (func->type == Function::eDestructor && destructor) { - func->hasBody = true; + func->hasBody(true); } else if (func->type != Function::eDestructor && !destructor) { // normal function? if ((*tok)->next()->link()) { const bool hasConstKeyword = (*tok)->next()->link()->next()->str() == "const"; - if ((func->isConst && hasConstKeyword) || - (!func->isConst && !hasConstKeyword)) { - func->hasBody = true; + if ((func->isConst() && hasConstKeyword) || + (!func->isConst() && !hasConstKeyword)) { + func->hasBody(true); } } } - if (func->hasBody) { + if (func->hasBody()) { func->token = *tok; func->arg = argStart; addNewFunction(scope, tok); @@ -2072,19 +2106,21 @@ void SymbolDatabase::printOut(const char *title) const func->access == Protected ? "Protected" : func->access == Private ? "Private" : "???") << std::endl; - std::cout << " hasBody: " << (func->hasBody ? "true" : "false") << std::endl; - std::cout << " isInline: " << (func->isInline ? "true" : "false") << std::endl; - std::cout << " isConst: " << (func->isConst ? "true" : "false") << std::endl; - std::cout << " isVirtual: " << (func->isVirtual ? "true" : "false") << std::endl; - std::cout << " isPure: " << (func->isPure ? "true" : "false") << std::endl; - std::cout << " isStatic: " << (func->isStatic ? "true" : "false") << std::endl; - std::cout << " isFriend: " << (func->isFriend ? "true" : "false") << std::endl; - std::cout << " isExplicit: " << (func->isExplicit ? "true" : "false") << std::endl; - std::cout << " isDefault: " << (func->isDefault ? "true" : "false") << std::endl; - std::cout << " isDelete: " << (func->isDelete ? "true" : "false") << std::endl; - std::cout << " isNoExcept: " << (func->isNoExcept ? "true" : "false") << std::endl; - std::cout << " isThrow: " << (func->isThrow ? "true" : "false") << std::endl; - std::cout << " isOperator: " << (func->isOperator ? "true" : "false") << std::endl; + std::cout << " hasBody: " << (func->hasBody() ? "true" : "false") << std::endl; + std::cout << " isInline: " << (func->isInline() ? "true" : "false") << std::endl; + std::cout << " isConst: " << (func->isConst() ? "true" : "false") << std::endl; + std::cout << " isVirtual: " << (func->isVirtual() ? "true" : "false") << std::endl; + std::cout << " isPure: " << (func->isPure() ? "true" : "false") << std::endl; + std::cout << " isStatic: " << (func->isStatic() ? "true" : "false") << std::endl; + std::cout << " isStaticLocal: " << (func->isStaticLocal() ? "true" : "false") << std::endl; + std::cout << " isExtern: " << (func->isExtern() ? "true" : "false") << std::endl; + std::cout << " isFriend: " << (func->isFriend() ? "true" : "false") << std::endl; + std::cout << " isExplicit: " << (func->isExplicit() ? "true" : "false") << std::endl; + std::cout << " isDefault: " << (func->isDefault() ? "true" : "false") << std::endl; + std::cout << " isDelete: " << (func->isDelete() ? "true" : "false") << std::endl; + std::cout << " isNoExcept: " << (func->isNoExcept() ? "true" : "false") << std::endl; + std::cout << " isThrow: " << (func->isThrow() ? "true" : "false") << std::endl; + std::cout << " isOperator: " << (func->isOperator() ? "true" : "false") << std::endl; std::cout << " isAttributeConst: " << (func->isAttributeConst() ? "true" : "false") << std::endl; std::cout << " isAttributePure: " << (func->isAttributePure() ? "true" : "false") << std::endl; std::cout << " isAttributeNoreturn: " << (func->isAttributeNoreturn() ? "true" : "false") << std::endl; @@ -2097,7 +2133,7 @@ void SymbolDatabase::printOut(const char *title) const if (!func->isConstructor() && !func->isDestructor()) std::cout << " retDef: " << func->retDef->str() << " " <<_tokenizer->list.fileLine(func->retDef) << std::endl; std::cout << " retType: " << func->retType << std::endl; - if (func->hasBody) { + if (func->hasBody()) { std::cout << " token: " << _tokenizer->list.fileLine(func->token) << std::endl; std::cout << " arg: " << _tokenizer->list.fileLine(func->arg) << std::endl; } @@ -2394,7 +2430,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s nameTok = tok->previous(); endTok = nameTok->previous(); - if (hasBody) + if (hasBody()) symbolDatabase->debugMessage(nameTok, "Function::addArguments found argument \'" + nameTok->str() + "\' with varid 0."); } else endTok = startTok; @@ -2449,7 +2485,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s bool Function::isImplicitlyVirtual(bool defaultVal) const { - if (isVirtual) + if (isVirtual()) return true; else if (access == Private || access == Public || access == Protected) { bool safe = true; @@ -2476,7 +2512,7 @@ bool Function::isImplicitlyVirtual_rec(const ::Type* baseType, bool& safe) const // check if function defined in base class for (std::multimap::const_iterator it = parent->functionMap.find(tokenDef->str()); it != parent->functionMap.end() && it->first == tokenDef->str(); ++it) { const Function * func = it->second; - if (func->isVirtual) { // Base is virtual and of same name + if (func->isVirtual()) { // Base is virtual and of same name const Token *temp1 = func->tokenDef->previous(); const Token *temp2 = tokenDef->previous(); bool returnMatch = true; @@ -3104,7 +3140,7 @@ const Function* Scope::findFunction(const Token *tok) const // check if this function is a member function if (scope && scope->functionOf && scope->functionOf->isClassOrStruct()) { // check if isConst match - if (scope->function && scope->function->isConst == func->isConst) + if (scope->function && scope->function->isConst() == func->isConst()) return func; } else return func; diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index a80905001..cfd560ceb 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -557,6 +557,43 @@ private: }; class CPPCHECKLIB Function { + /** @brief flags mask used to access specific bit. */ + enum { + fHasBody = (1 << 0), /** @brief has implementation */ + fIsInline = (1 << 1), /** @brief implementation in class definition */ + fIsConst = (1 << 2), /** @brief is const */ + fIsVirtual = (1 << 3), /** @brief is virtual */ + fIsPure = (1 << 4), /** @brief is pure virtual */ + fIsStatic = (1 << 5), /** @brief is static */ + fIsStaticLocal = (1 << 6), /** @brief is static local */ + fIsExtern = (1 << 7), /** @brief is extern */ + fIsFriend = (1 << 8), /** @brief is friend */ + fIsExplicit = (1 << 9), /** @brief is explicit */ + fIsDefault = (1 << 10), /** @brief is default */ + fIsDelete = (1 << 11), /** @brief is delete */ + fIsNoExcept = (1 << 12), /** @brief is noexcept */ + fIsThrow = (1 << 13), /** @brief is throw */ + fIsOperator = (1 << 14) /** @brief is operator */ + }; + + /** + * Get specified flag state. + * @param flag flag to get state of + * @return true if flag set or false in flag not set + */ + bool getFlag(int flag) const { + return bool((flags & flag) != 0); + } + + /** + * Set specified flag state. + * @param flag flag to set state + * @param state new state of flag + */ + void setFlag(int flag, bool state) { + flags = state ? flags | flag : flags & ~flag; + } + public: enum Type { eConstructor, eCopyConstructor, eMoveConstructor, eOperatorEqual, eDestructor, eFunction }; @@ -572,21 +609,9 @@ public: initArgCount(0), type(eFunction), access(Public), - hasBody(false), - isInline(false), - isConst(false), - isVirtual(false), - isPure(false), - isStatic(false), - isFriend(false), - isExplicit(false), - isDefault(false), - isDelete(false), - isNoExcept(false), - isThrow(false), - isOperator(false), noexceptArg(nullptr), - throwArg(nullptr) { + throwArg(nullptr), + flags(0) { } const std::string &name() const { @@ -638,6 +663,98 @@ public: return tokenDef->isDeclspecNothrow(); } + bool hasBody() const { + return getFlag(fHasBody); + } + bool isInline() const { + return getFlag(fIsInline); + } + bool isConst() const { + return getFlag(fIsConst); + } + bool isVirtual() const { + return getFlag(fIsVirtual); + } + bool isPure() const { + return getFlag(fIsPure); + } + bool isStatic() const { + return getFlag(fIsStatic); + } + bool isStaticLocal() const { + return getFlag(fIsStaticLocal); + } + bool isExtern() const { + return getFlag(fIsExtern); + } + bool isFriend() const { + return getFlag(fIsFriend); + } + bool isExplicit() const { + return getFlag(fIsExplicit); + } + bool isDefault() const { + return getFlag(fIsDefault); + } + bool isDelete() const { + return getFlag(fIsDelete); + } + bool isNoExcept() const { + return getFlag(fIsNoExcept); + } + bool isThrow() const { + return getFlag(fIsThrow); + } + bool isOperator() const { + return getFlag(fIsOperator); + } + + void hasBody(bool state) { + setFlag(fHasBody, state); + } + void isInline(bool state) { + setFlag(fIsInline, state); + } + void isConst(bool state) { + setFlag(fIsConst, state); + } + void isVirtual(bool state) { + setFlag(fIsVirtual, state); + } + void isPure(bool state) { + setFlag(fIsPure, state); + } + void isStatic(bool state) { + setFlag(fIsStatic, state); + } + void isStaticLocal(bool state) { + setFlag(fIsStaticLocal, state); + } + void isExtern(bool state) { + setFlag(fIsExtern, state); + } + void isFriend(bool state) { + setFlag(fIsFriend, state); + } + void isExplicit(bool state) { + setFlag(fIsExplicit, state); + } + void isDefault(bool state) { + setFlag(fIsDefault, state); + } + void isDelete(bool state) { + setFlag(fIsDelete, state); + } + void isNoExcept(bool state) { + setFlag(fIsNoExcept, state); + } + void isThrow(bool state) { + setFlag(fIsThrow, state); + } + void isOperator(bool state) { + setFlag(fIsOperator, state); + } + const Token *tokenDef; // function name token in class definition const Token *argDef; // function argument start '(' in class definition const Token *token; // function name token in implementation @@ -650,19 +767,6 @@ public: unsigned int initArgCount; // number of args with default values Type type; // constructor, destructor, ... AccessControl access; // public/protected/private - bool hasBody; // has implementation - bool isInline; // implementation in class definition - bool isConst; // is const - bool isVirtual; // is virtual - bool isPure; // is pure virtual - bool isStatic; // is static - bool isFriend; // is friend - bool isExplicit; // is explicit - bool isDefault; // is default - bool isDelete; // is delete - bool isNoExcept; // is noexcept - bool isThrow; // is throw - bool isOperator; // is operator const Token *noexceptArg; const Token *throwArg; @@ -670,6 +774,8 @@ public: private: bool isImplicitlyVirtual_rec(const ::Type* type, bool& safe) const; + + unsigned int flags; }; class CPPCHECKLIB Scope { diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 1618c4786..72a6ea043 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -148,6 +148,7 @@ private: TEST_CASE(memberFunctionOfUnknownClassMacro1); TEST_CASE(memberFunctionOfUnknownClassMacro2); TEST_CASE(memberFunctionOfUnknownClassMacro3); + TEST_CASE(functionLinkage); TEST_CASE(classWithFriend); @@ -764,7 +765,7 @@ private: ASSERT(function && function->token->str() == "func"); ASSERT(function && function->token == tokenizer.tokens()->next()); - ASSERT(function && function->hasBody); + ASSERT(function && function->hasBody()); ASSERT(function && function->functionScope == scope && scope->function == function && function->nestedIn != scope); ASSERT(function && function->retDef == tokenizer.tokens()); } @@ -788,7 +789,7 @@ private: ASSERT(function && function->token->str() == "func"); ASSERT(function && function->token == functionToken); - ASSERT(function && function->hasBody && function->isInline); + ASSERT(function && function->hasBody() && function->isInline()); ASSERT(function && function->functionScope == scope && scope->function == function && function->nestedIn == db->findScopeByName("Fred")); ASSERT(function && function->retDef == functionToken->previous()); @@ -813,7 +814,7 @@ private: ASSERT(function && function->token->str() == "func"); ASSERT(function && function->token == functionToken); - ASSERT(function && !function->hasBody); + ASSERT(function && !function->hasBody()); } } @@ -835,7 +836,7 @@ private: ASSERT(function && function->token->str() == "func"); ASSERT(function && function->token == functionToken); - ASSERT(function && function->hasBody && !function->isInline); + ASSERT(function && function->hasBody() && !function->isInline()); ASSERT(function && function->functionScope == scope && scope->function == function && function->nestedIn == db->findScopeByName("Fred")); } } @@ -857,7 +858,7 @@ private: ASSERT(function && function->token->str() == "func"); ASSERT(function && function->token == functionToken); - ASSERT(function && function->hasBody); + ASSERT(function && function->hasBody()); } } @@ -878,7 +879,7 @@ private: ASSERT(function && function->token->str() == "func"); ASSERT(function && function->token == functionToken); - ASSERT(function && function->hasBody && function->isInline); + ASSERT(function && function->hasBody() && function->isInline()); } } @@ -899,7 +900,7 @@ private: ASSERT(function && function->token->str() == "func"); ASSERT(function && function->token == functionToken); - ASSERT(function && !function->hasBody); + ASSERT(function && !function->hasBody()); } } @@ -920,7 +921,7 @@ private: ASSERT(function && function->token->str() == "func"); ASSERT(function && function->token == functionToken); - ASSERT(function && function->hasBody && !function->isInline); + ASSERT(function && function->hasBody() && !function->isInline()); } } @@ -977,7 +978,7 @@ private: for (std::list::const_iterator scope = db->scopeList.begin(); scope != db->scopeList.end(); ++scope) { for (std::list::const_iterator func = scope->functionList.begin(); func != scope->functionList.end(); ++func) { ASSERT_EQUALS("Sub", func->token->str()); - ASSERT_EQUALS(true, func->hasBody); + ASSERT_EQUALS(true, func->hasBody()); ASSERT_EQUALS(Function::eConstructor, func->type); seen_something = true; } @@ -990,13 +991,13 @@ private: { GET_SYMBOL_DB("class Foo { Foo(Foo f); };"); const Function* ctor = tokenizer.tokens()->tokAt(3)->function(); - ASSERT(db && ctor && ctor->type == Function::eConstructor && !ctor->isExplicit); + ASSERT(db && ctor && ctor->type == Function::eConstructor && !ctor->isExplicit()); ASSERT(ctor && ctor->retDef == 0); } { GET_SYMBOL_DB("class Foo { explicit Foo(Foo f); };"); const Function* ctor = tokenizer.tokens()->tokAt(4)->function(); - ASSERT(db && ctor && ctor->type == Function::eConstructor && ctor->isExplicit); + ASSERT(db && ctor && ctor->type == Function::eConstructor && ctor->isExplicit()); ASSERT(ctor && ctor->retDef == 0); } { @@ -1027,7 +1028,7 @@ private: const Function *foo = &scope->functionList.front(); ASSERT(foo && foo->token->str() == "foo"); - ASSERT(foo && foo->hasBody); + ASSERT(foo && foo->hasBody()); } } @@ -1046,12 +1047,12 @@ private: const Function *foo_int = &scope->functionList.back(); ASSERT(foo && foo->token->str() == "foo"); - ASSERT(foo && foo->hasBody); + ASSERT(foo && foo->hasBody()); ASSERT(foo && foo->token->strAt(2) == ")"); ASSERT(foo_int && !foo_int->token); ASSERT(foo_int && foo_int->tokenDef->str() == "foo"); - ASSERT(foo_int && !foo_int->hasBody); + ASSERT(foo_int && !foo_int->hasBody()); ASSERT(foo_int && foo_int->tokenDef->strAt(2) == "int"); ASSERT(&foo_int->argumentList.front() == db->getVariableFromVarId(1)); @@ -1123,6 +1124,37 @@ private: } } + void functionLinkage() { + GET_SYMBOL_DB("static void f1() { }\n" + "void f2();\n" + "extern void f3();\n" + "void f4();\n" + "extern void f5() { };\n" + "void f6() { }"); + + ASSERT(db && errout.str() == ""); + + if (db) { + const Token *f = Token::findsimplematch(tokenizer.tokens(), "f1"); + ASSERT(f && f->function() && f->function()->isStaticLocal()); + + f = Token::findsimplematch(tokenizer.tokens(), "f2"); + ASSERT(f && f->function() && !f->function()->isStaticLocal()); + + f = Token::findsimplematch(tokenizer.tokens(), "f3"); + ASSERT(f && f->function() && f->function()->isExtern()); + + f = Token::findsimplematch(tokenizer.tokens(), "f4"); + ASSERT(f && f->function() && !f->function()->isExtern()); + + f = Token::findsimplematch(tokenizer.tokens(), "f5"); + ASSERT(f && f->function() && f->function()->isExtern()); + + f = Token::findsimplematch(tokenizer.tokens(), "f6"); + ASSERT(f && f->function() && !f->function()->isExtern()); + } + } + void classWithFriend() { GET_SYMBOL_DB("class Foo {}; class Bar1 { friend class Foo; }; class Bar2 { friend Foo; };") // 3 scopes: Global, 3 classes @@ -1373,7 +1405,7 @@ private: // The class has a constructor but the implementation _is not_ seen ASSERT_EQUALS(1U, scope->functionList.size()); const Function *function = &(scope->functionList.front()); - ASSERT_EQUALS(false, function->hasBody); + ASSERT_EQUALS(false, function->hasBody()); } // based on namespaces1 but here the namespaces match @@ -1408,7 +1440,7 @@ private: ASSERT_EQUALS(1U, scope->functionList.size()); const Function *function = &(scope->functionList.front()); ASSERT_EQUALS("X", function->tokenDef->str()); - ASSERT_EQUALS(true, function->hasBody); + ASSERT_EQUALS(true, function->hasBody()); } void namespaces3() { // #3854 - namespace with unknown macro @@ -1915,7 +1947,7 @@ private: void symboldatabase41() { // ticket #5197 (unknown macro) GET_SYMBOL_DB("struct X1 { MACRO1 f(int spd) MACRO2; };\n"); - ASSERT(db && db->findScopeByName("X1") && db->findScopeByName("X1")->functionList.size() == 1 && !db->findScopeByName("X1")->functionList.front().hasBody); + ASSERT(db && db->findScopeByName("X1") && db->findScopeByName("X1")->functionList.size() == 1 && !db->findScopeByName("X1")->functionList.front().hasBody()); } void symboldatabase42() { // only put variables in variable list @@ -2379,7 +2411,7 @@ private: #define FUNC(x) const Function *x = findFunctionByName(#x, &db->scopeList.front()); \ ASSERT_EQUALS(true, x != nullptr); \ - if (x) ASSERT_EQUALS(true, x->isNoExcept); + if (x) ASSERT_EQUALS(true, x->isNoExcept()); void noexceptFunction1() { GET_SYMBOL_DB("void func1() noexcept;\n" @@ -2410,7 +2442,7 @@ private: #define CLASS_FUNC(x, y, z) const Function *x = findFunctionByName(#x, y); \ ASSERT_EQUALS(true, x != nullptr); \ - if (x) ASSERT_EQUALS(z, x->isNoExcept); + if (x) ASSERT_EQUALS(z, x->isNoExcept()); void noexceptFunction3() { GET_SYMBOL_DB("struct Fred {\n" @@ -2478,7 +2510,7 @@ private: #define FUNC_THROW(x) const Function *x = findFunctionByName(#x, &db->scopeList.front()); \ ASSERT_EQUALS(true, x != nullptr); \ - if (x) ASSERT_EQUALS(true, x->isThrow); + if (x) ASSERT_EQUALS(true, x->isThrow()); void throwFunction1() { GET_SYMBOL_DB("void func1() throw();\n" @@ -2498,7 +2530,7 @@ private: #define CLASS_FUNC_THROW(x, y) const Function *x = findFunctionByName(#x, y); \ ASSERT_EQUALS(true, x != nullptr); \ - if (x) ASSERT_EQUALS(true, x->isThrow); + if (x) ASSERT_EQUALS(true, x->isThrow()); void throwFunction2() { GET_SYMBOL_DB("struct Fred {\n" " void func1() throw();\n"