@@ -458,6 +458,72 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
458458 scope->functionList .push_back (function);
459459 }
460460
461+ // noexcept;
462+ // const noexcept;
463+ else if (Token::Match (end, " ) const| noexcept ;" )) {
464+ function.isNoExcept = true ;
465+
466+ if (end->next ()->str () == " const" )
467+ tok = end->tokAt (3 );
468+ else
469+ tok = end->tokAt (2 );
470+
471+ scope->functionList .push_back (function);
472+ }
473+
474+ // noexcept const;
475+ else if (Token::simpleMatch (end, " ) noexcept const ;" )) {
476+ function.isNoExcept = true ;
477+
478+ tok = end->tokAt (3 );
479+
480+ scope->functionList .push_back (function);
481+ }
482+
483+ // noexcept(...);
484+ // noexcept(...) const;
485+ else if (Token::simpleMatch (end, " ) noexcept (" ) &&
486+ Token::Match (end->linkAt (2 ), " ) const| ;" )) {
487+ function.isNoExcept = true ;
488+
489+ if (end->linkAt (2 )->strAt (1 ) == " const" )
490+ tok = end->linkAt (2 )->tokAt (2 );
491+ else
492+ tok = end->linkAt (2 )->next ();
493+
494+ scope->functionList .push_back (function);
495+ }
496+
497+ // const noexcept(...);
498+ else if (Token::simpleMatch (end, " ) const noexcept (" ) &&
499+ Token::simpleMatch (end->linkAt (3 ), " ) ;" )) {
500+ function.isNoExcept = true ;
501+
502+ tok = end->linkAt (3 )->next ();
503+
504+ scope->functionList .push_back (function);
505+ }
506+
507+ // throw()
508+ // const throw()
509+ else if (Token::Match (end, " ) const| throw (" ) &&
510+ (end->next ()->str () == " const" ? Token::Match (end->linkAt (3 ), " ) ;" ) :
511+ Token::Match (end->linkAt (2 ), " ) ;" ))) {
512+ function.isThrow = true ;
513+
514+ if (end->next ()->str () == " const" ) {
515+ if (end->strAt (4 ) != " )" )
516+ function.throwArg = end->tokAt (4 );
517+ tok = end->linkAt (3 )->next ();
518+ } else {
519+ if (end->strAt (3 ) != " )" )
520+ function.throwArg = end->tokAt (3 );
521+ tok = end->linkAt (2 )->next ();
522+ }
523+
524+ scope->functionList .push_back (function);
525+ }
526+
461527 // pure virtual function
462528 else if (Token::Match (end, " ) const| = %any% ;" )) {
463529 function.isPure = true ;
@@ -481,6 +547,28 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
481547 function.isInline = true ;
482548 function.hasBody = true ;
483549
550+ if (Token::Match (end, " ) const| noexcept" )) {
551+ int arg = 2 ;
552+
553+ if (end->strAt (1 ) == " const" )
554+ arg++;
555+
556+ if (end->strAt (arg) == " (" )
557+ function.noexceptArg = end->tokAt (arg + 1 );
558+
559+ function.isNoExcept = true ;
560+ } else if (Token::Match (end, " ) const| throw (" )) {
561+ int arg = 3 ;
562+
563+ if (end->strAt (1 ) == " const" )
564+ arg++;
565+
566+ if (end->strAt (arg) != " )" )
567+ function.throwArg = end->tokAt (arg);
568+
569+ function.isThrow = true ;
570+ }
571+
484572 // find start of function '{'
485573 while (end && end->str () != " {" && end->str () != " ;" )
486574 end = end->next ();
@@ -549,11 +637,13 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
549637 if (isFunction (tok, scope, &funcStart, &argStart)) {
550638 bool retFuncPtr = Token::simpleMatch (argStart->link (), " ) ) (" );
551639 const Token* scopeBegin = argStart->link ()->next ();
552-
553640 if (retFuncPtr)
554641 scopeBegin = scopeBegin->next ()->link ()->next ();
555642 if (scopeBegin->isName ()) { // Jump behind 'const' or unknown Macro
556643 scopeBegin = scopeBegin->next ();
644+ if (scopeBegin->str () == " throw" )
645+ scopeBegin = scopeBegin->next ();
646+
557647 if (scopeBegin->link () && scopeBegin->str () == " (" ) // Jump behind unknown macro of type THROW(...)
558648 scopeBegin = scopeBegin->link ()->next ();
559649 }
@@ -576,6 +666,29 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
576666 else {
577667 Function* function = addGlobalFunction (scope, tok, argStart, funcStart);
578668 function->retFuncPtr = retFuncPtr;
669+
670+ // global functions can't be const but we have tests that are
671+ if (Token::Match (argStart->link (), " ) const| noexcept" )) {
672+ int arg = 2 ;
673+
674+ if (argStart->link ()->strAt (1 ) == " const" )
675+ arg++;
676+
677+ if (argStart->link ()->strAt (arg) == " (" )
678+ function->noexceptArg = argStart->link ()->tokAt (arg + 1 );
679+
680+ function->isNoExcept = true ;
681+ } else if (Token::Match (argStart->link (), " ) const| throw (" )) {
682+ int arg = 3 ;
683+
684+ if (argStart->link ()->strAt (1 ) == " const" )
685+ arg++;
686+
687+ if (argStart->link ()->strAt (arg) != " )" )
688+ function->throwArg = argStart->link ()->tokAt (arg);
689+
690+ function->isThrow = true ;
691+ }
579692 }
580693
581694 // syntax error?
@@ -598,6 +711,28 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
598711 if (newFunc) {
599712 Function* func = addGlobalFunctionDecl (scope, tok, argStart, funcStart);
600713 func->retFuncPtr = retFuncPtr;
714+
715+ if (Token::Match (argStart->link (), " ) const| noexcept" )) {
716+ int arg = 2 ;
717+
718+ if (argStart->link ()->strAt (1 ) == " const" )
719+ arg++;
720+
721+ if (argStart->link ()->strAt (arg) == " (" )
722+ func->noexceptArg = argStart->link ()->tokAt (arg + 1 );
723+
724+ func->isNoExcept = true ;
725+ } else if (Token::Match (argStart->link (), " ) const| throw (" )) {
726+ int arg = 3 ;
727+
728+ if (argStart->link ()->strAt (1 ) == " const" )
729+ arg++;
730+
731+ if (argStart->link ()->strAt (arg) != " )" )
732+ func->throwArg = argStart->link ()->tokAt (arg);
733+
734+ func->isThrow = true ;
735+ }
601736 }
602737
603738 tok = scopeBegin;
@@ -965,11 +1100,16 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
9651100 tok->strAt (-1 ) == " ::" || tok->strAt (-1 ) == " ~" || // or a scope qualifier in front of tok
9661101 outerScope->isClassOrStruct ())) { // or a ctor/dtor
9671102 const Token* tok2 = tok->next ()->link ()->next ();
968- if ((Token::Match (tok2, " const| ;|{|=" ) ||
1103+ if (tok2 &&
1104+ (Token::Match (tok2, " const| ;|{|=" ) ||
9691105 (Token::Match (tok2, " %var% ;|{" ) && tok2->isUpperCaseName ()) ||
9701106 (Token::Match (tok2, " %var% (" ) && tok2->isUpperCaseName () && tok2->next ()->link ()->strAt (1 ) == " {" ) ||
9711107 Token::Match (tok2, " : ::| %var% (|::|<|{" ) ||
972- Token::Match (tok2, " = delete|default ;" ))) {
1108+ Token::Match (tok2, " = delete|default ;" ) ||
1109+ Token::Match (tok2, " const| noexcept const| {|:|;" ) ||
1110+ (Token::Match (tok2, " const| noexcept|throw (" ) &&
1111+ tok2->str () == " const" ? (tok2->tokAt (2 ) && Token::Match (tok2->tokAt (2 )->link (), " ) const| {|:|;" )) :
1112+ (tok2->next () && Token::Match (tok2->next ()->link (), " ) const| {|:|;" ))))) {
9731113 *funcStart = tok;
9741114 *argStart = tok->next ();
9751115 return true ;
@@ -980,7 +1120,8 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
9801120 else if (Token::Match (tok, " %var% <" ) && Token::simpleMatch (tok->next ()->link (), " > (" )) {
9811121 const Token* tok2 = tok->next ()->link ()->next ()->link ();
9821122 if (Token::Match (tok2, " ) const| ;|{|=" ) ||
983- Token::Match (tok2, " ) : ::| %var% (|::|<|{" )) {
1123+ Token::Match (tok2, " ) : ::| %var% (|::|<|{" ) ||
1124+ Token::Match (tok->next ()->link ()->next ()->link (), " ) const| noexcept {|;|(" )) {
9841125 *funcStart = tok;
9851126 *argStart = tok2->link ();
9861127 return true ;
@@ -1772,8 +1913,12 @@ void SymbolDatabase::printOut(const char *title) const
17721913 std::cout << " isExplicit: " << (func->isExplicit ? " true" : " false" ) << std::endl;
17731914 std::cout << " isDefault: " << (func->isDefault ? " true" : " false" ) << std::endl;
17741915 std::cout << " isDelete: " << (func->isDelete ? " true" : " false" ) << std::endl;
1916+ std::cout << " isNoExcept: " << (func->isNoExcept ? " true" : " false" ) << std::endl;
1917+ std::cout << " isThrow: " << (func->isThrow ? " true" : " false" ) << std::endl;
17751918 std::cout << " isOperator: " << (func->isOperator ? " true" : " false" ) << std::endl;
17761919 std::cout << " retFuncPtr: " << (func->retFuncPtr ? " true" : " false" ) << std::endl;
1920+ std::cout << " noexceptArg: " << (func->noexceptArg ? func->noexceptArg ->str () : " none" ) << std::endl;
1921+ std::cout << " throwArg: " << (func->throwArg ? func->throwArg ->str () : " none" ) << std::endl;
17771922 std::cout << " tokenDef: " << func->tokenDef ->str () << " " <<_tokenizer->list .fileLine (func->tokenDef ) << std::endl;
17781923 std::cout << " argDef: " << _tokenizer->list .fileLine (func->argDef ) << std::endl;
17791924 if (!func->isConstructor () && !func->isDestructor ())
0 commit comments