2010-11-13 08:08:45 +01:00
/*
* Cppcheck - A tool for static C / C + + code analysis
2019-02-09 07:24:06 +01:00
* Copyright ( C ) 2007 - 2019 Cppcheck team .
2010-11-13 08:08:45 +01:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
# include "symboldatabase.h"
2019-03-30 10:32:36 +01:00
# include "astutils.h"
2010-11-13 08:08:45 +01:00
# include "errorlogger.h"
2017-05-27 04:33:47 +02:00
# include "platform.h"
# include "settings.h"
# include "token.h"
# include "tokenize.h"
# include "tokenlist.h"
2015-11-29 10:49:10 +01:00
# include "utils.h"
2017-05-27 04:33:47 +02:00
# include "valueflow.h"
2010-11-13 08:08:45 +01:00
2017-05-27 04:33:47 +02:00
# include <algorithm>
2017-09-15 00:11:27 +02:00
# include <cassert>
2011-06-24 04:35:15 +02:00
# include <climits>
2015-01-09 21:34:57 +01:00
# include <iomanip>
2017-05-27 04:33:47 +02:00
# include <iostream>
2010-11-13 08:08:45 +01:00
//---------------------------------------------------------------------------
SymbolDatabase : : SymbolDatabase ( const Tokenizer * tokenizer , const Settings * settings , ErrorLogger * errorLogger )
2018-06-16 16:10:28 +02:00
: mTokenizer ( tokenizer ) , mSettings ( settings ) , mErrorLogger ( errorLogger )
2017-01-01 11:34:05 +01:00
{
2018-06-16 23:30:00 +02:00
mIsCpp = isCPP ( ) ;
2017-03-22 02:55:22 +01:00
2018-06-16 16:10:28 +02:00
if ( mSettings - > defaultSign = = ' s ' | | mSettings - > defaultSign = = ' S ' )
2018-06-16 23:25:35 +02:00
mDefaultSignedness = ValueType : : SIGNED ;
2018-06-16 16:10:28 +02:00
else if ( mSettings - > defaultSign = = ' u ' | | mSettings - > defaultSign = = ' U ' )
2018-06-16 23:25:35 +02:00
mDefaultSignedness = ValueType : : UNSIGNED ;
2017-03-22 02:55:22 +01:00
else
2018-06-16 23:25:35 +02:00
mDefaultSignedness = ValueType : : UNKNOWN_SIGN ;
2017-03-22 02:55:22 +01:00
2017-01-01 11:34:05 +01:00
createSymbolDatabaseFindAllScopes ( ) ;
createSymbolDatabaseClassInfo ( ) ;
createSymbolDatabaseVariableInfo ( ) ;
2018-01-07 14:20:19 +01:00
createSymbolDatabaseCopyAndMoveConstructors ( ) ;
2017-01-01 11:34:05 +01:00
createSymbolDatabaseFunctionScopes ( ) ;
createSymbolDatabaseClassAndStructScopes ( ) ;
createSymbolDatabaseFunctionReturnTypes ( ) ;
createSymbolDatabaseNeedInitialization ( ) ;
createSymbolDatabaseVariableSymbolTable ( ) ;
createSymbolDatabaseSetScopePointers ( ) ;
createSymbolDatabaseSetVariablePointers ( ) ;
2019-08-05 13:42:00 +02:00
setValueTypeInTokenList ( false ) ;
2019-05-30 20:26:45 +02:00
createSymbolDatabaseSetFunctionPointers ( true ) ;
2017-01-01 11:34:05 +01:00
createSymbolDatabaseSetTypePointers ( ) ;
createSymbolDatabaseEnums ( ) ;
2019-08-08 07:46:47 +02:00
createSymbolDatabaseEscapeFunctions ( ) ;
2019-08-05 07:18:06 +02:00
createSymbolDatabaseIncompleteVars ( ) ;
2017-01-01 11:34:05 +01:00
}
2018-05-01 07:32:19 +02:00
static const Token * skipScopeIdentifiers ( const Token * tok )
{
if ( tok & & tok - > str ( ) = = " :: " ) {
tok = tok - > next ( ) ;
}
while ( Token : : Match ( tok , " %name% :: " ) | |
2018-05-06 08:23:07 +02:00
( Token : : Match ( tok , " %name% < " ) & & Token : : simpleMatch ( tok - > linkAt ( 1 ) , " > :: " ) ) ) {
2018-05-01 07:32:19 +02:00
if ( tok - > strAt ( 1 ) = = " :: " )
tok = tok - > tokAt ( 2 ) ;
else
tok = tok - > linkAt ( 1 ) - > tokAt ( 2 ) ;
}
return tok ;
}
2019-04-15 06:37:27 +02:00
static bool isExecutableScope ( const Token * tok )
{
if ( ! Token : : simpleMatch ( tok , " { " ) )
return false ;
const Token * tok2 = tok - > link ( ) - > previous ( ) ;
if ( Token : : simpleMatch ( tok2 , " ; } " ) )
return true ;
if ( Token : : Match ( tok2 , " {|} } " ) ) {
const Token * startTok = tok2 - > str ( ) = = " { " ? tok2 : tok2 - > link ( ) ;
if ( Token : : Match ( startTok - > previous ( ) , " do|try|else { " ) )
return true ;
if ( Token : : simpleMatch ( startTok - > previous ( ) , " ) { " ) )
return ! findLambdaStartToken ( tok2 ) ;
if ( tok - > str ( ) = = " { " )
return false ;
else
return isExecutableScope ( startTok ) ;
}
return false ;
}
2017-01-01 11:34:05 +01:00
void SymbolDatabase : : createSymbolDatabaseFindAllScopes ( )
2010-11-13 08:08:45 +01:00
{
2011-03-11 01:43:29 +01:00
// create global scope
2018-04-11 09:44:35 +02:00
scopeList . emplace_back ( this , nullptr , nullptr ) ;
2011-03-11 01:43:29 +01:00
// pointer to current scope
Scope * scope = & scopeList . back ( ) ;
2012-04-18 13:00:34 +02:00
// Store current access in each scope (depends on evaluation progress)
std : : map < const Scope * , AccessControl > access ;
2011-03-11 01:43:29 +01:00
// find all scopes
2018-06-16 16:10:28 +02:00
for ( const Token * tok = mTokenizer - > tokens ( ) ; tok ; tok = tok ? tok - > next ( ) : nullptr ) {
2014-04-18 20:42:22 +02:00
// #5593 suggested to add here:
2018-06-16 16:10:28 +02:00
if ( mErrorLogger )
mErrorLogger - > reportProgress ( mTokenizer - > list . getSourceFilePath ( ) ,
2014-04-18 21:19:49 +02:00
" SymbolDatabase " ,
tok - > progressValue ( ) ) ;
2010-11-13 08:08:45 +01:00
// Locate next class
2018-06-16 16:10:28 +02:00
if ( ( mTokenizer - > isCPP ( ) & & ( ( Token : : Match ( tok , " class|struct|union|namespace ::| %name% {|:|::|< " ) & &
2019-03-24 17:31:34 +01:00
! Token : : Match ( tok - > previous ( ) , " new|friend|const|enum|typedef|mutable|volatile|using|)|(|< " ) ) | |
2018-04-06 21:32:32 +02:00
( Token : : Match ( tok , " enum class| %name% { " ) | |
Token : : Match ( tok , " enum class| %name% : %name% { " ) ) ) )
2018-06-16 16:10:28 +02:00
| | ( mTokenizer - > isC ( ) & & Token : : Match ( tok , " struct|union|enum %name% { " ) ) ) {
2012-11-30 06:03:58 +01:00
const Token * tok2 = tok - > tokAt ( 2 ) ;
2012-10-16 06:11:28 +02:00
2012-11-30 06:03:58 +01:00
if ( tok - > strAt ( 1 ) = = " :: " )
tok2 = tok2 - > next ( ) ;
2018-06-16 16:10:28 +02:00
else if ( mTokenizer - > isCPP ( ) & & tok - > strAt ( 1 ) = = " class " )
2016-04-22 06:02:54 +02:00
tok2 = tok2 - > next ( ) ;
2012-04-18 13:00:34 +02:00
2018-03-31 17:54:47 +02:00
while ( Token : : Match ( tok2 , " :: %name% " ) )
2012-11-30 06:03:58 +01:00
tok2 = tok2 - > tokAt ( 2 ) ;
2018-04-06 16:03:58 +02:00
while ( Token : : Match ( tok2 , " %name% :: %name% " ) )
tok2 = tok2 - > tokAt ( 2 ) ;
2012-11-30 06:03:58 +01:00
2015-01-19 16:15:11 +01:00
// skip over template args
2018-05-01 07:32:19 +02:00
while ( tok2 & & tok2 - > str ( ) = = " < " & & tok2 - > link ( ) ) {
2015-01-19 16:15:11 +01:00
tok2 = tok2 - > link ( ) - > next ( ) ;
2018-05-01 07:32:19 +02:00
while ( Token : : Match ( tok2 , " :: %name% " ) )
tok2 = tok2 - > tokAt ( 2 ) ;
}
2015-01-19 16:15:11 +01:00
2018-05-21 21:23:21 +02:00
// skip over final
2018-06-16 16:10:28 +02:00
if ( mTokenizer - > isCPP ( ) & & Token : : simpleMatch ( tok2 , " final " ) )
2018-05-21 21:23:21 +02:00
tok2 = tok2 - > next ( ) ;
2012-11-30 06:03:58 +01:00
// make sure we have valid code
2018-01-01 04:21:30 +01:00
if ( ! Token : : Match ( tok2 , " {|: " ) ) {
2013-03-28 06:36:49 +01:00
// check for qualified variable
if ( tok2 & & tok2 - > next ( ) ) {
if ( tok2 - > next ( ) - > str ( ) = = " ; " )
tok = tok2 - > next ( ) ;
2014-03-14 16:26:37 +01:00
else if ( Token : : simpleMatch ( tok2 - > next ( ) , " = { " ) &&
2015-05-23 23:18:59 +02:00
Token : : simpleMatch ( tok2 - > linkAt ( 2 ) , " } ; " ) )
2013-03-28 06:36:49 +01:00
tok = tok2 - > linkAt ( 2 ) - > next ( ) ;
2014-03-23 20:08:16 +01:00
else if ( Token : : Match ( tok2 - > next ( ) , " (| { " ) &&
tok2 - > next ( ) - > link ( ) - > strAt ( 1 ) = = " ; " )
2013-03-28 06:36:49 +01:00
tok = tok2 - > next ( ) - > link ( ) - > next ( ) ;
2015-01-19 06:38:54 +01:00
// skip variable declaration
2016-07-09 09:22:52 +02:00
else if ( Token : : Match ( tok2 , " *|&|> " ) )
2015-01-19 06:38:54 +01:00
continue ;
2018-06-16 16:10:28 +02:00
else if ( Token : : Match ( tok2 , " %name% ( " ) & & mTokenizer - > isFunctionHead ( tok2 - > next ( ) , " { ; " ))
2018-04-02 13:14:48 +02:00
continue ;
2018-04-06 16:03:58 +02:00
else if ( Token : : Match ( tok2 , " %name% [ " ) )
continue ;
2018-04-08 07:29:19 +02:00
// skip template
2018-05-13 19:00:42 +02:00
else if ( Token : : simpleMatch ( tok2 , " ; " ) & &
Token : : Match ( tok - > previous ( ) , " template|> class|struct " ) ) {
2018-04-08 07:29:19 +02:00
tok = tok2 ;
continue ;
2018-05-13 19:00:42 +02:00
}
// forward declaration
else if ( Token : : simpleMatch ( tok2 , " ; " ) & &
Token : : Match ( tok , " class|struct|union " ) ) {
// TODO: see if it can be used
tok = tok2 ;
continue ;
}
// skip constructor
else if ( Token : : simpleMatch ( tok2 , " ( " ) & &
Token : : simpleMatch ( tok2 - > link ( ) , " ) ; " ) ) {
tok = tok2 - > link ( ) - > next ( ) ;
continue ;
2018-04-08 07:29:19 +02:00
} else
2018-04-02 13:14:48 +02:00
throw InternalError ( tok2 , " SymbolDatabase bailout; unhandled code " , InternalError : : SYNTAX ) ;
2013-03-28 06:36:49 +01:00
continue ;
}
break ; // bail
}
2012-11-30 06:03:58 +01:00
2018-05-04 07:56:20 +02:00
const Token * name = tok - > next ( ) ;
if ( name - > str ( ) = = " class " & & name - > strAt ( - 1 ) = = " enum " )
name = name - > next ( ) ;
Scope * new_scope = findScope ( name , scope ) ;
2012-10-16 19:12:27 +02:00
2012-11-30 06:03:58 +01:00
if ( new_scope ) {
// only create base list for classes and structures
if ( new_scope - > isClassOrStruct ( ) ) {
// goto initial '{'
2018-02-05 23:28:33 +01:00
if ( ! new_scope - > definedType )
2018-06-16 16:10:28 +02:00
mTokenizer - > syntaxError ( nullptr ) ; // #6808
2018-02-02 08:45:13 +01:00
tok2 = new_scope - > definedType - > initBaseInfo ( tok , tok2 ) ;
2012-11-30 06:03:58 +01:00
// make sure we have valid code
if ( ! tok2 ) {
break ;
}
}
2013-02-01 06:31:02 +01:00
// definition may be different than declaration
2018-06-16 16:10:28 +02:00
if ( mTokenizer - > isCPP ( ) & & tok - > str ( ) = = " class " ) {
2019-07-23 14:29:02 +02:00
access [ new_scope ] = AccessControl : : Private ;
2013-02-01 06:31:02 +01:00
new_scope - > type = Scope : : eClass ;
} else if ( tok - > str ( ) = = " struct " ) {
2019-07-23 14:29:02 +02:00
access [ new_scope ] = AccessControl : : Public ;
2013-02-01 06:31:02 +01:00
new_scope - > type = Scope : : eStruct ;
}
2012-11-30 06:03:58 +01:00
new_scope - > classDef = tok ;
2018-04-27 22:36:30 +02:00
new_scope - > bodyStart = tok2 ;
new_scope - > bodyEnd = tok2 - > link ( ) ;
2017-09-19 21:13:50 +02:00
// make sure we have valid code
2018-04-27 22:36:30 +02:00
if ( ! new_scope - > bodyEnd ) {
2018-06-16 16:10:28 +02:00
mTokenizer - > syntaxError ( tok ) ;
2017-09-19 21:13:50 +02:00
}
2012-11-30 06:03:58 +01:00
scope = new_scope ;
tok = tok2 ;
} else {
2018-04-11 09:44:35 +02:00
scopeList . emplace_back ( this , tok , scope ) ;
2012-11-30 06:03:58 +01:00
new_scope = & scopeList . back ( ) ;
if ( tok - > str ( ) = = " class " )
2019-07-23 14:29:02 +02:00
access [ new_scope ] = AccessControl : : Private ;
2017-10-15 11:49:36 +02:00
else if ( tok - > str ( ) = = " struct " | | tok - > str ( ) = = " union " )
2019-07-23 14:29:02 +02:00
access [ new_scope ] = AccessControl : : Public ;
2012-11-30 06:03:58 +01:00
2013-03-05 15:28:40 +01:00
// fill typeList...
2017-10-15 11:49:36 +02:00
if ( new_scope - > isClassOrStructOrUnion ( ) | | new_scope - > type = = Scope : : eEnum ) {
2018-05-04 07:56:20 +02:00
Type * new_type = findType ( name , scope ) ;
2013-03-05 15:28:40 +01:00
if ( ! new_type ) {
2018-04-11 09:44:35 +02:00
typeList . emplace_back ( new_scope - > classDef , new_scope , scope ) ;
2013-03-05 15:28:40 +01:00
new_type = & typeList . back ( ) ;
2017-10-15 02:53:41 +02:00
scope - > definedTypesMap [ new_type - > name ( ) ] = new_type ;
2013-03-05 15:28:40 +01:00
} else
new_type - > classScope = new_scope ;
new_scope - > definedType = new_type ;
}
2012-11-30 06:03:58 +01:00
// only create base list for classes and structures
if ( new_scope - > isClassOrStruct ( ) ) {
// goto initial '{'
2013-03-05 15:28:40 +01:00
tok2 = new_scope - > definedType - > initBaseInfo ( tok , tok2 ) ;
2012-11-30 06:03:58 +01:00
// make sure we have valid code
if ( ! tok2 ) {
2018-06-16 16:10:28 +02:00
mTokenizer - > syntaxError ( tok ) ;
2012-11-30 06:03:58 +01:00
}
2016-04-22 06:02:54 +02:00
} else if ( new_scope - > type = = Scope : : eEnum ) {
if ( tok2 - > str ( ) = = " : " )
tok2 = tok2 - > tokAt ( 2 ) ;
2012-11-30 06:03:58 +01:00
}
2018-04-27 22:36:30 +02:00
new_scope - > bodyStart = tok2 ;
new_scope - > bodyEnd = tok2 - > link ( ) ;
2011-02-19 20:38:00 +01:00
// make sure we have valid code
2018-04-27 22:36:30 +02:00
if ( ! new_scope - > bodyEnd ) {
2018-06-16 16:10:28 +02:00
mTokenizer - > syntaxError ( tok ) ;
2011-02-19 20:38:00 +01:00
}
2010-11-13 08:08:45 +01:00
2016-04-22 06:02:54 +02:00
if ( new_scope - > type = = Scope : : eEnum ) {
2018-06-16 16:10:28 +02:00
tok2 = new_scope - > addEnum ( tok , mTokenizer - > isCPP ( ) ) ;
2016-04-22 06:02:54 +02:00
scope - > nestedList . push_back ( new_scope ) ;
if ( ! tok2 )
2018-06-16 16:10:28 +02:00
mTokenizer - > syntaxError ( tok ) ;
2016-04-22 06:02:54 +02:00
} else {
// make the new scope the current scope
scope - > nestedList . push_back ( new_scope ) ;
scope = new_scope ;
}
2010-12-16 19:04:47 +01:00
2012-11-30 06:03:58 +01:00
tok = tok2 ;
}
2012-06-05 06:37:55 +02:00
}
// Namespace and unknown macro (#3854)
2018-06-16 16:10:28 +02:00
else if ( mTokenizer - > isCPP ( ) & &
2015-01-31 10:50:39 +01:00
Token : : Match ( tok , " namespace %name% %type% ( " ) & &
2012-06-21 19:00:53 +02:00
tok - > tokAt ( 2 ) - > isUpperCaseName ( ) & &
2012-06-05 06:37:55 +02:00
Token : : simpleMatch ( tok - > linkAt ( 3 ) , " ) { " ) ) {
2018-04-11 09:44:35 +02:00
scopeList . emplace_back ( this , tok , scope ) ;
2012-06-05 06:37:55 +02:00
Scope * new_scope = & scopeList . back ( ) ;
2019-07-23 14:29:02 +02:00
access [ new_scope ] = AccessControl : : Public ;
2012-06-05 06:37:55 +02:00
const Token * tok2 = tok - > linkAt ( 3 ) - > next ( ) ;
2018-04-27 22:36:30 +02:00
new_scope - > bodyStart = tok2 ;
new_scope - > bodyEnd = tok2 - > link ( ) ;
2012-06-05 06:37:55 +02:00
// make sure we have valid code
2018-04-27 22:36:30 +02:00
if ( ! new_scope - > bodyEnd ) {
2012-06-05 06:37:55 +02:00
scopeList . pop_back ( ) ;
break ;
}
// make the new scope the current scope
2013-03-05 18:42:42 +01:00
scope - > nestedList . push_back ( new_scope ) ;
2012-06-05 06:37:55 +02:00
scope = & scopeList . back ( ) ;
2010-11-13 08:08:45 +01:00
tok = tok2 ;
}
2011-01-20 18:02:52 +01:00
// forward declaration
2015-01-31 10:50:39 +01:00
else if ( Token : : Match ( tok , " class|struct|union %name% ; " ) & &
2012-11-30 06:03:58 +01:00
tok - > strAt ( - 1 ) ! = " friend " ) {
2013-03-05 13:33:38 +01:00
if ( ! findType ( tok - > next ( ) , scope ) ) {
// fill typeList..
2018-04-11 09:44:35 +02:00
typeList . emplace_back ( tok , nullptr , scope ) ;
2017-10-15 02:53:41 +02:00
Type * new_type = & typeList . back ( ) ;
scope - > definedTypesMap [ new_type - > name ( ) ] = new_type ;
2012-11-30 06:03:58 +01:00
}
2011-01-20 18:02:52 +01:00
tok = tok - > tokAt ( 2 ) ;
}
2011-03-14 02:01:33 +01:00
// using namespace
2018-06-16 16:10:28 +02:00
else if ( mTokenizer - > isCPP ( ) & & Token : : Match ( tok , " using namespace ::| %type% ; | : : " )) {
2012-12-20 06:53:04 +01:00
Scope : : UsingInfo using_info ;
using_info . start = tok ; // save location
2014-04-10 16:11:11 +02:00
using_info . scope = findNamespace ( tok - > tokAt ( 2 ) , scope ) ;
2012-12-20 06:53:04 +01:00
scope - > usingList . push_back ( using_info ) ;
2011-03-14 02:01:33 +01:00
2013-02-14 06:31:41 +01:00
// check for global namespace
if ( tok - > strAt ( 2 ) = = " :: " )
tok = tok - > tokAt ( 4 ) ;
else
tok = tok - > tokAt ( 3 ) ;
// skip over qualification
2016-11-26 17:08:36 +01:00
while ( Token : : Match ( tok , " %type% :: " ) )
2013-02-14 06:31:41 +01:00
tok = tok - > tokAt ( 2 ) ;
2011-03-14 02:01:33 +01:00
}
2018-01-10 22:16:18 +01:00
// using type alias
2018-06-16 16:10:28 +02:00
else if ( mTokenizer - > isCPP ( ) & & Token : : Match ( tok , " using %name% = " ) ) {
2018-01-21 21:22:26 +01:00
if ( tok - > strAt ( - 1 ) ! = " > " & & ! findType ( tok - > next ( ) , scope ) ) {
2018-01-10 22:16:18 +01:00
// fill typeList..
2018-04-11 09:44:35 +02:00
typeList . emplace_back ( tok , nullptr , scope ) ;
2018-01-10 22:16:18 +01:00
Type * new_type = & typeList . back ( ) ;
scope - > definedTypesMap [ new_type - > name ( ) ] = new_type ;
}
tok = tok - > tokAt ( 3 ) ;
while ( tok & & tok - > str ( ) ! = " ; " )
tok = tok - > next ( ) ;
}
2011-03-30 01:48:12 +02:00
// unnamed struct and union
2011-03-29 13:08:59 +02:00
else if ( Token : : Match ( tok , " struct|union { " ) & &
2018-10-20 09:43:08 +02:00
Token : : Match ( tok - > next ( ) - > link ( ) , " } *|&| %name% ;|[|= " ) ) {
2018-04-11 09:44:35 +02:00
scopeList . emplace_back ( this , tok , scope ) ;
2011-03-27 19:48:41 +02:00
Scope * new_scope = & scopeList . back ( ) ;
2019-07-23 14:29:02 +02:00
access [ new_scope ] = AccessControl : : Public ;
2011-03-27 19:48:41 +02:00
2011-12-17 19:04:03 +01:00
const Token * varNameTok = tok - > next ( ) - > link ( ) - > next ( ) ;
if ( varNameTok - > str ( ) = = " * " ) {
varNameTok = varNameTok - > next ( ) ;
2012-01-26 17:04:25 +01:00
} else if ( varNameTok - > str ( ) = = " & " ) {
varNameTok = varNameTok - > next ( ) ;
2011-12-17 19:04:03 +01:00
}
2018-04-11 09:44:35 +02:00
typeList . emplace_back ( tok , new_scope , scope ) ;
2017-10-15 02:53:41 +02:00
{
2017-10-17 10:59:23 +02:00
Type * new_type = & typeList . back ( ) ;
new_scope - > definedType = new_type ;
scope - > definedTypesMap [ new_type - > name ( ) ] = new_type ;
2017-10-15 02:53:41 +02:00
}
2013-03-05 13:33:38 +01:00
2018-06-20 10:00:15 +02:00
scope - > addVariable ( varNameTok , tok , tok , access [ scope ] , new_scope - > definedType , scope , mSettings ) ;
2011-03-27 19:48:41 +02:00
const Token * tok2 = tok - > next ( ) ;
2018-04-27 22:36:30 +02:00
new_scope - > bodyStart = tok2 ;
new_scope - > bodyEnd = tok2 - > link ( ) ;
2011-03-27 19:48:41 +02:00
// make sure we have valid code
2018-04-27 22:36:30 +02:00
if ( ! new_scope - > bodyEnd ) {
2011-03-27 19:48:41 +02:00
scopeList . pop_back ( ) ;
break ;
}
// make the new scope the current scope
2013-03-05 18:42:42 +01:00
scope - > nestedList . push_back ( new_scope ) ;
2013-03-05 13:33:38 +01:00
scope = new_scope ;
2011-03-27 19:48:41 +02:00
tok = tok2 ;
}
2014-09-24 06:09:08 +02:00
// anonymous struct, union and namespace
else if ( ( Token : : Match ( tok , " struct|union { " ) & &
Token : : simpleMatch ( tok - > next ( ) - > link ( ) , " } ; " ) ) | |
Token : : simpleMatch ( tok , " namespace { " ) ) {
2018-04-11 09:44:35 +02:00
scopeList . emplace_back ( this , tok , scope ) ;
2011-04-01 02:54:23 +02:00
Scope * new_scope = & scopeList . back ( ) ;
2019-07-23 14:29:02 +02:00
access [ new_scope ] = AccessControl : : Public ;
2011-04-01 02:54:23 +02:00
const Token * tok2 = tok - > next ( ) ;
2018-04-27 22:36:30 +02:00
new_scope - > bodyStart = tok2 ;
new_scope - > bodyEnd = tok2 - > link ( ) ;
2011-04-01 02:54:23 +02:00
2018-04-11 09:44:35 +02:00
typeList . emplace_back ( tok , new_scope , scope ) ;
2017-10-15 02:53:41 +02:00
{
2017-10-17 10:59:23 +02:00
Type * new_type = & typeList . back ( ) ;
new_scope - > definedType = new_type ;
scope - > definedTypesMap [ new_type - > name ( ) ] = new_type ;
2017-10-15 02:53:41 +02:00
}
2013-03-05 13:33:38 +01:00
2011-04-01 02:54:23 +02:00
// make sure we have valid code
2018-04-27 22:36:30 +02:00
if ( ! new_scope - > bodyEnd ) {
2011-04-01 02:54:23 +02:00
scopeList . pop_back ( ) ;
break ;
}
// make the new scope the current scope
2013-03-05 18:42:42 +01:00
scope - > nestedList . push_back ( new_scope ) ;
2013-03-05 13:33:38 +01:00
scope = new_scope ;
2011-04-01 02:54:23 +02:00
tok = tok2 ;
}
2016-04-22 06:02:54 +02:00
// forward declared enum
else if ( Token : : Match ( tok , " enum class| %name% ; " ) | | Token : : Match ( tok , " enum class| %name% : %name% ; " ) ) {
2018-04-11 09:44:35 +02:00
typeList . emplace_back ( tok , nullptr , scope ) ;
2017-10-15 02:53:41 +02:00
Type * new_type = & typeList . back ( ) ;
scope - > definedTypesMap [ new_type - > name ( ) ] = new_type ;
2016-04-22 06:02:54 +02:00
tok = tok - > tokAt ( 2 ) ;
}
2017-01-09 22:48:05 +01:00
// check for end of scope
2018-04-27 22:36:30 +02:00
else if ( tok = = scope - > bodyEnd ) {
2017-01-09 22:48:05 +01:00
access . erase ( scope ) ;
scope = const_cast < Scope * > ( scope - > nestedIn ) ;
continue ;
}
2010-11-13 08:08:45 +01:00
2017-10-15 11:49:36 +02:00
// check if in class or structure or union
else if ( scope - > isClassOrStructOrUnion ( ) ) {
2017-01-09 22:48:05 +01:00
const Token * funcStart = nullptr ;
const Token * argStart = nullptr ;
const Token * declEnd = nullptr ;
// What section are we in..
if ( tok - > str ( ) = = " private: " )
2019-07-23 14:29:02 +02:00
access [ scope ] = AccessControl : : Private ;
2017-01-09 22:48:05 +01:00
else if ( tok - > str ( ) = = " protected: " )
2019-07-23 14:29:02 +02:00
access [ scope ] = AccessControl : : Protected ;
2017-01-09 22:48:05 +01:00
else if ( tok - > str ( ) = = " public: " | | tok - > str ( ) = = " __published: " )
2019-07-23 14:29:02 +02:00
access [ scope ] = AccessControl : : Public ;
2017-01-09 22:48:05 +01:00
else if ( Token : : Match ( tok , " public|protected|private %name% : " ) ) {
if ( tok - > str ( ) = = " private " )
2019-07-23 14:29:02 +02:00
access [ scope ] = AccessControl : : Private ;
2017-01-09 22:48:05 +01:00
else if ( tok - > str ( ) = = " protected " )
2019-07-23 14:29:02 +02:00
access [ scope ] = AccessControl : : Protected ;
2017-01-09 22:48:05 +01:00
else
2019-07-23 14:29:02 +02:00
access [ scope ] = AccessControl : : Public ;
2010-11-13 08:08:45 +01:00
2017-01-09 22:48:05 +01:00
tok = tok - > tokAt ( 2 ) ;
}
2010-11-13 08:08:45 +01:00
2017-01-09 22:48:05 +01:00
// class function?
else if ( isFunction ( tok , scope , & funcStart , & argStart , & declEnd ) ) {
if ( tok - > previous ( ) - > str ( ) ! = " :: " | | tok - > strAt ( - 2 ) = = scope - > className ) {
2018-06-16 16:10:28 +02:00
Function function ( mTokenizer , tok , scope , funcStart , argStart ) ;
2010-11-13 08:08:45 +01:00
2017-01-09 22:48:05 +01:00
// save the access type
function . access = access [ scope ] ;
2010-11-13 08:08:45 +01:00
2017-01-09 22:48:05 +01:00
const Token * end = function . argDef - > link ( ) ;
// count the number of constructors
if ( function . isConstructor ( ) )
scope - > numConstructors + + ;
// assume implementation is inline (definition and implementation same)
function . token = function . tokenDef ;
function . arg = function . argDef ;
// out of line function
2018-06-16 16:10:28 +02:00
if ( const Token * endTok = mTokenizer - > isFunctionHead ( end , " ; " ) ) {
2018-04-25 12:05:49 +02:00
tok = endTok ;
2017-01-09 22:48:05 +01:00
scope - > addFunction ( function ) ;
}
2013-11-25 03:43:39 +01:00
2017-01-09 22:48:05 +01:00
// inline function
else {
// find start of function '{'
bool foundInitList = false ;
while ( end & & end - > str ( ) ! = " { " & & end - > str ( ) ! = " ; " ) {
if ( end - > link ( ) & & Token : : Match ( end , " (|< " ) ) {
end = end - > link ( ) ;
} else if ( foundInitList & &
Token : : Match ( end , " %name%|> { " ) & &
Token : : Match ( end - > linkAt ( 1 ) , " } ,|{ " ) ) {
end = end - > linkAt ( 1 ) ;
} else {
if ( end - > str ( ) = = " : " )
foundInitList = true ;
end = end - > next ( ) ;
2015-04-06 19:47:21 +02:00
}
2017-01-09 22:48:05 +01:00
}
2015-04-06 19:47:21 +02:00
2017-01-09 22:48:05 +01:00
if ( ! end | | end - > str ( ) = = " ; " )
continue ;
2011-02-20 14:25:42 +01:00
2017-01-09 22:48:05 +01:00
scope - > addFunction ( function ) ;
2010-11-13 08:08:45 +01:00
2017-01-09 22:48:05 +01:00
Function * funcptr = & scope - > functionList . back ( ) ;
const Token * tok2 = funcStart ;
2010-11-13 08:08:45 +01:00
2017-01-09 22:48:05 +01:00
addNewFunction ( & scope , & tok2 ) ;
if ( scope ) {
scope - > functionOf = function . nestedIn ;
scope - > function = funcptr ;
scope - > function - > functionScope = scope ;
2011-03-14 02:18:49 +01:00
}
2014-03-30 11:06:44 +02:00
2017-01-09 22:48:05 +01:00
tok = tok2 ;
2011-02-03 07:57:10 +01:00
}
}
2010-11-13 08:08:45 +01:00
2017-01-09 22:48:05 +01:00
// nested class or friend function?
else {
/** @todo check entire qualification for match */
2018-09-23 20:24:51 +02:00
const Scope * const nested = scope - > findInNestedListRecursive ( tok - > strAt ( - 2 ) ) ;
2010-11-13 08:08:45 +01:00
2017-01-09 22:48:05 +01:00
if ( nested )
addClassFunction ( & scope , & tok , argStart ) ;
else {
/** @todo handle friend functions */
}
}
}
2012-12-05 20:31:17 +01:00
2017-01-09 22:48:05 +01:00
// friend class declaration?
2018-06-16 16:10:28 +02:00
else if ( mTokenizer - > isCPP ( ) & & Token : : Match ( tok , " friend class| ::| %any% ; | : : " )) {
2017-01-09 22:48:05 +01:00
Type : : FriendInfo friendInfo ;
2012-12-05 20:31:17 +01:00
2017-01-09 22:48:05 +01:00
// save the name start
friendInfo . nameStart = tok - > strAt ( 1 ) = = " class " ? tok - > tokAt ( 2 ) : tok - > next ( ) ;
friendInfo . nameEnd = friendInfo . nameStart ;
2012-12-05 20:31:17 +01:00
2017-01-09 22:48:05 +01:00
// skip leading "::"
if ( friendInfo . nameEnd - > str ( ) = = " :: " )
friendInfo . nameEnd = friendInfo . nameEnd - > next ( ) ;
2012-12-05 20:31:17 +01:00
2017-01-09 22:48:05 +01:00
// skip qualification "name ::"
while ( friendInfo . nameEnd & & friendInfo . nameEnd - > strAt ( 1 ) = = " :: " )
friendInfo . nameEnd = friendInfo . nameEnd - > tokAt ( 2 ) ;
2010-11-13 08:08:45 +01:00
2017-01-09 22:48:05 +01:00
// fill this in after parsing is complete
2017-08-09 20:00:26 +02:00
friendInfo . type = nullptr ;
2014-04-20 20:40:55 +02:00
2017-01-09 22:48:05 +01:00
if ( ! scope - > definedType )
2018-06-16 16:10:28 +02:00
mTokenizer - > syntaxError ( tok ) ;
2014-04-10 16:17:10 +02:00
2017-01-09 22:48:05 +01:00
scope - > definedType - > friendList . push_back ( friendInfo ) ;
}
} else if ( scope - > type = = Scope : : eNamespace | | scope - > type = = Scope : : eGlobal ) {
const Token * funcStart = nullptr ;
const Token * argStart = nullptr ;
const Token * declEnd = nullptr ;
// function?
if ( isFunction ( tok , scope , & funcStart , & argStart , & declEnd ) ) {
// has body?
if ( declEnd & & declEnd - > str ( ) = = " { " ) {
tok = funcStart ;
// class function
if ( tok - > previous ( ) & & tok - > previous ( ) - > str ( ) = = " :: " )
addClassFunction ( & scope , & tok , argStart ) ;
// class destructor
else if ( tok - > previous ( ) & &
tok - > previous ( ) - > str ( ) = = " ~ " & &
tok - > strAt ( - 2 ) = = " :: " )
addClassFunction ( & scope , & tok , argStart ) ;
// regular function
else {
2018-09-23 20:24:51 +02:00
const Function * const function = addGlobalFunction ( scope , tok , argStart , funcStart ) ;
2014-04-10 16:17:10 +02:00
2017-01-09 22:48:05 +01:00
if ( ! function )
2018-06-16 16:10:28 +02:00
mTokenizer - > syntaxError ( tok ) ;
2017-01-09 22:48:05 +01:00
}
2013-08-31 18:58:55 +02:00
2017-01-09 22:48:05 +01:00
// syntax error?
if ( ! scope )
2018-06-16 16:10:28 +02:00
mTokenizer - > syntaxError ( tok ) ;
2017-01-09 22:48:05 +01:00
}
// function prototype?
else if ( declEnd & & declEnd - > str ( ) = = " ; " ) {
bool newFunc = true ; // Is this function already in the database?
for ( std : : multimap < std : : string , const Function * > : : const_iterator i = scope - > functionMap . find ( tok - > str ( ) ) ; i ! = scope - > functionMap . end ( ) & & i - > first = = tok - > str ( ) ; + + i ) {
2018-11-09 06:11:48 +01:00
if ( Function : : argsMatch ( scope , i - > second - > argDef , argStart , emptyString , 0 ) ) {
2017-01-09 22:48:05 +01:00
newFunc = false ;
break ;
}
}
2014-04-10 16:17:10 +02:00
2017-01-09 22:48:05 +01:00
// save function prototype in database
if ( newFunc ) {
2018-04-25 12:05:49 +02:00
addGlobalFunctionDecl ( scope , tok , argStart , funcStart ) ;
2011-03-14 03:59:25 +01:00
}
2017-01-09 22:48:05 +01:00
tok = declEnd ;
continue ;
2010-11-20 07:26:50 +01:00
}
2017-01-09 22:48:05 +01:00
}
} else if ( scope - > isExecutable ( ) ) {
if ( Token : : Match ( tok , " else|try|do { " ) ) {
const Token * tok1 = tok - > next ( ) ;
if ( tok - > str ( ) = = " else " )
2018-04-11 09:44:35 +02:00
scopeList . emplace_back ( this , tok , scope , Scope : : eElse , tok1 ) ;
2017-04-30 08:58:41 +02:00
else if ( tok - > str ( ) = = " do " )
2018-04-11 09:44:35 +02:00
scopeList . emplace_back ( this , tok , scope , Scope : : eDo , tok1 ) ;
2017-01-09 22:48:05 +01:00
else //if (tok->str() == "try")
2018-04-11 09:44:35 +02:00
scopeList . emplace_back ( this , tok , scope , Scope : : eTry , tok1 ) ;
2017-01-09 22:48:05 +01:00
tok = tok1 ;
scope - > nestedList . push_back ( & scopeList . back ( ) ) ;
scope = & scopeList . back ( ) ;
} else if ( Token : : Match ( tok , " if|for|while|catch|switch ( " ) & & Token : : simpleMatch ( tok - > next ( ) - > link ( ) , " ) { " )) {
const Token * scopeStartTok = tok - > next ( ) - > link ( ) - > next ( ) ;
if ( tok - > str ( ) = = " if " )
2018-04-11 09:44:35 +02:00
scopeList . emplace_back ( this , tok , scope , Scope : : eIf , scopeStartTok ) ;
2017-01-09 22:48:05 +01:00
else if ( tok - > str ( ) = = " for " ) {
2018-04-11 09:44:35 +02:00
scopeList . emplace_back ( this , tok , scope , Scope : : eFor , scopeStartTok ) ;
2017-01-09 22:48:05 +01:00
} else if ( tok - > str ( ) = = " while " )
2018-04-11 09:44:35 +02:00
scopeList . emplace_back ( this , tok , scope , Scope : : eWhile , scopeStartTok ) ;
2017-01-09 22:48:05 +01:00
else if ( tok - > str ( ) = = " catch " ) {
2018-04-11 09:44:35 +02:00
scopeList . emplace_back ( this , tok , scope , Scope : : eCatch , scopeStartTok ) ;
2017-01-09 22:48:05 +01:00
} else // if (tok->str() == "switch")
2018-04-11 09:44:35 +02:00
scopeList . emplace_back ( this , tok , scope , Scope : : eSwitch , scopeStartTok ) ;
2017-01-09 22:48:05 +01:00
scope - > nestedList . push_back ( & scopeList . back ( ) ) ;
scope = & scopeList . back ( ) ;
if ( scope - > type = = Scope : : eFor )
2019-07-23 14:29:02 +02:00
scope - > checkVariable ( tok - > tokAt ( 2 ) , AccessControl : : Local , mSettings ) ; // check for variable declaration and add it to new scope if found
2017-01-09 22:48:05 +01:00
else if ( scope - > type = = Scope : : eCatch )
2019-07-23 14:29:02 +02:00
scope - > checkVariable ( tok - > tokAt ( 2 ) , AccessControl : : Throw , mSettings ) ; // check for variable declaration and add it to new scope if found
2017-01-09 22:48:05 +01:00
tok = scopeStartTok ;
2019-03-30 10:32:36 +01:00
} else if ( Token : : Match ( tok , " %var% { " ) ) {
tok = tok - > linkAt ( 1 ) ;
} else if ( const Token * lambdaEndToken = findLambdaEndToken ( tok ) ) {
const Token * lambdaStartToken = lambdaEndToken - > link ( ) ;
2019-07-05 12:30:42 +02:00
const Token * argStart = lambdaStartToken - > astParent ( ) ;
const Token * funcStart = Token : : simpleMatch ( argStart , " [ " ) ? argStart : argStart - > astParent ( ) ;
2019-07-06 10:46:17 +02:00
const Function * function = addGlobalFunction ( scope , tok , argStart , funcStart ) ;
if ( ! function )
mTokenizer - > syntaxError ( tok ) ;
2019-03-30 10:32:36 +01:00
tok = lambdaStartToken ;
2017-01-09 22:48:05 +01:00
} else if ( tok - > str ( ) = = " { " ) {
2019-04-15 06:37:27 +02:00
if ( isExecutableScope ( tok ) ) {
2019-03-30 10:32:36 +01:00
scopeList . emplace_back ( this , tok , scope , Scope : : eUnconditional , tok ) ;
scope - > nestedList . push_back ( & scopeList . back ( ) ) ;
scope = & scopeList . back ( ) ;
} else {
2017-01-09 22:48:05 +01:00
tok = tok - > link ( ) ;
2011-02-26 21:53:57 +01:00
}
}
2019-07-06 10:46:17 +02:00
// syntax error?
if ( ! scope )
mTokenizer - > syntaxError ( tok ) ;
2010-11-20 07:26:50 +01:00
}
2010-11-13 08:08:45 +01:00
}
2017-01-01 11:34:05 +01:00
}
2010-11-13 08:08:45 +01:00
2017-01-01 11:34:05 +01:00
void SymbolDatabase : : createSymbolDatabaseClassInfo ( )
{
2018-06-16 16:10:28 +02:00
if ( mTokenizer - > isC ( ) )
2018-04-04 10:50:10 +02:00
return ;
// fill in using info
for ( std : : list < Scope > : : iterator it = scopeList . begin ( ) ; it ! = scopeList . end ( ) ; + + it ) {
for ( std : : list < Scope : : UsingInfo > : : iterator i = it - > usingList . begin ( ) ; i ! = it - > usingList . end ( ) ; + + i ) {
// only find if not already found
if ( i - > scope = = nullptr ) {
// check scope for match
2018-09-23 20:24:51 +02:00
const Scope * const scope = findScope ( i - > start - > tokAt ( 2 ) , & ( * it ) ) ;
2018-04-04 10:50:10 +02:00
if ( scope ) {
// set found scope
i - > scope = scope ;
break ;
2017-07-16 01:14:15 +02:00
}
}
}
2018-04-04 10:50:10 +02:00
}
2017-07-16 01:14:15 +02:00
2018-04-04 10:50:10 +02:00
// fill in base class info
for ( std : : list < Type > : : iterator it = typeList . begin ( ) ; it ! = typeList . end ( ) ; + + it ) {
// finish filling in base class info
2019-09-25 15:25:19 +02:00
for ( Type : : BaseInfo & i : it - > derivedFrom ) {
const Type * found = findType ( i . nameTok , it - > enclosingScope ) ;
2018-04-04 10:50:10 +02:00
if ( found & & found - > findDependency ( & ( * it ) ) ) {
// circular dependency
2018-06-16 16:10:28 +02:00
//mTokenizer->syntaxError(nullptr);
2018-04-04 10:50:10 +02:00
} else {
2019-09-25 15:25:19 +02:00
i . type = found ;
2015-07-01 07:50:13 +02:00
}
2014-09-01 17:01:05 +02:00
}
2018-04-04 10:50:10 +02:00
}
2010-11-13 08:08:45 +01:00
2018-04-04 10:50:10 +02:00
// fill in friend info
for ( std : : list < Type > : : iterator it = typeList . begin ( ) ; it ! = typeList . end ( ) ; + + it ) {
2019-07-18 14:54:39 +02:00
for ( Type : : FriendInfo & friendInfo : it - > friendList ) {
friendInfo . type = findType ( friendInfo . nameStart , it - > enclosingScope ) ;
2012-02-24 20:45:56 +01:00
}
2012-12-20 06:53:04 +01:00
}
2017-01-01 11:34:05 +01:00
}
2012-12-20 06:53:04 +01:00
2017-01-01 11:34:05 +01:00
void SymbolDatabase : : createSymbolDatabaseVariableInfo ( )
{
2010-12-02 07:35:01 +01:00
// fill in variable info
2013-03-05 15:28:40 +01:00
for ( std : : list < Scope > : : iterator it = scopeList . begin ( ) ; it ! = scopeList . end ( ) ; + + it ) {
2011-02-26 21:57:16 +01:00
// find variables
2018-06-20 10:00:15 +02:00
it - > getVariableList ( mSettings ) ;
2010-12-02 07:35:01 +01:00
}
2011-02-26 21:51:12 +01:00
// fill in function arguments
2013-03-05 15:28:40 +01:00
for ( std : : list < Scope > : : iterator it = scopeList . begin ( ) ; it ! = scopeList . end ( ) ; + + it ) {
2011-02-26 21:51:12 +01:00
std : : list < Function > : : iterator func ;
2012-03-23 17:59:51 +01:00
for ( func = it - > functionList . begin ( ) ; func ! = it - > functionList . end ( ) ; + + func ) {
2011-02-26 21:51:12 +01:00
// add arguments
2016-04-22 06:02:54 +02:00
func - > addArguments ( this , & * it ) ;
2011-02-26 21:51:12 +01:00
}
}
2017-01-01 11:34:05 +01:00
}
2011-02-26 21:51:12 +01:00
2018-01-07 14:20:19 +01:00
void SymbolDatabase : : createSymbolDatabaseCopyAndMoveConstructors ( )
{
// fill in class and struct copy/move constructors
for ( std : : list < Scope > : : iterator scope = scopeList . begin ( ) ; scope ! = scopeList . end ( ) ; + + scope ) {
if ( ! scope - > isClassOrStruct ( ) )
continue ;
std : : list < Function > : : iterator func ;
for ( func = scope - > functionList . begin ( ) ; func ! = scope - > functionList . end ( ) ; + + func ) {
if ( ! func - > isConstructor ( ) | | func - > minArgCount ( ) ! = 1 )
continue ;
const Variable * firstArg = func - > getArgumentVar ( 0 ) ;
if ( firstArg - > type ( ) = = scope - > definedType ) {
if ( firstArg - > isRValueReference ( ) )
func - > type = Function : : eMoveConstructor ;
2018-01-20 14:46:09 +01:00
else if ( firstArg - > isReference ( ) & & ! firstArg - > isPointer ( ) )
2018-01-07 14:20:19 +01:00
func - > type = Function : : eCopyConstructor ;
}
if ( func - > type = = Function : : eCopyConstructor | |
func - > type = = Function : : eMoveConstructor )
scope - > numCopyOrMoveConstructors + + ;
}
}
}
2017-01-01 11:34:05 +01:00
void SymbolDatabase : : createSymbolDatabaseFunctionScopes ( )
{
2012-10-10 20:42:07 +02:00
// fill in function scopes
2013-03-05 15:28:40 +01:00
for ( std : : list < Scope > : : iterator it = scopeList . begin ( ) ; it ! = scopeList . end ( ) ; + + it ) {
2012-10-08 16:15:07 +02:00
if ( it - > type = = Scope : : eFunction )
2012-10-10 20:42:07 +02:00
functionScopes . push_back ( & * it ) ;
}
2017-01-01 11:34:05 +01:00
}
2012-10-10 20:42:07 +02:00
2017-01-01 11:34:05 +01:00
void SymbolDatabase : : createSymbolDatabaseClassAndStructScopes ( )
{
2012-10-10 20:42:07 +02:00
// fill in class and struct scopes
2013-03-05 15:28:40 +01:00
for ( std : : list < Scope > : : iterator it = scopeList . begin ( ) ; it ! = scopeList . end ( ) ; + + it ) {
2012-10-10 20:42:07 +02:00
if ( it - > isClassOrStruct ( ) )
classAndStructScopes . push_back ( & * it ) ;
2012-10-08 16:15:07 +02:00
}
2017-01-01 11:34:05 +01:00
}
2012-10-08 16:15:07 +02:00
2017-01-01 11:34:05 +01:00
void SymbolDatabase : : createSymbolDatabaseFunctionReturnTypes ( )
{
2013-08-26 06:03:26 +02:00
// fill in function return types
for ( std : : list < Scope > : : iterator it = scopeList . begin ( ) ; it ! = scopeList . end ( ) ; + + it ) {
std : : list < Function > : : iterator func ;
for ( func = it - > functionList . begin ( ) ; func ! = it - > functionList . end ( ) ; + + func ) {
// add return types
if ( func - > retDef ) {
const Token * type = func - > retDef ;
2016-04-22 06:02:54 +02:00
while ( Token : : Match ( type , " static|const|struct|union|enum " ) )
2013-08-26 06:03:26 +02:00
type = type - > next ( ) ;
2016-06-05 14:08:33 +02:00
if ( type ) {
func - > retType = findVariableTypeInBase ( & * it , type ) ;
if ( ! func - > retType )
func - > retType = findTypeInNested ( type , func - > nestedIn ) ;
}
2013-08-26 06:03:26 +02:00
}
}
}
2017-01-01 11:34:05 +01:00
}
2013-08-26 06:03:26 +02:00
2017-01-01 11:34:05 +01:00
void SymbolDatabase : : createSymbolDatabaseNeedInitialization ( )
{
2018-06-16 16:10:28 +02:00
if ( mTokenizer - > isC ( ) ) {
2015-01-21 10:34:58 +01:00
// For C code it is easy, as there are no constructors and no default values
2013-03-05 15:28:40 +01:00
for ( std : : list < Scope > : : iterator it = scopeList . begin ( ) ; it ! = scopeList . end ( ) ; + + it ) {
2017-01-01 11:34:05 +01:00
Scope * scope = & ( * it ) ;
2015-01-21 10:34:58 +01:00
if ( scope - > definedType )
2019-08-02 21:14:29 +02:00
scope - > definedType - > needInitialization = Type : : NeedInitialization : : True ;
2015-01-21 10:34:58 +01:00
}
} else {
// For C++, it is more difficult: Determine if user defined type needs initialization...
unsigned int unknowns = 0 ; // stop checking when there are no unknowns
unsigned int retry = 0 ; // bail if we don't resolve all the variable types for some reason
2010-12-02 07:35:01 +01:00
2015-01-21 10:34:58 +01:00
do {
unknowns = 0 ;
2013-07-08 11:45:26 +02:00
2015-01-21 10:34:58 +01:00
for ( std : : list < Scope > : : iterator it = scopeList . begin ( ) ; it ! = scopeList . end ( ) ; + + it ) {
2017-01-01 11:34:05 +01:00
Scope * scope = & ( * it ) ;
2010-12-02 07:35:01 +01:00
2015-01-21 10:34:58 +01:00
if ( ! scope - > definedType ) {
2019-09-25 15:25:19 +02:00
mBlankTypes . emplace_back ( ) ;
2018-06-16 20:33:07 +02:00
scope - > definedType = & mBlankTypes . back ( ) ;
2015-01-21 10:34:58 +01:00
}
2010-12-02 07:35:01 +01:00
2019-08-02 21:14:29 +02:00
if ( scope - > isClassOrStruct ( ) & & scope - > definedType - > needInitialization = = Type : : NeedInitialization : : Unknown ) {
2015-01-21 10:34:58 +01:00
// check for default constructor
bool hasDefaultConstructor = false ;
2011-01-15 07:59:37 +01:00
2015-01-21 10:34:58 +01:00
std : : list < Function > : : const_iterator func ;
2010-12-02 07:35:01 +01:00
2015-01-21 10:34:58 +01:00
for ( func = scope - > functionList . begin ( ) ; func ! = scope - > functionList . end ( ) ; + + func ) {
if ( func - > type = = Function : : eConstructor ) {
// check for no arguments: func ( )
if ( func - > argCount ( ) = = 0 ) {
hasDefaultConstructor = true ;
break ;
2010-12-02 07:35:01 +01:00
}
2015-01-21 10:34:58 +01:00
/** check for arguments with default values */
else if ( func - > argCount ( ) = = func - > initializedArgCount ( ) ) {
hasDefaultConstructor = true ;
break ;
}
}
2010-12-02 07:35:01 +01:00
}
2015-01-21 10:34:58 +01:00
// User defined types with user defined default constructor doesn't need initialization.
// We assume the default constructor initializes everything.
// Another check will figure out if the constructor actually initializes everything.
if ( hasDefaultConstructor )
2019-08-02 21:14:29 +02:00
scope - > definedType - > needInitialization = Type : : NeedInitialization : : False ;
2015-01-21 10:34:58 +01:00
// check each member variable to see if it needs initialization
else {
bool needInitialization = false ;
bool unknown = false ;
std : : list < Variable > : : const_iterator var ;
for ( var = scope - > varlist . begin ( ) ; var ! = scope - > varlist . end ( ) & & ! needInitialization ; + + var ) {
if ( var - > isClass ( ) ) {
if ( var - > type ( ) ) {
// does this type need initialization?
2019-08-02 21:14:29 +02:00
if ( var - > type ( ) - > needInitialization = = Type : : NeedInitialization : : True )
2015-01-21 10:34:58 +01:00
needInitialization = true ;
2019-08-02 21:14:29 +02:00
else if ( var - > type ( ) - > needInitialization = = Type : : NeedInitialization : : Unknown ) {
2019-01-31 16:53:51 +01:00
if ( ! ( var - > valueType ( ) & & var - > valueType ( ) - > type = = ValueType : : CONTAINER ) )
unknown = true ;
}
2015-01-21 10:34:58 +01:00
}
} else if ( ! var - > hasDefault ( ) )
needInitialization = true ;
}
2010-12-02 07:35:01 +01:00
if ( needInitialization )
2019-08-02 21:14:29 +02:00
scope - > definedType - > needInitialization = Type : : NeedInitialization : : True ;
2015-01-21 10:34:58 +01:00
else if ( ! unknown )
2019-08-02 21:14:29 +02:00
scope - > definedType - > needInitialization = Type : : NeedInitialization : : False ;
2017-09-12 22:20:07 +02:00
else {
2019-08-02 21:14:29 +02:00
if ( scope - > definedType - > needInitialization = = Type : : NeedInitialization : : Unknown )
2017-09-12 22:20:07 +02:00
unknowns + + ;
}
2015-01-21 10:34:58 +01:00
}
2019-08-02 21:14:29 +02:00
} else if ( scope - > type = = Scope : : eUnion & & scope - > definedType - > needInitialization = = Type : : NeedInitialization : : Unknown )
scope - > definedType - > needInitialization = Type : : NeedInitialization : : True ;
2015-01-21 10:34:58 +01:00
}
2010-12-02 07:35:01 +01:00
2015-01-21 10:34:58 +01:00
retry + + ;
} while ( unknowns & & retry < 100 ) ;
2010-12-02 07:35:01 +01:00
2015-01-21 10:34:58 +01:00
// this shouldn't happen so output a debug warning
2018-06-16 16:10:28 +02:00
if ( retry = = 100 & & mSettings - > debugwarnings ) {
2015-01-21 10:34:58 +01:00
for ( std : : list < Scope > : : iterator it = scopeList . begin ( ) ; it ! = scopeList . end ( ) ; + + it ) {
2017-01-01 11:34:05 +01:00
const Scope * scope = & ( * it ) ;
2010-12-02 07:35:01 +01:00
2019-08-02 21:14:29 +02:00
if ( scope - > isClassOrStruct ( ) & & scope - > definedType - > needInitialization = = Type : : NeedInitialization : : Unknown )
2015-01-21 10:34:58 +01:00
debugMessage ( scope - > classDef , " SymbolDatabase::SymbolDatabase couldn't resolve all user defined types. " ) ;
}
2010-12-02 07:35:01 +01:00
}
2010-11-13 08:08:45 +01:00
}
2017-01-01 11:34:05 +01:00
}
2011-02-26 21:57:16 +01:00
2017-01-01 11:34:05 +01:00
void SymbolDatabase : : createSymbolDatabaseVariableSymbolTable ( )
{
2011-02-26 21:57:16 +01:00
// create variable symbol table
2018-06-16 20:31:47 +02:00
mVariableList . resize ( mTokenizer - > varIdCount ( ) + 1 ) ;
std : : fill_n ( mVariableList . begin ( ) , mVariableList . size ( ) , ( const Variable * ) nullptr ) ;
2011-02-26 21:57:16 +01:00
// check all scopes for variables
2013-03-05 15:28:40 +01:00
for ( std : : list < Scope > : : iterator it = scopeList . begin ( ) ; it ! = scopeList . end ( ) ; + + it ) {
2017-01-01 11:34:05 +01:00
Scope * scope = & ( * it ) ;
2011-02-26 21:57:16 +01:00
// add all variables
2014-08-31 11:27:12 +02:00
for ( std : : list < Variable > : : iterator var = scope - > varlist . begin ( ) ; var ! = scope - > varlist . end ( ) ; + + var ) {
2018-05-29 13:24:48 +02:00
const unsigned int varId = var - > declarationId ( ) ;
2011-02-26 21:57:16 +01:00
if ( varId )
2018-06-16 20:31:47 +02:00
mVariableList [ varId ] = & ( * var ) ;
2013-08-12 06:21:03 +02:00
// fix up variables without type
2013-08-16 05:42:12 +02:00
if ( ! var - > type ( ) & & ! var - > typeStartToken ( ) - > isStandardType ( ) ) {
2013-08-12 06:21:03 +02:00
const Type * type = findType ( var - > typeStartToken ( ) , scope ) ;
if ( type )
var - > type ( type ) ;
}
2011-02-26 21:57:16 +01:00
}
2013-01-16 15:37:07 +01:00
// add all function parameters
2014-08-31 11:27:12 +02:00
for ( std : : list < Function > : : iterator func = scope - > functionList . begin ( ) ; func ! = scope - > functionList . end ( ) ; + + func ) {
for ( std : : list < Variable > : : iterator arg = func - > argumentList . begin ( ) ; arg ! = func - > argumentList . end ( ) ; + + arg ) {
2011-02-26 21:57:16 +01:00
// check for named parameters
2013-07-20 12:31:04 +02:00
if ( arg - > nameToken ( ) & & arg - > declarationId ( ) ) {
const unsigned int declarationId = arg - > declarationId ( ) ;
if ( declarationId > 0U )
2018-06-16 20:31:47 +02:00
mVariableList [ declarationId ] = & ( * arg ) ;
2013-08-12 06:21:03 +02:00
// fix up parameters without type
2013-08-16 05:42:12 +02:00
if ( ! arg - > type ( ) & & ! arg - > typeStartToken ( ) - > isStandardType ( ) ) {
2013-08-17 18:43:15 +02:00
const Type * type = findTypeInNested ( arg - > typeStartToken ( ) , scope ) ;
2013-08-12 06:21:03 +02:00
if ( type )
arg - > type ( type ) ;
}
2011-02-26 21:57:16 +01:00
}
}
}
}
2011-06-24 04:35:15 +02:00
2013-01-25 06:49:04 +01:00
// fill in missing variables if possible
2013-02-20 07:46:06 +01:00
const std : : size_t functions = functionScopes . size ( ) ;
for ( std : : size_t i = 0 ; i < functions ; + + i ) {
const Scope * func = functionScopes [ i ] ;
2018-04-27 22:36:30 +02:00
for ( const Token * tok = func - > bodyStart - > next ( ) ; tok & & tok ! = func - > bodyEnd ; tok = tok - > next ( ) ) {
2013-02-20 07:46:06 +01:00
// check for member variable
2014-08-12 08:02:54 +02:00
if ( tok - > varId ( ) & & tok - > next ( ) & &
2013-07-20 17:51:13 +02:00
( tok - > next ( ) - > str ( ) = = " . " | |
( tok - > next ( ) - > str ( ) = = " [ " & & tok - > linkAt ( 1 ) - > strAt ( 1 ) = = " . " ) ) ) {
const Token * tok1 = tok - > next ( ) - > str ( ) = = " . " ? tok - > tokAt ( 2 ) : tok - > linkAt ( 1 ) - > tokAt ( 2 ) ;
2019-06-30 21:39:22 +02:00
if ( tok1 & & tok1 - > varId ( ) & & mVariableList [ tok1 - > varId ( ) ] = = nullptr ) {
2018-06-16 20:31:47 +02:00
const Variable * var = mVariableList [ tok - > varId ( ) ] ;
2013-03-05 13:33:38 +01:00
if ( var & & var - > typeScope ( ) ) {
2013-02-20 07:46:06 +01:00
// find the member variable of this variable
2013-03-05 13:33:38 +01:00
const Variable * var1 = var - > typeScope ( ) - > getVariable ( tok1 - > str ( ) ) ;
2013-02-20 07:46:06 +01:00
if ( var1 ) {
// add this variable to the look up table
2018-06-16 20:31:47 +02:00
mVariableList [ tok1 - > varId ( ) ] = var1 ;
2013-01-25 06:49:04 +01:00
}
}
}
}
}
}
2017-01-01 11:34:05 +01:00
}
2013-01-25 06:49:04 +01:00
2017-01-01 11:34:05 +01:00
void SymbolDatabase : : createSymbolDatabaseSetScopePointers ( )
{
2014-11-01 14:36:17 +01:00
// Set scope pointers
for ( std : : list < Scope > : : iterator it = scopeList . begin ( ) ; it ! = scopeList . end ( ) ; + + it ) {
2018-04-27 22:36:30 +02:00
Token * start = const_cast < Token * > ( it - > bodyStart ) ;
Token * end = const_cast < Token * > ( it - > bodyEnd ) ;
2014-11-01 14:36:17 +01:00
if ( it - > type = = Scope : : eGlobal ) {
2018-06-16 16:10:28 +02:00
start = const_cast < Token * > ( mTokenizer - > list . front ( ) ) ;
end = const_cast < Token * > ( mTokenizer - > list . back ( ) ) ;
2014-11-01 14:36:17 +01:00
}
2019-05-07 10:28:31 +02:00
assert ( start ) ;
assert ( end ) ;
2017-09-20 23:06:19 +02:00
end - > scope ( & * it ) ;
for ( Token * tok = start ; tok ! = end ; tok = tok - > next ( ) ) {
if ( start ! = end & & tok - > str ( ) = = " { " ) {
bool isEndOfScope = false ;
for ( std : : list < Scope * > : : const_iterator innerScope = it - > nestedList . begin ( ) ; innerScope ! = it - > nestedList . end ( ) ; + + innerScope ) {
2018-04-27 22:36:30 +02:00
if ( tok = = ( * innerScope ) - > bodyStart ) { // Is begin of inner scope
2017-09-20 23:06:19 +02:00
tok = tok - > link ( ) ;
if ( tok - > next ( ) = = end | | ! tok - > next ( ) ) {
isEndOfScope = true ;
2014-11-01 14:36:17 +01:00
break ;
}
2017-09-20 23:06:19 +02:00
tok = tok - > next ( ) ;
2014-11-01 14:36:17 +01:00
break ;
2017-09-20 23:06:19 +02:00
}
2014-11-01 14:36:17 +01:00
}
2017-09-20 23:06:19 +02:00
if ( isEndOfScope )
break ;
2014-11-01 14:36:17 +01:00
}
2017-09-20 23:06:19 +02:00
tok - > scope ( & * it ) ;
2014-11-01 14:36:17 +01:00
}
}
2017-01-01 11:34:05 +01:00
}
2014-11-01 14:36:17 +01:00
2017-03-24 12:19:14 +01:00
void SymbolDatabase : : createSymbolDatabaseSetFunctionPointers ( bool firstPass )
2017-01-01 11:34:05 +01:00
{
2017-03-24 12:19:14 +01:00
if ( firstPass ) {
// Set function definition and declaration pointers
for ( std : : list < Scope > : : iterator it = scopeList . begin ( ) ; it ! = scopeList . end ( ) ; + + it ) {
for ( std : : list < Function > : : const_iterator func = it - > functionList . begin ( ) ; func ! = it - > functionList . end ( ) ; + + func ) {
if ( func - > tokenDef )
const_cast < Token * > ( func - > tokenDef ) - > function ( & * func ) ;
2014-11-01 14:36:17 +01:00
2017-03-24 12:19:14 +01:00
if ( func - > token )
const_cast < Token * > ( func - > token ) - > function ( & * func ) ;
}
2014-11-01 14:36:17 +01:00
}
}
// Set function call pointers
2018-06-16 16:10:28 +02:00
for ( const Token * tok = mTokenizer - > list . front ( ) ; tok ! = mTokenizer - > list . back ( ) ; tok = tok - > next ( ) ) {
2017-03-24 12:19:14 +01:00
if ( ! tok - > function ( ) & & tok - > varId ( ) = = 0 & & Token : : Match ( tok , " %name% ( " ) & & ! isReservedName ( tok - > str ( ) ) ) {
const Function * function = findFunction ( tok ) ;
if ( function )
const_cast < Token * > ( tok ) - > function ( function ) ;
2014-11-01 14:36:17 +01:00
}
}
2014-11-13 06:29:51 +01:00
// Set C++ 11 delegate constructor function call pointers
for ( std : : list < Scope > : : iterator it = scopeList . begin ( ) ; it ! = scopeList . end ( ) ; + + it ) {
for ( std : : list < Function > : : const_iterator func = it - > functionList . begin ( ) ; func ! = it - > functionList . end ( ) ; + + func ) {
// look for initializer list
2018-04-02 18:32:45 +02:00
if ( func - > isConstructor ( ) & & func - > functionScope & & func - > functionScope - > functionOf & & func - > arg ) {
2017-09-02 22:54:23 +02:00
const Token * tok = func - > arg - > link ( ) - > next ( ) ;
if ( tok - > str ( ) = = " noexcept " ) {
2017-09-06 17:00:23 +02:00
const Token * closingParenTok = tok - > linkAt ( 1 ) ;
if ( ! closingParenTok | | ! closingParenTok - > next ( ) ) {
2017-09-02 22:54:23 +02:00
continue ;
}
2017-09-06 17:00:23 +02:00
tok = closingParenTok - > next ( ) ;
2017-09-02 22:54:23 +02:00
}
if ( tok - > str ( ) ! = " : " ) {
continue ;
}
tok = tok - > next ( ) ;
2018-04-27 22:36:30 +02:00
while ( tok & & tok ! = func - > functionScope - > bodyStart ) {
2015-05-10 11:27:47 +02:00
if ( Token : : Match ( tok , " %name% {|( " ) ) {
2014-11-13 06:29:51 +01:00
if ( tok - > str ( ) = = func - > tokenDef - > str ( ) ) {
2016-04-22 06:02:54 +02:00
const Function * function = func - > functionScope - > functionOf - > findFunction ( tok ) ;
if ( function )
const_cast < Token * > ( tok ) - > function ( function ) ;
2014-11-13 06:29:51 +01:00
break ;
}
tok = tok - > linkAt ( 1 ) ;
}
tok = tok - > next ( ) ;
}
}
}
}
2017-01-01 11:34:05 +01:00
}
2014-11-13 06:29:51 +01:00
2017-01-01 11:34:05 +01:00
void SymbolDatabase : : createSymbolDatabaseSetTypePointers ( )
{
2018-05-09 13:48:55 +02:00
std : : set < std : : string > typenames ;
for ( const Type & t : typeList ) {
typenames . insert ( t . name ( ) ) ;
}
2015-08-14 20:46:13 +02:00
// Set type pointers
2018-06-16 16:10:28 +02:00
for ( const Token * tok = mTokenizer - > list . front ( ) ; tok ! = mTokenizer - > list . back ( ) ; tok = tok - > next ( ) ) {
2016-04-22 06:02:54 +02:00
if ( ! tok - > isName ( ) | | tok - > varId ( ) | | tok - > function ( ) | | tok - > type ( ) | | tok - > enumerator ( ) )
2015-08-14 20:46:13 +02:00
continue ;
2018-05-09 13:48:55 +02:00
if ( typenames . find ( tok - > str ( ) ) = = typenames . end ( ) )
continue ;
2016-04-22 06:02:54 +02:00
const Type * type = findVariableType ( tok - > scope ( ) , tok ) ;
if ( type )
const_cast < Token * > ( tok ) - > type ( type ) ;
2015-08-14 20:46:13 +02:00
}
2017-01-01 11:34:05 +01:00
}
2015-08-14 20:46:13 +02:00
2017-03-30 10:07:58 +02:00
void SymbolDatabase : : fixVarId ( VarIdMap & varIds , const Token * vartok , Token * membertok , const Variable * membervar )
{
VarIdMap : : iterator varId = varIds . find ( vartok - > varId ( ) ) ;
if ( varId = = varIds . end ( ) ) {
MemberIdMap memberId ;
if ( membertok - > varId ( ) = = 0 ) {
2018-06-16 16:10:28 +02:00
memberId [ membervar - > nameToken ( ) - > varId ( ) ] = const_cast < Tokenizer * > ( mTokenizer ) - > newVarId ( ) ;
2018-06-16 20:31:47 +02:00
mVariableList . push_back ( membervar ) ;
2017-03-30 10:07:58 +02:00
} else
2018-06-16 20:31:47 +02:00
mVariableList [ membertok - > varId ( ) ] = membervar ;
2017-03-30 10:07:58 +02:00
varIds . insert ( std : : make_pair ( vartok - > varId ( ) , memberId ) ) ;
varId = varIds . find ( vartok - > varId ( ) ) ;
}
MemberIdMap : : iterator memberId = varId - > second . find ( membervar - > nameToken ( ) - > varId ( ) ) ;
if ( memberId = = varId - > second . end ( ) ) {
if ( membertok - > varId ( ) = = 0 ) {
2018-06-16 16:10:28 +02:00
varId - > second . insert ( std : : make_pair ( membervar - > nameToken ( ) - > varId ( ) , const_cast < Tokenizer * > ( mTokenizer ) - > newVarId ( ) ) ) ;
2018-06-16 20:31:47 +02:00
mVariableList . push_back ( membervar ) ;
2017-09-06 17:02:27 +02:00
memberId = varId - > second . find ( membervar - > nameToken ( ) - > varId ( ) ) ;
2017-03-30 10:07:58 +02:00
} else
2018-06-16 20:31:47 +02:00
mVariableList [ membertok - > varId ( ) ] = membervar ;
2017-03-30 10:07:58 +02:00
}
if ( membertok - > varId ( ) = = 0 )
membertok - > varId ( memberId - > second ) ;
}
2017-01-01 11:34:05 +01:00
void SymbolDatabase : : createSymbolDatabaseSetVariablePointers ( )
{
2017-03-30 10:07:58 +02:00
VarIdMap varIds ;
2014-11-01 14:36:17 +01:00
// Set variable pointers
2018-06-16 16:10:28 +02:00
for ( const Token * tok = mTokenizer - > list . front ( ) ; tok ! = mTokenizer - > list . back ( ) ; tok = tok - > next ( ) ) {
2014-11-01 14:36:17 +01:00
if ( tok - > varId ( ) )
const_cast < Token * > ( tok ) - > variable ( getVariableFromVarId ( tok - > varId ( ) ) ) ;
// Set Token::variable pointer for array member variable
// Since it doesn't point at a fixed location it doesn't have varid
if ( tok - > variable ( ) ! = nullptr & &
2017-03-24 01:14:49 +01:00
( tok - > variable ( ) - > typeScope ( ) | | ( tok - > valueType ( ) & & tok - > valueType ( ) - > type = = ValueType : : CONTAINER ) ) & &
2015-01-31 10:50:39 +01:00
Token : : Match ( tok , " %name% [|. " ) ) {
2014-11-01 14:36:17 +01:00
Token * tok2 = tok - > next ( ) ;
// Locate "]"
2015-08-16 14:22:46 +02:00
while ( tok2 & & tok2 - > str ( ) = = " [ " )
tok2 = tok2 - > link ( ) - > next ( ) ;
2014-11-01 14:36:17 +01:00
Token * membertok = nullptr ;
2015-01-31 10:50:39 +01:00
if ( Token : : Match ( tok2 , " . %name% " ) )
2014-11-01 14:36:17 +01:00
membertok = tok2 - > next ( ) ;
2015-01-31 10:50:39 +01:00
else if ( Token : : Match ( tok2 , " ) . %name% " ) & & tok - > strAt ( - 1 ) = = " ( " )
2014-11-01 14:36:17 +01:00
membertok = tok2 - > tokAt ( 2 ) ;
if ( membertok ) {
const Variable * var = tok - > variable ( ) ;
if ( var & & var - > typeScope ( ) ) {
const Variable * membervar = var - > typeScope ( ) - > getVariable ( membertok - > str ( ) ) ;
2017-03-23 03:09:40 +01:00
if ( membervar ) {
2014-11-01 14:36:17 +01:00
membertok - > variable ( membervar ) ;
2018-06-16 20:31:47 +02:00
if ( membertok - > varId ( ) = = 0 | | mVariableList [ membertok - > varId ( ) ] = = nullptr )
2017-03-30 10:07:58 +02:00
fixVarId ( varIds , tok , const_cast < Token * > ( membertok ) , membervar ) ;
2017-03-23 03:09:40 +01:00
}
2017-03-24 01:14:49 +01:00
} else if ( var & & tok - > valueType ( ) & & tok - > valueType ( ) - > type = = ValueType : : CONTAINER ) {
if ( Token : : Match ( var - > typeStartToken ( ) , " std :: %type% < %type% *| *| > " ) ) {
const Type * type = var - > typeStartToken ( ) - > tokAt ( 4 ) - > type ( ) ;
if ( type & & type - > classScope & & type - > classScope - > definedType ) {
const Variable * membervar = type - > classScope - > getVariable ( membertok - > str ( ) ) ;
if ( membervar ) {
membertok - > variable ( membervar ) ;
2018-06-16 20:31:47 +02:00
if ( membertok - > varId ( ) = = 0 | | mVariableList [ membertok - > varId ( ) ] = = nullptr )
2017-03-30 10:07:58 +02:00
fixVarId ( varIds , tok , const_cast < Token * > ( membertok ) , membervar ) ;
2017-03-24 01:14:49 +01:00
}
}
}
2014-11-01 14:36:17 +01:00
}
}
}
// check for function returning record type
// func(...).var
// func(...)[...].var
else if ( tok - > function ( ) & & tok - > next ( ) - > str ( ) = = " ( " & &
2015-01-31 10:50:39 +01:00
( Token : : Match ( tok - > next ( ) - > link ( ) , " ) . %name% !!( " ) | |
( Token : : Match ( tok - > next ( ) - > link ( ) , " ) [ " ) & & Token : : Match ( tok - > next ( ) - > link ( ) - > next ( ) - > link ( ) , " ] . %name% !!( " ) ) ) ) {
2014-11-01 14:36:17 +01:00
const Type * type = tok - > function ( ) - > retType ;
if ( type ) {
Token * membertok ;
if ( tok - > next ( ) - > link ( ) - > next ( ) - > str ( ) = = " . " )
membertok = tok - > next ( ) - > link ( ) - > next ( ) - > next ( ) ;
else
membertok = tok - > next ( ) - > link ( ) - > next ( ) - > link ( ) - > next ( ) - > next ( ) ;
const Variable * membervar = membertok - > variable ( ) ;
if ( ! membervar ) {
if ( type - > classScope ) {
membervar = type - > classScope - > getVariable ( membertok - > str ( ) ) ;
2017-04-20 21:22:57 +02:00
if ( membervar ) {
2014-11-01 14:36:17 +01:00
membertok - > variable ( membervar ) ;
2018-06-16 20:31:47 +02:00
if ( membertok - > varId ( ) = = 0 | | mVariableList [ membertok - > varId ( ) ] = = nullptr ) {
2017-04-20 21:22:57 +02:00
if ( tok - > function ( ) - > retDef )
fixVarId ( varIds , tok - > function ( ) - > retDef , const_cast < Token * > ( membertok ) , membervar ) ;
}
}
2014-11-01 14:36:17 +01:00
}
}
}
}
}
2017-01-01 11:34:05 +01:00
}
2016-04-22 06:02:54 +02:00
2017-01-01 11:34:05 +01:00
void SymbolDatabase : : createSymbolDatabaseEnums ( )
{
2016-05-29 14:45:45 +02:00
// fill in enumerators in enum
for ( std : : list < Scope > : : iterator it = scopeList . begin ( ) ; it ! = scopeList . end ( ) ; + + it ) {
if ( it - > type ! = Scope : : eEnum )
continue ;
// add enumerators to enumerator tokens
2019-09-19 20:29:33 +02:00
for ( Enumerator & i : it - > enumeratorList )
const_cast < Token * > ( i . name ) - > enumerator ( & i ) ;
2016-05-29 14:45:45 +02:00
}
// fill in enumerator values
for ( std : : list < Scope > : : iterator it = scopeList . begin ( ) ; it ! = scopeList . end ( ) ; + + it ) {
if ( it - > type ! = Scope : : eEnum )
continue ;
MathLib : : bigint value = 0 ;
2019-09-19 20:29:33 +02:00
for ( Enumerator & enumerator : it - > enumeratorList ) {
2016-05-29 14:45:45 +02:00
// look for initialization tokens that can be converted to enumerators and convert them
if ( enumerator . start ) {
2017-05-25 09:50:14 +02:00
if ( ! enumerator . end )
2018-06-16 16:10:28 +02:00
mTokenizer - > syntaxError ( enumerator . start ) ;
2016-05-29 14:45:45 +02:00
for ( const Token * tok3 = enumerator . start ; tok3 & & tok3 ! = enumerator . end - > next ( ) ; tok3 = tok3 - > next ( ) ) {
if ( tok3 - > tokType ( ) = = Token : : eName ) {
const Enumerator * e = findEnumerator ( tok3 ) ;
if ( e )
const_cast < Token * > ( tok3 ) - > enumerator ( e ) ;
}
}
// look for possible constant folding expressions
2017-05-25 09:50:14 +02:00
// rhs of operator:
2019-06-16 10:09:38 +02:00
Token * rhs = enumerator . start - > previous ( ) - > astOperand2 ( ) ;
2017-05-25 09:50:14 +02:00
// constant folding of expression:
2018-06-16 16:10:28 +02:00
ValueFlow : : valueFlowConstantFoldAST ( rhs , mSettings ) ;
2017-05-25 09:50:14 +02:00
// get constant folded value:
2018-11-14 06:59:25 +01:00
if ( rhs & & rhs - > hasKnownIntValue ( ) ) {
2017-05-25 09:50:14 +02:00
enumerator . value = rhs - > values ( ) . front ( ) . intvalue ;
enumerator . value_known = true ;
value = enumerator . value + 1 ;
2016-05-29 14:45:45 +02:00
}
}
// not initialized so use default value
else {
enumerator . value = value + + ;
enumerator . value_known = true ;
}
}
}
2016-04-22 06:02:54 +02:00
// find enumerators
2018-06-16 16:10:28 +02:00
for ( const Token * tok = mTokenizer - > list . front ( ) ; tok ! = mTokenizer - > list . back ( ) ; tok = tok - > next ( ) ) {
2016-05-25 15:30:49 +02:00
if ( tok - > tokType ( ) ! = Token : : eName )
2016-04-22 06:02:54 +02:00
continue ;
const Enumerator * enumerator = findEnumerator ( tok ) ;
if ( enumerator )
const_cast < Token * > ( tok ) - > enumerator ( enumerator ) ;
}
2017-01-01 11:34:05 +01:00
}
2016-04-22 06:02:54 +02:00
2019-08-05 07:18:06 +02:00
void SymbolDatabase : : createSymbolDatabaseIncompleteVars ( )
{
const std : : set < std : : string > cpp20keywords = {
" alignas " ,
" alignof " ,
" axiom " ,
" co_await " ,
" co_return " ,
" co_yield " ,
" concept " ,
" synchronized " ,
" consteval " ,
" reflexpr " ,
" requires " ,
} ;
const std : : set < std : : string > cppkeywords = {
" asm " ,
" auto " ,
" catch " ,
" char " ,
" class " ,
" const " ,
" constexpr " ,
" decltype " ,
" default " ,
" do " ,
" enum " ,
" explicit " ,
" export " ,
" extern " ,
" final " ,
" friend " ,
" inline " ,
" mutable " ,
" namespace " ,
" new " ,
" noexcept " ,
" override " ,
" private " ,
" protected " ,
" public " ,
" register " ,
" sizeof " ,
" static " ,
" static_assert " ,
" struct " ,
" template " ,
" this " ,
" thread_local " ,
" throw " ,
" try " ,
" typedef " ,
" typeid " ,
" typename " ,
" union " ,
" using " ,
" virtual " ,
" void " ,
" volatile " ,
} ;
for ( const Token * tok = mTokenizer - > list . front ( ) ; tok ! = mTokenizer - > list . back ( ) ; tok = tok - > next ( ) ) {
const Scope * scope = tok - > scope ( ) ;
if ( ! scope )
continue ;
if ( ! scope - > isExecutable ( ) )
continue ;
if ( ! Token : : Match ( tok , " %name% " ) )
continue ;
if ( ! tok - > isNameOnly ( ) )
continue ;
if ( Token : : Match ( tok , " %var% " ) )
continue ;
if ( tok - > type ( ) )
continue ;
if ( Token : : Match ( tok - > next ( ) , " ::|.|(|:|%var% " ) )
continue ;
if ( Token : : Match ( tok - > next ( ) , " &|&&|* )|%var% " ) )
continue ;
if ( Token : : simpleMatch ( tok - > next ( ) , " ) " ) & & Token : : simpleMatch ( tok - > next ( ) - > link ( ) - > previous ( ) , " catch ( " ) )
continue ;
// Very likely a typelist
if ( Token : : Match ( tok - > tokAt ( - 2 ) , " %type% , " ) )
continue ;
// Inside template brackets
if ( Token : : Match ( tok - > next ( ) , " <|> " ) & & tok - > next ( ) - > link ( ) )
continue ;
if ( Token : : simpleMatch ( tok - > previous ( ) , " < " ) & & tok - > previous ( ) - > link ( ) )
continue ;
// Skip goto labels
if ( Token : : simpleMatch ( tok - > previous ( ) , " goto " ) )
continue ;
if ( cppkeywords . count ( tok - > str ( ) ) > 0 )
continue ;
if ( mSettings - > standards . cpp > = Standards : : CPP20 & & cpp20keywords . count ( tok - > str ( ) ) > 0 )
continue ;
const_cast < Token * > ( tok ) - > isIncompleteVar ( true ) ;
}
}
2019-08-08 07:46:47 +02:00
void SymbolDatabase : : createSymbolDatabaseEscapeFunctions ( )
{
for ( Scope & scope : scopeList ) {
if ( scope . type ! = Scope : : eFunction )
continue ;
Function * function = scope . function ;
if ( ! function )
continue ;
function - > isEscapeFunction ( isReturnScope ( scope . bodyEnd , mSettings , true ) ) ;
}
}
2019-03-15 19:00:42 +01:00
void SymbolDatabase : : setArrayDimensionsUsingValueFlow ( )
2017-01-01 11:34:05 +01:00
{
2016-04-22 06:02:54 +02:00
// set all unknown array dimensions
2019-03-14 19:57:58 +01:00
for ( const Variable * var : mVariableList ) {
2016-04-22 06:02:54 +02:00
// check each array variable
2019-03-14 19:57:58 +01:00
if ( ! var | | ! var - > isArray ( ) )
2019-03-14 19:53:45 +01:00
continue ;
// check each array dimension
2019-03-14 19:57:58 +01:00
for ( const Dimension & const_dimension : var - > dimensions ( ) ) {
Dimension & dimension = const_cast < Dimension & > ( const_dimension ) ;
2019-03-15 19:00:42 +01:00
if ( dimension . num ! = 0 | | ! dimension . tok )
2019-03-14 19:53:45 +01:00
continue ;
dimension . known = false ;
2019-03-15 19:00:42 +01:00
// check for a single token dimension
if ( dimension . tok - > hasKnownIntValue ( ) ) {
dimension . known = true ;
dimension . num = dimension . tok - > getKnownIntValue ( ) ;
continue ;
2016-04-22 06:02:54 +02:00
}
2019-03-14 19:53:45 +01:00
2019-03-15 19:00:42 +01:00
else if ( dimension . tok - > valueType ( ) & & dimension . tok - > valueType ( ) - > pointer = = 0 ) {
int bits = 0 ;
switch ( dimension . tok - > valueType ( ) - > type ) {
case ValueType : : Type : : CHAR :
bits = mSettings - > char_bit ;
break ;
case ValueType : : Type : : SHORT :
bits = mSettings - > short_bit ;
break ;
case ValueType : : Type : : INT :
bits = mSettings - > int_bit ;
break ;
case ValueType : : Type : : LONG :
bits = mSettings - > long_bit ;
break ;
case ValueType : : Type : : LONGLONG :
bits = mSettings - > long_long_bit ;
break ;
default :
break ;
} ;
2019-03-14 19:53:45 +01:00
2019-06-15 13:23:21 +02:00
if ( bits > 0 & & bits < = 62 ) {
2019-03-16 19:41:13 +01:00
if ( dimension . tok - > valueType ( ) - > sign = = ValueType : : Sign : : UNSIGNED )
2019-03-15 19:00:42 +01:00
dimension . num = 1LL < < bits ;
2019-03-16 19:41:13 +01:00
else
dimension . num = 1LL < < ( bits - 1 ) ;
2019-03-14 19:53:45 +01:00
}
}
2016-04-22 06:02:54 +02:00
}
}
2010-11-13 08:08:45 +01:00
}
2014-11-02 10:36:52 +01:00
SymbolDatabase : : ~ SymbolDatabase ( )
{
2015-08-14 20:46:13 +02:00
// Clear scope, type, function and variable pointers
2018-06-16 16:10:28 +02:00
for ( const Token * tok = mTokenizer - > list . front ( ) ; tok ; tok = tok - > next ( ) ) {
2017-08-09 20:00:26 +02:00
const_cast < Token * > ( tok ) - > scope ( nullptr ) ;
const_cast < Token * > ( tok ) - > type ( nullptr ) ;
const_cast < Token * > ( tok ) - > function ( nullptr ) ;
const_cast < Token * > ( tok ) - > variable ( nullptr ) ;
const_cast < Token * > ( tok ) - > enumerator ( nullptr ) ;
const_cast < Token * > ( tok ) - > setValueType ( nullptr ) ;
2014-11-02 10:36:52 +01:00
}
}
2016-07-17 15:47:32 +02:00
bool SymbolDatabase : : isFunction ( const Token * tok , const Scope * outerScope , const Token * * funcStart , const Token * * argStart , const Token * * declEnd ) const
2010-11-13 08:08:45 +01:00
{
2014-09-29 13:05:51 +02:00
if ( tok - > varId ( ) )
return false ;
2015-01-31 10:50:39 +01:00
// function returning function pointer? '... ( ... %name% ( ... ))( ... ) {'
2018-01-24 09:51:22 +01:00
// function returning reference to array '... ( & %name% ( ... ))[ ... ] {'
2018-04-25 18:48:26 +02:00
// TODO: Activate this again
if ( false & & tok - > str ( ) = = " ( " & & tok - > strAt ( 1 ) ! = " * " & &
2018-01-24 09:51:22 +01:00
( tok - > link ( ) - > previous ( ) - > str ( ) = = " ) " | | Token : : simpleMatch ( tok - > link ( ) - > tokAt ( - 2 ) , " ) const " ) ) ) {
2014-04-01 10:13:00 +02:00
const Token * tok2 = tok - > link ( ) - > next ( ) ;
if ( tok2 & & tok2 - > str ( ) = = " ( " & & Token : : Match ( tok2 - > link ( ) - > next ( ) , " {|;|const|= " ) ) {
2018-01-24 09:51:22 +01:00
const Token * argStartTok ;
if ( tok - > link ( ) - > previous ( ) - > str ( ) = = " const " )
argStartTok = tok - > link ( ) - > linkAt ( - 2 ) ;
else
argStartTok = tok - > link ( ) - > linkAt ( - 1 ) ;
2014-11-30 13:00:27 +01:00
* funcStart = argStartTok - > previous ( ) ;
* argStart = argStartTok ;
2016-07-17 15:47:32 +02:00
* declEnd = Token : : findmatch ( tok2 - > link ( ) - > next ( ) , " {|; " ) ;
2014-04-01 10:13:00 +02:00
return true ;
2018-01-24 09:51:22 +01:00
} 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 ;
}
2014-04-01 10:13:00 +02:00
}
2010-11-13 08:08:45 +01:00
}
// regular function?
2015-05-26 00:28:08 +02:00
else if ( Token : : Match ( tok , " %name% ( " ) & & ! isReservedName ( tok - > str ( ) ) & & tok - > previous ( ) & &
2016-11-18 22:01:15 +01:00
( Token : : Match ( tok - > previous ( ) , " %name%|>|&|*|::|~ " ) | | // Either a return type or scope qualifier in front of tok
2017-10-15 11:49:36 +02:00
outerScope - > isClassOrStructOrUnion ( ) ) ) { // or a ctor/dtor
2015-02-24 06:11:31 +01:00
const Token * tok1 = tok - > previous ( ) ;
2016-07-17 15:47:32 +02:00
const Token * tok2 = tok - > next ( ) - > link ( ) - > next ( ) ;
2015-02-24 06:11:31 +01:00
2018-06-16 16:10:28 +02:00
if ( ! mTokenizer - > isFunctionHead ( tok - > next ( ) , " ;:{ " ) )
2018-04-27 10:24:02 +02:00
return false ;
2015-02-24 06:11:31 +01:00
// skip over destructor "~"
if ( tok1 - > str ( ) = = " ~ " )
tok1 = tok1 - > previous ( ) ;
// skip over qualification
while ( Token : : simpleMatch ( tok1 , " :: " ) ) {
2016-12-06 22:11:40 +01:00
tok1 = tok1 - > previous ( ) ;
if ( Token : : Match ( tok1 , " %name% " ) )
tok1 = tok1 - > previous ( ) ;
else if ( tok1 & & tok1 - > str ( ) = = " > " & & tok1 - > link ( ) & & Token : : Match ( tok1 - > link ( ) - > previous ( ) , " %name% " ) )
tok1 = tok1 - > link ( ) - > tokAt ( - 2 ) ;
2015-02-24 06:11:31 +01:00
}
2018-05-10 07:40:01 +02:00
// skip over const, noexcept, throw, override, final and volatile specifiers
2018-12-13 06:34:10 +01:00
while ( Token : : Match ( tok2 , " const|noexcept|throw|override|final|volatile|&|&& " ) ) {
2016-07-17 15:47:32 +02:00
tok2 = tok2 - > next ( ) ;
if ( tok2 & & tok2 - > str ( ) = = " ( " )
tok2 = tok2 - > link ( ) - > next ( ) ;
}
2018-12-13 06:34:10 +01:00
// skip over trailing return type
2016-07-17 15:47:32 +02:00
if ( tok2 & & tok2 - > str ( ) = = " . " ) {
for ( tok2 = tok2 - > next ( ) ; tok2 ; tok2 = tok2 - > next ( ) ) {
2018-12-13 06:34:10 +01:00
if ( Token : : Match ( tok2 , " ;|{|=|override|final " ) )
2016-07-17 15:47:32 +02:00
break ;
if ( tok2 - > link ( ) & & Token : : Match ( tok2 , " <|[|( " ) )
tok2 = tok2 - > link ( ) ;
}
}
2015-04-04 11:33:25 +02:00
// done if constructor or destructor
if ( ! Token : : Match ( tok1 , " {|}|;|public:|protected:|private: " ) & & tok1 ) {
// skip over pointers and references
2018-04-29 15:35:31 +02:00
while ( Token : : Match ( tok1 , " %type%|*|& " ) & & ! endsWith ( tok1 - > str ( ) , ' : ' ) & & ( ! isReservedName ( tok1 - > str ( ) ) | | tok1 - > str ( ) = = " const " ) )
2016-12-06 22:11:40 +01:00
tok1 = tok1 - > previous ( ) ;
2015-02-24 06:11:31 +01:00
2015-04-04 11:33:25 +02:00
// skip over template
if ( tok1 & & tok1 - > str ( ) = = " > " ) {
if ( tok1 - > link ( ) )
tok1 = tok1 - > link ( ) - > previous ( ) ;
else
return false ;
}
2015-02-24 06:11:31 +01:00
2015-04-04 11:33:25 +02:00
// function can't have number or variable as return type
if ( tok1 & & ( tok1 - > isNumber ( ) | | tok1 - > varId ( ) ) )
2015-02-28 16:07:43 +01:00
return false ;
2015-02-24 06:11:31 +01:00
2015-04-04 11:33:25 +02:00
// skip over return type
if ( Token : : Match ( tok1 , " %name% " ) ) {
if ( tok1 - > str ( ) = = " return " )
return false ;
tok1 = tok1 - > previous ( ) ;
}
2015-02-24 06:11:31 +01:00
2015-04-04 11:33:25 +02:00
// skip over qualification
while ( Token : : simpleMatch ( tok1 , " :: " ) ) {
2016-12-06 22:11:40 +01:00
tok1 = tok1 - > previous ( ) ;
if ( Token : : Match ( tok1 , " %name% " ) )
tok1 = tok1 - > previous ( ) ;
2018-05-01 07:32:19 +02:00
else if ( tok1 & & tok1 - > str ( ) = = " > " & & tok1 - > link ( ) & & Token : : Match ( tok1 - > link ( ) - > previous ( ) , " %name% " ) )
tok1 = tok1 - > link ( ) - > tokAt ( - 2 ) ;
2015-04-04 11:33:25 +02:00
}
// skip over modifiers and other stuff
2017-02-20 23:09:35 +01:00
while ( Token : : Match ( tok1 , " const|static|extern|template|virtual|struct|class|enum|%name% " ) ) {
// friend type func(); is not a function
if ( isCPP ( ) & & tok1 - > str ( ) = = " friend " & & tok2 - > str ( ) = = " ; " )
return false ;
2015-04-04 11:33:25 +02:00
tok1 = tok1 - > previous ( ) ;
2017-02-20 23:09:35 +01:00
}
2015-02-24 06:11:31 +01:00
2015-04-04 11:33:25 +02:00
// should be at a sequence point if this is a function
if ( ! Token : : Match ( tok1 , " >|{|}|;|public:|protected:|private: " ) & & tok1 )
return false ;
}
2015-02-24 06:11:31 +01:00
2014-04-10 16:17:10 +02:00
if ( tok2 & &
2016-07-17 15:47:32 +02:00
( Token : : Match ( tok2 , " ;|{|= " ) | |
2015-01-31 10:50:39 +01:00
( tok2 - > isUpperCaseName ( ) & & Token : : Match ( tok2 , " %name% ;|{ " ) ) | |
( tok2 - > isUpperCaseName ( ) & & Token : : Match ( tok2 , " %name% ( " ) & & tok2 - > next ( ) - > link ( ) - > strAt ( 1 ) = = " { " ) | |
Token : : Match ( tok2 , " : ::| %name% (|::|<|{ " ) | |
2016-07-17 15:47:32 +02:00
Token : : Match ( tok2 , " &|&&| ;|{ " ) | |
Token : : Match ( tok2 , " = delete|default ; " ) ) ) {
2014-03-31 20:33:01 +02:00
* funcStart = tok ;
* argStart = tok - > next ( ) ;
2016-07-17 15:47:32 +02:00
* declEnd = Token : : findmatch ( tok2 , " {|; " ) ;
2014-03-31 20:33:01 +02:00
return true ;
}
2010-11-13 08:08:45 +01:00
}
2014-04-13 13:05:30 +02:00
// UNKNOWN_MACRO(a,b) { ... }
else if ( outerScope - > type = = Scope : : eGlobal & &
2015-01-31 10:50:39 +01:00
Token : : Match ( tok , " %name% ( " ) & &
2014-04-13 13:05:30 +02:00
tok - > isUpperCaseName ( ) & &
2014-05-18 20:39:52 +02:00
Token : : simpleMatch ( tok - > linkAt ( 1 ) , " ) { " ) & &
2014-04-13 13:05:30 +02:00
( ! tok - > previous ( ) | | Token : : Match ( tok - > previous ( ) , " [;{}] " ) ) ) {
* funcStart = tok ;
* argStart = tok - > next ( ) ;
2016-07-17 15:47:32 +02:00
* declEnd = tok - > linkAt ( 1 ) - > next ( ) ;
2014-04-13 13:05:30 +02:00
return true ;
}
2013-01-04 10:35:24 +01:00
// template constructor?
2015-01-31 10:50:39 +01:00
else if ( Token : : Match ( tok , " %name% < " ) & & Token : : simpleMatch ( tok - > next ( ) - > link ( ) , " > ( " ) ) {
2014-04-01 10:13:00 +02:00
const Token * tok2 = tok - > next ( ) - > link ( ) - > next ( ) - > link ( ) ;
if ( Token : : Match ( tok2 , " ) const| ;|{|= " ) | |
2015-01-31 10:50:39 +01:00
Token : : Match ( tok2 , " ) : ::| %name% (|::|<|{ " ) | |
2016-12-06 22:11:40 +01:00
Token : : Match ( tok2 , " ) const| noexcept {|;|( " ) ) {
2014-04-01 10:13:00 +02:00
* funcStart = tok ;
* argStart = tok2 - > link ( ) ;
2016-07-17 15:47:32 +02:00
* declEnd = Token : : findmatch ( tok2 - > next ( ) , " {|; " ) ;
2014-04-01 10:13:00 +02:00
return true ;
}
2013-01-04 10:35:24 +01:00
}
2017-01-06 11:53:17 +01:00
// regular C function with missing return or invalid C++ ?
else if ( Token : : Match ( tok , " %name% ( " ) & & ! isReservedName ( tok - > str ( ) ) & &
Token : : simpleMatch ( tok - > linkAt ( 1 ) , " ) { " ) & &
( ! tok - > previous ( ) | | Token : : Match ( tok - > previous ( ) , " ;|} " ) ) ) {
2018-06-16 16:10:28 +02:00
if ( mTokenizer - > isC ( ) ) {
2017-01-06 11:53:17 +01:00
debugMessage ( tok , " SymbolDatabase::isFunction found C function ' " + tok - > str ( ) + " ' without a return type. " ) ;
* funcStart = tok ;
* argStart = tok - > next ( ) ;
* declEnd = tok - > linkAt ( 1 ) - > next ( ) ;
return true ;
}
2018-06-16 16:10:28 +02:00
mTokenizer - > syntaxError ( tok ) ;
2017-01-06 11:53:17 +01:00
}
2010-11-13 08:08:45 +01:00
return false ;
}
2016-02-03 17:08:46 +01:00
void SymbolDatabase : : validateExecutableScopes ( ) const
2015-12-05 20:55:26 +01:00
{
2016-02-03 17:08:46 +01:00
const std : : size_t functions = functionScopes . size ( ) ;
for ( std : : size_t i = 0 ; i < functions ; + + i ) {
const Scope * const scope = functionScopes [ i ] ;
const Function * const function = scope - > function ;
if ( scope - > isExecutable ( ) & & ! function ) {
const std : : list < const Token * > callstack ( 1 , scope - > classDef ) ;
const std : : string msg = std : : string ( " Executable scope ' " ) + scope - > classDef - > str ( ) + " ' with unknown function. " ;
2018-06-16 16:10:28 +02:00
const ErrorLogger : : ErrorMessage errmsg ( callstack , & mTokenizer - > list , Severity : : debug ,
2016-02-03 17:08:46 +01:00
" symbolDatabaseWarning " ,
msg ,
false ) ;
2018-06-16 16:10:28 +02:00
mErrorLogger - > reportErr ( errmsg ) ;
2016-02-03 17:08:46 +01:00
}
}
}
2015-12-06 08:14:04 +01:00
2016-02-03 21:52:02 +01:00
namespace {
const Function * getFunctionForArgumentvariable ( const Variable * const var , const std : : vector < const Scope * > & functionScopes )
{
const std : : size_t functions = functionScopes . size ( ) ;
for ( std : : size_t i = 0 ; i < functions ; + + i ) {
const Scope * const scope = functionScopes [ i ] ;
const Function * const function = scope - > function ;
if ( function ) {
for ( std : : size_t arg = 0 ; arg < function - > argCount ( ) ; + + arg ) {
if ( var = = function - > getArgumentVar ( arg ) )
return function ;
}
}
}
return nullptr ;
}
}
2016-02-03 17:08:46 +01:00
void SymbolDatabase : : validateVariables ( ) const
{
2018-06-16 20:31:47 +02:00
for ( std : : vector < const Variable * > : : const_iterator iter = mVariableList . begin ( ) ; iter ! = mVariableList . end ( ) ; + + iter ) {
2017-08-28 17:15:15 +02:00
const Variable * const var = * iter ;
if ( var ) {
2016-02-03 21:52:02 +01:00
if ( ! var - > scope ( ) ) {
const Function * function = getFunctionForArgumentvariable ( var , functionScopes ) ;
if ( ! var - > isArgument ( ) | | ( function & & function - > hasBody ( ) ) ) {
throw InternalError ( var - > nameToken ( ) , " Analysis failed (variable without scope). If the code is valid then please report this failure. " , InternalError : : INTERNAL ) ;
//std::cout << "!!!Variable found without scope: " << var->nameToken()->str() << std::endl;
}
}
2015-12-05 20:55:26 +01:00
}
}
}
2016-02-03 17:08:46 +01:00
void SymbolDatabase : : validate ( ) const
{
2018-06-16 16:10:28 +02:00
if ( mSettings - > debugwarnings ) {
2016-02-03 17:08:46 +01:00
validateExecutableScopes ( ) ;
}
//validateVariables();
}
2018-06-20 10:00:15 +02:00
Variable : : ~ Variable ( )
{
delete mValueType ;
}
2015-08-29 00:09:33 +02:00
bool Variable : : isPointerArray ( ) const
{
2015-08-28 23:06:39 +02:00
return isArray ( ) & & nameToken ( ) & & nameToken ( ) - > previous ( ) & & ( nameToken ( ) - > previous ( ) - > str ( ) = = " * " ) ;
}
2014-10-16 09:11:09 +02:00
const Token * Variable : : declEndToken ( ) const
{
Token const * declEnd = typeStartToken ( ) ;
while ( declEnd & & ! Token : : Match ( declEnd , " [;,)={] " ) ) {
if ( declEnd - > link ( ) & & Token : : Match ( declEnd , " (|[ " ) )
declEnd = declEnd - > link ( ) ;
declEnd = declEnd - > next ( ) ;
}
return declEnd ;
}
2018-06-20 10:00:15 +02:00
void Variable : : evaluate ( const Settings * settings )
2012-05-11 17:56:47 +02:00
{
2018-06-20 10:00:15 +02:00
const Library * const lib = settings ? & settings - > library : nullptr ;
2018-04-12 20:23:34 +02:00
2018-06-16 15:57:16 +02:00
if ( mNameToken )
2019-03-15 19:00:42 +01:00
setFlag ( fIsArray , arrayDimensions ( settings ) ) ;
2015-08-25 21:19:19 +02:00
2018-06-20 10:00:15 +02:00
if ( mTypeStartToken )
setValueType ( ValueType : : parseDecl ( mTypeStartToken , settings ) ) ;
2018-06-16 16:03:36 +02:00
const Token * tok = mTypeStartToken ;
2012-05-15 21:03:43 +02:00
while ( tok & & tok - > previous ( ) & & tok - > previous ( ) - > isName ( ) )
2012-05-11 17:56:47 +02:00
tok = tok - > previous ( ) ;
2018-06-16 16:03:36 +02:00
const Token * end = mTypeEndToken ;
2017-05-07 09:03:30 +02:00
if ( end )
end = end - > next ( ) ;
while ( tok ! = end ) {
2012-05-11 17:56:47 +02:00
if ( tok - > str ( ) = = " static " )
setFlag ( fIsStatic , true ) ;
2012-06-22 11:23:50 +02:00
else if ( tok - > str ( ) = = " extern " )
setFlag ( fIsExtern , true ) ;
2016-07-18 12:43:23 +02:00
else if ( tok - > str ( ) = = " volatile " )
setFlag ( fIsVolatile , true ) ;
2012-05-11 17:56:47 +02:00
else if ( tok - > str ( ) = = " mutable " )
setFlag ( fIsMutable , true ) ;
2018-06-20 10:00:15 +02:00
else if ( tok - > str ( ) = = " const " )
2012-05-11 17:56:47 +02:00
setFlag ( fIsConst , true ) ;
2018-06-20 10:00:15 +02:00
else if ( tok - > str ( ) = = " * " ) {
2015-08-25 21:19:19 +02:00
setFlag ( fIsPointer , ! isArray ( ) | | Token : : Match ( tok - > previous ( ) , " ( * %name% ) " ) ) ;
2012-05-11 17:56:47 +02:00
setFlag ( fIsConst , false ) ; // Points to const, isn't necessarily const itself
2013-04-04 18:47:44 +02:00
} else if ( tok - > str ( ) = = " & " ) {
if ( isReference ( ) )
setFlag ( fIsRValueRef , true ) ;
2012-05-11 17:56:47 +02:00
setFlag ( fIsReference , true ) ;
2013-04-04 18:47:44 +02:00
} else if ( tok - > str ( ) = = " && " ) { // Before simplification, && isn't split up
setFlag ( fIsRValueRef , true ) ;
setFlag ( fIsReference , true ) ; // Set also fIsReference
}
2012-05-14 21:47:02 +02:00
2013-04-15 22:48:28 +02:00
if ( tok - > str ( ) = = " < " & & tok - > link ( ) )
tok = tok - > link ( ) ;
2012-05-14 21:47:02 +02:00
else
tok = tok - > next ( ) ;
2012-05-11 17:56:47 +02:00
}
2018-06-16 16:03:36 +02:00
while ( Token : : Match ( mTypeStartToken , " static|const|volatile %any% " ) )
mTypeStartToken = mTypeStartToken - > next ( ) ;
while ( mTypeEndToken & & mTypeEndToken - > previous ( ) & & Token : : Match ( mTypeEndToken , " const|volatile " ) )
mTypeEndToken = mTypeEndToken - > previous ( ) ;
2012-06-08 18:05:02 +02:00
2018-06-16 16:03:36 +02:00
if ( mTypeStartToken ) {
std : : string strtype = mTypeStartToken - > str ( ) ;
for ( const Token * typeToken = mTypeStartToken ; Token : : Match ( typeToken , " %type% :: %type% " ) ; typeToken = typeToken - > tokAt ( 2 ) )
2015-11-15 17:51:27 +01:00
strtype + = " :: " + typeToken - > strAt ( 2 ) ;
2019-09-04 08:07:30 +02:00
setFlag ( fIsClass , ! lib - > podtype ( strtype ) & & ! mTypeStartToken - > isStandardType ( ) & & ! isEnumType ( ) & & ! isPointer ( ) & & ! isReference ( ) & & strtype ! = " ... " ) ;
2018-06-16 16:03:36 +02:00
setFlag ( fIsStlType , Token : : simpleMatch ( mTypeStartToken , " std :: " ) ) ;
setFlag ( fIsStlString , isStlType ( ) & & ( Token : : Match ( mTypeStartToken - > tokAt ( 2 ) , " string|wstring|u16string|u32string !!:: " ) | | ( Token : : simpleMatch ( mTypeStartToken - > tokAt ( 2 ) , " basic_string < " ) & & ! Token : : simpleMatch ( mTypeStartToken - > linkAt ( 3 ) , " > :: " ) ) ) ) ;
2019-04-26 11:30:09 +02:00
setFlag ( fIsSmartPointer , lib - > isSmartPointer ( mTypeStartToken ) ) ;
2014-01-28 15:44:56 +01:00
}
2019-07-23 14:29:02 +02:00
if ( mAccess = = AccessControl : : Argument ) {
2018-06-16 15:57:16 +02:00
tok = mNameToken ;
2012-12-29 08:32:43 +01:00
if ( ! tok ) {
// Argument without name
2018-06-16 16:03:36 +02:00
tok = mTypeEndToken ;
2012-12-29 08:32:43 +01:00
// back up to start of array dimensions
while ( tok & & tok - > str ( ) = = " ] " )
tok = tok - > link ( ) - > previous ( ) ;
// add array dimensions if present
2013-03-12 15:42:00 +01:00
if ( tok & & tok - > next ( ) - > str ( ) = = " [ " )
2019-03-15 19:00:42 +01:00
setFlag ( fIsArray , arrayDimensions ( settings ) ) ;
2012-12-29 08:32:43 +01:00
}
2012-09-06 20:50:46 +02:00
if ( ! tok )
return ;
tok = tok - > next ( ) ;
2012-05-11 17:56:47 +02:00
while ( tok - > str ( ) = = " [ " )
tok = tok - > link ( ) ;
setFlag ( fHasDefault , tok - > str ( ) = = " = " ) ;
}
2013-02-18 06:33:53 +01:00
// check for C++11 member initialization
2018-06-16 20:29:17 +02:00
if ( mScope & & mScope - > isClassOrStruct ( ) ) {
2014-10-12 15:06:07 +02:00
// type var = x or
// type var = {x}
2013-02-18 06:33:53 +01:00
// type var = x; gets simplified to: type var ; var = x ;
2014-10-16 09:11:09 +02:00
Token const * declEnd = declEndToken ( ) ;
2018-06-16 15:57:16 +02:00
if ( ( Token : : Match ( declEnd , " ; %name% = " ) & & declEnd - > strAt ( 1 ) = = mNameToken - > str ( ) ) | |
2014-10-16 09:11:09 +02:00
Token : : Match ( declEnd , " =|{ " ) )
2013-02-18 06:33:53 +01:00
setFlag ( fHasDefault , true ) ;
}
2014-08-09 11:44:55 +02:00
2018-06-16 16:03:36 +02:00
if ( mTypeStartToken ) {
if ( Token : : Match ( mTypeStartToken , " float|double " ) )
2014-08-09 11:44:55 +02:00
setFlag ( fIsFloatType , true ) ;
}
2012-05-11 17:56:47 +02:00
}
2018-06-20 10:00:15 +02:00
void Variable : : setValueType ( const ValueType & valueType )
{
delete mValueType ;
mValueType = new ValueType ( valueType ) ;
if ( ( mValueType - > pointer > 0 ) & & ( ! isArray ( ) | | Token : : Match ( mNameToken - > previous ( ) , " ( * %name% ) " ) ) )
setFlag ( fIsPointer , true ) ;
setFlag ( fIsConst , mValueType - > constness & ( 1U < < mValueType - > pointer ) ) ;
2019-07-09 17:32:19 +02:00
if ( mValueType - > smartPointerType )
setFlag ( fIsSmartPointer , true ) ;
2018-06-20 10:00:15 +02:00
}
2019-07-07 21:52:49 +02:00
const Type * Variable : : smartPointerType ( ) const
{
if ( ! isSmartPointer ( ) )
return nullptr ;
2019-07-09 17:32:19 +02:00
if ( mValueType - > smartPointerType )
return mValueType - > smartPointerType ;
2019-07-07 21:52:49 +02:00
// TODO: Cache result
const Token * ptrType = typeStartToken ( ) ;
while ( Token : : Match ( ptrType , " %name%|:: " ) )
ptrType = ptrType - > next ( ) ;
if ( Token : : Match ( ptrType , " < %name% > " ) )
return ptrType - > next ( ) - > type ( ) ;
return nullptr ;
}
2019-07-24 09:59:01 +02:00
Function : : Function ( const Tokenizer * mTokenizer ,
const Token * tok ,
const Scope * scope ,
const Token * tokDef ,
const Token * tokArgDef )
2018-04-25 12:05:49 +02:00
: tokenDef ( tokDef ) ,
argDef ( tokArgDef ) ,
token ( nullptr ) ,
arg ( nullptr ) ,
retDef ( nullptr ) ,
retType ( nullptr ) ,
functionScope ( nullptr ) ,
nestedIn ( scope ) ,
initArgCount ( 0 ) ,
type ( eFunction ) ,
2019-07-23 14:29:02 +02:00
access ( AccessControl : : Public ) ,
2018-04-25 12:05:49 +02:00
noexceptArg ( nullptr ) ,
throwArg ( nullptr ) ,
2019-07-24 09:59:01 +02:00
templateDef ( nullptr ) ,
2018-06-16 23:11:45 +02:00
mFlags ( 0 )
2018-04-25 12:05:49 +02:00
{
// operator function
if ( tokenDef - > isOperatorKeyword ( ) ) {
isOperator ( true ) ;
// 'operator =' is special
if ( tokenDef - > str ( ) = = " operator= " )
type = Function : : eOperatorEqual ;
}
2019-07-05 12:30:42 +02:00
else if ( tokenDef - > str ( ) = = " [ " ) {
type = Function : : eLambda ;
}
2018-04-25 12:05:49 +02:00
// class constructor/destructor
else if ( tokenDef - > str ( ) = = scope - > className ) {
// destructor
if ( tokenDef - > previous ( ) - > str ( ) = = " ~ " )
type = Function : : eDestructor ;
// constructor of any kind
else
type = Function : : eConstructor ;
isExplicit ( tokenDef - > previous ( ) - > str ( ) = = " explicit " ) ;
}
const Token * tok1 = tok ;
// look for end of previous statement
while ( tok1 - > previous ( ) & & ! Token : : Match ( tok1 - > previous ( ) , " ;|}|{|public:|protected:|private: " ) ) {
tok1 = tok1 - > previous ( ) ;
// extern function
if ( tok1 - > str ( ) = = " extern " ) {
isExtern ( true ) ;
}
// virtual function
else if ( tok1 - > str ( ) = = " virtual " ) {
2019-07-04 12:32:32 +02:00
hasVirtualSpecifier ( true ) ;
2018-04-25 12:05:49 +02:00
}
// static function
else if ( tok1 - > str ( ) = = " static " ) {
isStatic ( true ) ;
if ( scope - > type = = Scope : : eNamespace | | scope - > type = = Scope : : eGlobal )
isStaticLocal ( true ) ;
}
// friend function
else if ( tok1 - > str ( ) = = " friend " ) {
isFriend ( true ) ;
}
// Function template
2019-07-24 09:59:01 +02:00
else if ( tok1 - > link ( ) & & tok1 - > str ( ) = = " > " & & Token : : simpleMatch ( tok1 - > link ( ) - > previous ( ) , " template < " ) ) {
templateDef = tok1 - > link ( ) - > previous ( ) ;
2018-04-25 12:05:49 +02:00
break ;
2019-07-24 09:59:01 +02:00
}
2018-04-25 12:05:49 +02:00
}
// find the return type
2019-07-05 12:30:42 +02:00
if ( ! isConstructor ( ) & & ! isDestructor ( ) & & ! isLambda ( ) ) {
2018-12-13 06:34:10 +01:00
// @todo auto type deduction should be checked
// @todo attributes and exception specification can also precede trailing return type
if ( Token : : Match ( argDef - > link ( ) - > next ( ) , " const|volatile| &|&&| . " ) ) { // Trailing return type
hasTrailingReturnType ( true ) ;
if ( argDef - > link ( ) - > strAt ( 1 ) = = " . " )
retDef = argDef - > link ( ) - > tokAt ( 2 ) ;
else if ( argDef - > link ( ) - > strAt ( 2 ) = = " . " )
retDef = argDef - > link ( ) - > tokAt ( 3 ) ;
else if ( argDef - > link ( ) - > strAt ( 3 ) = = " . " )
retDef = argDef - > link ( ) - > tokAt ( 4 ) ;
} else {
2018-04-25 12:05:49 +02:00
if ( tok1 - > str ( ) = = " > " )
tok1 = tok1 - > next ( ) ;
while ( Token : : Match ( tok1 , " extern|virtual|static|friend|struct|union|enum " ) )
tok1 = tok1 - > next ( ) ;
retDef = tok1 ;
}
}
const Token * end = argDef - > link ( ) ;
2018-04-27 10:35:11 +02:00
// parse function attributes..
2018-04-25 14:35:09 +02:00
tok = end - > next ( ) ;
while ( tok ) {
2018-04-25 12:05:49 +02:00
if ( tok - > str ( ) = = " const " )
2018-04-25 14:35:09 +02:00
isConst ( true ) ;
else if ( tok - > str ( ) = = " & " )
2018-04-25 12:05:49 +02:00
hasLvalRefQualifier ( true ) ;
2018-04-25 14:35:09 +02:00
else if ( tok - > str ( ) = = " && " )
2018-04-25 12:05:49 +02:00
hasRvalRefQualifier ( true ) ;
2018-04-27 14:57:43 +02:00
else if ( tok - > str ( ) = = " override " )
setFlag ( fHasOverrideSpecifier , true ) ;
else if ( tok - > str ( ) = = " final " )
setFlag ( fHasFinalSpecifier , true ) ;
2018-05-10 07:40:01 +02:00
else if ( tok - > str ( ) = = " volatile " )
isVolatile ( true ) ;
2018-04-25 14:35:09 +02:00
else if ( tok - > str ( ) = = " noexcept " ) {
2018-04-25 12:05:49 +02:00
isNoExcept ( ! Token : : simpleMatch ( tok - > next ( ) , " ( false ) " ) ) ;
2018-05-05 08:31:56 +02:00
if ( tok - > next ( ) - > str ( ) = = " ( " )
tok = tok - > linkAt ( 1 ) ;
2018-04-25 12:05:49 +02:00
} else if ( Token : : simpleMatch ( tok , " throw ( " ) ) {
isThrow ( true ) ;
if ( tok - > strAt ( 2 ) ! = " ) " )
2018-04-25 14:35:09 +02:00
throwArg = tok - > next ( ) ;
tok = tok - > linkAt ( 1 ) ;
} else if ( Token : : Match ( tok , " = 0|default|delete ; " ) ) {
2018-04-25 12:05:49 +02:00
const std : : string & modifier = tok - > strAt ( 1 ) ;
isPure ( modifier = = " 0 " ) ;
isDefault ( modifier = = " default " ) ;
isDelete ( modifier = = " delete " ) ;
2018-12-13 06:34:10 +01:00
} else if ( tok - > str ( ) = = " . " ) { // trailing return type
// skip over return type
while ( tok & & ! Token : : Match ( tok - > next ( ) , " ;|{|override|final " ) )
tok = tok - > next ( ) ;
2018-04-25 14:35:09 +02:00
} else
break ;
2018-12-13 06:34:10 +01:00
if ( tok )
tok = tok - > next ( ) ;
2018-04-25 14:35:09 +02:00
}
2018-06-16 16:10:28 +02:00
if ( mTokenizer - > isFunctionHead ( end , " :{ " ) ) {
2018-04-25 12:05:49 +02:00
// assume implementation is inline (definition and implementation same)
token = tokenDef ;
arg = argDef ;
isInline ( true ) ;
hasBody ( true ) ;
}
}
2019-07-22 11:25:51 +02:00
bool Function : : argsMatch ( const Scope * scope , const Token * first , const Token * second , const std : : string & path , nonneg int path_length )
2010-11-13 08:08:45 +01:00
{
2012-11-26 16:34:44 +01:00
const bool isCPP = scope - > check - > isCPP ( ) ;
2014-09-01 17:01:05 +02:00
if ( ! isCPP ) // C does not support overloads
return true ;
2012-11-26 16:34:44 +01:00
2019-07-22 11:25:51 +02:00
int arg_path_length = path_length ;
2018-05-01 07:32:19 +02:00
2013-03-14 19:11:29 +01:00
while ( first - > str ( ) = = second - > str ( ) & &
first - > isLong ( ) = = second - > isLong ( ) & &
first - > isUnsigned ( ) = = second - > isUnsigned ( ) ) {
2018-05-01 07:32:19 +02:00
2018-11-09 15:54:17 +01:00
// skip optional type information
if ( Token : : Match ( first - > next ( ) , " struct|enum|union|class " ) )
2018-11-09 06:11:48 +01:00
first = first - > next ( ) ;
2018-11-09 15:54:17 +01:00
if ( Token : : Match ( second - > next ( ) , " struct|enum|union|class " ) )
2018-11-09 06:11:48 +01:00
second = second - > next ( ) ;
// skip const on type passed by value
if ( Token : : Match ( first - > next ( ) , " const %type% %name%|,|) " ) & &
! Token : : Match ( first - > next ( ) , " const %type% %name%| [ " ) )
first = first - > next ( ) ;
if ( Token : : Match ( second - > next ( ) , " const %type% %name%|,|) " ) & &
! Token : : Match ( second - > next ( ) , " const %type% %name%| [ " ) )
second = second - > next ( ) ;
2010-11-13 08:08:45 +01:00
// at end of argument list
2011-10-13 20:53:06 +02:00
if ( first - > str ( ) = = " ) " ) {
2012-04-18 13:00:34 +02:00
return true ;
2010-11-13 08:08:45 +01:00
}
// skip default value assignment
2011-10-13 20:53:06 +02:00
else if ( first - > next ( ) - > str ( ) = = " = " ) {
2012-02-11 12:26:48 +01:00
first = first - > nextArgument ( ) ;
2013-05-18 18:33:24 +02:00
if ( first )
first = first - > tokAt ( - 2 ) ;
2012-02-11 12:26:48 +01:00
if ( second - > next ( ) - > str ( ) = = " = " ) {
second = second - > nextArgument ( ) ;
2013-05-18 18:33:24 +02:00
if ( second )
second = second - > tokAt ( - 2 ) ;
2012-02-11 12:26:48 +01:00
if ( ! first | | ! second ) { // End of argument list (first or second)
2012-04-18 13:00:34 +02:00
return ! first & & ! second ;
2012-02-11 12:26:48 +01:00
}
} else if ( ! first ) { // End of argument list (first)
2016-08-09 14:02:06 +02:00
return ! second - > nextArgument ( ) ; // End of argument list (second)
2012-02-11 12:26:48 +01:00
}
2013-05-18 18:33:24 +02:00
} else if ( second - > next ( ) - > str ( ) = = " = " ) {
second = second - > nextArgument ( ) ;
if ( second )
second = second - > tokAt ( - 2 ) ;
2015-02-19 15:16:38 +01:00
if ( ! second ) { // End of argument list (second)
return false ;
2013-05-18 18:33:24 +02:00
}
2011-08-26 01:13:53 +02:00
}
2010-11-13 08:08:45 +01:00
// definition missing variable name
2015-08-16 14:22:46 +02:00
else if ( ( first - > next ( ) - > str ( ) = = " , " & & second - > next ( ) - > str ( ) ! = " , " ) | |
( first - > next ( ) - > str ( ) = = " ) " & & second - > next ( ) - > str ( ) ! = " ) " ) ) {
2010-11-13 08:08:45 +01:00
second = second - > next ( ) ;
2013-05-18 18:33:24 +02:00
// skip default value assignment
if ( second - > next ( ) - > str ( ) = = " = " ) {
2015-08-16 14:22:46 +02:00
do {
2013-05-18 18:33:24 +02:00
second = second - > next ( ) ;
2015-08-16 14:22:46 +02:00
} while ( ! Token : : Match ( second - > next ( ) , " ,|) " ) ) ;
2013-05-18 18:33:24 +02:00
}
} else if ( first - > next ( ) - > str ( ) = = " [ " & & second - > next ( ) - > str ( ) ! = " [ " )
2012-12-28 16:28:29 +01:00
second = second - > next ( ) ;
2010-11-13 08:08:45 +01:00
// function missing variable name
2015-08-16 14:22:46 +02:00
else if ( ( second - > next ( ) - > str ( ) = = " , " & & first - > next ( ) - > str ( ) ! = " , " ) | |
( second - > next ( ) - > str ( ) = = " ) " & & first - > next ( ) - > str ( ) ! = " ) " ) ) {
2010-11-13 08:08:45 +01:00
first = first - > next ( ) ;
2013-05-18 18:33:24 +02:00
// skip default value assignment
if ( first - > next ( ) - > str ( ) = = " = " ) {
2015-08-16 14:22:46 +02:00
do {
2013-05-18 18:33:24 +02:00
first = first - > next ( ) ;
2015-08-16 14:22:46 +02:00
} while ( ! Token : : Match ( first - > next ( ) , " ,|) " ) ) ;
2013-05-18 18:33:24 +02:00
}
} else if ( second - > next ( ) - > str ( ) = = " [ " & & first - > next ( ) - > str ( ) ! = " [ " )
2012-12-28 16:28:29 +01:00
first = first - > next ( ) ;
2010-11-13 08:08:45 +01:00
// argument list has different number of arguments
else if ( second - > str ( ) = = " ) " )
break ;
2016-08-20 17:56:48 +02:00
// ckeck for type * x == type x[]
else if ( Token : : Match ( first - > next ( ) , " * %name%| ,|)|= " ) & &
Token : : Match ( second - > next ( ) , " %name%| [ ] ,|) " ) ) {
do {
first = first - > next ( ) ;
} while ( ! Token : : Match ( first - > next ( ) , " ,|) " ) ) ;
do {
second = second - > next ( ) ;
} while ( ! Token : : Match ( second - > next ( ) , " ,|) " ) ) ;
}
2016-08-20 07:43:15 +02:00
// const after *
else if ( first - > next ( ) - > str ( ) = = " * " & & first - > strAt ( 2 ) ! = " const " & &
second - > next ( ) - > str ( ) = = " * " & & second - > strAt ( 2 ) = = " const " ) {
first = first - > next ( ) ;
second = second - > tokAt ( 2 ) ;
}
2010-11-13 08:08:45 +01:00
// variable names are different
2016-08-09 14:02:06 +02:00
else if ( ( Token : : Match ( first - > next ( ) , " %name% ,|)|=|[ " ) & &
Token : : Match ( second - > next ( ) , " %name% ,|)|[ " ) ) & &
2011-10-13 20:53:06 +02:00
( first - > next ( ) - > str ( ) ! = second - > next ( ) - > str ( ) ) ) {
2010-11-13 08:08:45 +01:00
// skip variable names
first = first - > next ( ) ;
second = second - > next ( ) ;
2016-03-22 14:10:20 +01:00
// skip default value assignment
if ( first - > next ( ) - > str ( ) = = " = " ) {
do {
first = first - > next ( ) ;
} while ( ! Token : : Match ( first - > next ( ) , " ,|) " ) ) ;
}
2010-11-13 08:08:45 +01:00
}
// variable with class path
2018-05-01 07:32:19 +02:00
else if ( arg_path_length & & Token : : Match ( first - > next ( ) , " %name% " ) & & first - > strAt ( 1 ) ! = " const " ) {
std : : string param = path ;
2010-11-13 08:08:45 +01:00
2015-12-03 13:04:55 +01:00
if ( Token : : simpleMatch ( second - > next ( ) , param . c_str ( ) ) ) {
2018-05-01 07:32:19 +02:00
second = second - > tokAt ( int ( arg_path_length ) ) ;
arg_path_length = 0 ;
}
// nested or base class variable
else if ( arg_path_length < = 2 & & Token : : Match ( first - > next ( ) , " %name% " ) & &
( Token : : Match ( second - > next ( ) , " %name% :: %name% " ) | |
( Token : : Match ( second - > next ( ) , " %name% < " ) & &
Token : : Match ( second - > linkAt ( 1 ) , " > :: %name% " ) ) ) & &
( ( second - > next ( ) - > str ( ) = = scope - > className ) | |
( scope - > definedType & & scope - > definedType - > isDerivedFrom ( second - > next ( ) - > str ( ) ) ) ) & &
( first - > next ( ) - > str ( ) = = second - > strAt ( 3 ) ) ) {
if ( Token : : Match ( second - > next ( ) , " %name% < " ) )
second = second - > linkAt ( 1 ) - > next ( ) ;
else
second = second - > tokAt ( 2 ) ;
}
// remove class name
2018-11-05 06:55:30 +01:00
else if ( arg_path_length > 2 & & first - > strAt ( 1 ) ! = second - > strAt ( 1 ) ) {
2012-04-18 13:00:34 +02:00
std : : string short_path = path ;
2018-05-01 07:32:19 +02:00
unsigned int short_path_length = arg_path_length ;
2010-11-13 08:08:45 +01:00
// remove last " :: "
short_path . resize ( short_path . size ( ) - 4 ) ;
2018-05-01 07:32:19 +02:00
short_path_length - - ;
2010-11-13 08:08:45 +01:00
// remove last name
2018-05-01 07:32:19 +02:00
std : : string : : size_type lastSpace = short_path . find_last_of ( ' ' ) ;
if ( lastSpace ! = std : : string : : npos ) {
2015-08-16 14:22:46 +02:00
short_path . resize ( lastSpace + 1 ) ;
2018-05-01 07:32:19 +02:00
short_path_length - - ;
if ( short_path [ short_path . size ( ) - 1 ] = = ' > ' ) {
short_path . resize ( short_path . size ( ) - 3 ) ;
while ( short_path [ short_path . size ( ) - 1 ] = = ' < ' ) {
lastSpace = short_path . find_last_of ( ' ' ) ;
short_path . resize ( lastSpace + 1 ) ;
short_path_length - - ;
}
}
}
2010-11-13 08:08:45 +01:00
2018-05-01 07:32:19 +02:00
param = short_path ;
2015-12-03 13:04:55 +01:00
if ( Token : : simpleMatch ( second - > next ( ) , param . c_str ( ) ) ) {
2018-05-01 07:32:19 +02:00
second = second - > tokAt ( int ( short_path_length ) ) ;
arg_path_length = 0 ;
2010-11-13 08:08:45 +01:00
}
}
}
first = first - > next ( ) ;
second = second - > next ( ) ;
2012-11-26 16:34:44 +01:00
2018-05-01 07:32:19 +02:00
// reset path length
if ( first - > str ( ) = = " , " | | second - > str ( ) = = " , " )
arg_path_length = path_length ;
2010-11-13 08:08:45 +01:00
}
2012-04-18 13:00:34 +02:00
return false ;
2010-11-13 08:08:45 +01:00
}
2019-01-23 07:29:16 +01:00
bool Function : : returnsReference ( const Function * function )
{
if ( ! function )
return false ;
if ( function - > type ! = Function : : eFunction )
return false ;
return function - > tokenDef - > strAt ( - 1 ) = = " & " ;
}
2016-11-20 15:14:49 +01:00
const Token * Function : : constructorMemberInitialization ( ) const
{
2018-04-27 22:36:30 +02:00
if ( ! isConstructor ( ) | | ! functionScope | | ! functionScope - > bodyStart )
2016-11-20 15:14:49 +01:00
return nullptr ;
if ( Token : : Match ( token , " %name% ( " ) & & Token : : simpleMatch ( token - > linkAt ( 1 ) , " ) : " ) )
return token - > linkAt ( 1 ) - > next ( ) ;
return nullptr ;
}
2019-07-10 16:59:05 +02:00
bool Function : : isSafe ( const Settings * settings ) const
{
2019-07-25 17:28:32 +02:00
if ( settings - > safeChecks . externalFunctions ) {
2019-07-25 20:52:24 +02:00
if ( nestedIn - > type = = Scope : : ScopeType : : eNamespace & & token - > fileIndex ( ) ! = 0 )
return true ;
if ( nestedIn - > type = = Scope : : ScopeType : : eGlobal & & ( token - > fileIndex ( ) ! = 0 | | ! isStatic ( ) ) )
return true ;
2019-07-24 08:23:05 +02:00
}
2019-07-25 17:28:32 +02:00
if ( settings - > safeChecks . internalFunctions ) {
2019-07-25 20:52:24 +02:00
if ( nestedIn - > type = = Scope : : ScopeType : : eNamespace & & token - > fileIndex ( ) = = 0 )
return true ;
if ( nestedIn - > type = = Scope : : ScopeType : : eGlobal & & ( token - > fileIndex ( ) = = 0 | | isStatic ( ) ) )
return true ;
2019-07-25 17:28:32 +02:00
}
2019-07-25 20:52:24 +02:00
if ( settings - > safeChecks . classes & & access = = AccessControl : : Public & & ( nestedIn - > type = = Scope : : ScopeType : : eClass | | nestedIn - > type = = Scope : : ScopeType : : eStruct ) )
2019-07-25 17:28:32 +02:00
return true ;
2019-07-24 08:23:05 +02:00
2019-07-23 11:54:38 +02:00
return false ;
2019-07-10 16:59:05 +02:00
}
2012-02-11 12:26:48 +01:00
Function * SymbolDatabase : : addGlobalFunction ( Scope * & scope , const Token * & tok , const Token * argStart , const Token * funcStart )
2012-03-23 17:59:51 +01:00
{
2015-12-06 08:14:04 +01:00
Function * function = nullptr ;
2019-07-05 12:30:42 +02:00
// Lambda functions are always unique
if ( tok - > str ( ) ! = " [ " ) {
for ( std : : multimap < std : : string , const Function * > : : iterator i = scope - > functionMap . find ( tok - > str ( ) ) ; i ! = scope - > functionMap . end ( ) & & i - > first = = tok - > str ( ) ; + + i ) {
const Function * f = i - > second ;
if ( f - > hasBody ( ) )
continue ;
if ( Function : : argsMatch ( scope , f - > argDef , argStart , emptyString , 0 ) ) {
function = const_cast < Function * > ( i - > second ) ;
break ;
}
2014-03-14 05:40:17 +01:00
}
2012-03-23 17:59:51 +01:00
}
2012-10-14 17:30:37 +02:00
2012-03-23 17:59:51 +01:00
if ( ! function )
2013-08-31 18:58:55 +02:00
function = addGlobalFunctionDecl ( scope , tok , argStart , funcStart ) ;
2012-03-23 17:59:51 +01:00
function - > arg = argStart ;
function - > token = funcStart ;
2015-01-08 05:45:31 +01:00
function - > hasBody ( true ) ;
2012-03-23 17:59:51 +01:00
addNewFunction ( & scope , & tok ) ;
if ( scope ) {
2012-04-25 20:52:59 +02:00
scope - > function = function ;
2012-04-27 21:51:13 +02:00
function - > functionScope = scope ;
2012-03-23 17:59:51 +01:00
return function ;
}
2015-12-06 08:14:04 +01:00
return nullptr ;
2012-03-23 17:59:51 +01:00
}
2013-08-31 18:58:55 +02:00
Function * SymbolDatabase : : addGlobalFunctionDecl ( Scope * & scope , const Token * tok , const Token * argStart , const Token * funcStart )
2012-02-11 12:26:48 +01:00
{
2018-06-16 16:10:28 +02:00
Function function ( mTokenizer , tok , scope , funcStart , argStart ) ;
2015-01-02 21:38:19 +01:00
scope - > addFunction ( function ) ;
2012-03-23 17:59:51 +01:00
return & scope - > functionList . back ( ) ;
2012-02-11 12:26:48 +01:00
}
void SymbolDatabase : : addClassFunction ( Scope * * scope , const Token * * tok , const Token * argStart )
2010-11-13 08:08:45 +01:00
{
2012-01-22 19:34:53 +01:00
const bool destructor ( ( * tok ) - > previous ( ) - > str ( ) = = " ~ " ) ;
2016-01-02 18:53:51 +01:00
const bool has_const ( argStart - > link ( ) - > strAt ( 1 ) = = " const " ) ;
const bool lval ( argStart - > link ( ) - > strAt ( has_const ? 2 : 1 ) = = " & " ) ;
const bool rval ( argStart - > link ( ) - > strAt ( has_const ? 2 : 1 ) = = " && " ) ;
2014-07-24 16:34:13 +02:00
int count = 0 ;
std : : string path ;
unsigned int path_length = 0 ;
2018-05-01 07:32:19 +02:00
const Token * tok1 = ( * tok ) ;
if ( destructor )
tok1 = tok1 - > previous ( ) ;
2014-07-24 16:34:13 +02:00
2010-11-13 08:08:45 +01:00
// back up to head of path
2018-05-01 07:32:19 +02:00
while ( tok1 & & tok1 - > previous ( ) & & tok1 - > previous ( ) - > str ( ) = = " :: " & & tok1 - > tokAt ( - 2 ) & &
( tok1 - > tokAt ( - 2 ) - > isName ( ) | |
( tok1 - > strAt ( - 2 ) = = " > " & & tok1 - > linkAt ( - 2 ) & & Token : : Match ( tok1 - > linkAt ( - 2 ) - > previous ( ) , " %name% " ) ) ) ) {
count + + ;
const Token * tok2 = tok1 - > tokAt ( - 2 ) ;
if ( tok2 - > str ( ) = = " > " )
tok2 = tok2 - > link ( ) - > previous ( ) ;
if ( tok2 ) {
do {
path = tok1 - > previous ( ) - > str ( ) + " " + path ;
tok1 = tok1 - > previous ( ) ;
path_length + + ;
} while ( tok1 ! = tok2 ) ;
} else
return ; // syntax error ?
2010-11-13 08:08:45 +01:00
}
2018-05-01 07:32:19 +02:00
// syntax error?
if ( ! tok1 )
return ;
2010-11-13 08:08:45 +01:00
2011-03-11 01:43:29 +01:00
std : : list < Scope > : : iterator it1 ;
2010-11-13 08:08:45 +01:00
// search for match
2011-10-13 20:53:06 +02:00
for ( it1 = scopeList . begin ( ) ; it1 ! = scopeList . end ( ) ; + + it1 ) {
2011-03-11 01:43:29 +01:00
Scope * scope1 = & ( * it1 ) ;
2010-11-13 08:08:45 +01:00
bool match = false ;
2014-04-10 16:11:11 +02:00
// check in namespace if using found
if ( * scope = = scope1 & & ! scope1 - > usingList . empty ( ) ) {
std : : list < Scope : : UsingInfo > : : const_iterator it2 ;
for ( it2 = scope1 - > usingList . begin ( ) ; it2 ! = scope1 - > usingList . end ( ) ; + + it2 ) {
if ( it2 - > scope ) {
2018-05-01 07:32:19 +02:00
Function * func = findFunctionInScope ( tok1 , it2 - > scope , path , path_length ) ;
2014-04-10 16:11:11 +02:00
if ( func ) {
2015-01-08 05:45:31 +01:00
if ( ! func - > hasBody ( ) ) {
func - > hasBody ( true ) ;
2014-04-10 16:11:11 +02:00
func - > token = * tok ;
func - > arg = argStart ;
addNewFunction ( scope , tok ) ;
if ( * scope ) {
( * scope ) - > functionOf = func - > nestedIn ;
2015-01-17 16:28:39 +01:00
( * scope ) - > function = func ;
2014-04-10 16:11:11 +02:00
( * scope ) - > function - > functionScope = * scope ;
}
return ;
}
}
}
}
}
2011-10-13 20:53:06 +02:00
if ( scope1 - > className = = tok1 - > str ( ) & & ( scope1 - > type ! = Scope : : eFunction ) ) {
2011-04-01 02:54:23 +02:00
// do the scopes match (same scope) or do their names match (multiple namespaces)
2013-08-21 16:32:10 +02:00
if ( ( * scope = = scope1 - > nestedIn ) | | ( * scope & &
2011-01-21 07:42:41 +01:00
( * scope ) - > className = = scope1 - > nestedIn - > className & &
! ( * scope ) - > className . empty ( ) & &
2011-10-13 20:53:06 +02:00
( * scope ) - > type = = scope1 - > nestedIn - > type ) ) {
2012-01-07 09:28:26 +01:00
// nested scopes => check that they match
{
const Scope * s1 = * scope ;
const Scope * s2 = scope1 - > nestedIn ;
while ( s1 & & s2 ) {
if ( s1 - > className ! = s2 - > className )
break ;
s1 = s1 - > nestedIn ;
s2 = s2 - > nestedIn ;
}
// Not matching scopes
if ( s1 | | s2 )
continue ;
}
2011-01-21 07:42:41 +01:00
Scope * scope2 = scope1 ;
2010-11-13 08:08:45 +01:00
2018-05-01 07:32:19 +02:00
while ( scope2 & & count > 1 ) {
2010-11-20 07:26:50 +01:00
count - - ;
2018-05-01 07:32:19 +02:00
if ( tok1 - > strAt ( 1 ) = = " < " )
tok1 = tok1 - > linkAt ( 1 ) - > tokAt ( 2 ) ;
else
tok1 = tok1 - > tokAt ( 2 ) ;
2018-04-24 22:43:47 +02:00
scope2 = scope2 - > findRecordInNestedList ( tok1 - > str ( ) ) ;
2010-11-20 07:26:50 +01:00
}
2018-05-01 07:32:19 +02:00
if ( count = = 1 & & scope2 ) {
2010-11-20 07:26:50 +01:00
match = true ;
2011-01-21 07:42:41 +01:00
scope1 = scope2 ;
2010-11-20 07:26:50 +01:00
}
2010-11-13 08:08:45 +01:00
}
}
2011-10-13 20:53:06 +02:00
if ( match ) {
2015-01-02 21:38:19 +01:00
for ( std : : multimap < std : : string , const Function * > : : iterator it = scope1 - > functionMap . find ( ( * tok ) - > str ( ) ) ; it ! = scope1 - > functionMap . end ( ) & & it - > first = = ( * tok ) - > str ( ) ; + + it ) {
Function * func = const_cast < Function * > ( it - > second ) ;
2015-01-08 05:45:31 +01:00
if ( ! func - > hasBody ( ) ) {
2012-05-22 21:58:46 +02:00
if ( Function : : argsMatch ( scope1 , func - > argDef , ( * tok ) - > next ( ) , path , path_length ) ) {
if ( func - > type = = Function : : eDestructor & & destructor ) {
2015-01-08 05:45:31 +01:00
func - > hasBody ( true ) ;
2012-05-22 21:58:46 +02:00
} else if ( func - > type ! = Function : : eDestructor & & ! destructor ) {
2010-11-13 08:08:45 +01:00
// normal function?
2014-04-12 16:06:31 +02:00
if ( ( * tok ) - > next ( ) - > link ( ) ) {
2014-09-19 09:29:31 +02:00
const bool hasConstKeyword = ( * tok ) - > next ( ) - > link ( ) - > next ( ) - > str ( ) = = " const " ;
2016-01-02 18:53:51 +01:00
if ( ( func - > isConst ( ) = = hasConstKeyword ) & &
( func - > hasLvalRefQualifier ( ) = = lval ) & &
( func - > hasRvalRefQualifier ( ) = = rval ) ) {
2015-01-08 05:45:31 +01:00
func - > hasBody ( true ) ;
2010-11-13 08:08:45 +01:00
}
}
}
2015-01-08 05:45:31 +01:00
if ( func - > hasBody ( ) ) {
2012-05-22 21:58:46 +02:00
func - > token = * tok ;
func - > arg = argStart ;
addNewFunction ( scope , tok ) ;
if ( * scope ) {
( * scope ) - > functionOf = scope1 ;
2015-01-17 16:28:39 +01:00
( * scope ) - > function = func ;
2012-05-22 21:58:46 +02:00
( * scope ) - > function - > functionScope = * scope ;
}
return ;
2010-12-16 19:04:47 +01:00
}
2010-11-13 08:08:45 +01:00
}
}
}
}
}
2012-04-27 21:51:13 +02:00
// class function of unknown class
addNewFunction ( scope , tok ) ;
2010-11-13 08:08:45 +01:00
}
2011-01-21 07:42:41 +01:00
void SymbolDatabase : : addNewFunction ( Scope * * scope , const Token * * tok )
2010-11-13 08:08:45 +01:00
{
const Token * tok1 = * tok ;
2018-04-11 09:44:35 +02:00
scopeList . emplace_back ( this , tok1 , * scope ) ;
2015-09-04 16:00:44 +02:00
Scope * newScope = & scopeList . back ( ) ;
2010-11-13 08:08:45 +01:00
2015-04-06 19:47:21 +02:00
// find start of function '{'
bool foundInitList = false ;
while ( tok1 & & tok1 - > str ( ) ! = " { " & & tok1 - > str ( ) ! = " ; " ) {
if ( tok1 - > link ( ) & & Token : : Match ( tok1 , " (|< " ) ) {
2012-07-10 15:15:11 +02:00
tok1 = tok1 - > link ( ) ;
2015-04-06 19:47:21 +02:00
} else if ( foundInitList & &
Token : : Match ( tok1 , " %name%|> { " ) & &
Token : : Match ( tok1 - > linkAt ( 1 ) , " } ,|{ " ) ) {
tok1 = tok1 - > linkAt ( 1 ) ;
} else {
if ( tok1 - > str ( ) = = " : " )
foundInitList = true ;
tok1 = tok1 - > next ( ) ;
}
2012-07-10 15:15:11 +02:00
}
2010-11-13 08:08:45 +01:00
2015-04-06 19:47:21 +02:00
if ( tok1 & & tok1 - > str ( ) = = " { " ) {
2018-04-27 22:36:30 +02:00
newScope - > bodyStart = tok1 ;
newScope - > bodyEnd = tok1 - > link ( ) ;
2010-11-13 08:08:45 +01:00
2010-12-16 19:04:47 +01:00
// syntax error?
2018-04-27 22:36:30 +02:00
if ( ! newScope - > bodyEnd ) {
2011-03-11 01:43:29 +01:00
scopeList . pop_back ( ) ;
2010-12-16 19:04:47 +01:00
while ( tok1 - > next ( ) )
tok1 = tok1 - > next ( ) ;
2014-02-16 10:32:10 +01:00
* scope = nullptr ;
2010-12-16 19:04:47 +01:00
* tok = tok1 ;
return ;
}
2015-09-04 16:00:44 +02:00
( * scope ) - > nestedList . push_back ( newScope ) ;
* scope = newScope ;
2010-11-13 08:08:45 +01:00
* tok = tok1 ;
2011-10-13 20:53:06 +02:00
} else {
2011-03-11 01:43:29 +01:00
scopeList . pop_back ( ) ;
2014-02-16 10:32:10 +01:00
* scope = nullptr ;
* tok = nullptr ;
2011-01-22 08:36:47 +01:00
}
2010-11-13 08:08:45 +01:00
}
2013-03-05 15:28:40 +01:00
const Token * Type : : initBaseInfo ( const Token * tok , const Token * tok1 )
2010-11-13 08:08:45 +01:00
{
// goto initial '{'
2012-11-30 06:03:58 +01:00
const Token * tok2 = tok1 ;
2011-10-13 20:53:06 +02:00
while ( tok2 & & tok2 - > str ( ) ! = " { " ) {
2010-11-13 08:08:45 +01:00
// skip unsupported templates
if ( tok2 - > str ( ) = = " < " )
2013-04-15 22:48:28 +02:00
tok2 = tok2 - > link ( ) ;
2010-11-13 08:08:45 +01:00
// check for base classes
2012-04-27 21:51:13 +02:00
else if ( Token : : Match ( tok2 , " :|, " ) ) {
2010-11-13 08:08:45 +01:00
tok2 = tok2 - > next ( ) ;
2011-02-19 20:38:00 +01:00
// check for invalid code
2011-02-21 20:25:35 +01:00
if ( ! tok2 | | ! tok2 - > next ( ) )
2014-02-16 10:32:10 +01:00
return nullptr ;
2011-02-19 20:38:00 +01:00
2014-09-19 09:29:31 +02:00
Type : : BaseInfo base ;
2011-10-13 20:53:06 +02:00
if ( tok2 - > str ( ) = = " virtual " ) {
2011-03-22 01:03:41 +01:00
base . isVirtual = true ;
tok2 = tok2 - > next ( ) ;
}
2011-10-13 20:53:06 +02:00
if ( tok2 - > str ( ) = = " public " ) {
2019-07-23 14:29:02 +02:00
base . access = AccessControl : : Public ;
2010-11-13 08:08:45 +01:00
tok2 = tok2 - > next ( ) ;
2011-10-13 20:53:06 +02:00
} else if ( tok2 - > str ( ) = = " protected " ) {
2019-07-23 14:29:02 +02:00
base . access = AccessControl : : Protected ;
2010-11-13 08:08:45 +01:00
tok2 = tok2 - > next ( ) ;
2011-10-13 20:53:06 +02:00
} else if ( tok2 - > str ( ) = = " private " ) {
2019-07-23 14:29:02 +02:00
base . access = AccessControl : : Private ;
2010-11-13 08:08:45 +01:00
tok2 = tok2 - > next ( ) ;
2011-10-13 20:53:06 +02:00
} else {
2010-11-13 08:08:45 +01:00
if ( tok - > str ( ) = = " class " )
2019-07-23 14:29:02 +02:00
base . access = AccessControl : : Private ;
2010-11-13 08:08:45 +01:00
else if ( tok - > str ( ) = = " struct " )
2019-07-23 14:29:02 +02:00
base . access = AccessControl : : Public ;
2010-11-13 08:08:45 +01:00
}
2015-06-02 18:28:43 +02:00
if ( ! tok2 )
return nullptr ;
2011-10-13 20:53:06 +02:00
if ( tok2 - > str ( ) = = " virtual " ) {
2011-03-22 01:03:41 +01:00
base . isVirtual = true ;
tok2 = tok2 - > next ( ) ;
2011-06-30 01:43:39 +02:00
}
2015-06-02 20:15:21 +02:00
if ( ! tok2 )
return nullptr ;
2015-09-04 15:06:20 +02:00
base . nameTok = tok2 ;
2011-06-30 01:43:39 +02:00
// handle global namespace
2011-10-13 20:53:06 +02:00
if ( tok2 - > str ( ) = = " :: " ) {
2011-06-30 01:43:39 +02:00
tok2 = tok2 - > next ( ) ;
2011-03-22 01:03:41 +01:00
}
2010-11-13 08:08:45 +01:00
// handle derived base classes
2015-01-31 10:50:39 +01:00
while ( Token : : Match ( tok2 , " %name% :: " ) ) {
2010-11-13 08:08:45 +01:00
tok2 = tok2 - > tokAt ( 2 ) ;
}
2015-06-02 20:15:21 +02:00
if ( ! tok2 )
return nullptr ;
2010-11-13 08:08:45 +01:00
2013-03-05 15:28:40 +01:00
base . name = tok2 - > str ( ) ;
2010-11-13 08:08:45 +01:00
2015-01-09 22:03:43 +01:00
tok2 = tok2 - > next ( ) ;
2011-02-15 01:50:13 +01:00
// add unhandled templates
2015-01-09 22:03:43 +01:00
if ( tok2 & & tok2 - > link ( ) & & tok2 - > str ( ) = = " < " ) {
for ( const Token * const end = tok2 - > link ( ) - > next ( ) ; tok2 ! = end ; tok2 = tok2 - > next ( ) ) {
base . name + = tok2 - > str ( ) ;
2010-11-30 19:52:42 +01:00
}
2010-11-25 07:43:39 +01:00
}
2010-11-13 08:08:45 +01:00
// save pattern for base class name
2012-05-17 10:33:24 +02:00
derivedFrom . push_back ( base ) ;
2015-01-09 22:03:43 +01:00
} else
2013-06-16 21:46:01 +02:00
tok2 = tok2 - > next ( ) ;
2010-11-13 08:08:45 +01:00
}
return tok2 ;
}
2011-01-15 07:59:37 +01:00
2016-04-22 06:02:54 +02:00
const std : : string & Type : : name ( ) const
{
const Token * next = classDef - > next ( ) ;
2016-07-25 18:22:15 +02:00
if ( classScope & & classScope - > enumClass & & isEnumType ( ) )
2016-04-22 06:02:54 +02:00
return next - > strAt ( 1 ) ;
2018-05-04 07:56:20 +02:00
else if ( next - > str ( ) = = " class " )
return next - > strAt ( 1 ) ;
2016-04-22 06:02:54 +02:00
else if ( next - > isName ( ) )
return next - > str ( ) ;
return emptyString ;
}
2011-03-03 03:08:27 +01:00
void SymbolDatabase : : debugMessage ( const Token * tok , const std : : string & msg ) const
{
2018-06-16 16:10:28 +02:00
if ( tok & & mSettings - > debugwarnings ) {
2012-05-06 13:01:56 +02:00
const std : : list < const Token * > locationList ( 1 , tok ) ;
2018-06-16 16:10:28 +02:00
const ErrorLogger : : ErrorMessage errmsg ( locationList , & mTokenizer - > list ,
2011-03-03 03:08:27 +01:00
Severity : : debug ,
2011-04-14 18:02:01 +02:00
" debug " ,
2012-08-12 11:11:54 +02:00
msg ,
2011-04-14 18:02:01 +02:00
false ) ;
2018-06-16 16:10:28 +02:00
if ( mErrorLogger )
mErrorLogger - > reportErr ( errmsg ) ;
2011-03-03 03:08:27 +01:00
}
}
2013-03-14 17:00:22 +01:00
const Function * Type : : getFunction ( const std : : string & funcName ) const
{
if ( classScope ) {
2018-04-04 21:51:31 +02:00
const std : : multimap < std : : string , const Function * > : : const_iterator it = classScope - > functionMap . find ( funcName ) ;
2015-01-02 21:38:19 +01:00
if ( it ! = classScope - > functionMap . end ( ) )
return it - > second ;
2013-03-14 17:00:22 +01:00
}
2019-09-19 20:29:33 +02:00
for ( const Type : : BaseInfo & i : derivedFrom ) {
if ( i . type ) {
const Function * const func = i . type - > getFunction ( funcName ) ;
2013-03-14 17:00:22 +01:00
if ( func )
return func ;
}
}
2017-08-09 20:00:26 +02:00
return nullptr ;
2013-03-14 17:00:22 +01:00
}
2015-09-04 15:12:40 +02:00
bool Type : : hasCircularDependencies ( std : : set < BaseInfo > * ancestors ) const
2014-03-29 12:21:35 +01:00
{
2015-09-04 15:12:40 +02:00
std : : set < BaseInfo > knownAncestors ;
if ( ! ancestors ) {
ancestors = & knownAncestors ;
2014-03-29 12:21:35 +01:00
}
for ( std : : vector < BaseInfo > : : const_iterator parent = derivedFrom . begin ( ) ; parent ! = derivedFrom . end ( ) ; + + parent ) {
if ( ! parent - > type )
continue ;
else if ( this = = parent - > type )
return true ;
2015-09-04 15:12:40 +02:00
else if ( ancestors - > find ( * parent ) ! = ancestors - > end ( ) )
2014-03-29 12:21:35 +01:00
return true ;
else {
2015-09-04 15:12:40 +02:00
ancestors - > insert ( * parent ) ;
if ( parent - > type - > hasCircularDependencies ( ancestors ) )
2014-03-29 12:21:35 +01:00
return true ;
}
}
return false ;
}
2015-09-04 15:12:40 +02:00
bool Type : : findDependency ( const Type * ancestor ) const
2015-07-01 07:50:13 +02:00
{
2015-09-04 15:12:40 +02:00
if ( this = = ancestor )
2015-07-01 07:50:13 +02:00
return true ;
for ( std : : vector < BaseInfo > : : const_iterator parent = derivedFrom . begin ( ) ; parent ! = derivedFrom . end ( ) ; + + parent ) {
2015-09-04 15:12:40 +02:00
if ( parent - > type & & parent - > type - > findDependency ( ancestor ) )
2015-07-01 07:50:13 +02:00
return true ;
}
return false ;
2015-07-01 00:04:01 +02:00
}
2016-08-19 19:06:15 +02:00
bool Type : : isDerivedFrom ( const std : : string & ancestor ) const
{
for ( std : : vector < BaseInfo > : : const_iterator parent = derivedFrom . begin ( ) ; parent ! = derivedFrom . end ( ) ; + + parent ) {
if ( parent - > name = = ancestor )
return true ;
if ( parent - > type & & parent - > type - > isDerivedFrom ( ancestor ) )
return true ;
}
return false ;
}
2019-03-15 19:00:42 +01:00
bool Variable : : arrayDimensions ( const Settings * settings )
2011-06-23 04:41:11 +02:00
{
2019-03-15 19:00:42 +01:00
const Library : : Container * container = settings - > library . detectContainer ( mTypeStartToken ) ;
2015-01-30 21:56:27 +01:00
if ( container & & container - > arrayLike_indexOp & & container - > size_templateArgNo > 0 ) {
2018-06-16 16:03:36 +02:00
const Token * tok = Token : : findsimplematch ( mTypeStartToken , " < " ) ;
2015-01-30 21:56:27 +01:00
if ( tok ) {
2015-08-26 13:48:19 +02:00
Dimension dimension_ ;
2015-01-30 21:56:27 +01:00
tok = tok - > next ( ) ;
for ( int i = 0 ; i < container - > size_templateArgNo & & tok ; i + + ) {
tok = tok - > nextTemplateArgument ( ) ;
}
if ( tok ) {
2019-03-15 19:00:42 +01:00
while ( ! tok - > astParent ( ) & & ! Token : : Match ( tok - > next ( ) , " [,<>] " ) )
tok = tok - > next ( ) ;
while ( tok - > astParent ( ) & & ! Token : : Match ( tok - > astParent ( ) , " [,<>] " ) )
tok = tok - > astParent ( ) ;
dimension_ . tok = tok ;
2019-06-16 10:09:38 +02:00
ValueFlow : : valueFlowConstantFoldAST ( const_cast < Token * > ( dimension_ . tok ) , settings ) ;
2019-03-15 19:00:42 +01:00
if ( tok - > hasKnownIntValue ( ) ) {
dimension_ . num = tok - > getKnownIntValue ( ) ;
2016-04-22 06:02:54 +02:00
dimension_ . known = true ;
}
2015-01-30 21:56:27 +01:00
}
2018-06-16 20:23:58 +02:00
mDimensions . push_back ( dimension_ ) ;
2015-01-30 21:56:27 +01:00
return true ;
}
}
2011-06-23 04:41:11 +02:00
2018-06-16 15:57:16 +02:00
const Token * dim = mNameToken ;
2015-01-30 21:56:27 +01:00
if ( ! dim ) {
// Argument without name
2018-06-16 16:03:36 +02:00
dim = mTypeEndToken ;
2015-01-30 21:56:27 +01:00
// back up to start of array dimensions
while ( dim & & dim - > str ( ) = = " ] " )
dim = dim - > link ( ) - > previous ( ) ;
}
if ( dim )
dim = dim - > next ( ) ;
2015-01-31 13:12:06 +01:00
if ( dim & & dim - > str ( ) = = " ) " )
dim = dim - > next ( ) ;
2011-06-23 04:41:11 +02:00
2015-01-30 22:04:26 +01:00
bool arr = false ;
2011-10-13 20:53:06 +02:00
while ( dim & & dim - > next ( ) & & dim - > str ( ) = = " [ " ) {
2015-01-30 22:04:26 +01:00
Dimension dimension_ ;
2019-03-15 19:00:42 +01:00
dimension_ . known = false ;
2011-08-28 19:32:42 +02:00
// check for empty array dimension []
2011-10-13 20:53:06 +02:00
if ( dim - > next ( ) - > str ( ) ! = " ] " ) {
2019-03-15 19:00:42 +01:00
dimension_ . tok = dim - > astOperand2 ( ) ;
2019-06-16 10:09:38 +02:00
ValueFlow : : valueFlowConstantFoldAST ( const_cast < Token * > ( dimension_ . tok ) , settings ) ;
2019-03-15 19:00:42 +01:00
if ( dimension_ . tok & & dimension_ . tok - > hasKnownIntValue ( ) ) {
dimension_ . num = dimension_ . tok - > getKnownIntValue ( ) ;
2016-04-22 06:02:54 +02:00
dimension_ . known = true ;
}
2011-08-28 19:32:42 +02:00
}
2018-06-16 20:23:58 +02:00
mDimensions . push_back ( dimension_ ) ;
2011-06-23 04:41:11 +02:00
dim = dim - > link ( ) - > next ( ) ;
2015-01-30 22:04:26 +01:00
arr = true ;
2011-06-23 04:41:11 +02:00
}
2015-01-30 22:04:26 +01:00
return arr ;
2011-06-23 04:41:11 +02:00
}
2012-01-05 18:22:54 +01:00
static std : : ostream & operator < < ( std : : ostream & s , Scope : : ScopeType type )
{
s < < ( type = = Scope : : eGlobal ? " Global " :
type = = Scope : : eClass ? " Class " :
type = = Scope : : eStruct ? " Struct " :
type = = Scope : : eUnion ? " Union " :
type = = Scope : : eNamespace ? " Namespace " :
type = = Scope : : eFunction ? " Function " :
type = = Scope : : eIf ? " If " :
type = = Scope : : eElse ? " Else " :
type = = Scope : : eFor ? " For " :
type = = Scope : : eWhile ? " While " :
type = = Scope : : eDo ? " Do " :
type = = Scope : : eSwitch ? " Switch " :
2012-01-26 04:05:29 +01:00
type = = Scope : : eTry ? " Try " :
type = = Scope : : eCatch ? " Catch " :
2012-01-05 18:22:54 +01:00
type = = Scope : : eUnconditional ? " Unconditional " :
2014-08-31 10:21:10 +02:00
type = = Scope : : eLambda ? " Lambda " :
2016-04-22 06:02:54 +02:00
type = = Scope : : eEnum ? " Enum " :
2012-01-05 18:22:54 +01:00
" Unknown " ) ;
return s ;
}
2017-04-29 07:18:16 +02:00
static std : : string accessControlToString ( const AccessControl & access )
{
switch ( access ) {
2019-07-23 14:29:02 +02:00
case AccessControl : : Public :
2017-04-29 07:18:16 +02:00
return " Public " ;
2019-07-23 14:29:02 +02:00
case AccessControl : : Protected :
2017-04-29 07:18:16 +02:00
return " Protected " ;
2019-07-23 14:29:02 +02:00
case AccessControl : : Private :
2017-04-29 07:18:16 +02:00
return " Private " ;
2019-07-23 14:29:02 +02:00
case AccessControl : : Global :
2017-04-29 07:18:16 +02:00
return " Global " ;
2019-07-23 14:29:02 +02:00
case AccessControl : : Namespace :
2017-04-29 07:18:16 +02:00
return " Namespace " ;
2019-07-23 14:29:02 +02:00
case AccessControl : : Argument :
2017-04-29 07:18:16 +02:00
return " Argument " ;
2019-07-23 14:29:02 +02:00
case AccessControl : : Local :
2017-04-29 07:18:16 +02:00
return " Local " ;
2019-07-23 14:29:02 +02:00
case AccessControl : : Throw :
2017-04-29 07:18:16 +02:00
return " Throw " ;
}
return " Unknown " ;
}
2015-01-09 21:40:50 +01:00
static std : : string tokenToString ( const Token * tok , const Tokenizer * tokenizer )
2015-01-09 21:34:57 +01:00
{
std : : ostringstream oss ;
if ( tok ) {
oss < < tok - > str ( ) < < " " ;
2015-01-09 21:40:50 +01:00
oss < < tokenizer - > list . fileLine ( tok ) < < " " ;
2015-01-09 21:34:57 +01:00
}
oss < < tok ;
return oss . str ( ) ;
}
2015-01-09 21:40:50 +01:00
static std : : string scopeToString ( const Scope * scope , const Tokenizer * tokenizer )
2015-01-09 21:34:57 +01:00
{
std : : ostringstream oss ;
if ( scope ) {
oss < < scope - > type < < " " ;
if ( scope - > classDef )
2015-01-09 21:40:50 +01:00
oss < < tokenizer - > list . fileLine ( scope - > classDef ) < < " " ;
2015-01-09 21:34:57 +01:00
}
oss < < scope ;
return oss . str ( ) ;
}
2017-04-08 01:57:10 +02:00
static std : : string tokenType ( const Token * tok )
{
std : : ostringstream oss ;
if ( tok ) {
if ( tok - > isUnsigned ( ) )
oss < < " unsigned " ;
else if ( tok - > isSigned ( ) )
oss < < " signed " ;
if ( tok - > isComplex ( ) )
oss < < " _Complex " ;
if ( tok - > isLong ( ) )
oss < < " long " ;
oss < < tok - > str ( ) ;
}
return oss . str ( ) ;
}
2012-01-05 18:22:54 +01:00
void SymbolDatabase : : printVariable ( const Variable * var , const char * indent ) const
{
2018-06-16 16:10:28 +02:00
std : : cout < < indent < < " mNameToken: " < < tokenToString ( var - > nameToken ( ) , mTokenizer ) < < std : : endl ;
2012-01-05 18:24:27 +01:00
if ( var - > nameToken ( ) ) {
2013-07-20 12:31:04 +02:00
std : : cout < < indent < < " declarationId: " < < var - > declarationId ( ) < < std : : endl ;
2015-01-09 21:34:57 +01:00
}
2018-06-16 16:10:28 +02:00
std : : cout < < indent < < " mTypeStartToken: " < < tokenToString ( var - > typeStartToken ( ) , mTokenizer ) < < std : : endl ;
std : : cout < < indent < < " mTypeEndToken: " < < tokenToString ( var - > typeEndToken ( ) , mTokenizer ) < < std : : endl ;
2017-04-08 01:57:10 +02:00
const Token * autoTok = nullptr ;
std : : cout < < indent < < " " ;
for ( const Token * tok = var - > typeStartToken ( ) ; tok ! = var - > typeEndToken ( ) - > next ( ) ; tok = tok - > next ( ) ) {
std : : cout < < " " < < tokenType ( tok ) ;
if ( tok - > str ( ) = = " auto " )
autoTok = tok ;
}
std : : cout < < std : : endl ;
if ( autoTok ) {
const ValueType * valueType = autoTok - > valueType ( ) ;
std : : cout < < indent < < " auto valueType: " < < valueType < < std : : endl ;
if ( var - > typeStartToken ( ) - > valueType ( ) ) {
std : : cout < < indent < < " " < < valueType - > str ( ) < < std : : endl ;
}
}
2018-06-16 16:11:40 +02:00
std : : cout < < indent < < " mIndex: " < < var - > index ( ) < < std : : endl ;
2018-11-04 13:29:29 +01:00
std : : cout < < indent < < " mAccess: " < < accessControlToString ( var - > accessControl ( ) ) < < std : : endl ;
2018-06-16 16:14:34 +02:00
std : : cout < < indent < < " mFlags: " < < std : : endl ;
2015-01-09 21:34:57 +01:00
std : : cout < < indent < < " isMutable: " < < var - > isMutable ( ) < < std : : endl ;
std : : cout < < indent < < " isStatic: " < < var - > isStatic ( ) < < std : : endl ;
std : : cout < < indent < < " isExtern: " < < var - > isExtern ( ) < < std : : endl ;
std : : cout < < indent < < " isLocal: " < < var - > isLocal ( ) < < std : : endl ;
std : : cout < < indent < < " isConst: " < < var - > isConst ( ) < < std : : endl ;
std : : cout < < indent < < " isClass: " < < var - > isClass ( ) < < std : : endl ;
std : : cout < < indent < < " isArray: " < < var - > isArray ( ) < < std : : endl ;
std : : cout < < indent < < " isPointer: " < < var - > isPointer ( ) < < std : : endl ;
std : : cout < < indent < < " isReference: " < < var - > isReference ( ) < < std : : endl ;
std : : cout < < indent < < " isRValueRef: " < < var - > isRValueReference ( ) < < std : : endl ;
std : : cout < < indent < < " hasDefault: " < < var - > hasDefault ( ) < < std : : endl ;
std : : cout < < indent < < " isStlType: " < < var - > isStlType ( ) < < std : : endl ;
2018-06-16 20:25:54 +02:00
std : : cout < < indent < < " mType: " ;
2012-01-05 18:24:27 +01:00
if ( var - > type ( ) ) {
2016-08-04 09:06:32 +02:00
std : : cout < < var - > type ( ) - > type ( ) < < " " < < var - > type ( ) - > name ( ) ;
2018-06-16 16:10:28 +02:00
std : : cout < < " " < < mTokenizer - > list . fileLine ( var - > type ( ) - > classDef ) ;
2015-02-04 06:08:41 +01:00
std : : cout < < " " < < var - > type ( ) < < std : : endl ;
2012-01-05 18:24:27 +01:00
} else
2012-01-05 18:22:54 +01:00
std : : cout < < " none " < < std : : endl ;
2017-04-08 01:57:10 +02:00
if ( var - > nameToken ( ) ) {
const ValueType * valueType = var - > nameToken ( ) - > valueType ( ) ;
std : : cout < < indent < < " valueType: " < < valueType < < std : : endl ;
if ( valueType ) {
std : : cout < < indent < < " " < < valueType - > str ( ) < < std : : endl ;
}
}
2018-06-16 20:29:17 +02:00
std : : cout < < indent < < " mScope: " < < scopeToString ( var - > scope ( ) , mTokenizer ) < < std : : endl ;
2012-01-05 18:22:54 +01:00
2018-06-16 20:23:58 +02:00
std : : cout < < indent < < " mDimensions: " ;
2012-07-08 23:39:46 +02:00
for ( std : : size_t i = 0 ; i < var - > dimensions ( ) . size ( ) ; i + + ) {
2012-01-05 18:24:27 +01:00
std : : cout < < " " < < var - > dimension ( i ) ;
2012-09-10 16:14:24 +02:00
if ( ! var - > dimensions ( ) [ i ] . known )
std : : cout < < " ? " ;
2012-01-05 18:22:54 +01:00
}
std : : cout < < std : : endl ;
}
void SymbolDatabase : : printOut ( const char * title ) const
{
2015-01-09 21:34:57 +01:00
std : : cout < < std : : setiosflags ( std : : ios : : boolalpha ) ;
2012-01-05 18:22:54 +01:00
if ( title )
std : : cout < < " \n ### " < < title < < " ### \n " ;
2013-03-05 15:28:40 +01:00
for ( std : : list < Scope > : : const_iterator scope = scopeList . begin ( ) ; scope ! = scopeList . end ( ) ; + + scope ) {
2015-01-09 21:34:57 +01:00
std : : cout < < " Scope: " < < & * scope < < " " < < scope - > type < < std : : endl ;
2012-01-05 18:22:54 +01:00
std : : cout < < " className: " < < scope - > className < < std : : endl ;
2018-06-16 16:10:28 +02:00
std : : cout < < " classDef: " < < tokenToString ( scope - > classDef , mTokenizer ) < < std : : endl ;
std : : cout < < " bodyStart: " < < tokenToString ( scope - > bodyStart , mTokenizer ) < < std : : endl ;
std : : cout < < " bodyEnd: " < < tokenToString ( scope - > bodyEnd , mTokenizer ) < < std : : endl ;
2012-01-05 18:22:54 +01:00
std : : list < Function > : : const_iterator func ;
// find the function body if not implemented inline
2012-01-05 18:24:27 +01:00
for ( func = scope - > functionList . begin ( ) ; func ! = scope - > functionList . end ( ) ; + + func ) {
2012-01-05 18:22:54 +01:00
std : : cout < < " Function: " < < & * func < < std : : endl ;
2018-06-16 16:10:28 +02:00
std : : cout < < " name: " < < tokenToString ( func - > tokenDef , mTokenizer ) < < std : : endl ;
2012-01-05 18:22:54 +01:00
std : : cout < < " type: " < < ( func - > type = = Function : : eConstructor ? " Constructor " :
func - > type = = Function : : eCopyConstructor ? " CopyConstructor " :
2013-04-04 19:53:55 +02:00
func - > type = = Function : : eMoveConstructor ? " MoveConstructor " :
2012-01-05 18:22:54 +01:00
func - > type = = Function : : eOperatorEqual ? " OperatorEqual " :
func - > type = = Function : : eDestructor ? " Destructor " :
func - > type = = Function : : eFunction ? " Function " :
2019-07-11 08:25:25 +02:00
func - > type = = Function : : eLambda ? " Lambda " :
2015-01-09 21:34:57 +01:00
" Unknown " ) < < std : : endl ;
2018-11-04 13:29:29 +01:00
std : : cout < < " access: " < < accessControlToString ( func - > access ) < < std : : endl ;
2015-01-09 21:34:57 +01:00
std : : cout < < " hasBody: " < < func - > hasBody ( ) < < std : : endl ;
std : : cout < < " isInline: " < < func - > isInline ( ) < < std : : endl ;
std : : cout < < " isConst: " < < func - > isConst ( ) < < std : : endl ;
2019-07-04 12:32:32 +02:00
std : : cout < < " hasVirtualSpecifier: " < < func - > hasVirtualSpecifier ( ) < < std : : endl ;
2015-01-09 21:34:57 +01:00
std : : cout < < " isPure: " < < func - > isPure ( ) < < std : : endl ;
std : : cout < < " isStatic: " < < func - > isStatic ( ) < < std : : endl ;
std : : cout < < " isStaticLocal: " < < func - > isStaticLocal ( ) < < std : : endl ;
std : : cout < < " isExtern: " < < func - > isExtern ( ) < < std : : endl ;
std : : cout < < " isFriend: " < < func - > isFriend ( ) < < std : : endl ;
std : : cout < < " isExplicit: " < < func - > isExplicit ( ) < < std : : endl ;
std : : cout < < " isDefault: " < < func - > isDefault ( ) < < std : : endl ;
std : : cout < < " isDelete: " < < func - > isDelete ( ) < < std : : endl ;
2018-12-13 06:34:10 +01:00
std : : cout < < " hasOverrideSpecifier: " < < func - > hasOverrideSpecifier ( ) < < std : : endl ;
std : : cout < < " hasFinalSpecifier: " < < func - > hasFinalSpecifier ( ) < < std : : endl ;
2015-01-09 21:34:57 +01:00
std : : cout < < " isNoExcept: " < < func - > isNoExcept ( ) < < std : : endl ;
std : : cout < < " isThrow: " < < func - > isThrow ( ) < < std : : endl ;
std : : cout < < " isOperator: " < < func - > isOperator ( ) < < std : : endl ;
2016-01-02 18:53:51 +01:00
std : : cout < < " hasLvalRefQual: " < < func - > hasLvalRefQualifier ( ) < < std : : endl ;
std : : cout < < " hasRvalRefQual: " < < func - > hasRvalRefQualifier ( ) < < std : : endl ;
2016-08-02 08:58:11 +02:00
std : : cout < < " isVariadic: " < < func - > isVariadic ( ) < < std : : endl ;
2018-05-10 07:40:01 +02:00
std : : cout < < " isVolatile: " < < func - > isVolatile ( ) < < std : : endl ;
2018-12-13 06:34:10 +01:00
std : : cout < < " hasTrailingReturnType: " < < func - > hasTrailingReturnType ( ) < < std : : endl ;
2015-01-09 21:34:57 +01:00
std : : cout < < " attributes: " ;
if ( func - > isAttributeConst ( ) )
std : : cout < < " const " ;
if ( func - > isAttributePure ( ) )
std : : cout < < " pure " ;
if ( func - > isAttributeNoreturn ( ) )
std : : cout < < " noreturn " ;
if ( func - > isAttributeNothrow ( ) )
std : : cout < < " nothrow " ;
if ( func - > isAttributeConstructor ( ) )
std : : cout < < " constructor " ;
if ( func - > isAttributeDestructor ( ) )
std : : cout < < " destructor " ;
2018-05-29 21:43:56 +02:00
if ( func - > isAttributeNodiscard ( ) )
std : : cout < < " nodiscard " ;
2015-01-09 21:34:57 +01:00
std : : cout < < std : : endl ;
2014-04-10 16:17:10 +02:00
std : : cout < < " noexceptArg: " < < ( func - > noexceptArg ? func - > noexceptArg - > str ( ) : " none " ) < < std : : endl ;
std : : cout < < " throwArg: " < < ( func - > throwArg ? func - > throwArg - > str ( ) : " none " ) < < std : : endl ;
2018-06-16 16:10:28 +02:00
std : : cout < < " tokenDef: " < < tokenToString ( func - > tokenDef , mTokenizer ) < < std : : endl ;
std : : cout < < " argDef: " < < tokenToString ( func - > argDef , mTokenizer ) < < std : : endl ;
2013-09-03 10:48:01 +02:00
if ( ! func - > isConstructor ( ) & & ! func - > isDestructor ( ) )
2018-06-16 16:10:28 +02:00
std : : cout < < " retDef: " < < tokenToString ( func - > retDef , mTokenizer ) < < std : : endl ;
2017-04-08 01:57:10 +02:00
if ( func - > retDef ) {
std : : cout < < " " ;
2018-12-13 06:34:10 +01:00
for ( const Token * tok = func - > retDef ; tok & & tok ! = func - > tokenDef & & ! Token : : Match ( tok , " {|;|override|final " ) ; tok = tok - > next ( ) )
2017-04-08 01:57:10 +02:00
std : : cout < < " " < < tokenType ( tok ) ;
std : : cout < < std : : endl ;
}
2013-08-26 06:03:26 +02:00
std : : cout < < " retType: " < < func - > retType < < std : : endl ;
2017-04-08 01:57:10 +02:00
if ( func - > tokenDef - > next ( ) - > valueType ( ) ) {
const ValueType * valueType = func - > tokenDef - > next ( ) - > valueType ( ) ;
std : : cout < < " valueType: " < < valueType < < std : : endl ;
if ( valueType ) {
std : : cout < < " " < < valueType - > str ( ) < < std : : endl ;
}
}
2015-01-08 05:45:31 +01:00
if ( func - > hasBody ( ) ) {
2018-06-16 16:10:28 +02:00
std : : cout < < " token: " < < tokenToString ( func - > token , mTokenizer ) < < std : : endl ;
std : : cout < < " arg: " < < tokenToString ( func - > arg , mTokenizer ) < < std : : endl ;
2012-03-23 17:59:51 +01:00
}
2018-06-16 16:10:28 +02:00
std : : cout < < " nestedIn: " < < scopeToString ( func - > nestedIn , mTokenizer ) < < std : : endl ;
std : : cout < < " functionScope: " < < scopeToString ( func - > functionScope , mTokenizer ) < < std : : endl ;
2012-01-05 18:22:54 +01:00
std : : list < Variable > : : const_iterator var ;
2012-01-05 18:24:27 +01:00
for ( var = func - > argumentList . begin ( ) ; var ! = func - > argumentList . end ( ) ; + + var ) {
2012-01-05 18:22:54 +01:00
std : : cout < < " Variable: " < < & * var < < std : : endl ;
printVariable ( & * var , " " ) ;
}
}
std : : list < Variable > : : const_iterator var ;
2012-01-05 18:24:27 +01:00
for ( var = scope - > varlist . begin ( ) ; var ! = scope - > varlist . end ( ) ; + + var ) {
2012-01-05 18:22:54 +01:00
std : : cout < < " Variable: " < < & * var < < std : : endl ;
printVariable ( & * var , " " ) ;
}
2016-04-22 06:02:54 +02:00
if ( scope - > type = = Scope : : eEnum ) {
std : : cout < < " enumType: " ;
if ( scope - > enumType )
scope - > enumType - > stringify ( std : : cout , false , true , false ) ;
else
std : : cout < < " int " ;
std : : cout < < std : : endl ;
std : : cout < < " enumClass: " < < scope - > enumClass < < std : : endl ;
2016-04-25 11:12:35 +02:00
for ( std : : vector < Enumerator > : : const_iterator enumerator = scope - > enumeratorList . begin ( ) ; enumerator ! = scope - > enumeratorList . end ( ) ; + + enumerator ) {
2016-04-24 23:02:56 +02:00
std : : cout < < " Enumerator: " < < enumerator - > name - > str ( ) < < " = " ;
if ( enumerator - > value_known ) {
std : : cout < < enumerator - > value ;
2016-04-22 06:02:54 +02:00
}
2016-04-24 23:02:56 +02:00
if ( enumerator - > start ) {
const Token * tok = enumerator - > start ;
std : : cout < < ( enumerator - > value_known ? " " : " " ) < < " [ " < < tok - > str ( ) ;
while ( tok & & tok ! = enumerator - > end ) {
2016-04-22 06:02:54 +02:00
if ( tok - > next ( ) )
std : : cout < < " " < < tok - > next ( ) - > str ( ) ;
tok = tok - > next ( ) ;
}
std : : cout < < " ] " ;
}
std : : cout < < std : : endl ;
}
}
2012-01-05 18:22:54 +01:00
std : : cout < < " nestedIn: " < < scope - > nestedIn ;
2012-01-05 18:24:27 +01:00
if ( scope - > nestedIn ) {
std : : cout < < " " < < scope - > nestedIn - > type < < " "
2012-01-23 04:32:53 +01:00
< < scope - > nestedIn - > className ;
2012-01-05 18:22:54 +01:00
}
2012-01-23 04:32:53 +01:00
std : : cout < < std : : endl ;
2012-01-05 18:22:54 +01:00
2013-03-14 06:34:12 +01:00
std : : cout < < " definedType: " < < scope - > definedType < < std : : endl ;
2013-03-05 15:28:40 +01:00
2012-01-05 18:22:54 +01:00
std : : cout < < " nestedList[ " < < scope - > nestedList . size ( ) < < " ] = ( " ;
std : : list < Scope * > : : const_iterator nsi ;
2013-03-05 15:28:40 +01:00
std : : size_t count = scope - > nestedList . size ( ) ;
2012-01-05 18:24:27 +01:00
for ( nsi = scope - > nestedList . begin ( ) ; nsi ! = scope - > nestedList . end ( ) ; + + nsi ) {
2012-11-30 06:03:58 +01:00
std : : cout < < " " < < ( * nsi ) < < " " < < ( * nsi ) - > type < < " " < < ( * nsi ) - > className ;
2012-01-05 18:22:54 +01:00
if ( count - - > 1 )
std : : cout < < " , " ;
}
std : : cout < < " ) " < < std : : endl ;
2012-12-20 06:53:04 +01:00
std : : list < Scope : : UsingInfo > : : const_iterator use ;
2012-01-05 18:22:54 +01:00
2012-01-05 18:24:27 +01:00
for ( use = scope - > usingList . begin ( ) ; use ! = scope - > usingList . end ( ) ; + + use ) {
2012-12-20 06:53:04 +01:00
std : : cout < < " using: " < < use - > scope < < " " < < use - > start - > strAt ( 2 ) ;
const Token * tok1 = use - > start - > tokAt ( 3 ) ;
2012-01-05 18:24:27 +01:00
while ( tok1 & & tok1 - > str ( ) = = " :: " ) {
2012-01-05 18:22:54 +01:00
std : : cout < < " :: " < < tok1 - > strAt ( 1 ) ;
tok1 = tok1 - > tokAt ( 2 ) ;
}
2018-06-16 16:10:28 +02:00
std : : cout < < " " < < mTokenizer - > list . fileLine ( use - > start ) < < std : : endl ;
2012-01-05 18:22:54 +01:00
}
2018-06-16 16:10:28 +02:00
std : : cout < < " functionOf: " < < scopeToString ( scope - > functionOf , mTokenizer ) < < std : : endl ;
2012-01-05 18:22:54 +01:00
std : : cout < < " function: " < < scope - > function ;
2015-01-09 21:34:57 +01:00
if ( scope - > function )
std : : cout < < " " < < scope - > function - > name ( ) ;
2012-01-05 18:22:54 +01:00
std : : cout < < std : : endl ;
}
2013-03-05 15:28:40 +01:00
for ( std : : list < Type > : : const_iterator type = typeList . begin ( ) ; type ! = typeList . end ( ) ; + + type ) {
2013-08-19 06:06:53 +02:00
std : : cout < < " Type: " < < & ( * type ) < < std : : endl ;
std : : cout < < " name: " < < type - > name ( ) < < std : : endl ;
2018-06-16 16:10:28 +02:00
std : : cout < < " classDef: " < < tokenToString ( type - > classDef , mTokenizer ) < < std : : endl ;
2013-03-05 15:28:40 +01:00
std : : cout < < " classScope: " < < type - > classScope < < std : : endl ;
2018-09-24 06:40:20 +02:00
std : : cout < < " enclosingScope: " < < type - > enclosingScope ;
if ( type - > enclosingScope ) {
std : : cout < < " " < < type - > enclosingScope - > type < < " "
< < type - > enclosingScope - > className ;
}
std : : cout < < std : : endl ;
2019-08-02 21:14:29 +02:00
std : : cout < < " needInitialization: " < < ( type - > needInitialization = = Type : : NeedInitialization : : Unknown ? " Unknown " :
type - > needInitialization = = Type : : NeedInitialization : : True ? " True " :
type - > needInitialization = = Type : : NeedInitialization : : False ? " False " :
2013-03-05 15:28:40 +01:00
" Invalid " ) < < std : : endl ;
std : : cout < < " derivedFrom[ " < < type - > derivedFrom . size ( ) < < " ] = ( " ;
std : : size_t count = type - > derivedFrom . size ( ) ;
2019-09-19 20:29:33 +02:00
for ( const Type : : BaseInfo & i : type - > derivedFrom ) {
if ( i . isVirtual )
2013-03-05 15:28:40 +01:00
std : : cout < < " Virtual " ;
2019-09-19 20:29:33 +02:00
std : : cout < < ( i . access = = AccessControl : : Public ? " Public " :
i . access = = AccessControl : : Protected ? " Protected " :
i . access = = AccessControl : : Private ? " Private " :
2013-03-05 15:28:40 +01:00
" Unknown " ) ;
2019-09-19 20:29:33 +02:00
if ( i . type )
std : : cout < < " " < < i . type ;
2013-03-05 15:28:40 +01:00
else
std : : cout < < " Unknown " ;
2019-09-19 20:29:33 +02:00
std : : cout < < " " < < i . name ;
2013-03-05 15:28:40 +01:00
if ( count - - > 1 )
std : : cout < < " , " ;
}
std : : cout < < " ) " < < std : : endl ;
std : : cout < < " friendList[ " < < type - > friendList . size ( ) < < " ] = ( " ;
2018-05-14 12:18:59 +02:00
for ( size_t i = 0 ; i < type - > friendList . size ( ) ; i + + ) {
if ( type - > friendList [ i ] . type )
std : : cout < < type - > friendList [ i ] . type ;
2013-03-05 15:28:40 +01:00
else
std : : cout < < " Unknown " ;
2018-05-14 15:24:09 +02:00
std : : cout < < ' ' ;
if ( type - > friendList [ i ] . nameEnd )
std : : cout < < type - > friendList [ i ] . nameEnd - > str ( ) ;
2018-05-14 12:18:59 +02:00
if ( i + 1 < type - > friendList . size ( ) )
2018-05-14 15:24:09 +02:00
std : : cout < < ' , ' ;
2013-03-05 15:28:40 +01:00
}
std : : cout < < " ) " < < std : : endl ;
}
2018-06-16 20:31:47 +02:00
for ( std : : size_t i = 1 ; i < mVariableList . size ( ) ; i + + ) {
std : : cout < < " mVariableList[ " < < i < < " ]: " < < mVariableList [ i ] ;
if ( mVariableList [ i ] ) {
std : : cout < < " " < < mVariableList [ i ] - > name ( ) < < " "
< < mTokenizer - > list . fileLine ( mVariableList [ i ] - > nameToken ( ) ) ;
2013-03-13 06:31:13 +01:00
}
std : : cout < < std : : endl ;
2012-01-05 18:22:54 +01:00
}
2015-01-09 21:34:57 +01:00
std : : cout < < std : : resetiosflags ( std : : ios : : boolalpha ) ;
2012-01-05 18:22:54 +01:00
}
2014-07-14 15:51:45 +02:00
void SymbolDatabase : : printXml ( std : : ostream & out ) const
2014-07-13 17:21:45 +02:00
{
2015-01-09 21:34:57 +01:00
out < < std : : setiosflags ( std : : ios : : boolalpha ) ;
2018-04-10 11:10:10 +02:00
std : : set < const Variable * > variables ;
2014-07-13 17:21:45 +02:00
// Scopes..
2014-07-14 15:51:45 +02:00
out < < " <scopes> " < < std : : endl ;
2014-07-13 17:21:45 +02:00
for ( std : : list < Scope > : : const_iterator scope = scopeList . begin ( ) ; scope ! = scopeList . end ( ) ; + + scope ) {
2014-07-14 15:51:45 +02:00
out < < " <scope " ;
out < < " id= \" " < < & * scope < < " \" " ;
out < < " type= \" " < < scope - > type < < " \" " ;
2014-07-13 17:21:45 +02:00
if ( ! scope - > className . empty ( ) )
2015-12-07 18:11:13 +01:00
out < < " className= \" " < < ErrorLogger : : toxml ( scope - > className ) < < " \" " ;
2018-04-27 22:36:30 +02:00
if ( scope - > bodyStart )
out < < " bodyStart= \" " < < scope - > bodyStart < < ' \" ' ;
if ( scope - > bodyEnd )
out < < " bodyEnd= \" " < < scope - > bodyEnd < < ' \" ' ;
2014-07-14 15:51:45 +02:00
if ( scope - > nestedIn )
out < < " nestedIn= \" " < < scope - > nestedIn < < " \" " ;
2014-07-20 11:44:01 +02:00
if ( scope - > function )
out < < " function= \" " < < scope - > function < < " \" " ;
if ( scope - > functionList . empty ( ) & & scope - > varlist . empty ( ) )
2014-07-14 15:51:45 +02:00
out < < " /> " < < std : : endl ;
2014-07-20 11:44:01 +02:00
else {
2014-07-14 15:51:45 +02:00
out < < ' > ' < < std : : endl ;
if ( ! scope - > functionList . empty ( ) ) {
out < < " <functionList> " < < std : : endl ;
for ( std : : list < Function > : : const_iterator function = scope - > functionList . begin ( ) ; function ! = scope - > functionList . end ( ) ; + + function ) {
2015-12-07 18:11:13 +01:00
out < < " <function id= \" " < < & * function < < " \" tokenDef= \" " < < function - > tokenDef < < " \" name= \" " < < ErrorLogger : : toxml ( function - > name ( ) ) < < ' \" ' ;
2018-04-30 16:52:51 +02:00
out < < " type= \" " < < ( function - > type = = Function : : eConstructor ? " Constructor " :
function - > type = = Function : : eCopyConstructor ? " CopyConstructor " :
function - > type = = Function : : eMoveConstructor ? " MoveConstructor " :
function - > type = = Function : : eOperatorEqual ? " OperatorEqual " :
function - > type = = Function : : eDestructor ? " Destructor " :
function - > type = = Function : : eFunction ? " Function " :
2019-07-11 08:25:25 +02:00
function - > type = = Function : : eLambda ? " Lambda " :
2018-04-30 16:52:51 +02:00
" Unknown " ) < < ' \" ' ;
2018-04-13 21:15:43 +02:00
if ( function - > nestedIn - > definedType ) {
2019-07-04 12:32:32 +02:00
if ( function - > hasVirtualSpecifier ( ) )
out < < " hasVirtualSpecifier= \" true \" " ;
2018-04-13 21:15:43 +02:00
else if ( function - > isImplicitlyVirtual ( ) )
out < < " isImplicitlyVirtual= \" true \" " ;
}
2014-07-14 15:51:45 +02:00
if ( function - > argCount ( ) = = 0U )
out < < " /> " < < std : : endl ;
else {
out < < " > " < < std : : endl ;
for ( unsigned int argnr = 0 ; argnr < function - > argCount ( ) ; + + argnr ) {
const Variable * arg = function - > getArgumentVar ( argnr ) ;
2014-07-14 18:35:15 +02:00
out < < " <arg nr= \" " < < argnr + 1 < < " \" variable= \" " < < arg < < " \" /> " < < std : : endl ;
2018-04-10 11:10:10 +02:00
variables . insert ( arg ) ;
2014-07-14 15:51:45 +02:00
}
out < < " </function> " < < std : : endl ;
}
}
out < < " </functionList> " < < std : : endl ;
}
2014-07-14 19:25:30 +02:00
if ( ! scope - > varlist . empty ( ) ) {
out < < " <varlist> " < < std : : endl ;
for ( std : : list < Variable > : : const_iterator var = scope - > varlist . begin ( ) ; var ! = scope - > varlist . end ( ) ; + + var )
out < < " <var id= \" " < < & * var < < " \" /> " < < std : : endl ;
out < < " </varlist> " < < std : : endl ;
}
out < < " </scope> " < < std : : endl ;
2014-07-14 15:51:45 +02:00
}
2014-07-13 17:21:45 +02:00
}
2014-07-14 15:51:45 +02:00
out < < " </scopes> " < < std : : endl ;
2014-07-14 18:35:15 +02:00
// Variables..
2018-06-16 20:31:47 +02:00
for ( const Variable * var : mVariableList )
2018-04-10 11:10:10 +02:00
variables . insert ( var ) ;
2014-07-14 18:35:15 +02:00
out < < " <variables> " < < std : : endl ;
2018-04-10 11:10:10 +02:00
for ( const Variable * var : variables ) {
2014-07-14 19:17:39 +02:00
if ( ! var )
continue ;
2014-07-14 18:35:15 +02:00
out < < " <var id= \" " < < var < < ' \" ' ;
out < < " nameToken= \" " < < var - > nameToken ( ) < < ' \" ' ;
out < < " typeStartToken= \" " < < var - > typeStartToken ( ) < < ' \" ' ;
out < < " typeEndToken= \" " < < var - > typeEndToken ( ) < < ' \" ' ;
2018-06-19 08:50:32 +02:00
out < < " access= \" " < < accessControlToString ( var - > mAccess ) < < ' \" ' ;
out < < " scope= \" " < < var - > scope ( ) < < ' \" ' ;
2018-06-20 14:13:04 +02:00
out < < " constness= \" " < < var - > valueType ( ) - > constness < < ' \" ' ;
2015-01-09 21:34:57 +01:00
out < < " isArgument= \" " < < var - > isArgument ( ) < < ' \" ' ;
out < < " isArray= \" " < < var - > isArray ( ) < < ' \" ' ;
out < < " isClass= \" " < < var - > isClass ( ) < < ' \" ' ;
2018-03-14 11:54:23 +01:00
out < < " isConst= \" " < < var - > isConst ( ) < < ' \" ' ;
2017-04-17 07:45:27 +02:00
out < < " isExtern= \" " < < var - > isExtern ( ) < < ' \" ' ;
2015-01-09 21:34:57 +01:00
out < < " isLocal= \" " < < var - > isLocal ( ) < < ' \" ' ;
out < < " isPointer= \" " < < var - > isPointer ( ) < < ' \" ' ;
out < < " isReference= \" " < < var - > isReference ( ) < < ' \" ' ;
out < < " isStatic= \" " < < var - > isStatic ( ) < < ' \" ' ;
2014-07-14 18:35:15 +02:00
out < < " /> " < < std : : endl ;
}
out < < " </variables> " < < std : : endl ;
2015-01-09 21:34:57 +01:00
out < < std : : resetiosflags ( std : : ios : : boolalpha ) ;
2014-07-13 17:21:45 +02:00
}
2011-01-15 07:59:37 +01:00
//---------------------------------------------------------------------------
2015-12-18 08:24:02 +01:00
static const Type * findVariableTypeIncludingUsedNamespaces ( const SymbolDatabase * symbolDatabase , const Scope * scope , const Token * typeTok )
{
const Type * argType = symbolDatabase - > findVariableType ( scope , typeTok ) ;
if ( argType )
return argType ;
// look for variable type in any using namespace in this scope or above
while ( scope ) {
2018-04-23 21:45:25 +02:00
for ( const Scope : : UsingInfo & ui : scope - > usingList ) {
if ( ui . scope ) {
argType = symbolDatabase - > findVariableType ( ui . scope , typeTok ) ;
2015-12-18 08:24:02 +01:00
if ( argType )
return argType ;
}
}
scope = scope - > nestedIn ;
}
return nullptr ;
}
//---------------------------------------------------------------------------
2012-04-27 21:51:13 +02:00
void Function : : addArguments ( const SymbolDatabase * symbolDatabase , const Scope * scope )
2011-02-26 21:51:12 +01:00
{
// check for non-empty argument list "( ... )"
2012-10-30 15:48:06 +01:00
const Token * start = arg ? arg : argDef ;
2019-07-05 12:30:42 +02:00
if ( ! Token : : simpleMatch ( start , " ( " ) )
return ;
2017-07-09 13:09:36 +02:00
if ( ! ( start & & start - > link ( ) ! = start - > next ( ) & & ! Token : : simpleMatch ( start , " ( void ) " ) ) )
return ;
2014-09-19 09:29:31 +02:00
2017-07-09 13:09:36 +02:00
unsigned int count = 0 ;
2011-02-26 21:51:12 +01:00
2017-07-09 13:09:36 +02:00
for ( const Token * tok = start - > next ( ) ; tok ; tok = tok - > next ( ) ) {
if ( Token : : Match ( tok , " ,|) " ) )
return ; // Syntax error
2011-03-03 03:08:27 +01:00
2017-07-09 13:09:36 +02:00
const Token * startTok = tok ;
const Token * endTok = nullptr ;
const Token * nameTok = nullptr ;
2011-04-29 02:53:31 +02:00
2017-07-09 13:09:36 +02:00
do {
2019-03-30 07:44:36 +01:00
if ( tok ! = startTok & & ! nameTok & & Token : : Match ( tok , " ( & %var% ) [ " ) ) {
nameTok = tok - > tokAt ( 2 ) ;
endTok = nameTok - > previous ( ) ;
tok = tok - > link ( ) ;
} else if ( tok - > varId ( ) ! = 0 ) {
2017-07-09 13:09:36 +02:00
nameTok = tok ;
endTok = tok - > previous ( ) ;
} else if ( tok - > str ( ) = = " [ " ) {
// skip array dimension(s)
tok = tok - > link ( ) ;
while ( tok - > next ( ) - > str ( ) = = " [ " )
tok = tok - > next ( ) - > link ( ) ;
} else if ( tok - > str ( ) = = " < " ) {
tok = tok - > link ( ) ;
if ( ! tok ) // something is wrong so just bail out
2011-04-29 02:53:31 +02:00
return ;
2017-07-09 13:09:36 +02:00
}
2011-02-26 21:51:12 +01:00
2017-07-09 13:09:36 +02:00
tok = tok - > next ( ) ;
if ( ! tok ) // something is wrong so just bail
return ;
} while ( tok - > str ( ) ! = " , " & & tok - > str ( ) ! = " ) " & & tok - > str ( ) ! = " = " ) ;
const Token * typeTok = startTok ;
// skip over stuff to get to type
2018-05-10 07:40:01 +02:00
while ( Token : : Match ( typeTok , " const|volatile|enum|struct|:: " ) )
2017-07-09 13:09:36 +02:00
typeTok = typeTok - > next ( ) ;
2018-01-18 08:51:35 +01:00
if ( Token : : Match ( typeTok , " ,|) " ) ) { // #8333
2018-06-16 16:10:28 +02:00
symbolDatabase - > mTokenizer - > syntaxError ( typeTok ) ;
2018-01-18 08:51:35 +01:00
return ;
}
2017-07-09 13:09:36 +02:00
// skip over qualification
while ( Token : : Match ( typeTok , " %type% :: " ) )
typeTok = typeTok - > tokAt ( 2 ) ;
// check for argument with no name or missing varid
if ( ! endTok ) {
2018-05-10 07:40:01 +02:00
if ( tok - > previous ( ) - > isName ( ) & & ! Token : : Match ( tok - > tokAt ( - 1 ) , " const|volatile " ) ) {
2017-07-09 13:09:36 +02:00
if ( tok - > previous ( ) ! = typeTok ) {
nameTok = tok - > previous ( ) ;
endTok = nameTok - > previous ( ) ;
if ( hasBody ( ) )
symbolDatabase - > debugMessage ( nameTok , " Function::addArguments found argument \' " + nameTok - > str ( ) + " \' with varid 0. " ) ;
2011-10-13 20:53:06 +02:00
} else
2017-07-09 13:09:36 +02:00
endTok = typeTok ;
} else
endTok = tok - > previous ( ) ;
}
2011-02-26 21:51:12 +01:00
2017-07-09 13:09:36 +02:00
const : : Type * argType = nullptr ;
if ( ! typeTok - > isStandardType ( ) ) {
argType = findVariableTypeIncludingUsedNamespaces ( symbolDatabase , scope , typeTok ) ;
2016-04-22 06:02:54 +02:00
2017-07-09 13:09:36 +02:00
// save type
const_cast < Token * > ( typeTok ) - > type ( argType ) ;
}
2011-02-26 21:51:12 +01:00
2017-07-09 13:09:36 +02:00
// skip default values
if ( tok - > str ( ) = = " = " ) {
do {
if ( tok - > link ( ) & & Token : : Match ( tok , " [{[(<] " ) )
tok = tok - > link ( ) ;
tok = tok - > next ( ) ;
} while ( tok - > str ( ) ! = " , " & & tok - > str ( ) ! = " ) " ) ;
}
2011-03-30 05:16:13 +02:00
2017-07-09 13:09:36 +02:00
// skip over stuff before type
2018-05-10 07:40:01 +02:00
while ( Token : : Match ( startTok , " enum|struct|const|volatile " ) )
2017-07-09 13:09:36 +02:00
startTok = startTok - > next ( ) ;
2016-08-04 09:06:32 +02:00
2019-07-23 14:29:02 +02:00
argumentList . emplace_back ( nameTok , startTok , endTok , count + + , AccessControl : : Argument , argType , functionScope , symbolDatabase - > mSettings ) ;
2011-03-31 03:59:43 +02:00
2017-07-09 13:09:36 +02:00
if ( tok - > str ( ) = = " ) " ) {
// check for a variadic function
2019-09-04 08:07:30 +02:00
if ( Token : : simpleMatch ( startTok , " ... " ) )
2017-07-09 13:09:36 +02:00
isVariadic ( true ) ;
2016-08-02 08:58:11 +02:00
2017-07-09 13:09:36 +02:00
break ;
2011-02-26 21:51:12 +01:00
}
2017-07-09 13:09:36 +02:00
}
2013-02-27 06:59:04 +01:00
2017-07-09 13:09:36 +02:00
// count default arguments
for ( const Token * tok = argDef - > next ( ) ; tok & & tok ! = argDef - > link ( ) ; tok = tok - > next ( ) ) {
if ( tok - > str ( ) = = " = " )
initArgCount + + ;
2011-02-26 21:51:12 +01:00
}
}
2012-04-17 19:50:44 +02:00
bool Function : : isImplicitlyVirtual ( bool defaultVal ) const
{
2019-07-04 12:32:32 +02:00
if ( hasVirtualSpecifier ( ) ) //If it has the virtual specifier it's definitely virtual
return true ;
if ( hasOverrideSpecifier ( ) ) //If it has the override specifier then it's either virtual or not going to compile
2012-04-17 19:50:44 +02:00
return true ;
2018-04-27 11:12:09 +02:00
bool foundAllBaseClasses = true ;
2019-07-04 12:32:32 +02:00
if ( getOverriddenFunction ( & foundAllBaseClasses ) ) //If it overrides a base class's method then it's virtual
2018-04-27 11:12:09 +02:00
return true ;
2019-07-04 12:32:32 +02:00
if ( foundAllBaseClasses ) //If we've seen all the base classes and none of the above were true then it must not be virtual
2018-04-27 11:12:09 +02:00
return false ;
2019-07-04 12:32:32 +02:00
return defaultVal ; //If we can't see all the bases classes then we can't say conclusively
2018-04-25 12:05:49 +02:00
}
2019-01-14 18:36:21 +01:00
const Function * Function : : getOverriddenFunction ( bool * foundAllBaseClasses ) const
2018-04-25 12:05:49 +02:00
{
2018-04-27 11:12:09 +02:00
if ( foundAllBaseClasses )
* foundAllBaseClasses = true ;
2018-04-24 13:53:58 +02:00
if ( ! nestedIn - > isClassOrStruct ( ) )
2018-04-27 11:12:09 +02:00
return nullptr ;
2019-01-14 18:36:21 +01:00
return getOverriddenFunctionRecursive ( nestedIn - > definedType , foundAllBaseClasses ) ;
2012-04-17 19:50:44 +02:00
}
2019-01-14 18:36:21 +01:00
const Function * Function : : getOverriddenFunctionRecursive ( const : : Type * baseType , bool * foundAllBaseClasses ) const
2012-04-17 19:50:44 +02:00
{
// check each base class
2019-09-25 15:25:19 +02:00
for ( const : : Type : : BaseInfo & i : baseType - > derivedFrom ) {
const : : Type * derivedFromType = i . type ;
2012-04-17 19:50:44 +02:00
// check if base class exists in database
2018-04-27 11:12:09 +02:00
if ( ! derivedFromType | | ! derivedFromType - > classScope ) {
if ( foundAllBaseClasses )
* foundAllBaseClasses = false ;
continue ;
}
2012-04-17 19:50:44 +02:00
2018-04-27 11:12:09 +02:00
const Scope * parent = derivedFromType - > classScope ;
2012-04-17 19:50:44 +02:00
2018-04-27 11:12:09 +02:00
// check if function defined in base class
for ( std : : multimap < std : : string , const Function * > : : const_iterator it = parent - > functionMap . find ( tokenDef - > str ( ) ) ; it ! = parent - > functionMap . end ( ) & & it - > first = = tokenDef - > str ( ) ; + + it ) {
const Function * func = it - > second ;
2019-07-04 12:32:32 +02:00
if ( func - > hasVirtualSpecifier ( ) ) { // Base is virtual and of same name
2018-04-27 11:12:09 +02:00
const Token * temp1 = func - > tokenDef - > previous ( ) ;
const Token * temp2 = tokenDef - > previous ( ) ;
bool match = true ;
// check for matching return parameters
while ( temp1 - > str ( ) ! = " virtual " ) {
if ( temp1 - > str ( ) ! = temp2 - > str ( ) & &
! ( temp1 - > str ( ) = = derivedFromType - > name ( ) & &
temp2 - > str ( ) = = baseType - > name ( ) ) ) {
match = false ;
break ;
2012-04-17 19:50:44 +02:00
}
2018-04-27 11:12:09 +02:00
temp1 = temp1 - > previous ( ) ;
temp2 = temp2 - > previous ( ) ;
2012-04-17 19:50:44 +02:00
}
2018-04-27 11:12:09 +02:00
// check for matching function parameters
2018-08-17 08:42:22 +02:00
match = match & & argsMatch ( baseType - > classScope , func - > argDef , argDef , emptyString , 0 ) ;
// check for matching cv-ref qualifiers
match = match
2018-08-17 19:55:21 +02:00
& & isConst ( ) = = func - > isConst ( )
& & isVolatile ( ) = = func - > isVolatile ( )
& & hasRvalRefQualifier ( ) = = func - > hasRvalRefQualifier ( )
& & hasLvalRefQualifier ( ) = = func - > hasLvalRefQualifier ( ) ;
2018-08-17 08:42:22 +02:00
// it's a match
if ( match ) {
2018-04-27 11:12:09 +02:00
return func ;
2014-03-22 08:49:28 +01:00
}
2014-01-05 19:10:16 +01:00
}
2018-04-27 11:12:09 +02:00
}
if ( ! derivedFromType - > derivedFrom . empty ( ) & & ! derivedFromType - > hasCircularDependencies ( ) ) {
// avoid endless recursion, see #5289 Crash: Stack overflow in isImplicitlyVirtual_rec when checking SVN and
// #5590 with a loop within the class hierarchy.
2019-01-14 18:36:21 +01:00
const Function * func = getOverriddenFunctionRecursive ( derivedFromType , foundAllBaseClasses ) ;
2018-04-27 11:12:09 +02:00
if ( func ) {
return func ;
}
2012-04-17 19:50:44 +02:00
}
}
2018-04-27 11:12:09 +02:00
return nullptr ;
2012-04-17 19:50:44 +02:00
}
2019-07-22 11:25:51 +02:00
const Variable * Function : : getArgumentVar ( nonneg int num ) const
2012-05-03 13:29:41 +02:00
{
for ( std : : list < Variable > : : const_iterator i = argumentList . begin ( ) ; i ! = argumentList . end ( ) ; + + i ) {
if ( i - > index ( ) = = num )
2013-08-07 16:27:37 +02:00
return ( & * i ) ;
2012-05-03 13:29:41 +02:00
else if ( i - > index ( ) > num )
2017-08-09 20:00:26 +02:00
return nullptr ;
2012-05-03 13:29:41 +02:00
}
2017-08-09 20:00:26 +02:00
return nullptr ;
2012-05-03 13:29:41 +02:00
}
2012-04-17 19:50:44 +02:00
2010-11-13 08:08:45 +01:00
//---------------------------------------------------------------------------
2013-03-05 18:42:42 +01:00
Scope : : Scope ( const SymbolDatabase * check_ , const Token * classDef_ , const Scope * nestedIn_ , ScopeType type_ , const Token * start_ ) :
2011-02-26 21:53:57 +01:00
check ( check_ ) ,
classDef ( classDef_ ) ,
2018-04-27 22:36:30 +02:00
bodyStart ( start_ ) ,
bodyEnd ( start_ - > link ( ) ) ,
2011-02-26 21:53:57 +01:00
nestedIn ( nestedIn_ ) ,
numConstructors ( 0 ) ,
2013-04-10 21:57:22 +02:00
numCopyOrMoveConstructors ( 0 ) ,
2012-05-14 20:46:23 +02:00
type ( type_ ) ,
2014-02-16 10:32:10 +01:00
definedType ( nullptr ) ,
functionOf ( nullptr ) ,
2016-04-22 06:02:54 +02:00
function ( nullptr ) ,
enumType ( nullptr ) ,
enumClass ( false )
2011-02-26 21:53:57 +01:00
{
}
2013-03-05 18:42:42 +01:00
Scope : : Scope ( const SymbolDatabase * check_ , const Token * classDef_ , const Scope * nestedIn_ ) :
2010-11-13 08:08:45 +01:00
check ( check_ ) ,
classDef ( classDef_ ) ,
2018-04-27 22:36:30 +02:00
bodyStart ( nullptr ) ,
bodyEnd ( nullptr ) ,
2010-11-13 08:08:45 +01:00
nestedIn ( nestedIn_ ) ,
2010-12-02 07:35:01 +01:00
numConstructors ( 0 ) ,
2013-04-10 21:57:22 +02:00
numCopyOrMoveConstructors ( 0 ) ,
2014-02-16 10:32:10 +01:00
definedType ( nullptr ) ,
functionOf ( nullptr ) ,
2016-04-22 06:02:54 +02:00
function ( nullptr ) ,
enumType ( nullptr ) ,
enumClass ( false )
2010-11-13 08:08:45 +01:00
{
2013-03-05 13:33:38 +01:00
const Token * nameTok = classDef ;
2011-10-13 20:53:06 +02:00
if ( ! classDef ) {
2011-01-17 18:29:19 +01:00
type = Scope : : eGlobal ;
2017-01-06 21:16:28 +01:00
} else if ( classDef - > str ( ) = = " class " & & check & & check - > isCPP ( ) ) {
2011-01-17 18:29:19 +01:00
type = Scope : : eClass ;
2013-03-05 13:33:38 +01:00
nameTok = nameTok - > next ( ) ;
2011-10-13 20:53:06 +02:00
} else if ( classDef - > str ( ) = = " struct " ) {
2011-01-17 18:29:19 +01:00
type = Scope : : eStruct ;
2013-03-05 13:33:38 +01:00
nameTok = nameTok - > next ( ) ;
2011-10-13 20:53:06 +02:00
} else if ( classDef - > str ( ) = = " union " ) {
2011-01-17 18:29:19 +01:00
type = Scope : : eUnion ;
2013-03-05 13:33:38 +01:00
nameTok = nameTok - > next ( ) ;
2011-10-13 20:53:06 +02:00
} else if ( classDef - > str ( ) = = " namespace " ) {
2011-01-17 18:29:19 +01:00
type = Scope : : eNamespace ;
2013-03-05 13:33:38 +01:00
nameTok = nameTok - > next ( ) ;
2016-04-22 06:02:54 +02:00
} else if ( classDef - > str ( ) = = " enum " ) {
type = Scope : : eEnum ;
nameTok = nameTok - > next ( ) ;
if ( nameTok - > str ( ) = = " class " ) {
enumClass = true ;
nameTok = nameTok - > next ( ) ;
}
2019-07-05 12:30:42 +02:00
} else if ( classDef - > str ( ) = = " [ " ) {
type = Scope : : eLambda ;
2011-10-13 20:53:06 +02:00
} else {
2011-01-17 18:29:19 +01:00
type = Scope : : eFunction ;
2010-11-13 08:08:45 +01:00
}
2013-03-05 13:33:38 +01:00
// skip over qualification if present
2018-05-01 07:32:19 +02:00
nameTok = skipScopeIdentifiers ( nameTok ) ;
2016-04-22 06:02:54 +02:00
if ( nameTok & & ( ( type = = Scope : : eEnum & & Token : : Match ( nameTok , " :|{ " ) ) | | nameTok - > str ( ) ! = " { " ) ) // anonymous and unnamed structs/unions don't have a name
2013-03-05 13:33:38 +01:00
className = nameTok - > str ( ) ;
2010-11-13 08:08:45 +01:00
}
2011-12-17 19:04:03 +01:00
bool Scope : : hasDefaultConstructor ( ) const
2010-12-21 08:13:40 +01:00
{
2011-10-13 20:53:06 +02:00
if ( numConstructors ) {
2011-01-17 18:29:19 +01:00
std : : list < Function > : : const_iterator func ;
2010-12-21 08:13:40 +01:00
2011-10-13 20:53:06 +02:00
for ( func = functionList . begin ( ) ; func ! = functionList . end ( ) ; + + func ) {
2011-03-31 03:59:43 +02:00
if ( func - > type = = Function : : eConstructor & & func - > argCount ( ) = = 0 )
2010-12-21 08:13:40 +01:00
return true ;
}
}
return false ;
}
2011-02-26 15:08:59 +01:00
AccessControl Scope : : defaultAccess ( ) const
{
2011-10-13 20:53:06 +02:00
switch ( type ) {
2011-02-26 15:08:59 +01:00
case eGlobal :
2019-07-23 14:29:02 +02:00
return AccessControl : : Global ;
2011-02-26 15:08:59 +01:00
case eClass :
2019-07-23 14:29:02 +02:00
return AccessControl : : Private ;
2011-02-26 15:08:59 +01:00
case eStruct :
2019-07-23 14:29:02 +02:00
return AccessControl : : Public ;
2011-02-26 15:08:59 +01:00
case eUnion :
2019-07-23 14:29:02 +02:00
return AccessControl : : Public ;
2011-02-26 15:08:59 +01:00
case eNamespace :
2019-07-23 14:29:02 +02:00
return AccessControl : : Namespace ;
2011-02-26 21:53:57 +01:00
default :
2019-07-23 14:29:02 +02:00
return AccessControl : : Local ;
2011-02-26 15:08:59 +01:00
}
}
2010-11-20 07:26:50 +01:00
// Get variable list..
2018-06-20 10:00:15 +02:00
void Scope : : getVariableList ( const Settings * settings )
2010-11-13 08:08:45 +01:00
{
2010-11-20 07:26:50 +01:00
const Token * start ;
2018-04-27 22:36:30 +02:00
if ( bodyStart )
start = bodyStart - > next ( ) ;
2012-12-16 07:18:03 +01:00
// global scope
else if ( className . empty ( ) )
2018-06-16 16:10:28 +02:00
start = check - > mTokenizer - > tokens ( ) ;
2010-11-20 07:26:50 +01:00
2012-12-16 07:18:03 +01:00
// forward declaration
else
return ;
2014-07-10 09:23:14 +02:00
AccessControl varaccess = defaultAccess ( ) ;
2018-04-27 22:36:30 +02:00
for ( const Token * tok = start ; tok & & tok ! = bodyEnd ; tok = tok - > next ( ) ) {
2010-12-16 19:04:47 +01:00
// syntax error?
2015-03-15 12:37:50 +01:00
if ( tok - > next ( ) = = nullptr )
2010-12-16 19:04:47 +01:00
break ;
2010-11-20 07:26:50 +01:00
// Is it a function?
2011-10-13 20:53:06 +02:00
else if ( tok - > str ( ) = = " { " ) {
2010-11-20 07:26:50 +01:00
tok = tok - > link ( ) ;
continue ;
2010-11-13 08:08:45 +01:00
}
2010-11-20 07:26:50 +01:00
// Is it a nested class or structure?
2011-10-13 20:53:06 +02:00
else if ( Token : : Match ( tok , " class|struct|union|namespace %type% :|{ " ) ) {
2010-11-20 07:26:50 +01:00
tok = tok - > tokAt ( 2 ) ;
while ( tok & & tok - > str ( ) ! = " { " )
tok = tok - > next ( ) ;
2011-10-13 20:53:06 +02:00
if ( tok ) {
2010-11-20 07:26:50 +01:00
// skip implementation
tok = tok - > link ( ) ;
continue ;
2011-10-13 20:53:06 +02:00
} else
2010-11-20 07:26:50 +01:00
break ;
2014-06-25 20:41:22 +02:00
} else if ( Token : : Match ( tok , " struct|union { " ) ) {
2015-01-31 10:50:39 +01:00
if ( Token : : Match ( tok - > next ( ) - > link ( ) , " } %name% ;|[ " ) ) {
2014-06-25 20:41:22 +02:00
tok = tok - > next ( ) - > link ( ) - > tokAt ( 2 ) ;
continue ;
} else if ( Token : : simpleMatch ( tok - > next ( ) - > link ( ) , " } ; " )) {
tok = tok - > next ( ) ;
continue ;
}
2011-04-01 02:54:23 +02:00
}
2010-11-13 08:08:45 +01:00
// Borland C++: Skip all variables in the __published section.
2010-12-15 18:45:53 +01:00
// These are automatically initialized.
2011-10-13 20:53:06 +02:00
else if ( tok - > str ( ) = = " __published: " ) {
for ( ; tok ; tok = tok - > next ( ) ) {
2010-11-13 08:08:45 +01:00
if ( tok - > str ( ) = = " { " )
tok = tok - > link ( ) ;
if ( Token : : Match ( tok - > next ( ) , " private:|protected:|public: " ) )
break ;
}
if ( tok )
continue ;
else
break ;
}
// "private:" "public:" "protected:" etc
2011-10-13 20:53:06 +02:00
else if ( tok - > str ( ) = = " public: " ) {
2019-07-23 14:29:02 +02:00
varaccess = AccessControl : : Public ;
2010-11-20 07:26:50 +01:00
continue ;
2011-10-13 20:53:06 +02:00
} else if ( tok - > str ( ) = = " protected: " ) {
2019-07-23 14:29:02 +02:00
varaccess = AccessControl : : Protected ;
2010-11-20 07:26:50 +01:00
continue ;
2011-10-13 20:53:06 +02:00
} else if ( tok - > str ( ) = = " private: " ) {
2019-07-23 14:29:02 +02:00
varaccess = AccessControl : : Private ;
2010-11-13 08:08:45 +01:00
continue ;
2010-11-20 07:26:50 +01:00
}
2010-11-13 08:08:45 +01:00
// Is it a forward declaration?
2015-01-31 10:50:39 +01:00
else if ( Token : : Match ( tok , " class|struct|union %name% ; " ) ) {
2010-11-13 08:08:45 +01:00
tok = tok - > tokAt ( 2 ) ;
continue ;
}
2010-11-20 07:26:50 +01:00
// Borland C++: Ignore properties..
else if ( tok - > str ( ) = = " __property " )
2010-11-13 08:08:45 +01:00
continue ;
2015-03-15 12:37:50 +01:00
// skip return, goto and delete
else if ( Token : : Match ( tok , " return|delete|goto " ) ) {
2013-08-31 14:22:06 +02:00
while ( tok - > next ( ) & &
tok - > next ( ) - > str ( ) ! = " ; " & &
tok - > next ( ) - > str ( ) ! = " } " /* ticket #4994 */ ) {
2011-02-27 16:13:40 +01:00
tok = tok - > next ( ) ;
2013-08-31 14:22:06 +02:00
}
2011-02-27 16:13:40 +01:00
continue ;
}
2011-12-30 20:01:33 +01:00
2018-09-04 06:39:02 +02:00
// skip case/default
if ( Token : : Match ( tok , " case|default " ) ) {
while ( tok - > next ( ) & & ! Token : : Match ( tok - > next ( ) , " [:;{}] " ) )
tok = tok - > next ( ) ;
continue ;
}
2010-11-20 07:26:50 +01:00
// Search for start of statement..
2011-02-25 13:17:55 +01:00
else if ( tok - > previous ( ) & & ! Token : : Match ( tok - > previous ( ) , " ; | { | } | public : | protected : | private : " ))
2010-11-13 08:08:45 +01:00
continue ;
2015-03-15 12:37:50 +01:00
else if ( tok - > str ( ) = = " ; " )
2010-12-02 07:35:01 +01:00
continue ;
2010-11-13 08:08:45 +01:00
2018-06-20 10:00:15 +02:00
tok = checkVariable ( tok , varaccess , settings ) ;
2011-03-16 03:33:14 +01:00
if ( ! tok )
break ;
2011-03-06 21:21:42 +01:00
}
}
2010-11-20 07:26:50 +01:00
2018-06-20 10:00:15 +02:00
const Token * Scope : : checkVariable ( const Token * tok , AccessControl varaccess , const Settings * settings )
2011-03-06 21:21:42 +01:00
{
2012-01-26 04:05:29 +01:00
// Is it a throw..?
if ( Token : : Match ( tok , " throw %any% ( " ) & &
Token : : simpleMatch ( tok - > linkAt ( 2 ) , " ) ; " ) ) {
return tok - > linkAt ( 2 ) ;
2018-04-23 16:27:56 +02:00
}
if ( ( Token : : Match ( tok , " throw %any% :: %any% ( " ) & &
2018-04-23 21:45:25 +02:00
Token : : simpleMatch ( tok - > linkAt ( 4 ) , " ) ; " ) ) ) {
2012-01-26 04:05:29 +01:00
return tok - > linkAt ( 4 ) ;
}
2012-08-12 12:01:24 +02:00
// friend?
2013-03-14 06:34:12 +01:00
if ( Token : : Match ( tok , " friend %type% " ) & & tok - > next ( ) - > varId ( ) = = 0 ) {
const Token * next = Token : : findmatch ( tok - > tokAt ( 2 ) , " ;|{ " ) ;
if ( next & & next - > str ( ) = = " { " )
next = next - > link ( ) ;
return next ;
}
2012-08-12 12:01:24 +02:00
2018-05-10 07:40:01 +02:00
// skip const|volatile|static|mutable|extern
while ( Token : : Match ( tok , " const|volatile|static|mutable|extern " ) ) {
2011-03-06 21:21:42 +01:00
tok = tok - > next ( ) ;
}
2010-11-13 08:08:45 +01:00
2011-04-22 15:12:08 +02:00
// the start of the type tokens does not include the above modifiers
const Token * typestart = tok ;
2016-04-22 06:02:54 +02:00
if ( Token : : Match ( tok , " class|struct|union|enum " ) ) {
2011-03-06 21:21:42 +01:00
tok = tok - > next ( ) ;
}
2010-11-13 08:08:45 +01:00
2014-09-19 09:29:31 +02:00
// This is the start of a statement
const Token * vartok = nullptr ;
const Token * typetok = nullptr ;
2012-05-11 17:56:47 +02:00
if ( tok & & isVariableDeclaration ( tok , vartok , typetok ) ) {
// If the vartok was set in the if-blocks above, create a entry for this variable..
tok = vartok - > next ( ) ;
2014-09-14 11:35:04 +02:00
while ( Token : : Match ( tok , " [|{ " ) )
2012-05-11 17:56:47 +02:00
tok = tok - > link ( ) - > next ( ) ;
2011-01-01 01:19:32 +01:00
2013-12-31 17:51:56 +01:00
if ( vartok - > varId ( ) = = 0 ) {
if ( ! vartok - > isBoolean ( ) )
check - > debugMessage ( vartok , " Scope::checkVariable found variable \' " + vartok - > str ( ) + " \' with varid 0. " ) ;
return tok ;
}
2010-11-13 08:08:45 +01:00
2014-02-16 10:32:10 +01:00
const Type * vType = nullptr ;
2010-12-02 07:35:01 +01:00
2012-12-20 06:53:04 +01:00
if ( typetok ) {
2015-12-18 08:24:02 +01:00
vType = findVariableTypeIncludingUsedNamespaces ( check , this , typetok ) ;
2016-04-22 06:02:54 +02:00
const_cast < Token * > ( typetok ) - > type ( vType ) ;
2012-12-20 06:53:04 +01:00
}
2010-12-02 07:35:01 +01:00
2016-08-04 09:06:32 +02:00
// skip "enum" or "struct"
if ( Token : : Match ( typestart , " enum|struct " ) )
typestart = typestart - > next ( ) ;
2018-06-20 10:00:15 +02:00
addVariable ( vartok , typestart , vartok - > previous ( ) , varaccess , vType , this , settings ) ;
2010-12-02 07:35:01 +01:00
}
2011-03-06 21:21:42 +01:00
return tok ;
2010-12-02 07:35:01 +01:00
}
2011-09-03 03:07:29 +02:00
const Variable * Scope : : getVariable ( const std : : string & varname ) const
{
std : : list < Variable > : : const_iterator iter ;
2011-10-13 20:53:06 +02:00
for ( iter = varlist . begin ( ) ; iter ! = varlist . end ( ) ; + + iter ) {
2011-09-03 03:07:29 +02:00
if ( iter - > name ( ) = = varname )
return & * iter ;
}
2014-02-16 10:32:10 +01:00
return nullptr ;
2011-09-03 03:07:29 +02:00
}
2012-02-11 12:26:48 +01:00
static const Token * skipPointers ( const Token * tok )
2010-12-30 22:57:43 +01:00
{
2016-12-18 20:16:38 +01:00
while ( Token : : Match ( tok , " *|&|&& " ) | | ( Token : : Match ( tok , " ( [*&] " ) & & Token : : Match ( tok - > link ( ) - > next ( ) , " (|[ " ) ) ) {
2012-02-11 12:26:48 +01:00
tok = tok - > next ( ) ;
2014-04-12 11:43:10 +02:00
if ( tok - > strAt ( - 1 ) = = " ( " & & Token : : Match ( tok , " %type% :: " ) )
tok = tok - > tokAt ( 2 ) ;
2010-12-30 09:46:44 +01:00
}
2010-12-30 22:57:43 +01:00
2012-02-11 12:26:48 +01:00
return tok ;
2010-12-30 22:57:43 +01:00
}
2018-09-25 06:19:26 +02:00
static const Token * skipPointersAndQualifiers ( const Token * tok )
{
tok = skipPointers ( tok ) ;
while ( Token : : Match ( tok , " const|volatile " ) ) {
tok = tok - > next ( ) ;
tok = skipPointers ( tok ) ;
}
return tok ;
}
2016-01-30 14:04:48 +01:00
bool Scope : : isVariableDeclaration ( const Token * const tok , const Token * & vartok , const Token * & typetok ) const
2010-12-30 22:57:43 +01:00
{
2018-06-16 16:10:28 +02:00
const bool isCPP = check & & check - > mTokenizer - > isCPP ( ) ;
2018-01-10 22:16:18 +01:00
if ( isCPP & & Token : : Match ( tok , " throw|new " ) )
return false ;
2018-06-16 16:10:28 +02:00
const bool isCPP11 = isCPP & & check - > mSettings - > standards . cpp > = Standards : : CPP11 ;
2018-01-10 22:16:18 +01:00
if ( isCPP11 & & tok - > str ( ) = = " using " )
2012-01-28 01:24:01 +01:00
return false ;
2011-01-02 00:36:22 +01:00
const Token * localTypeTok = skipScopeIdentifiers ( tok ) ;
2014-02-16 10:32:10 +01:00
const Token * localVarTok = nullptr ;
2010-12-30 22:57:43 +01:00
2011-10-13 20:53:06 +02:00
if ( Token : : Match ( localTypeTok , " %type% < " ) ) {
2014-10-12 16:06:50 +02:00
if ( Token : : Match ( tok , " const_cast|dynamic_cast|reinterpret_cast|static_cast < " ) )
return false ;
2013-04-15 22:48:28 +02:00
const Token * closeTok = localTypeTok - > next ( ) - > link ( ) ;
if ( closeTok ) {
2011-01-18 10:51:57 +01:00
localVarTok = skipPointers ( closeTok - > next ( ) ) ;
2011-01-18 10:14:12 +01:00
2015-01-31 10:50:39 +01:00
if ( Token : : Match ( localVarTok , " :: %type% %name% [;=({] " ) ) {
2013-03-30 13:49:56 +01:00
if ( localVarTok - > strAt ( 3 ) ! = " ( " | |
2014-08-05 15:33:57 +02:00
Token : : Match ( localVarTok - > linkAt ( 3 ) , " [)}] ; " ) ) {
2013-03-30 13:49:56 +01:00
localTypeTok = localVarTok - > next ( ) ;
localVarTok = localVarTok - > tokAt ( 2 ) ;
}
2011-01-02 00:36:22 +01:00
}
}
2011-10-13 20:53:06 +02:00
} else if ( Token : : Match ( localTypeTok , " %type% " ) ) {
2018-09-25 06:19:26 +02:00
localVarTok = skipPointersAndQualifiers ( localTypeTok - > next ( ) ) ;
2011-01-18 10:51:57 +01:00
}
2010-12-30 22:57:43 +01:00
2015-10-26 19:20:42 +01:00
if ( ! localVarTok )
return false ;
if ( localVarTok - > str ( ) = = " const " )
2012-05-14 21:47:02 +02:00
localVarTok = localVarTok - > next ( ) ;
2016-02-03 22:49:57 +01:00
if ( Token : : Match ( localVarTok , " %name% ;|= " ) | | ( localVarTok & & localVarTok - > varId ( ) & & localVarTok - > strAt ( 1 ) = = " : " ) ) {
2011-02-27 16:21:14 +01:00
vartok = localVarTok ;
typetok = localTypeTok ;
2015-01-31 10:50:39 +01:00
} else if ( Token : : Match ( localVarTok , " %name% ) | [ " ) && localVarTok->str() != " operator " ) {
2011-01-18 10:51:57 +01:00
vartok = localVarTok ;
typetok = localTypeTok ;
2016-02-03 22:49:57 +01:00
} else if ( localVarTok & & localVarTok - > varId ( ) & & Token : : Match ( localVarTok , " %name% (| { " ) &&
2014-08-05 15:33:57 +02:00
Token : : Match ( localVarTok - > next ( ) - > link ( ) , " )|} ; " ) ) {
2011-07-23 21:12:30 +02:00
vartok = localVarTok ;
typetok = localTypeTok ;
2012-01-26 04:05:29 +01:00
} else if ( type = = eCatch & &
2015-01-31 10:50:39 +01:00
Token : : Match ( localVarTok , " %name% ) " ) ) {
2012-01-26 04:05:29 +01:00
vartok = localVarTok ;
typetok = localTypeTok ;
2011-07-23 21:12:30 +02:00
}
2012-01-26 04:05:29 +01:00
2014-02-16 10:32:10 +01:00
return nullptr ! = vartok ;
2010-12-30 09:46:44 +01:00
}
2016-04-22 06:02:54 +02:00
const Token * Scope : : addEnum ( const Token * tok , bool isCpp )
{
const Token * tok2 = tok - > next ( ) ;
// skip over class if present
if ( isCpp & & tok2 - > str ( ) = = " class " )
tok2 = tok2 - > next ( ) ;
// skip over name
tok2 = tok2 - > next ( ) ;
// save type if present
if ( tok2 - > str ( ) = = " : " ) {
tok2 = tok2 - > next ( ) ;
enumType = tok2 ;
tok2 = tok2 - > next ( ) ;
}
// add enumerators
if ( tok2 - > str ( ) = = " { " ) {
const Token * end = tok2 - > link ( ) ;
tok2 = tok2 - > next ( ) ;
while ( Token : : Match ( tok2 , " %name% =|,|} " ) | |
( Token : : Match ( tok2 , " %name% ( " ) & & Token : : Match ( tok2 - > linkAt ( 1 ) , " ) ,|} " ) ) ) {
Enumerator enumerator ( this ) ;
// save enumerator name
enumerator . name = tok2 ;
// skip over name
tok2 = tok2 - > next ( ) ;
if ( tok2 - > str ( ) = = " = " ) {
// skip over "="
tok2 = tok2 - > next ( ) ;
if ( tok2 - > str ( ) = = " } " )
return nullptr ;
enumerator . start = tok2 ;
while ( ! Token : : Match ( tok2 , " ,|} " ) ) {
if ( tok2 - > link ( ) )
tok2 = tok2 - > link ( ) ;
enumerator . end = tok2 ;
tok2 = tok2 - > next ( ) ;
}
} else if ( tok2 - > str ( ) = = " ( " ) {
// skip over unknown macro
tok2 = tok2 - > link ( ) - > next ( ) ;
}
if ( tok2 - > str ( ) = = " , " ) {
enumeratorList . push_back ( enumerator ) ;
tok2 = tok2 - > next ( ) ;
} else if ( tok2 - > str ( ) = = " } " ) {
enumeratorList . push_back ( enumerator ) ;
break ;
}
}
if ( tok2 = = end ) {
tok2 = tok2 - > next ( ) ;
2016-05-25 13:14:34 +02:00
if ( tok2 & & tok2 - > str ( ) ! = " ; " )
2016-04-22 06:02:54 +02:00
tok2 = nullptr ;
} else
tok2 = nullptr ;
} else
tok2 = nullptr ;
return tok2 ;
}
const Enumerator * SymbolDatabase : : findEnumerator ( const Token * tok ) const
{
const Scope * scope = tok - > scope ( ) ;
2018-01-15 22:31:15 +01:00
const std : : string & tokStr = tok - > str ( ) ;
2017-10-18 18:01:36 +02:00
2018-06-17 17:20:16 +02:00
if ( mTokensThatAreNotEnumeratorValues . find ( tokStr ) ! = mTokensThatAreNotEnumeratorValues . end ( ) ) {
2017-10-20 01:53:20 +02:00
return nullptr ;
2017-10-18 18:01:36 +02:00
}
2016-04-22 06:02:54 +02:00
// check for qualified name
if ( tok - > strAt ( - 1 ) = = " :: " ) {
// find first scope
const Token * tok1 = tok ;
while ( Token : : Match ( tok1 - > tokAt ( - 2 ) , " %name% :: " ) )
tok1 = tok1 - > tokAt ( - 2 ) ;
if ( tok1 - > strAt ( - 1 ) = = " :: " )
scope = & scopeList . front ( ) ;
else {
// FIXME search base class here
// find first scope
while ( scope & & scope - > nestedIn ) {
const Scope * temp = scope - > nestedIn - > findRecordInNestedList ( tok1 - > str ( ) ) ;
if ( temp ) {
scope = temp ;
break ;
}
scope = scope - > nestedIn ;
}
}
if ( scope ) {
tok1 = tok1 - > tokAt ( 2 ) ;
while ( scope & & Token : : Match ( tok1 , " %name% :: " ) ) {
scope = scope - > findRecordInNestedList ( tok1 - > str ( ) ) ;
tok1 = tok1 - > tokAt ( 2 ) ;
}
if ( scope ) {
2017-10-18 18:01:36 +02:00
const Enumerator * enumerator = scope - > findEnumerator ( tokStr ) ;
2016-04-22 06:02:54 +02:00
if ( enumerator ) // enum class
return enumerator ;
// enum
else {
for ( std : : list < Scope * > : : const_iterator it = scope - > nestedList . begin ( ) , end = scope - > nestedList . end ( ) ; it ! = end ; + + it ) {
2017-10-18 18:01:36 +02:00
enumerator = ( * it ) - > findEnumerator ( tokStr ) ;
2016-04-22 06:02:54 +02:00
if ( enumerator )
return enumerator ;
}
}
}
}
} else {
2017-10-18 18:01:36 +02:00
const Enumerator * enumerator = scope - > findEnumerator ( tokStr ) ;
2016-04-22 06:02:54 +02:00
if ( enumerator )
return enumerator ;
2016-04-25 11:12:35 +02:00
for ( std : : list < Scope * > : : const_iterator s = scope - > nestedList . begin ( ) ; s ! = scope - > nestedList . end ( ) ; + + s ) {
2017-10-18 18:01:36 +02:00
enumerator = ( * s ) - > findEnumerator ( tokStr ) ;
2016-04-22 06:02:54 +02:00
if ( enumerator )
return enumerator ;
}
if ( scope - > definedType ) {
2017-08-28 17:19:03 +02:00
const std : : vector < Type : : BaseInfo > & derivedFrom = scope - > definedType - > derivedFrom ;
2019-09-19 20:29:33 +02:00
for ( const Type : : BaseInfo & i : derivedFrom ) {
const Type * derivedFromType = i . type ;
2017-08-28 17:19:03 +02:00
if ( derivedFromType & & derivedFromType - > classScope ) {
2017-10-18 18:01:36 +02:00
enumerator = derivedFromType - > classScope - > findEnumerator ( tokStr ) ;
2016-04-22 06:02:54 +02:00
if ( enumerator )
return enumerator ;
}
}
}
2011-01-02 00:36:22 +01:00
2017-08-02 08:17:29 +02:00
while ( scope - > nestedIn ) {
2016-05-09 13:08:00 +02:00
if ( scope - > type = = Scope : : eFunction & & scope - > functionOf )
2016-05-09 12:40:56 +02:00
scope = scope - > functionOf ;
else
scope = scope - > nestedIn ;
2017-10-18 18:01:36 +02:00
enumerator = scope - > findEnumerator ( tokStr ) ;
2016-05-09 12:40:56 +02:00
if ( enumerator )
return enumerator ;
2016-05-09 13:05:08 +02:00
for ( std : : list < Scope * > : : const_iterator s = scope - > nestedList . begin ( ) ; s ! = scope - > nestedList . end ( ) ; + + s ) {
2017-10-18 18:01:36 +02:00
enumerator = ( * s ) - > findEnumerator ( tokStr ) ;
2016-05-09 12:40:56 +02:00
if ( enumerator )
return enumerator ;
}
}
2016-04-22 06:02:54 +02:00
}
2011-01-02 00:36:22 +01:00
2018-06-17 17:20:16 +02:00
mTokensThatAreNotEnumeratorValues . insert ( tokStr ) ;
2017-10-18 18:01:36 +02:00
2016-04-22 06:02:54 +02:00
return nullptr ;
}
2015-01-02 21:38:19 +01:00
2010-12-02 07:35:01 +01:00
//---------------------------------------------------------------------------
2016-08-13 21:25:57 +02:00
const Type * SymbolDatabase : : findVariableTypeInBase ( const Scope * scope , const Token * typeTok ) const
{
if ( scope & & scope - > definedType & & ! scope - > definedType - > derivedFrom . empty ( ) ) {
2017-09-04 16:55:45 +02:00
const std : : vector < Type : : BaseInfo > & derivedFrom = scope - > definedType - > derivedFrom ;
2019-09-19 20:29:33 +02:00
for ( const Type : : BaseInfo & i : derivedFrom ) {
const Type * base = i . type ;
2016-08-13 21:25:57 +02:00
if ( base & & base - > classScope ) {
const Type * type = base - > classScope - > findType ( typeTok - > str ( ) ) ;
if ( type )
return type ;
type = findVariableTypeInBase ( base - > classScope , typeTok ) ;
if ( type )
return type ;
}
}
}
2017-10-18 18:01:36 +02:00
2016-08-13 21:25:57 +02:00
return nullptr ;
}
//---------------------------------------------------------------------------
2013-03-05 13:33:38 +01:00
const Type * SymbolDatabase : : findVariableType ( const Scope * start , const Token * typeTok ) const
2010-12-02 07:35:01 +01:00
{
2016-08-13 21:25:57 +02:00
const Scope * scope = start ;
2016-04-22 06:02:54 +02:00
// check if type does not have a namespace
if ( typeTok - > strAt ( - 1 ) ! = " :: " & & typeTok - > strAt ( 1 ) ! = " :: " ) {
2018-05-27 10:53:34 +02:00
// check if type same as scope
if ( start - > isClassOrStruct ( ) & & typeTok - > str ( ) = = start - > className )
return start - > definedType ;
2016-08-13 21:25:57 +02:00
while ( scope ) {
// look for type in this scope
const Type * type = scope - > findType ( typeTok - > str ( ) ) ;
2016-04-22 06:02:54 +02:00
2016-08-13 21:25:57 +02:00
if ( type )
return type ;
2016-04-22 06:02:54 +02:00
2016-08-13 21:25:57 +02:00
// look for type in base classes if possible
if ( scope - > isClassOrStruct ( ) ) {
type = findVariableTypeInBase ( scope , typeTok ) ;
if ( type )
return type ;
2016-04-22 06:02:54 +02:00
}
2016-08-13 21:25:57 +02:00
// check if in member function class to see if it's present in class
if ( scope - > type = = Scope : : eFunction & & scope - > functionOf ) {
const Scope * scope1 = scope - > functionOf ;
2016-04-22 06:02:54 +02:00
2016-08-13 21:25:57 +02:00
type = scope1 - > findType ( typeTok - > str ( ) ) ;
2016-08-04 09:06:32 +02:00
2016-08-13 21:25:57 +02:00
if ( type )
return type ;
2016-08-04 09:06:32 +02:00
2016-08-13 21:25:57 +02:00
type = findVariableTypeInBase ( scope1 , typeTok ) ;
if ( type )
return type ;
}
scope = scope - > nestedIn ;
2016-08-04 09:06:32 +02:00
}
2016-04-22 06:02:54 +02:00
}
2016-08-13 21:25:57 +02:00
// check for a qualified name and use it when given
else if ( typeTok - > strAt ( - 1 ) = = " :: " ) {
// check if type is not part of qualification
if ( typeTok - > strAt ( 1 ) = = " :: " )
return nullptr ;
2010-12-02 07:35:01 +01:00
2016-08-13 21:25:57 +02:00
// find start of qualified function name
const Token * tok1 = typeTok ;
2010-12-02 07:35:01 +01:00
2018-05-01 07:32:19 +02:00
while ( Token : : Match ( tok1 - > tokAt ( - 2 ) , " %type% :: " ) | |
2018-05-06 08:23:07 +02:00
( Token : : simpleMatch ( tok1 - > tokAt ( - 2 ) , " > :: " ) & & tok1 - > linkAt ( - 2 ) & & Token : : Match ( tok1 - > linkAt ( - 2 ) - > tokAt ( - 1 ) , " %type% " ) ) ) {
2018-05-01 07:32:19 +02:00
if ( tok1 - > strAt ( - 1 ) = = " :: " )
tok1 = tok1 - > tokAt ( - 2 ) ;
else
tok1 = tok1 - > linkAt ( - 2 ) - > tokAt ( - 1 ) ;
}
2010-12-02 07:35:01 +01:00
2016-08-13 21:25:57 +02:00
// check for global scope
if ( tok1 - > strAt ( - 1 ) = = " :: " ) {
scope = & scopeList . front ( ) ;
2016-08-04 09:06:32 +02:00
2016-08-13 21:25:57 +02:00
scope = scope - > findRecordInNestedList ( tok1 - > str ( ) ) ;
}
2016-08-04 09:06:32 +02:00
2016-08-13 21:25:57 +02:00
// find start of qualification
else {
while ( scope ) {
if ( scope - > className = = tok1 - > str ( ) )
break ;
else {
const Scope * scope1 = scope - > findRecordInNestedList ( tok1 - > str ( ) ) ;
if ( scope1 ) {
scope = scope1 ;
break ;
2018-04-23 22:27:15 +02:00
} else if ( scope - > type = = Scope : : eFunction & & scope - > functionOf )
scope = scope - > functionOf ;
else
2016-08-13 21:25:57 +02:00
scope = scope - > nestedIn ;
}
2016-08-02 23:30:46 +02:00
}
2016-01-30 14:04:48 +01:00
}
2016-08-13 21:25:57 +02:00
if ( scope ) {
// follow qualification
2018-05-01 07:32:19 +02:00
while ( scope & & ( Token : : Match ( tok1 , " %type% :: " ) | |
2018-05-06 08:23:07 +02:00
( Token : : Match ( tok1 , " %type% < " ) & & Token : : simpleMatch ( tok1 - > linkAt ( 1 ) , " > :: " ) ) ) ) {
2018-05-01 07:32:19 +02:00
if ( tok1 - > strAt ( 1 ) = = " :: " )
tok1 = tok1 - > tokAt ( 2 ) ;
else
tok1 = tok1 - > linkAt ( 1 ) - > tokAt ( 2 ) ;
2016-08-13 21:25:57 +02:00
const Scope * temp = scope - > findRecordInNestedList ( tok1 - > str ( ) ) ;
if ( ! temp ) {
// look in base classes
const Type * type = findVariableTypeInBase ( scope , tok1 ) ;
if ( type )
return type ;
2016-01-30 14:04:48 +01:00
}
2016-08-13 21:25:57 +02:00
scope = temp ;
}
2016-01-30 14:04:48 +01:00
2016-08-13 21:25:57 +02:00
if ( scope & & scope - > definedType )
return scope - > definedType ;
2010-11-13 08:08:45 +01:00
}
}
2010-12-02 07:35:01 +01:00
2014-02-16 10:32:10 +01:00
return nullptr ;
2010-11-13 08:08:45 +01:00
}
2016-05-26 18:07:56 +02:00
bool Scope : : hasInlineOrLambdaFunction ( ) const
2016-05-26 17:42:27 +02:00
{
2019-07-22 12:24:16 +02:00
for ( const Scope * s : nestedList ) {
2016-05-26 17:42:27 +02:00
// Inline function
2018-04-27 22:36:30 +02:00
if ( s - > type = = Scope : : eUnconditional & & Token : : simpleMatch ( s - > bodyStart - > previous ( ) , " ) { " ) )
2016-05-26 17:42:27 +02:00
return true ;
2016-05-26 18:07:56 +02:00
// Lambda function
if ( s - > type = = Scope : : eLambda )
return true ;
2016-05-26 17:42:27 +02:00
}
return false ;
}
2011-01-28 08:33:02 +01:00
2019-07-22 11:25:51 +02:00
void Scope : : findFunctionInBase ( const std : : string & name , nonneg int args , std : : vector < const Function * > & matches ) const
2014-11-17 16:04:44 +01:00
{
if ( isClassOrStruct ( ) & & definedType & & ! definedType - > derivedFrom . empty ( ) ) {
2017-09-04 16:55:45 +02:00
const std : : vector < Type : : BaseInfo > & derivedFrom = definedType - > derivedFrom ;
2019-09-19 20:29:33 +02:00
for ( const Type : : BaseInfo & i : derivedFrom ) {
const Type * base = i . type ;
2014-11-17 16:04:44 +01:00
if ( base & & base - > classScope ) {
if ( base - > classScope = = this ) // Ticket #5120, #5125: Recursive class; tok should have been found already
continue ;
2015-01-02 21:38:19 +01:00
for ( std : : multimap < std : : string , const Function * > : : const_iterator it = base - > classScope - > functionMap . find ( name ) ; it ! = base - > classScope - > functionMap . end ( ) & & it - > first = = name ; + + it ) {
const Function * func = it - > second ;
if ( args = = func - > argCount ( ) | | ( args < func - > argCount ( ) & & args > = func - > minArgCount ( ) ) ) {
matches . push_back ( func ) ;
2014-11-17 16:04:44 +01:00
}
}
2015-01-02 21:38:19 +01:00
base - > classScope - > findFunctionInBase ( name , args , matches ) ;
2014-11-17 16:04:44 +01:00
}
}
}
}
//---------------------------------------------------------------------------
2017-03-15 18:36:59 +01:00
static void checkVariableCallMatch ( const Variable * callarg , const Variable * funcarg , size_t & same , size_t & fallback1 , size_t & fallback2 )
{
if ( callarg ) {
2019-08-03 10:10:22 +02:00
ValueType : : MatchResult res = ValueType : : matchParameter ( callarg - > valueType ( ) , callarg , funcarg ) ;
2019-07-29 18:14:06 +02:00
if ( res = = ValueType : : MatchResult : : SAME ) {
same + + ;
return ;
}
2019-07-31 18:24:15 +02:00
if ( res = = ValueType : : MatchResult : : FALLBACK1 ) {
fallback1 + + ;
return ;
}
2019-07-31 18:25:47 +02:00
if ( res = = ValueType : : MatchResult : : FALLBACK2 ) {
fallback2 + + ;
return ;
}
2019-08-03 10:10:22 +02:00
if ( res = = ValueType : : MatchResult : : NOMATCH )
return ;
2019-07-29 18:14:06 +02:00
2017-03-15 18:36:59 +01:00
bool ptrequals = callarg - > isArrayOrPointer ( ) = = funcarg - > isArrayOrPointer ( ) ;
bool constEquals = ! callarg - > isArrayOrPointer ( ) | | ( ( callarg - > typeStartToken ( ) - > strAt ( - 1 ) = = " const " ) = = ( funcarg - > typeStartToken ( ) - > strAt ( - 1 ) = = " const " ) ) ;
if ( ptrequals & & constEquals & &
callarg - > typeStartToken ( ) - > str ( ) = = funcarg - > typeStartToken ( ) - > str ( ) & &
callarg - > typeStartToken ( ) - > isUnsigned ( ) = = funcarg - > typeStartToken ( ) - > isUnsigned ( ) & &
callarg - > typeStartToken ( ) - > isLong ( ) = = funcarg - > typeStartToken ( ) - > isLong ( ) ) {
same + + ;
} else if ( callarg - > isArrayOrPointer ( ) ) {
if ( ptrequals & & constEquals & & funcarg - > typeStartToken ( ) - > str ( ) = = " void " )
fallback1 + + ;
else if ( constEquals & & funcarg - > isStlStringType ( ) & & Token : : Match ( callarg - > typeStartToken ( ) , " char|wchar_t " ) )
fallback2 + + ;
} else if ( ptrequals ) {
2018-04-04 21:51:31 +02:00
const bool takesInt = Token : : Match ( funcarg - > typeStartToken ( ) , " char|short|int|long " ) ;
const bool takesFloat = Token : : Match ( funcarg - > typeStartToken ( ) , " float|double " ) ;
const bool passesInt = Token : : Match ( callarg - > typeStartToken ( ) , " char|short|int|long " ) ;
const bool passesFloat = Token : : Match ( callarg - > typeStartToken ( ) , " float|double " ) ;
2017-03-15 18:36:59 +01:00
if ( ( takesInt & & passesInt ) | | ( takesFloat & & passesFloat ) )
fallback1 + + ;
else if ( ( takesInt & & passesFloat ) | | ( takesFloat & & passesInt ) )
fallback2 + + ;
}
}
}
2019-08-03 10:10:22 +02:00
static std : : string getTypeString ( const Token * typeToken )
{
if ( ! typeToken )
return " " ;
while ( Token : : Match ( typeToken , " %name%|*|&|:: " ) ) {
if ( typeToken - > str ( ) = = " :: " ) {
std : : string ret ;
while ( Token : : Match ( typeToken , " :: %name% " ) ) {
ret + = " :: " + typeToken - > strAt ( 1 ) ;
typeToken = typeToken - > tokAt ( 2 ) ;
}
if ( typeToken - > str ( ) = = " < " ) {
for ( const Token * tok = typeToken ; tok ! = typeToken - > link ( ) ; tok = tok - > next ( ) )
ret + = tok - > str ( ) ;
ret + = " > " ;
}
return ret ;
}
if ( Token : : Match ( typeToken , " %name% const| %var%|*|& " ) ) {
return typeToken - > str ( ) ;
}
typeToken = typeToken - > next ( ) ;
}
return " " ;
}
2015-05-23 11:56:11 +02:00
const Function * Scope : : findFunction ( const Token * tok , bool requireConst ) const
2013-01-01 09:53:40 +01:00
{
2014-11-17 16:04:44 +01:00
// make sure this is a function call
const Token * end = tok - > linkAt ( 1 ) ;
if ( ! end )
return nullptr ;
2019-07-29 21:17:15 +02:00
const std : : vector < const Token * > arguments = getArguments ( tok ) ;
2014-11-17 16:04:44 +01:00
std : : vector < const Function * > matches ;
// find all the possible functions that could match
const std : : size_t args = arguments . size ( ) ;
2017-03-01 10:27:01 +01:00
for ( std : : multimap < std : : string , const Function * > : : const_iterator it = functionMap . find ( tok - > str ( ) ) ; it ! = functionMap . cend ( ) & & it - > first = = tok - > str ( ) ; + + it ) {
2015-01-02 21:38:19 +01:00
const Function * func = it - > second ;
2016-08-02 08:58:11 +02:00
if ( args = = func - > argCount ( ) | |
( func - > isVariadic ( ) & & args > = ( func - > argCount ( ) - 1 ) ) | |
( args < func - > argCount ( ) & & args > = func - > minArgCount ( ) ) ) {
2015-01-02 21:38:19 +01:00
matches . push_back ( func ) ;
2014-11-17 16:04:44 +01:00
}
}
// check in base classes
2015-01-02 21:38:19 +01:00
findFunctionInBase ( tok - > str ( ) , args , matches ) ;
2014-11-17 16:04:44 +01:00
2017-02-25 23:11:42 +01:00
const Function * fallback1Func = nullptr ;
const Function * fallback2Func = nullptr ;
2014-11-17 16:04:44 +01:00
// check each function against the arguments in the function call for a match
2014-11-20 06:18:29 +01:00
for ( std : : size_t i = 0 ; i < matches . size ( ) ; ) {
2017-04-01 10:18:53 +02:00
bool constFallback = false ;
2014-11-17 16:04:44 +01:00
const Function * func = matches [ i ] ;
size_t same = 0 ;
2017-02-25 23:11:42 +01:00
2019-05-30 21:25:14 +02:00
if ( requireConst & & ! func - > isConst ( ) ) {
i + + ;
2019-05-30 20:26:45 +02:00
continue ;
2019-05-30 21:25:14 +02:00
}
2019-05-30 20:26:45 +02:00
2017-02-28 22:08:18 +01:00
if ( ! requireConst | | ! func - > isConst ( ) ) {
2017-02-25 23:11:42 +01:00
// get the function this call is in
const Scope * scope = tok - > scope ( ) ;
// check if this function is a member function
2017-08-01 13:26:35 +02:00
if ( scope & & scope - > functionOf & & scope - > functionOf - > isClassOrStruct ( ) & & scope - > function ) {
2017-02-25 23:11:42 +01:00
// check if isConst mismatches
2017-08-01 13:26:35 +02:00
if ( scope - > function - > isConst ( ) ! = func - > isConst ( ) ) {
2017-04-01 10:18:53 +02:00
if ( scope - > function - > isConst ( ) ) {
2017-11-03 10:39:57 +01:00
+ + i ;
2017-04-01 10:18:53 +02:00
continue ;
}
constFallback = true ;
2017-02-25 23:11:42 +01:00
}
}
}
size_t fallback1 = 0 ;
size_t fallback2 = 0 ;
2017-11-03 10:39:57 +01:00
bool erased = false ;
2014-11-17 16:04:44 +01:00
for ( std : : size_t j = 0 ; j < args ; + + j ) {
2017-02-25 23:11:42 +01:00
2016-08-02 08:58:11 +02:00
// don't check variadic arguments
if ( func - > isVariadic ( ) & & j > ( func - > argCount ( ) - 1 ) ) {
break ;
}
2014-11-17 16:04:44 +01:00
const Variable * funcarg = func - > getArgumentVar ( j ) ;
2019-08-01 17:53:14 +02:00
if ( ! arguments [ j ] - > valueType ( ) ) {
const Token * vartok = arguments [ j ] ;
int pointer = 0 ;
while ( vartok & & ( vartok - > isUnaryOp ( " & " ) | | vartok - > isUnaryOp ( " * " ) ) ) {
pointer + = vartok - > isUnaryOp ( " & " ) ? 1 : - 1 ;
vartok = vartok - > astOperand1 ( ) ;
2018-04-06 07:53:05 +02:00
}
2019-08-01 17:53:14 +02:00
if ( vartok & & vartok - > variable ( ) ) {
const Token * callArgTypeToken = vartok - > variable ( ) - > typeStartToken ( ) ;
2019-08-01 13:25:03 +02:00
const Token * funcArgTypeToken = funcarg - > typeStartToken ( ) ;
auto parseDecl = [ ] ( const Token * typeToken ) - > ValueType {
ValueType ret ;
while ( Token : : Match ( typeToken - > previous ( ) , " %name% " ) )
typeToken = typeToken - > previous ( ) ;
2019-08-03 10:10:22 +02:00
while ( Token : : Match ( typeToken , " %name%|*|&|::|< " ) )
2019-08-01 13:25:03 +02:00
{
if ( typeToken - > str ( ) = = " const " )
ret . constness | = ( 1 < < ret . pointer ) ;
else if ( typeToken - > str ( ) = = " * " )
ret . pointer + + ;
2019-08-03 10:10:22 +02:00
else if ( typeToken - > str ( ) = = " < " ) {
if ( ! typeToken - > link ( ) )
break ;
typeToken = typeToken - > link ( ) ;
}
2019-08-01 13:25:03 +02:00
typeToken = typeToken - > next ( ) ;
2019-07-31 12:38:36 +02:00
}
2019-08-01 13:25:03 +02:00
return ret ;
} ;
2019-08-03 10:10:22 +02:00
const std : : string type1 = getTypeString ( callArgTypeToken ) ;
const std : : string type2 = getTypeString ( funcArgTypeToken ) ;
if ( ! type1 . empty ( ) & & type1 = = type2 ) {
ValueType callArgType = parseDecl ( callArgTypeToken ) ;
callArgType . pointer + = pointer ;
ValueType funcArgType = parseDecl ( funcArgTypeToken ) ;
2019-08-01 13:25:03 +02:00
callArgType . sign = funcArgType . sign = ValueType : : Sign : : SIGNED ;
callArgType . type = funcArgType . type = ValueType : : Type : : INT ;
2019-08-03 10:10:22 +02:00
2019-08-01 17:53:14 +02:00
ValueType : : MatchResult res = ValueType : : matchParameter ( & callArgType , & funcArgType ) ;
2019-08-01 13:25:03 +02:00
if ( res = = ValueType : : MatchResult : : SAME )
+ + same ;
else if ( res = = ValueType : : MatchResult : : FALLBACK1 )
+ + fallback1 ;
else if ( res = = ValueType : : MatchResult : : FALLBACK2 )
+ + fallback2 ;
2019-08-01 17:53:14 +02:00
continue ;
2016-08-02 23:34:11 +02:00
}
}
}
2019-08-01 17:53:14 +02:00
// check for a match with a variable
if ( Token : : Match ( arguments [ j ] , " %var% ,|) " ) ) {
2019-08-02 15:41:00 +02:00
const Variable * callarg = arguments [ j ] - > variable ( ) ;
2019-08-01 17:53:14 +02:00
checkVariableCallMatch ( callarg , funcarg , same , fallback1 , fallback2 ) ;
}
2019-08-01 16:14:00 +02:00
else if ( funcarg - > isStlStringType ( ) & & arguments [ j ] - > valueType ( ) & & arguments [ j ] - > valueType ( ) - > pointer = = 1 & & arguments [ j ] - > valueType ( ) - > type = = ValueType : : Type : : CHAR )
2019-08-01 17:53:14 +02:00
fallback2 + + ;
2016-08-02 08:58:11 +02:00
2017-02-28 22:43:47 +01:00
// check for a match with nullptr
2019-08-01 17:29:25 +02:00
else if ( funcarg - > isPointer ( ) & & Token : : Match ( arguments [ j ] , " nullptr|NULL ,|) " ) )
2017-02-28 22:43:47 +01:00
same + + ;
2019-08-01 17:29:25 +02:00
else if ( arguments [ j ] - > isNumber ( ) & & funcarg - > isPointer ( ) & & MathLib : : isNullValue ( arguments [ j ] - > str ( ) ) )
fallback1 + + ;
2017-02-28 22:43:47 +01:00
2017-03-15 18:36:59 +01:00
// Try to evaluate the apparently more complex expression
2017-03-15 18:45:33 +01:00
else {
2019-08-03 10:10:22 +02:00
const Token * vartok = arguments [ j ] ;
while ( vartok - > isUnaryOp ( " & " ) | | vartok - > isUnaryOp ( " * " ) )
vartok = vartok - > astOperand1 ( ) ;
ValueType : : MatchResult res = ValueType : : matchParameter ( arguments [ j ] - > valueType ( ) , vartok - > variable ( ) , funcarg ) ;
2019-07-31 18:35:56 +02:00
if ( res = = ValueType : : MatchResult : : SAME )
+ + same ;
else if ( res = = ValueType : : MatchResult : : FALLBACK1 )
+ + fallback1 ;
else if ( res = = ValueType : : MatchResult : : FALLBACK2 )
+ + fallback2 ;
2019-08-01 14:30:00 +02:00
else if ( res = = ValueType : : MatchResult : : NOMATCH ) {
// can't match so remove this function from possible matches
matches . erase ( matches . begin ( ) + i ) ;
erased = true ;
break ;
}
2017-03-15 18:36:59 +01:00
}
2013-01-01 09:53:40 +01:00
}
2018-04-04 21:51:31 +02:00
const size_t hasToBe = func - > isVariadic ( ) ? ( func - > argCount ( ) - 1 ) : args ;
2017-02-28 22:43:47 +01:00
2014-11-17 16:04:44 +01:00
// check if all arguments matched
2017-04-01 10:18:53 +02:00
if ( same = = hasToBe ) {
2019-05-30 19:24:27 +02:00
if ( constFallback | | ( ! requireConst & & func - > isConst ( ) ) )
2017-04-01 10:18:53 +02:00
fallback1Func = func ;
else
return func ;
}
2015-05-23 11:56:11 +02:00
2017-04-01 10:18:53 +02:00
else if ( ! fallback1Func ) {
2017-02-28 22:43:47 +01:00
if ( same + fallback1 = = hasToBe )
2017-02-25 23:11:42 +01:00
fallback1Func = func ;
2017-02-28 22:43:47 +01:00
else if ( ! fallback2Func & & same + fallback2 + fallback1 = = hasToBe )
2017-02-25 23:11:42 +01:00
fallback2Func = func ;
2014-11-01 14:36:17 +01:00
}
2014-11-20 06:18:29 +01:00
if ( ! erased )
+ + i ;
2014-11-01 14:36:17 +01:00
}
2017-02-25 23:11:42 +01:00
// Fallback cases
if ( fallback1Func )
return fallback1Func ;
if ( fallback2Func )
return fallback2Func ;
// Only one candidate left
2017-02-24 20:56:47 +01:00
if ( matches . size ( ) = = 1 )
2014-11-17 16:04:44 +01:00
return matches [ 0 ] ;
2014-10-30 13:47:20 +01:00
return nullptr ;
2013-01-01 09:53:40 +01:00
}
//---------------------------------------------------------------------------
2013-01-28 06:47:48 +01:00
const Function * SymbolDatabase : : findFunction ( const Token * tok ) const
2012-10-14 17:30:37 +02:00
{
2013-01-22 06:55:25 +01:00
// find the scope this function is in
2013-01-28 06:47:48 +01:00
const Scope * currScope = tok - > scope ( ) ;
2012-10-14 17:30:37 +02:00
while ( currScope & & currScope - > isExecutable ( ) ) {
if ( currScope - > functionOf )
currScope = currScope - > functionOf ;
else
currScope = currScope - > nestedIn ;
}
2013-01-22 06:55:25 +01:00
// check for a qualified name and use it when given
if ( tok - > strAt ( - 1 ) = = " :: " ) {
// find start of qualified function name
const Token * tok1 = tok ;
2018-05-01 07:32:19 +02:00
while ( Token : : Match ( tok1 - > tokAt ( - 2 ) , " >|%type% :: " ) ) {
if ( tok1 - > strAt ( - 2 ) = = " > " ) {
if ( tok1 - > linkAt ( - 2 ) )
tok1 = tok1 - > linkAt ( - 2 ) - > tokAt ( - 1 ) ;
else {
2018-06-16 16:10:28 +02:00
if ( mSettings - > debugwarnings )
2018-05-01 07:32:19 +02:00
debugMessage ( tok1 - > tokAt ( - 2 ) , " SymbolDatabase::findFunction found '>' without link. " ) ;
return nullptr ;
}
} else
tok1 = tok1 - > tokAt ( - 2 ) ;
}
2013-01-22 06:55:25 +01:00
// check for global scope
if ( tok1 - > strAt ( - 1 ) = = " :: " ) {
currScope = & scopeList . front ( ) ;
currScope = currScope - > findRecordInNestedList ( tok1 - > str ( ) ) ;
}
// find start of qualification
else {
while ( currScope ) {
if ( currScope - > className = = tok1 - > str ( ) )
break ;
else {
const Scope * scope = currScope - > findRecordInNestedList ( tok1 - > str ( ) ) ;
if ( scope ) {
currScope = scope ;
break ;
} else
currScope = currScope - > nestedIn ;
}
}
}
if ( currScope ) {
2018-05-01 07:32:19 +02:00
while ( currScope & & ! ( Token : : Match ( tok1 , " %type% :: %any% ( " ) | |
( Token : : Match ( tok1 , " %type% < " ) & & Token : : Match ( tok1 - > linkAt ( 1 ) , " > :: %any% ( " ) ) ) ) {
if ( tok1 - > strAt ( 1 ) = = " :: " )
tok1 = tok1 - > tokAt ( 2 ) ;
else
tok1 = tok1 - > linkAt ( 1 ) - > tokAt ( 2 ) ;
2015-08-15 20:24:26 +02:00
currScope = currScope - > findRecordInNestedList ( tok1 - > str ( ) ) ;
2013-01-22 06:55:25 +01:00
}
tok1 = tok1 - > tokAt ( 2 ) ;
if ( currScope & & tok1 )
2013-01-28 06:47:48 +01:00
return currScope - > findFunction ( tok1 ) ;
2013-01-22 06:55:25 +01:00
}
}
2013-01-23 16:53:55 +01:00
// check for member function
2013-07-08 06:38:33 +02:00
else if ( Token : : Match ( tok - > tokAt ( - 2 ) , " !!this . " ) ) {
2014-12-02 14:19:52 +01:00
const Token * tok1 = tok - > tokAt ( - 2 ) ;
if ( Token : : Match ( tok1 , " %var% . " ) ) {
2015-01-31 10:50:39 +01:00
const Variable * var = getVariableFromVarId ( tok1 - > varId ( ) ) ;
if ( var & & var - > typeScope ( ) )
2019-05-30 20:26:45 +02:00
return var - > typeScope ( ) - > findFunction ( tok , var - > valueType ( ) - > constness = = 1 ) ;
2019-07-08 17:43:45 +02:00
if ( var & & var - > smartPointerType ( ) & & var - > smartPointerType ( ) - > classScope & & tok1 - > next ( ) - > originalName ( ) = = " -> " )
return var - > smartPointerType ( ) - > classScope - > findFunction ( tok , var - > valueType ( ) - > constness = = 1 ) ;
2019-05-30 20:26:45 +02:00
} else if ( Token : : simpleMatch ( tok - > previous ( ) - > astOperand1 ( ) , " ( " ) ) {
const Token * castTok = tok - > previous ( ) - > astOperand1 ( ) ;
if ( castTok - > isCast ( ) ) {
ValueType vt = ValueType : : parseDecl ( castTok - > next ( ) , mSettings ) ;
if ( vt . typeScope )
return vt . typeScope - > findFunction ( tok , vt . constness = = 1 ) ;
}
2013-01-23 16:53:55 +01:00
}
}
2013-01-22 06:55:25 +01:00
// check in enclosing scopes
else {
while ( currScope ) {
2013-01-28 06:47:48 +01:00
const Function * func = currScope - > findFunction ( tok ) ;
2013-01-22 06:55:25 +01:00
if ( func )
return func ;
currScope = currScope - > nestedIn ;
}
2012-10-14 17:30:37 +02:00
}
2017-08-09 20:00:26 +02:00
return nullptr ;
2012-10-14 17:30:37 +02:00
}
2011-01-28 08:33:02 +01:00
//---------------------------------------------------------------------------
2010-11-13 08:08:45 +01:00
2013-01-03 22:37:19 +01:00
const Scope * SymbolDatabase : : findScopeByName ( const std : : string & name ) const
2012-02-24 20:45:56 +01:00
{
for ( std : : list < Scope > : : const_iterator it = scopeList . begin ( ) ; it ! = scopeList . end ( ) ; + + it ) {
if ( it - > className = = name )
return & * it ;
}
2017-08-09 20:00:26 +02:00
return nullptr ;
2012-02-24 20:45:56 +01:00
}
//---------------------------------------------------------------------------
2013-01-03 22:37:19 +01:00
Scope * Scope : : findInNestedList ( const std : : string & name )
2010-11-13 08:08:45 +01:00
{
2011-01-17 18:29:19 +01:00
std : : list < Scope * > : : iterator it ;
2010-11-13 08:08:45 +01:00
2011-10-13 20:53:06 +02:00
for ( it = nestedList . begin ( ) ; it ! = nestedList . end ( ) ; + + it ) {
2010-11-13 08:08:45 +01:00
if ( ( * it ) - > className = = name )
return ( * it ) ;
}
2017-08-09 20:00:26 +02:00
return nullptr ;
2010-11-13 08:08:45 +01:00
}
//---------------------------------------------------------------------------
2013-01-03 22:37:19 +01:00
const Scope * Scope : : findRecordInNestedList ( const std : : string & name ) const
2012-11-30 06:03:58 +01:00
{
std : : list < Scope * > : : const_iterator it ;
for ( it = nestedList . begin ( ) ; it ! = nestedList . end ( ) ; + + it ) {
if ( ( * it ) - > className = = name & & ( * it ) - > type ! = eFunction )
return ( * it ) ;
}
2018-04-24 22:43:47 +02:00
const Type * nested_type = findType ( name ) ;
2019-01-31 16:53:51 +01:00
if ( nested_type ) {
if ( nested_type - > isTypeAlias ( ) ) {
if ( nested_type - > typeStart = = nested_type - > typeEnd )
return findRecordInNestedList ( nested_type - > typeStart - > str ( ) ) ;
} else
return nested_type - > classScope ;
}
2018-04-24 22:43:47 +02:00
2017-08-09 20:00:26 +02:00
return nullptr ;
2012-11-30 06:03:58 +01:00
}
//---------------------------------------------------------------------------
2013-03-05 13:33:38 +01:00
const Type * Scope : : findType ( const std : : string & name ) const
{
2017-10-15 02:53:41 +02:00
auto it = definedTypesMap . find ( name ) ;
2013-03-05 13:33:38 +01:00
2018-04-26 17:55:04 +02:00
// Type was found
if ( definedTypesMap . end ( ) ! = it )
2017-10-17 10:59:23 +02:00
return ( * it ) . second ;
2018-04-26 17:55:04 +02:00
// is type defined in anonymous namespace..
it = definedTypesMap . find ( " " ) ;
if ( it ! = definedTypesMap . end ( ) ) {
for ( const Scope * scope : nestedList ) {
if ( scope - > className . empty ( ) & & ( scope - > type = = eNamespace | | scope - > isClassOrStructOrUnion ( ) ) ) {
const Type * t = scope - > findType ( name ) ;
if ( t )
return t ;
}
}
2013-03-05 13:33:38 +01:00
}
2018-04-26 17:55:04 +02:00
// Type was not found
return nullptr ;
2013-03-05 13:33:38 +01:00
}
//---------------------------------------------------------------------------
2013-01-03 22:37:19 +01:00
Scope * Scope : : findInNestedListRecursive ( const std : : string & name )
2011-02-03 07:57:10 +01:00
{
std : : list < Scope * > : : iterator it ;
2011-10-13 20:53:06 +02:00
for ( it = nestedList . begin ( ) ; it ! = nestedList . end ( ) ; + + it ) {
2011-02-03 07:57:10 +01:00
if ( ( * it ) - > className = = name )
return ( * it ) ;
}
2011-10-13 20:53:06 +02:00
for ( it = nestedList . begin ( ) ; it ! = nestedList . end ( ) ; + + it ) {
2011-02-03 07:57:10 +01:00
Scope * child = ( * it ) - > findInNestedListRecursive ( name ) ;
2011-02-19 19:40:02 +01:00
if ( child )
return child ;
2011-02-03 07:57:10 +01:00
}
2017-08-09 20:00:26 +02:00
return nullptr ;
2011-02-03 07:57:10 +01:00
}
//---------------------------------------------------------------------------
2011-01-17 18:29:19 +01:00
const Function * Scope : : getDestructor ( ) const
2010-11-13 08:08:45 +01:00
{
2011-01-17 18:29:19 +01:00
std : : list < Function > : : const_iterator it ;
2011-10-13 20:53:06 +02:00
for ( it = functionList . begin ( ) ; it ! = functionList . end ( ) ; + + it ) {
2011-01-17 18:29:19 +01:00
if ( it - > type = = Function : : eDestructor )
2011-03-11 01:43:29 +01:00
return & ( * it ) ;
2010-11-13 08:08:45 +01:00
}
2017-08-09 20:00:26 +02:00
return nullptr ;
2010-11-13 08:08:45 +01:00
}
//---------------------------------------------------------------------------
2012-11-26 16:34:44 +01:00
bool SymbolDatabase : : isCPP ( ) const
{
2018-06-16 16:10:28 +02:00
return mTokenizer - > isCPP ( ) ;
2012-11-26 16:34:44 +01:00
}
2012-11-30 06:03:58 +01:00
//---------------------------------------------------------------------------
2013-01-03 22:37:19 +01:00
const Scope * SymbolDatabase : : findScope ( const Token * tok , const Scope * startScope ) const
2012-11-30 06:03:58 +01:00
{
2014-02-16 11:47:52 +01:00
const Scope * scope = nullptr ;
2012-11-30 06:03:58 +01:00
// absolute path
if ( tok - > str ( ) = = " :: " ) {
tok = tok - > next ( ) ;
2013-03-05 13:33:38 +01:00
scope = & scopeList . front ( ) ;
}
// relative path
else if ( tok - > isName ( ) ) {
scope = startScope ;
}
2012-11-30 06:03:58 +01:00
2013-03-05 13:33:38 +01:00
while ( scope & & tok & & tok - > isName ( ) ) {
if ( tok - > strAt ( 1 ) = = " :: " ) {
2012-11-30 06:03:58 +01:00
scope = scope - > findRecordInNestedList ( tok - > str ( ) ) ;
2013-03-05 13:33:38 +01:00
tok = tok - > tokAt ( 2 ) ;
2018-05-06 08:23:07 +02:00
} else if ( tok - > strAt ( 1 ) = = " < " & & Token : : simpleMatch ( tok - > linkAt ( 1 ) , " > :: " ) ) {
2018-05-01 07:32:19 +02:00
scope = scope - > findRecordInNestedList ( tok - > str ( ) ) ;
tok = tok - > linkAt ( 1 ) - > tokAt ( 2 ) ;
2013-03-05 13:33:38 +01:00
} else
return scope - > findRecordInNestedList ( tok - > str ( ) ) ;
}
2012-11-30 06:03:58 +01:00
2013-03-05 13:33:38 +01:00
// not a valid path
2017-08-09 20:00:26 +02:00
return nullptr ;
2013-03-05 13:33:38 +01:00
}
2012-11-30 06:03:58 +01:00
2013-08-12 06:21:03 +02:00
//---------------------------------------------------------------------------
2013-03-05 15:28:40 +01:00
const Type * SymbolDatabase : : findType ( const Token * startTok , const Scope * startScope ) const
2013-03-05 13:33:38 +01:00
{
2013-08-12 06:21:03 +02:00
// skip over struct or union
if ( Token : : Match ( startTok , " struct|union " ) )
startTok = startTok - > next ( ) ;
// type same as scope
2016-08-21 16:11:23 +02:00
if ( startTok - > str ( ) = = startScope - > className & & startScope - > isClassOrStruct ( ) & & startTok - > strAt ( 1 ) ! = " :: " )
2013-08-12 06:21:03 +02:00
return startScope - > definedType ;
2017-07-16 01:14:15 +02:00
const Scope * start_scope = startScope ;
2013-03-05 15:28:40 +01:00
// absolute path - directly start in global scope
if ( startTok - > str ( ) = = " :: " ) {
startTok = startTok - > next ( ) ;
2017-07-16 01:14:15 +02:00
start_scope = & scopeList . front ( ) ;
2013-03-05 13:33:38 +01:00
}
2012-11-30 06:03:58 +01:00
2013-03-05 15:28:40 +01:00
const Token * tok = startTok ;
2017-07-16 01:14:15 +02:00
const Scope * scope = start_scope ;
2013-03-05 15:28:40 +01:00
2013-03-05 13:33:38 +01:00
while ( scope & & tok & & tok - > isName ( ) ) {
2018-05-06 08:23:07 +02:00
if ( tok - > strAt ( 1 ) = = " :: " | | ( tok - > strAt ( 1 ) = = " < " & & Token : : simpleMatch ( tok - > linkAt ( 1 ) , " > :: " ) ) ) {
2012-11-30 06:03:58 +01:00
scope = scope - > findRecordInNestedList ( tok - > str ( ) ) ;
2013-03-05 15:28:40 +01:00
if ( scope ) {
2018-05-01 07:32:19 +02:00
if ( tok - > strAt ( 1 ) = = " :: " )
tok = tok - > tokAt ( 2 ) ;
else
tok = tok - > linkAt ( 1 ) - > tokAt ( 2 ) ;
2013-03-05 15:28:40 +01:00
} else {
2017-07-16 01:14:15 +02:00
start_scope = start_scope - > nestedIn ;
if ( ! start_scope )
2013-03-05 15:28:40 +01:00
break ;
2017-07-16 01:14:15 +02:00
scope = start_scope ;
2013-03-05 15:28:40 +01:00
tok = startTok ;
}
2017-07-16 01:14:15 +02:00
} else {
const Type * type = scope - > findType ( tok - > str ( ) ) ;
if ( type )
return type ;
else
break ;
}
}
// check using namespaces
while ( startScope ) {
for ( std : : list < Scope : : UsingInfo > : : const_iterator it = startScope - > usingList . begin ( ) ;
it ! = startScope - > usingList . end ( ) ; + + it ) {
tok = startTok ;
scope = it - > scope ;
start_scope = startScope ;
while ( scope & & tok & & tok - > isName ( ) ) {
2018-05-06 08:23:07 +02:00
if ( tok - > strAt ( 1 ) = = " :: " | | ( tok - > strAt ( 1 ) = = " < " & & Token : : simpleMatch ( tok - > linkAt ( 1 ) , " > :: " ) ) ) {
2017-07-16 01:14:15 +02:00
scope = scope - > findRecordInNestedList ( tok - > str ( ) ) ;
if ( scope ) {
2018-05-01 07:32:19 +02:00
if ( tok - > strAt ( 1 ) = = " :: " )
tok = tok - > tokAt ( 2 ) ;
else
tok = tok - > linkAt ( 1 ) - > tokAt ( 2 ) ;
2017-07-16 01:14:15 +02:00
} else {
start_scope = start_scope - > nestedIn ;
if ( ! start_scope )
break ;
scope = start_scope ;
tok = startTok ;
}
} else {
const Type * type = scope - > findType ( tok - > str ( ) ) ;
if ( type )
return type ;
else
break ;
}
}
}
startScope = startScope - > nestedIn ;
2012-11-30 06:03:58 +01:00
}
// not a valid path
2017-08-09 20:00:26 +02:00
return nullptr ;
2012-11-30 06:03:58 +01:00
}
2014-04-10 16:11:11 +02:00
2013-08-17 18:43:15 +02:00
//---------------------------------------------------------------------------
const Type * SymbolDatabase : : findTypeInNested ( const Token * startTok , const Scope * startScope ) const
{
// skip over struct or union
2016-04-22 06:02:54 +02:00
if ( Token : : Match ( startTok , " struct|union|enum " ) )
2013-08-17 18:43:15 +02:00
startTok = startTok - > next ( ) ;
// type same as scope
if ( startTok - > str ( ) = = startScope - > className & & startScope - > isClassOrStruct ( ) )
return startScope - > definedType ;
bool hasPath = false ;
// absolute path - directly start in global scope
if ( startTok - > str ( ) = = " :: " ) {
hasPath = true ;
startTok = startTok - > next ( ) ;
startScope = & scopeList . front ( ) ;
}
const Token * tok = startTok ;
const Scope * scope = startScope ;
while ( scope & & tok & & tok - > isName ( ) ) {
2018-05-06 08:23:07 +02:00
if ( tok - > strAt ( 1 ) = = " :: " | | ( tok - > strAt ( 1 ) = = " < " & & Token : : simpleMatch ( tok - > linkAt ( 1 ) , " > :: " ) ) ) {
2013-08-17 18:43:15 +02:00
hasPath = true ;
scope = scope - > findRecordInNestedList ( tok - > str ( ) ) ;
if ( scope ) {
2018-05-01 07:32:19 +02:00
if ( tok - > strAt ( 1 ) = = " :: " )
tok = tok - > tokAt ( 2 ) ;
else
tok = tok - > linkAt ( 1 ) - > tokAt ( 2 ) ;
2013-08-17 18:43:15 +02:00
} else {
startScope = startScope - > nestedIn ;
if ( ! startScope )
break ;
scope = startScope ;
tok = startTok ;
}
} else {
const Type * type = scope - > findType ( tok - > str ( ) ) ;
if ( hasPath | | type )
return type ;
else {
scope = scope - > nestedIn ;
if ( ! scope )
break ;
}
}
}
// not a valid path
2017-08-09 20:00:26 +02:00
return nullptr ;
2013-08-17 18:43:15 +02:00
}
2014-04-10 16:11:11 +02:00
//---------------------------------------------------------------------------
const Scope * SymbolDatabase : : findNamespace ( const Token * tok , const Scope * scope ) const
{
const Scope * s = findScope ( tok , scope ) ;
if ( s )
return s ;
else if ( scope - > nestedIn )
return findNamespace ( tok , scope - > nestedIn ) ;
2017-08-09 20:00:26 +02:00
return nullptr ;
2014-04-10 16:11:11 +02:00
}
//---------------------------------------------------------------------------
2019-07-22 11:25:51 +02:00
Function * SymbolDatabase : : findFunctionInScope ( const Token * func , const Scope * ns , const std : : string & path , nonneg int path_length )
2014-04-10 16:11:11 +02:00
{
2014-04-11 05:40:37 +02:00
const Function * function = nullptr ;
2015-01-12 06:11:22 +01:00
const bool destructor = func - > strAt ( - 1 ) = = " ~ " ;
2014-04-11 05:40:37 +02:00
2015-01-02 21:38:19 +01:00
for ( std : : multimap < std : : string , const Function * > : : const_iterator it = ns - > functionMap . find ( func - > str ( ) ) ;
it ! = ns - > functionMap . end ( ) & & it - > first = = func - > str ( ) ; + + it ) {
2015-01-12 06:11:22 +01:00
2018-11-09 06:11:48 +01:00
if ( Function : : argsMatch ( ns , it - > second - > argDef , func - > next ( ) , path , path_length ) & &
2015-01-12 06:11:22 +01:00
it - > second - > isDestructor ( ) = = destructor ) {
2015-01-02 21:38:19 +01:00
function = it - > second ;
break ;
2014-04-11 05:40:37 +02:00
}
}
2014-04-10 16:11:11 +02:00
if ( ! function ) {
const Scope * scope = ns - > findRecordInNestedList ( func - > str ( ) ) ;
2018-05-01 07:32:19 +02:00
if ( scope & & Token : : Match ( func - > tokAt ( 1 ) , " ::|< " ) ) {
if ( func - > strAt ( 1 ) = = " :: " )
func = func - > tokAt ( 2 ) ;
2018-05-06 08:23:07 +02:00
else if ( func - > linkAt ( 1 ) )
2018-05-01 07:32:19 +02:00
func = func - > linkAt ( 1 ) - > tokAt ( 2 ) ;
2018-05-06 08:23:07 +02:00
else
return nullptr ;
2014-12-09 21:36:09 +01:00
if ( func - > str ( ) = = " ~ " )
func = func - > next ( ) ;
2018-05-01 07:32:19 +02:00
function = findFunctionInScope ( func , scope , path , path_length ) ;
2014-04-10 16:11:11 +02:00
}
}
return const_cast < Function * > ( function ) ;
}
2015-05-22 22:18:42 +02:00
//---------------------------------------------------------------------------
2015-06-18 19:07:51 +02:00
namespace {
2018-04-08 22:54:10 +02:00
# define C_KEYWORDS\
" _Bool " , " auto " , " break " , " case " , " char " , " const " , " continue " , " default " , " do " , \
" double " , " else " , " enum " , " extern " , " float " , " for " , " goto " , " if " , " inline " , \
" int " , " long " , " register " , " restrict " , " return " , " short " , " signed " , " sizeof " , \
" static " , " struct " , " switch " , " typedef " , " union " , " unsigned " , " void " , " volatile " , \
" while "
const std : : set < std : : string > c_keywords = { C_KEYWORDS } ;
const std : : set < std : : string > cpp_keywords = {
C_KEYWORDS ,
2018-06-17 17:05:36 +02:00
" alignas " , " alignof " , " and " , " and_eq " , " asm " , " bitand " , " bitor " , " bool " , " catch " , " class " , " compl " ,
" concept " , " constexpr " , " const_cast " , " decltype " ,
" delete " , " dynamic_cast " , " explicit " , " export " , " false " , " friend " ,
2018-04-08 22:54:10 +02:00
" mutable " , " namespace " , " new " , " noexcept " , " not " , " not_eq " , " nullptr " , " operator " ,
2018-06-17 17:05:36 +02:00
" or " , " or_eq " , " private " , " protected " , " public " , " reinterpret_cast " ,
" requires " , " static_assert " ,
" static_cast " , " template " , " this " , " thread_local " , " throw " ,
" true " , " try " , " typeid " , " typename " , " using " ,
" virtual " , " wchar_t " , " xor " , " xor_eq "
2018-04-08 22:54:10 +02:00
} ;
2015-06-18 19:07:51 +02:00
}
2015-11-29 13:23:13 +01:00
2015-06-18 19:07:51 +02:00
bool SymbolDatabase : : isReservedName ( const std : : string & iName ) const
{
2015-11-29 13:23:13 +01:00
if ( isCPP ( ) )
return cpp_keywords . find ( iName ) ! = cpp_keywords . cend ( ) ;
else
return c_keywords . find ( iName ) ! = c_keywords . cend ( ) ;
2015-05-22 22:18:42 +02:00
}
2015-10-04 19:42:58 +02:00
2019-07-22 11:25:51 +02:00
nonneg int SymbolDatabase : : sizeOfType ( const Token * type ) const
2016-07-08 20:53:08 +02:00
{
2019-07-22 11:25:51 +02:00
int size = mTokenizer - > sizeOfType ( type ) ;
2016-07-08 20:53:08 +02:00
2016-07-26 01:18:47 +02:00
if ( size = = 0 & & type - > type ( ) & & type - > type ( ) - > isEnumType ( ) & & type - > type ( ) - > classScope ) {
2018-06-16 16:10:28 +02:00
size = mSettings - > sizeof_int ;
2016-07-08 20:53:08 +02:00
const Token * enum_type = type - > type ( ) - > classScope - > enumType ;
if ( enum_type )
2018-06-16 16:10:28 +02:00
size = mTokenizer - > sizeOfType ( enum_type ) ;
2016-07-08 20:53:08 +02:00
}
return size ;
}
2016-07-31 19:47:34 +02:00
static const Token * parsedecl ( const Token * type , ValueType * const valuetype , ValueType : : Sign defaultSignedness , const Settings * settings ) ;
2015-10-11 10:48:08 +02:00
2017-03-22 02:55:22 +01:00
void SymbolDatabase : : setValueType ( Token * tok , const Variable & var )
2015-10-11 10:48:08 +02:00
{
ValueType valuetype ;
2018-05-02 20:55:11 +02:00
if ( var . nameToken ( ) )
valuetype . bits = var . nameToken ( ) - > bits ( ) ;
2015-10-11 10:48:08 +02:00
valuetype . pointer = var . dimensions ( ) . size ( ) ;
valuetype . typeScope = var . typeScope ( ) ;
2019-02-27 10:28:18 +01:00
if ( var . valueType ( ) ) {
valuetype . container = var . valueType ( ) - > container ;
}
2019-07-07 21:52:49 +02:00
valuetype . smartPointerType = var . smartPointerType ( ) ;
2019-02-24 19:11:18 +01:00
if ( parsedecl ( var . typeStartToken ( ) , & valuetype , mDefaultSignedness , mSettings ) ) {
if ( tok - > str ( ) = = " . " & & tok - > astOperand1 ( ) ) {
const ValueType * const vt = tok - > astOperand1 ( ) - > valueType ( ) ;
if ( vt & & ( vt - > constness & 1 ) ! = 0 )
valuetype . constness | = 1 ;
}
2017-03-22 02:55:22 +01:00
setValueType ( tok , valuetype ) ;
2019-02-24 19:11:18 +01:00
}
2016-04-22 06:02:54 +02:00
}
2017-03-22 02:55:22 +01:00
void SymbolDatabase : : setValueType ( Token * tok , const Enumerator & enumerator )
2016-04-22 06:02:54 +02:00
{
ValueType valuetype ;
valuetype . typeScope = enumerator . scope ;
const Token * type = enumerator . scope - > enumType ;
if ( type ) {
2017-03-04 11:13:28 +01:00
valuetype . type = ValueType : : typeFromString ( type - > str ( ) , type - > isLong ( ) ) ;
if ( valuetype . type = = ValueType : : Type : : UNKNOWN_TYPE & & type - > isStandardType ( ) )
2018-06-16 16:10:28 +02:00
valuetype . fromLibraryType ( type - > str ( ) , mSettings ) ;
2017-03-04 11:13:28 +01:00
if ( valuetype . isIntegral ( ) ) {
if ( type - > isSigned ( ) )
valuetype . sign = ValueType : : Sign : : SIGNED ;
else if ( type - > isUnsigned ( ) )
valuetype . sign = ValueType : : Sign : : UNSIGNED ;
else if ( valuetype . type = = ValueType : : Type : : CHAR )
2018-06-16 23:25:35 +02:00
valuetype . sign = mDefaultSignedness ;
2017-03-04 11:13:28 +01:00
else
valuetype . sign = ValueType : : Sign : : SIGNED ;
2016-05-04 15:39:56 +02:00
}
2016-04-22 06:02:54 +02:00
2017-03-22 02:55:22 +01:00
setValueType ( tok , valuetype ) ;
2016-04-22 06:02:54 +02:00
} else {
valuetype . sign = ValueType : : SIGNED ;
valuetype . type = ValueType : : INT ;
2017-03-22 02:55:22 +01:00
setValueType ( tok , valuetype ) ;
2016-04-22 06:02:54 +02:00
}
2015-10-11 10:48:08 +02:00
}
2017-02-27 23:04:25 +01:00
static void setAutoTokenProperties ( Token * const autoTok )
{
const ValueType * valuetype = autoTok - > valueType ( ) ;
if ( valuetype - > isIntegral ( ) | | valuetype - > isFloat ( ) )
autoTok - > isStandardType ( true ) ;
}
2017-03-22 02:55:22 +01:00
void SymbolDatabase : : setValueType ( Token * tok , const ValueType & valuetype )
2015-10-04 19:42:58 +02:00
{
2015-10-07 20:24:17 +02:00
tok - > setValueType ( new ValueType ( valuetype ) ) ;
2019-06-16 10:09:38 +02:00
Token * parent = tok - > astParent ( ) ;
2015-10-04 19:42:58 +02:00
if ( ! parent | | parent - > valueType ( ) )
return ;
2016-02-04 20:49:13 +01:00
if ( ! parent - > astOperand1 ( ) )
2015-10-04 19:42:58 +02:00
return ;
2016-02-04 20:49:13 +01:00
const ValueType * vt1 = parent - > astOperand1 ( ) ? parent - > astOperand1 ( ) - > valueType ( ) : nullptr ;
const ValueType * vt2 = parent - > astOperand2 ( ) ? parent - > astOperand2 ( ) - > valueType ( ) : nullptr ;
if ( vt1 & & Token : : Match ( parent , " <<|>> " ) ) {
2018-06-16 23:30:00 +02:00
if ( ! mIsCpp | | ( vt2 & & vt2 - > isIntegral ( ) ) )
2017-03-22 02:55:22 +01:00
setValueType ( parent , * vt1 ) ;
2015-12-31 20:18:35 +01:00
return ;
}
2019-07-09 17:32:19 +02:00
if ( vt1 & & vt1 - > smartPointerType & & Token : : Match ( parent , " . %name% ( " ) & & parent - > originalName ( ) = = " -> " & & ! parent - > next ( ) - > function ( ) ) {
2019-07-13 20:29:15 +02:00
const Scope * scope = vt1 - > smartPointerType - > classScope ;
2019-07-09 17:32:19 +02:00
const Function * f = scope ? scope - > findFunction ( parent - > next ( ) , false ) : nullptr ;
if ( f )
parent - > next ( ) - > function ( f ) ;
}
2016-03-21 19:51:09 +01:00
if ( parent - > isAssignmentOp ( ) ) {
if ( vt1 )
2017-03-22 02:55:22 +01:00
setValueType ( parent , * vt1 ) ;
2018-06-16 23:30:00 +02:00
else if ( mIsCpp & & ( ( Token : : Match ( parent - > tokAt ( - 3 ) , " %var% ; % var % = " ) && parent->strAt(-3) == parent->strAt(-1)) ||
2018-06-17 08:45:26 +02:00
Token : : Match ( parent - > tokAt ( - 1 ) , " %var% = " ) ) ) {
2017-04-20 21:22:57 +02:00
Token * var1Tok = parent - > strAt ( - 2 ) = = " ; " ? parent - > tokAt ( - 3 ) : parent - > tokAt ( - 1 ) ;
2017-02-26 22:43:10 +01:00
Token * autoTok = nullptr ;
2017-04-21 21:25:02 +02:00
if ( Token : : Match ( var1Tok - > tokAt ( - 2 ) , " ;|{|}|(|const auto " ) )
2017-02-26 22:43:10 +01:00
autoTok = var1Tok - > previous ( ) ;
2017-04-21 21:25:02 +02:00
else if ( Token : : Match ( var1Tok - > tokAt ( - 3 ) , " ; | { | } | ( | const auto * " ))
2017-02-26 22:43:10 +01:00
autoTok = var1Tok - > tokAt ( - 2 ) ;
if ( autoTok ) {
2017-03-23 03:09:40 +01:00
ValueType vt ( * vt2 ) ;
2019-02-24 19:11:18 +01:00
if ( vt . constness & ( 1 < < vt . pointer ) )
vt . constness & = ~ ( 1 < < vt . pointer ) ;
2017-03-23 03:09:40 +01:00
if ( autoTok - > strAt ( 1 ) = = " * " & & vt . pointer )
vt . pointer - - ;
if ( autoTok - > strAt ( - 1 ) = = " const " )
vt . constness | = 1 ;
setValueType ( autoTok , vt ) ;
2017-02-27 23:04:25 +01:00
setAutoTokenProperties ( autoTok ) ;
2019-02-24 19:11:18 +01:00
if ( vt2 - > pointer > vt . pointer )
vt . pointer + + ;
2019-02-23 18:15:05 +01:00
setValueType ( var1Tok , vt ) ;
if ( var1Tok ! = parent - > previous ( ) )
2019-02-24 19:11:18 +01:00
setValueType ( parent - > previous ( ) , vt ) ;
2017-04-21 21:25:02 +02:00
Variable * var = const_cast < Variable * > ( parent - > previous ( ) - > variable ( ) ) ;
2017-03-23 03:09:40 +01:00
if ( var ) {
2019-02-24 08:16:08 +01:00
ValueType vt2_ ( * vt2 ) ;
if ( vt2_ . pointer = = 0 & & autoTok - > strAt ( 1 ) = = " * " )
vt2_ . pointer = 1 ;
if ( ( vt . constness & ( 1 < < vt2 - > pointer ) ) ! = 0 )
vt2_ . constness | = ( 1 < < vt2 - > pointer ) ;
2019-05-14 08:57:36 +02:00
if ( ! Token : : Match ( autoTok - > tokAt ( 1 ) , " *|& " ) )
vt2_ . constness = vt . constness ;
2019-02-24 08:16:08 +01:00
var - > setValueType ( vt2_ ) ;
2017-03-23 03:09:40 +01:00
if ( vt2 - > typeScope & & vt2 - > typeScope - > definedType ) {
2017-04-21 21:25:02 +02:00
var - > type ( vt2 - > typeScope - > definedType ) ;
2017-03-23 03:09:40 +01:00
if ( autoTok - > valueType ( ) - > pointer = = 0 )
autoTok - > type ( vt2 - > typeScope - > definedType ) ;
}
}
2017-02-26 20:02:57 +01:00
}
}
2016-03-21 19:51:09 +01:00
return ;
}
2018-06-16 23:30:00 +02:00
if ( parent - > str ( ) = = " [ " & & ( ! mIsCpp | | parent - > astOperand1 ( ) = = tok ) & & valuetype . pointer > 0U & & ! Token : : Match ( parent - > previous ( ) , " [{,] " ) ) {
2017-03-30 11:01:29 +02:00
const Token * op1 = parent - > astOperand1 ( ) ;
while ( op1 & & op1 - > str ( ) = = " [ " )
op1 = op1 - > astOperand1 ( ) ;
2015-12-30 11:36:46 +01:00
ValueType vt ( valuetype ) ;
2017-03-30 11:01:29 +02:00
// the "[" is a dereference unless this is a variable declaration
if ( ! ( op1 & & op1 - > variable ( ) & & op1 - > variable ( ) - > nameToken ( ) = = op1 ) )
vt . pointer - = 1U ;
2017-03-22 02:55:22 +01:00
setValueType ( parent , vt ) ;
2015-10-04 19:42:58 +02:00
return ;
}
2016-12-04 16:02:50 +01:00
if ( Token : : Match ( parent - > previous ( ) , " %name% ( " ) & & parent - > astOperand1 ( ) = = tok & & valuetype . pointer > 0U ) {
ValueType vt ( valuetype ) ;
vt . pointer - = 1U ;
2017-03-22 02:55:22 +01:00
setValueType ( parent , vt ) ;
2016-12-04 16:02:50 +01:00
return ;
}
2015-10-07 20:24:17 +02:00
if ( parent - > str ( ) = = " * " & & ! parent - > astOperand2 ( ) & & valuetype . pointer > 0U ) {
2015-12-30 11:36:46 +01:00
ValueType vt ( valuetype ) ;
vt . pointer - = 1U ;
2017-03-22 02:55:22 +01:00
setValueType ( parent , vt ) ;
2015-10-04 19:42:58 +02:00
return ;
}
2019-03-19 06:25:10 +01:00
if ( parent - > str ( ) = = " * " & & Token : : simpleMatch ( parent - > astOperand2 ( ) , " [ " ) & & valuetype . pointer > 0U ) {
const Token * op1 = parent - > astOperand2 ( ) - > astOperand1 ( ) ;
while ( op1 & & op1 - > str ( ) = = " [ " )
op1 = op1 - > astOperand1 ( ) ;
ValueType vt ( valuetype ) ;
if ( op1 & & op1 - > variable ( ) & & op1 - > variable ( ) - > nameToken ( ) = = op1 ) {
setValueType ( parent , vt ) ;
return ;
}
}
2015-10-08 19:50:10 +02:00
if ( parent - > str ( ) = = " & " & & ! parent - > astOperand2 ( ) ) {
2015-12-30 11:36:46 +01:00
ValueType vt ( valuetype ) ;
vt . pointer + = 1U ;
2017-03-22 02:55:22 +01:00
setValueType ( parent , vt ) ;
2015-10-08 19:50:10 +02:00
return ;
}
2015-10-04 19:42:58 +02:00
2016-02-04 20:49:13 +01:00
if ( ( parent - > str ( ) = = " . " | | parent - > str ( ) = = " :: " ) & &
parent - > astOperand2 ( ) & & parent - > astOperand2 ( ) - > isName ( ) ) {
const Variable * var = parent - > astOperand2 ( ) - > variable ( ) ;
if ( ! var & & valuetype . typeScope & & vt1 ) {
const std : : string & name = parent - > astOperand2 ( ) - > str ( ) ;
const Scope * typeScope = vt1 - > typeScope ;
if ( ! typeScope )
2015-10-11 10:48:08 +02:00
return ;
2016-02-04 20:49:13 +01:00
for ( std : : list < Variable > : : const_iterator it = typeScope - > varlist . begin ( ) ; it ! = typeScope - > varlist . end ( ) ; + + it ) {
if ( it - > nameToken ( ) - > str ( ) = = name ) {
var = & * it ;
break ;
}
2015-10-11 10:48:08 +02:00
}
}
2016-02-04 20:49:13 +01:00
if ( var )
2017-03-22 02:55:22 +01:00
setValueType ( parent , * var ) ;
2016-02-04 20:49:13 +01:00
return ;
2015-10-11 10:48:08 +02:00
}
2017-02-27 02:09:33 +01:00
// range for loop, auto
if ( vt2 & &
parent - > str ( ) = = " : " & &
2017-03-24 00:48:20 +01:00
Token : : Match ( parent - > astParent ( ) , " ( const| auto *|&| %var% : " ) & &
2017-02-27 02:09:33 +01:00
! parent - > previous ( ) - > valueType ( ) & &
Token : : simpleMatch ( parent - > astParent ( ) - > astOperand1 ( ) , " for " ) ) {
2017-03-24 00:48:20 +01:00
const bool isconst = Token : : simpleMatch ( parent - > astParent ( ) - > next ( ) , " const " ) ;
2019-06-16 10:09:38 +02:00
Token * const autoToken = parent - > astParent ( ) - > tokAt ( isconst ? 2 : 1 ) ;
2017-02-27 02:09:33 +01:00
if ( vt2 - > pointer ) {
2017-03-24 00:48:20 +01:00
ValueType autovt ( * vt2 ) ;
autovt . pointer - - ;
autovt . constness = 0 ;
setValueType ( autoToken , autovt ) ;
2017-02-27 23:04:25 +01:00
setAutoTokenProperties ( autoToken ) ;
2017-03-24 00:48:20 +01:00
ValueType varvt ( * vt2 ) ;
varvt . pointer - - ;
if ( isconst )
varvt . constness | = 1 ;
setValueType ( parent - > previous ( ) , varvt ) ;
2017-05-01 20:12:50 +02:00
Variable * var = const_cast < Variable * > ( parent - > previous ( ) - > variable ( ) ) ;
if ( var ) {
2018-06-20 10:00:15 +02:00
var - > setValueType ( varvt ) ;
2017-05-01 20:12:50 +02:00
if ( vt2 - > typeScope & & vt2 - > typeScope - > definedType ) {
var - > type ( vt2 - > typeScope - > definedType ) ;
autoToken - > type ( vt2 - > typeScope - > definedType ) ;
}
2017-03-24 00:48:20 +01:00
}
2017-03-05 15:40:29 +01:00
} else if ( vt2 - > container ) {
// TODO: Determine exact type of RHS
const Token * typeStart = parent - > astOperand2 ( ) ;
while ( typeStart ) {
if ( typeStart - > variable ( ) )
typeStart = typeStart - > variable ( ) - > typeStartToken ( ) ;
else if ( typeStart - > str ( ) = = " ( " & & typeStart - > previous ( ) & & typeStart - > previous ( ) - > function ( ) )
typeStart = typeStart - > previous ( ) - > function ( ) - > retDef ;
else
break ;
}
2019-07-09 17:32:19 +02:00
const Token * containerElementType = typeStart ;
while ( Token : : Match ( containerElementType , " %name%|:: " ) )
containerElementType = containerElementType - > next ( ) ;
// Try to determine type of "auto" token.
2017-03-05 15:40:29 +01:00
// TODO: Get type better
2019-07-09 17:32:19 +02:00
bool setType = false ;
ValueType autovt ;
const Type * templateArgType = nullptr ; // container element type / smart pointer type
if ( Token : : Match ( containerElementType , " < %type% *| *| > " ) ) {
if ( parsedecl ( containerElementType - > next ( ) , & autovt , mDefaultSignedness , mSettings ) ) {
setType = true ;
templateArgType = containerElementType - > next ( ) - > type ( ) ;
}
} else if ( mSettings - > library . isSmartPointer ( containerElementType - > next ( ) ) ) {
const Token * smartPointerTypeTok = containerElementType - > next ( ) ;
while ( Token : : Match ( smartPointerTypeTok , " %name%|:: " ) )
smartPointerTypeTok = smartPointerTypeTok - > next ( ) ;
if ( Token : : Match ( smartPointerTypeTok , " < %name% > > " ) & & smartPointerTypeTok - > next ( ) - > type ( ) ) {
setType = true ;
templateArgType = smartPointerTypeTok - > next ( ) - > type ( ) ;
autovt . smartPointerType = templateArgType ;
autovt . type = ValueType : : Type : : NONSTD ;
}
}
if ( setType ) {
// Type of "auto" has been determined.. set type information for "auto" and variable tokens
setValueType ( autoToken , autovt ) ;
setAutoTokenProperties ( autoToken ) ;
ValueType varvt ( autovt ) ;
if ( isconst )
varvt . constness | = 1 ;
setValueType ( parent - > previous ( ) , varvt ) ;
Variable * var = const_cast < Variable * > ( parent - > previous ( ) - > variable ( ) ) ;
if ( var ) {
var - > setValueType ( varvt ) ;
if ( templateArgType & & templateArgType - > classScope & & templateArgType - > classScope - > definedType ) {
autoToken - > type ( templateArgType - > classScope - > definedType ) ;
var - > type ( templateArgType - > classScope - > definedType ) ;
2017-03-24 01:14:49 +01:00
}
2017-03-05 15:40:29 +01:00
}
}
2017-02-27 02:09:33 +01:00
}
}
2018-04-06 22:26:35 +02:00
if ( vt1 & & vt1 - > containerTypeToken & & parent - > str ( ) = = " [ " ) {
ValueType vtParent ;
2018-06-16 23:25:35 +02:00
if ( parsedecl ( vt1 - > containerTypeToken , & vtParent , mDefaultSignedness , mSettings ) ) {
2018-04-06 22:26:35 +02:00
setValueType ( parent , vtParent ) ;
return ;
}
}
2016-02-04 20:49:13 +01:00
if ( ! vt1 )
2015-10-04 19:42:58 +02:00
return ;
2016-02-04 20:49:13 +01:00
if ( parent - > astOperand2 ( ) & & ! vt2 )
return ;
2018-04-04 21:51:31 +02:00
const bool ternary = parent - > str ( ) = = " : " & & parent - > astParent ( ) & & parent - > astParent ( ) - > str ( ) = = " ? " ;
2017-07-01 22:45:51 +02:00
if ( ternary ) {
2017-08-02 07:48:11 +02:00
if ( vt2 & & vt1 - > pointer = = vt2 - > pointer & & vt1 - > type = = vt2 - > type & & vt1 - > sign = = vt2 - > sign )
2017-07-01 22:45:51 +02:00
setValueType ( parent , * vt2 ) ;
2019-06-16 10:09:38 +02:00
parent = parent - > astParent ( ) ;
2017-07-01 22:45:51 +02:00
}
2016-02-04 21:20:05 +01:00
2016-02-05 12:06:44 +01:00
if ( ternary | | parent - > isArithmeticalOp ( ) | | parent - > tokType ( ) = = Token : : eIncDecOp ) {
2016-02-04 21:03:54 +01:00
if ( vt1 - > pointer ! = 0U & & vt2 & & vt2 - > pointer = = 0U ) {
2017-03-22 02:55:22 +01:00
setValueType ( parent , * vt1 ) ;
2015-10-04 19:42:58 +02:00
return ;
}
2016-02-04 21:03:54 +01:00
if ( vt1 - > pointer = = 0U & & vt2 & & vt2 - > pointer ! = 0U ) {
2017-03-22 02:55:22 +01:00
setValueType ( parent , * vt2 ) ;
2015-10-04 19:42:58 +02:00
return ;
}
2016-02-05 09:59:27 +01:00
if ( vt1 - > pointer ! = 0U ) {
2016-02-05 12:06:44 +01:00
if ( ternary | | parent - > tokType ( ) = = Token : : eIncDecOp ) // result is pointer
2017-03-22 02:55:22 +01:00
setValueType ( parent , * vt1 ) ;
2016-02-05 09:59:27 +01:00
else // result is pointer diff
2017-03-22 02:55:22 +01:00
setValueType ( parent , ValueType ( ValueType : : Sign : : SIGNED , ValueType : : Type : : INT , 0U , 0U , " ptrdiff_t " ) ) ;
2015-10-04 19:42:58 +02:00
return ;
}
2016-02-04 21:03:54 +01:00
if ( vt1 - > type = = ValueType : : Type : : LONGDOUBLE | | ( vt2 & & vt2 - > type = = ValueType : : Type : : LONGDOUBLE ) ) {
2017-03-22 02:55:22 +01:00
setValueType ( parent , ValueType ( ValueType : : Sign : : UNKNOWN_SIGN , ValueType : : Type : : LONGDOUBLE , 0U ) ) ;
2015-10-08 19:50:10 +02:00
return ;
}
2016-02-04 21:03:54 +01:00
if ( vt1 - > type = = ValueType : : Type : : DOUBLE | | ( vt2 & & vt2 - > type = = ValueType : : Type : : DOUBLE ) ) {
2017-03-22 02:55:22 +01:00
setValueType ( parent , ValueType ( ValueType : : Sign : : UNKNOWN_SIGN , ValueType : : Type : : DOUBLE , 0U ) ) ;
2015-10-04 19:42:58 +02:00
return ;
}
2016-02-04 21:03:54 +01:00
if ( vt1 - > type = = ValueType : : Type : : FLOAT | | ( vt2 & & vt2 - > type = = ValueType : : Type : : FLOAT ) ) {
2017-03-22 02:55:22 +01:00
setValueType ( parent , ValueType ( ValueType : : Sign : : UNKNOWN_SIGN , ValueType : : Type : : FLOAT , 0U ) ) ;
2015-10-04 19:42:58 +02:00
return ;
}
2017-07-16 17:27:32 +02:00
// iterator +/- integral = iterator
if ( vt1 - > type = = ValueType : : Type : : ITERATOR & & vt2 & & vt2 - > isIntegral ( ) & &
( parent - > str ( ) = = " + " | | parent - > str ( ) = = " - " ) ) {
setValueType ( parent , * vt1 ) ;
return ;
}
2015-10-11 12:20:40 +02:00
}
2015-10-07 18:10:48 +02:00
2016-02-04 21:03:54 +01:00
if ( vt1 - > isIntegral ( ) & & vt1 - > pointer = = 0U & &
( ! vt2 | | ( vt2 - > isIntegral ( ) & & vt2 - > pointer = = 0U ) ) & &
2016-02-05 12:06:44 +01:00
( ternary | | parent - > isArithmeticalOp ( ) | | parent - > tokType ( ) = = Token : : eBitOp | | parent - > tokType ( ) = = Token : : eIncDecOp | | parent - > isAssignmentOp ( ) ) ) {
2015-10-11 12:20:40 +02:00
ValueType vt ;
2016-02-04 21:03:54 +01:00
if ( ! vt2 | | vt1 - > type > vt2 - > type ) {
vt . type = vt1 - > type ;
vt . sign = vt1 - > sign ;
vt . originalTypeName = vt1 - > originalTypeName ;
} else if ( vt1 - > type = = vt2 - > type ) {
2015-10-11 12:20:40 +02:00
vt . type = vt1 - > type ;
if ( vt1 - > sign = = ValueType : : Sign : : UNSIGNED | | vt2 - > sign = = ValueType : : Sign : : UNSIGNED )
vt . sign = ValueType : : Sign : : UNSIGNED ;
else if ( vt1 - > sign = = ValueType : : Sign : : UNKNOWN_SIGN | | vt2 - > sign = = ValueType : : Sign : : UNKNOWN_SIGN )
vt . sign = ValueType : : Sign : : UNKNOWN_SIGN ;
else
vt . sign = ValueType : : Sign : : SIGNED ;
vt . originalTypeName = ( vt1 - > originalTypeName . empty ( ) ? vt2 : vt1 ) - > originalTypeName ;
} else {
vt . type = vt2 - > type ;
vt . sign = vt2 - > sign ;
vt . originalTypeName = vt2 - > originalTypeName ;
}
2019-09-01 09:51:53 +02:00
if ( vt . type < ValueType : : Type : : INT & & ! ( ternary & & vt . type = = ValueType : : Type : : BOOL ) ) {
2015-10-11 12:20:40 +02:00
vt . type = ValueType : : Type : : INT ;
vt . sign = ValueType : : Sign : : SIGNED ;
vt . originalTypeName . clear ( ) ;
2015-10-04 19:42:58 +02:00
}
2015-10-11 12:20:40 +02:00
2017-03-22 02:55:22 +01:00
setValueType ( parent , vt ) ;
2015-10-11 12:20:40 +02:00
return ;
2015-10-04 19:42:58 +02:00
}
}
2016-07-31 19:47:34 +02:00
static const Token * parsedecl ( const Token * type , ValueType * const valuetype , ValueType : : Sign defaultSignedness , const Settings * settings )
2015-10-04 20:32:16 +02:00
{
2019-09-01 11:36:02 +02:00
const Token * const previousType = type ;
2015-10-10 08:32:45 +02:00
const unsigned int pointer0 = valuetype - > pointer ;
while ( Token : : Match ( type - > previous ( ) , " %name% " ) )
type = type - > previous ( ) ;
2016-01-01 20:03:31 +01:00
valuetype - > sign = ValueType : : Sign : : UNKNOWN_SIGN ;
2019-07-07 21:52:49 +02:00
if ( ! valuetype - > typeScope & & ! valuetype - > smartPointerType )
2016-05-09 11:11:13 +02:00
valuetype - > type = ValueType : : Type : : UNKNOWN_TYPE ;
2019-07-07 21:52:49 +02:00
else if ( valuetype - > smartPointerType )
valuetype - > type = ValueType : : Type : : NONSTD ;
2016-08-26 19:47:36 +02:00
else if ( valuetype - > typeScope - > type = = Scope : : eEnum ) {
const Token * enum_type = valuetype - > typeScope - > enumType ;
if ( enum_type ) {
if ( enum_type - > isSigned ( ) )
valuetype - > sign = ValueType : : Sign : : SIGNED ;
else if ( enum_type - > isUnsigned ( ) )
valuetype - > sign = ValueType : : Sign : : UNSIGNED ;
else
valuetype - > sign = defaultSignedness ;
2018-04-04 21:51:31 +02:00
const ValueType : : Type t = ValueType : : typeFromString ( enum_type - > str ( ) , enum_type - > isLong ( ) ) ;
2017-03-04 11:13:28 +01:00
if ( t ! = ValueType : : Type : : UNKNOWN_TYPE )
2017-03-01 18:09:50 +01:00
valuetype - > type = t ;
else if ( enum_type - > isStandardType ( ) )
2016-08-26 19:47:36 +02:00
valuetype - > fromLibraryType ( enum_type - > str ( ) , settings ) ;
} else
valuetype - > type = ValueType : : Type : : INT ;
} else
2017-03-05 14:53:32 +01:00
valuetype - > type = ValueType : : Type : : RECORD ;
2019-06-28 22:07:21 +02:00
while ( Token : : Match ( type , " %name%|*|&|:: " ) & & ! Token : : Match ( type , " typename|template " ) & &
! type - > variable ( ) & & ! type - > function ( ) ) {
2015-10-04 23:27:58 +02:00
if ( type - > isSigned ( ) )
2015-10-04 20:32:16 +02:00
valuetype - > sign = ValueType : : Sign : : SIGNED ;
2015-10-04 23:27:58 +02:00
else if ( type - > isUnsigned ( ) )
2015-10-04 20:32:16 +02:00
valuetype - > sign = ValueType : : Sign : : UNSIGNED ;
2018-01-10 22:16:18 +01:00
if ( valuetype - > type = = ValueType : : Type : : UNKNOWN_TYPE & &
2018-01-12 08:19:21 +01:00
type - > type ( ) & & type - > type ( ) - > isTypeAlias ( ) & & type - > type ( ) - > typeStart & &
2019-09-01 11:36:02 +02:00
type - > type ( ) - > typeStart - > str ( ) ! = type - > str ( ) & & type - > type ( ) - > typeStart ! = previousType )
2018-01-10 22:16:18 +01:00
parsedecl ( type - > type ( ) - > typeStart , valuetype , defaultSignedness , settings ) ;
else if ( type - > str ( ) = = " const " )
2015-10-10 08:32:45 +02:00
valuetype - > constness | = ( 1 < < ( valuetype - > pointer - pointer0 ) ) ;
2017-04-06 07:07:20 +02:00
else if ( const Library : : Container * container = settings - > library . detectContainer ( type ) ) {
valuetype - > type = ValueType : : Type : : CONTAINER ;
valuetype - > container = container ;
while ( Token : : Match ( type , " %name%|::|< " ) ) {
2018-04-06 22:26:35 +02:00
if ( type - > str ( ) = = " < " & & type - > link ( ) ) {
if ( container - > type_templateArgNo > = 0 ) {
const Token * templateType = type - > next ( ) ;
for ( int j = 0 ; templateType & & j < container - > type_templateArgNo ; j + + )
templateType = templateType - > nextTemplateArgument ( ) ;
valuetype - > containerTypeToken = templateType ;
}
2017-04-06 07:07:20 +02:00
type = type - > link ( ) ;
2018-04-06 22:26:35 +02:00
}
2017-04-06 07:07:20 +02:00
type = type - > next ( ) ;
}
continue ;
} else if ( Token : : Match ( type , " %name% :: %name% " ) ) {
std : : string typestr ;
const Token * end = type ;
while ( Token : : Match ( end , " %name% :: %name% " ) ) {
typestr + = end - > str ( ) + " :: " ;
end = end - > tokAt ( 2 ) ;
2017-03-05 01:21:02 +01:00
}
2017-04-06 07:07:20 +02:00
typestr + = end - > str ( ) ;
if ( valuetype - > fromLibraryType ( typestr , settings ) )
type = end ;
2017-03-05 01:39:56 +01:00
} else if ( ValueType : : Type : : UNKNOWN_TYPE ! = ValueType : : typeFromString ( type - > str ( ) , type - > isLong ( ) ) )
valuetype - > type = ValueType : : typeFromString ( type - > str ( ) , type - > isLong ( ) ) ;
2017-02-26 22:43:10 +01:00
else if ( type - > str ( ) = = " auto " ) {
2017-02-26 20:02:57 +01:00
const ValueType * vt = type - > valueType ( ) ;
2017-09-14 23:53:44 +02:00
if ( ! vt )
return nullptr ;
2017-02-26 20:02:57 +01:00
valuetype - > type = vt - > type ;
valuetype - > pointer = vt - > pointer ;
if ( vt - > sign ! = ValueType : : Sign : : UNKNOWN_SIGN )
valuetype - > sign = vt - > sign ;
2017-02-27 02:09:33 +01:00
valuetype - > constness = vt - > constness ;
2019-02-27 06:44:31 +01:00
valuetype - > originalTypeName = vt - > originalTypeName ;
2017-02-27 02:09:33 +01:00
while ( Token : : Match ( type , " %name%|*|&|:: " ) & & ! type - > variable ( ) )
type = type - > next ( ) ;
break ;
2017-02-26 20:02:57 +01:00
} else if ( ! valuetype - > typeScope & & ( type - > str ( ) = = " struct " | | type - > str ( ) = = " enum " ) )
2017-03-05 14:53:32 +01:00
valuetype - > type = type - > str ( ) = = " struct " ? ValueType : : Type : : RECORD : ValueType : : Type : : NONSTD ;
2016-05-25 13:56:36 +02:00
else if ( ! valuetype - > typeScope & & type - > type ( ) & & type - > type ( ) - > classScope ) {
2017-03-05 14:53:32 +01:00
valuetype - > type = ValueType : : Type : : RECORD ;
2016-05-25 13:56:36 +02:00
valuetype - > typeScope = type - > type ( ) - > classScope ;
} else if ( type - > isName ( ) & & valuetype - > sign ! = ValueType : : Sign : : UNKNOWN_SIGN & & valuetype - > pointer = = 0U )
2016-01-05 19:47:11 +01:00
return nullptr ;
2015-10-04 20:32:16 +02:00
else if ( type - > str ( ) = = " * " )
valuetype - > pointer + + ;
2016-07-31 19:47:34 +02:00
else if ( type - > isStandardType ( ) )
valuetype - > fromLibraryType ( type - > str ( ) , settings ) ;
2018-06-20 14:49:55 +02:00
else if ( Token : : Match ( type - > previous ( ) , " !!:: %name% !!:: " ) )
valuetype - > fromLibraryType ( type - > str ( ) , settings ) ;
2015-10-07 20:24:17 +02:00
if ( ! type - > originalName ( ) . empty ( ) )
valuetype - > originalTypeName = type - > originalName ( ) ;
2015-10-04 20:32:16 +02:00
type = type - > next ( ) ;
}
2016-01-01 20:03:31 +01:00
2016-01-31 14:34:26 +01:00
// Set signedness for integral types..
if ( valuetype - > isIntegral ( ) & & valuetype - > sign = = ValueType : : Sign : : UNKNOWN_SIGN ) {
if ( valuetype - > type = = ValueType : : Type : : CHAR )
valuetype - > sign = defaultSignedness ;
else if ( valuetype - > type > = ValueType : : Type : : SHORT )
valuetype - > sign = ValueType : : Sign : : SIGNED ;
}
2016-01-01 20:03:31 +01:00
2016-02-05 20:22:30 +01:00
return ( type & & ( valuetype - > type ! = ValueType : : Type : : UNKNOWN_TYPE | | valuetype - > pointer > 0 ) ) ? type : nullptr ;
2015-10-04 20:32:16 +02:00
}
2016-05-25 13:56:36 +02:00
static const Scope * getClassScope ( const Token * tok )
{
return tok & & tok - > valueType ( ) & & tok - > valueType ( ) - > typeScope & & tok - > valueType ( ) - > typeScope - > isClassOrStruct ( ) ?
tok - > valueType ( ) - > typeScope :
nullptr ;
}
static const Function * getOperatorFunction ( const Token * const tok )
{
const std : : string functionName ( " operator " + tok - > str ( ) ) ;
std : : multimap < std : : string , const Function * > : : const_iterator it ;
2018-04-04 21:51:31 +02:00
const Scope * classScope = getClassScope ( tok - > astOperand1 ( ) ) ;
2016-05-25 13:56:36 +02:00
if ( classScope ) {
it = classScope - > functionMap . find ( functionName ) ;
if ( it ! = classScope - > functionMap . end ( ) )
return it - > second ;
}
classScope = getClassScope ( tok - > astOperand2 ( ) ) ;
if ( classScope ) {
it = classScope - > functionMap . find ( functionName ) ;
if ( it ! = classScope - > functionMap . end ( ) )
return it - > second ;
}
return nullptr ;
}
2019-08-05 13:42:00 +02:00
void SymbolDatabase : : setValueTypeInTokenList ( bool reportDebugWarnings )
2015-10-04 19:42:58 +02:00
{
2018-06-16 16:10:28 +02:00
Token * tokens = const_cast < Tokenizer * > ( mTokenizer ) - > list . front ( ) ;
2016-01-01 17:33:59 +01:00
2015-10-04 19:42:58 +02:00
for ( Token * tok = tokens ; tok ; tok = tok - > next ( ) )
tok - > setValueType ( nullptr ) ;
for ( Token * tok = tokens ; tok ; tok = tok - > next ( ) ) {
if ( tok - > isNumber ( ) ) {
2015-10-07 18:10:48 +02:00
if ( MathLib : : isFloat ( tok - > str ( ) ) ) {
ValueType : : Type type = ValueType : : Type : : DOUBLE ;
2018-03-30 20:57:25 +02:00
const char suffix = tok - > str ( ) [ tok - > str ( ) . size ( ) - 1 ] ;
2016-01-03 13:34:47 +01:00
if ( suffix = = ' f ' | | suffix = = ' F ' )
2015-10-07 18:10:48 +02:00
type = ValueType : : Type : : FLOAT ;
2016-08-20 08:44:53 +02:00
else if ( suffix = = ' L ' | | suffix = = ' l ' )
type = ValueType : : Type : : LONGDOUBLE ;
2017-03-22 02:55:22 +01:00
setValueType ( tok , ValueType ( ValueType : : Sign : : UNKNOWN_SIGN , type , 0U ) ) ;
2015-10-07 18:10:48 +02:00
} else if ( MathLib : : isInt ( tok - > str ( ) ) ) {
2018-04-04 21:51:31 +02:00
const bool unsignedSuffix = ( tok - > str ( ) . find_last_of ( " uU " ) ! = std : : string : : npos ) ;
2017-03-04 14:19:14 +01:00
ValueType : : Sign sign = unsignedSuffix ? ValueType : : Sign : : UNSIGNED : ValueType : : Sign : : SIGNED ;
2016-10-16 11:36:22 +02:00
ValueType : : Type type ;
const MathLib : : bigint value = MathLib : : toLongNumber ( tok - > str ( ) ) ;
2018-06-16 16:10:28 +02:00
if ( mSettings - > platformType = = cppcheck : : Platform : : Unspecified )
2016-10-16 11:36:22 +02:00
type = ValueType : : Type : : INT ;
2018-06-16 16:10:28 +02:00
else if ( mSettings - > isIntValue ( unsignedSuffix ? ( value > > 1 ) : value ) )
2016-10-16 11:36:22 +02:00
type = ValueType : : Type : : INT ;
2018-06-16 16:10:28 +02:00
else if ( mSettings - > isLongValue ( unsignedSuffix ? ( value > > 1 ) : value ) )
2016-10-16 11:36:22 +02:00
type = ValueType : : Type : : LONG ;
else
type = ValueType : : Type : : LONGLONG ;
2015-10-07 18:10:48 +02:00
if ( MathLib : : isIntHex ( tok - > str ( ) ) )
sign = ValueType : : Sign : : UNSIGNED ;
2016-07-26 13:19:28 +02:00
for ( std : : size_t pos = tok - > str ( ) . size ( ) - 1U ; pos > 0U ; - - pos ) {
2016-01-03 13:34:47 +01:00
const char suffix = tok - > str ( ) [ pos ] ;
if ( suffix = = ' u ' | | suffix = = ' U ' )
sign = ValueType : : Sign : : UNSIGNED ;
2016-07-26 13:19:28 +02:00
else if ( suffix = = ' l ' | | suffix = = ' L ' )
2016-01-03 13:34:47 +01:00
type = ( type = = ValueType : : Type : : INT ) ? ValueType : : Type : : LONG : ValueType : : Type : : LONGLONG ;
2016-07-26 13:19:28 +02:00
else if ( pos > 2U & & suffix = = ' 4 ' & & tok - > str ( ) [ pos - 1 ] = = ' 6 ' & & tok - > str ( ) [ pos - 2 ] = = ' i ' ) {
type = ValueType : : Type : : LONGLONG ;
pos - = 2 ;
} else break ;
2015-10-07 18:10:48 +02:00
}
2017-03-22 02:55:22 +01:00
setValueType ( tok , ValueType ( sign , type , 0U ) ) ;
2015-10-07 18:10:48 +02:00
}
2016-05-25 13:56:36 +02:00
} else if ( tok - > isComparisonOp ( ) | | tok - > tokType ( ) = = Token : : eLogicalOp ) {
2018-06-16 23:30:00 +02:00
if ( mIsCpp & & tok - > isComparisonOp ( ) & & ( getClassScope ( tok - > astOperand1 ( ) ) | | getClassScope ( tok - > astOperand2 ( ) ) ) ) {
2016-05-25 13:56:36 +02:00
const Function * function = getOperatorFunction ( tok ) ;
if ( function ) {
ValueType vt ;
2018-06-16 23:25:35 +02:00
parsedecl ( function - > retDef , & vt , mDefaultSignedness , mSettings ) ;
2017-03-22 02:55:22 +01:00
setValueType ( tok , vt ) ;
2016-05-25 13:56:36 +02:00
continue ;
}
}
2017-03-22 02:55:22 +01:00
setValueType ( tok , ValueType ( ValueType : : Sign : : UNKNOWN_SIGN , ValueType : : Type : : BOOL , 0U ) ) ;
2019-03-09 17:27:27 +01:00
} else if ( tok - > isBoolean ( ) ) {
setValueType ( tok , ValueType ( ValueType : : Sign : : UNKNOWN_SIGN , ValueType : : Type : : BOOL , 0U ) ) ;
2019-07-31 09:35:32 +02:00
} else if ( tok - > tokType ( ) = = Token : : eChar ) {
setValueType ( tok , ValueType ( ValueType : : Sign : : UNKNOWN_SIGN , tok - > isLong ( ) ? ValueType : : Type : : WCHAR_T : ValueType : : Type : : CHAR , 0U ) ) ;
} else if ( tok - > tokType ( ) = = Token : : eString ) {
2015-10-11 08:13:30 +02:00
ValueType valuetype ( ValueType : : Sign : : UNKNOWN_SIGN , ValueType : : Type : : CHAR , 1U , 1U ) ;
if ( tok - > isLong ( ) ) {
valuetype . originalTypeName = " wchar_t " ;
2019-05-01 16:34:28 +02:00
valuetype . type = ValueType : : Type : : WCHAR_T ;
2015-10-11 08:13:30 +02:00
}
2017-03-22 02:55:22 +01:00
setValueType ( tok , valuetype ) ;
2015-10-11 08:13:30 +02:00
} else if ( tok - > str ( ) = = " ( " ) {
2015-10-04 19:42:58 +02:00
// cast
2019-02-23 17:29:53 +01:00
if ( tok - > isCast ( ) & & ! tok - > astOperand2 ( ) & & Token : : Match ( tok , " ( %name% " ) ) {
2015-10-04 20:32:16 +02:00
ValueType valuetype ;
2018-06-16 23:25:35 +02:00
if ( Token : : simpleMatch ( parsedecl ( tok - > next ( ) , & valuetype , mDefaultSignedness , mSettings ) , " ) " ) )
2017-03-22 02:55:22 +01:00
setValueType ( tok , valuetype ) ;
2015-10-04 19:42:58 +02:00
}
2015-10-11 08:42:31 +02:00
2015-12-26 15:20:17 +01:00
// C++ cast
2019-02-23 17:29:53 +01:00
else if ( tok - > astOperand2 ( ) & & Token : : Match ( tok - > astOperand1 ( ) , " static_cast|const_cast|dynamic_cast|reinterpret_cast < %name% " ) & & tok - > astOperand1 ( ) - > linkAt ( 1 ) ) {
2015-12-26 15:20:17 +01:00
ValueType valuetype ;
2018-06-16 23:25:35 +02:00
if ( Token : : simpleMatch ( parsedecl ( tok - > astOperand1 ( ) - > tokAt ( 2 ) , & valuetype , mDefaultSignedness , mSettings ) , " > " ) )
2017-03-22 02:55:22 +01:00
setValueType ( tok , valuetype ) ;
2015-12-26 15:20:17 +01:00
}
2015-10-11 08:42:31 +02:00
// function
2015-10-11 12:20:40 +02:00
else if ( tok - > previous ( ) & & tok - > previous ( ) - > function ( ) & & tok - > previous ( ) - > function ( ) - > retDef ) {
2015-10-11 08:42:31 +02:00
ValueType valuetype ;
2018-06-16 23:25:35 +02:00
if ( parsedecl ( tok - > previous ( ) - > function ( ) - > retDef , & valuetype , mDefaultSignedness , mSettings ) )
2017-03-22 02:55:22 +01:00
setValueType ( tok , valuetype ) ;
2015-10-11 08:42:31 +02:00
}
2015-10-11 12:20:40 +02:00
else if ( Token : : simpleMatch ( tok - > previous ( ) , " sizeof ( " ) ) {
// TODO: use specified size_t type
ValueType valuetype ( ValueType : : Sign : : UNSIGNED , ValueType : : Type : : LONG , 0U ) ;
valuetype . originalTypeName = " size_t " ;
2017-03-22 02:55:22 +01:00
setValueType ( tok , valuetype ) ;
2016-07-20 09:39:48 +02:00
if ( Token : : Match ( tok , " ( %type% %type%| *| *| ) " ) ) {
ValueType vt ;
2018-06-16 23:25:35 +02:00
if ( parsedecl ( tok - > next ( ) , & vt , mDefaultSignedness , mSettings ) ) {
2017-03-22 02:55:22 +01:00
setValueType ( tok - > next ( ) , vt ) ;
2016-07-20 09:39:48 +02:00
}
}
2015-10-11 12:20:40 +02:00
}
2016-10-23 23:20:36 +02:00
2018-05-20 22:58:05 +02:00
// function style cast
else if ( tok - > previous ( ) & & tok - > previous ( ) - > isStandardType ( ) ) {
ValueType valuetype ;
valuetype . type = ValueType : : typeFromString ( tok - > previous ( ) - > str ( ) , tok - > previous ( ) - > isLong ( ) ) ;
2019-02-23 17:29:53 +01:00
if ( tok - > previous ( ) - > isUnsigned ( ) )
valuetype . sign = ValueType : : Sign : : UNSIGNED ;
else if ( tok - > previous ( ) - > isSigned ( ) )
valuetype . sign = ValueType : : Sign : : SIGNED ;
2018-05-20 22:58:05 +02:00
setValueType ( tok , valuetype ) ;
}
2018-05-22 06:42:37 +02:00
// constructor
else if ( tok - > previous ( ) & & tok - > previous ( ) - > type ( ) & & tok - > previous ( ) - > type ( ) - > classScope ) {
ValueType valuetype ;
valuetype . type = ValueType : : RECORD ;
valuetype . typeScope = tok - > previous ( ) - > type ( ) - > classScope ;
setValueType ( tok , valuetype ) ;
}
2016-10-23 23:20:36 +02:00
// library function
else if ( tok - > previous ( ) ) {
2018-06-16 16:10:28 +02:00
const std : : string & typestr ( mSettings - > library . returnValueType ( tok - > previous ( ) ) ) ;
2019-09-28 14:57:24 +02:00
if ( ! typestr . empty ( ) ) {
ValueType valuetype ;
if ( valuetype . fromLibraryType ( typestr , mSettings ) ) {
setValueType ( tok , valuetype ) ;
}
}
2017-03-05 14:53:32 +01:00
if ( typestr . empty ( ) | | typestr = = " iterator " ) {
if ( Token : : simpleMatch ( tok - > astOperand1 ( ) , " . " ) & &
tok - > astOperand1 ( ) - > astOperand1 ( ) & &
tok - > astOperand1 ( ) - > astOperand2 ( ) & &
tok - > astOperand1 ( ) - > astOperand1 ( ) - > valueType ( ) & &
tok - > astOperand1 ( ) - > astOperand1 ( ) - > valueType ( ) - > container ) {
const Library : : Container * cont = tok - > astOperand1 ( ) - > astOperand1 ( ) - > valueType ( ) - > container ;
2018-04-04 21:51:31 +02:00
const std : : map < std : : string , Library : : Container : : Function > : : const_iterator it = cont - > functions . find ( tok - > astOperand1 ( ) - > astOperand2 ( ) - > str ( ) ) ;
2017-03-05 14:53:32 +01:00
if ( it ! = cont - > functions . end ( ) ) {
if ( it - > second . yield = = Library : : Container : : Yield : : START_ITERATOR | |
it - > second . yield = = Library : : Container : : Yield : : END_ITERATOR | |
it - > second . yield = = Library : : Container : : Yield : : ITERATOR ) {
ValueType vt ;
vt . type = ValueType : : Type : : ITERATOR ;
vt . container = cont ;
2017-03-22 02:55:22 +01:00
setValueType ( tok , vt ) ;
2017-03-05 14:53:32 +01:00
}
}
}
2016-10-23 23:20:36 +02:00
continue ;
2017-03-05 14:53:32 +01:00
}
2018-06-16 16:10:28 +02:00
TokenList tokenList ( mSettings ) ;
2016-10-23 23:20:36 +02:00
std : : istringstream istr ( typestr + " ; " ) ;
if ( tokenList . createTokens ( istr ) ) {
ValueType vt ;
2019-02-15 13:29:52 +01:00
tokenList . simplifyPlatformTypes ( ) ;
2017-10-03 22:10:13 +02:00
tokenList . simplifyStdType ( ) ;
2018-06-16 23:25:35 +02:00
if ( parsedecl ( tokenList . front ( ) , & vt , mDefaultSignedness , mSettings ) ) {
2017-03-22 02:55:22 +01:00
setValueType ( tok , vt ) ;
2016-10-23 23:20:36 +02:00
}
}
}
2015-10-04 19:42:58 +02:00
} else if ( tok - > variable ( ) ) {
2017-03-22 02:55:22 +01:00
setValueType ( tok , * tok - > variable ( ) ) ;
2016-04-22 06:02:54 +02:00
} else if ( tok - > enumerator ( ) ) {
2017-03-22 02:55:22 +01:00
setValueType ( tok , * tok - > enumerator ( ) ) ;
2018-06-16 23:30:00 +02:00
} else if ( mIsCpp & & tok - > str ( ) = = " new " ) {
2017-03-05 10:02:47 +01:00
const Token * typeTok = tok - > next ( ) ;
if ( Token : : Match ( typeTok , " ( std| ::| nothrow ) " ) )
typeTok = typeTok - > link ( ) - > next ( ) ;
2018-06-16 16:10:28 +02:00
if ( const Library : : Container * c = mSettings - > library . detectContainer ( typeTok ) ) {
2017-04-05 22:05:29 +02:00
ValueType vt ;
vt . pointer = 1 ;
vt . container = c ;
vt . type = ValueType : : Type : : CONTAINER ;
setValueType ( tok , vt ) ;
continue ;
}
2017-03-05 10:24:51 +01:00
std : : string typestr ;
while ( Token : : Match ( typeTok , " %name% :: %name% " ) ) {
typestr + = typeTok - > str ( ) + " :: " ;
typeTok = typeTok - > tokAt ( 2 ) ;
}
2017-03-05 10:02:47 +01:00
if ( ! Token : : Match ( typeTok , " %type% ;|[|( " ) )
2017-04-01 22:22:37 +02:00
continue ;
2017-03-05 10:24:51 +01:00
typestr + = typeTok - > str ( ) ;
2017-03-05 10:02:47 +01:00
ValueType vt ;
vt . pointer = 1 ;
if ( typeTok - > type ( ) & & typeTok - > type ( ) - > classScope ) {
2017-03-05 14:53:32 +01:00
vt . type = ValueType : : Type : : RECORD ;
2017-03-05 10:02:47 +01:00
vt . typeScope = typeTok - > type ( ) - > classScope ;
} else {
2017-03-05 10:24:51 +01:00
vt . type = ValueType : : typeFromString ( typestr , typeTok - > isLong ( ) ) ;
2017-03-02 22:24:26 +01:00
if ( vt . type = = ValueType : : Type : : UNKNOWN_TYPE )
2018-06-16 16:10:28 +02:00
vt . fromLibraryType ( typestr , mSettings ) ;
2017-03-05 10:02:47 +01:00
if ( vt . type = = ValueType : : Type : : UNKNOWN_TYPE )
2017-04-01 22:22:37 +02:00
continue ;
2017-02-27 20:57:28 +01:00
if ( typeTok - > isUnsigned ( ) )
vt . sign = ValueType : : Sign : : UNSIGNED ;
else if ( typeTok - > isSigned ( ) )
vt . sign = ValueType : : Sign : : SIGNED ;
if ( vt . sign = = ValueType : : Sign : : UNKNOWN_SIGN & & vt . isIntegral ( ) )
2018-06-16 23:25:35 +02:00
vt . sign = ( vt . type = = ValueType : : Type : : CHAR ) ? mDefaultSignedness : ValueType : : Sign : : SIGNED ;
2017-02-27 20:57:28 +01:00
}
2017-03-22 02:55:22 +01:00
setValueType ( tok , vt ) ;
2019-03-19 06:25:10 +01:00
} else if ( tok - > str ( ) = = " return " & & tok - > scope ( ) ) {
const Function * function = tok - > scope ( ) - > function ;
2019-03-22 01:56:09 +01:00
if ( function & & function - > retDef ) {
2019-03-19 06:25:10 +01:00
ValueType vt ;
parsedecl ( function - > retDef , & vt , mDefaultSignedness , mSettings ) ;
setValueType ( tok , vt ) ;
}
2015-10-04 19:42:58 +02:00
}
}
2017-03-23 03:09:40 +01:00
2019-08-05 13:42:00 +02:00
if ( reportDebugWarnings & & mSettings - > debugwarnings ) {
2019-03-31 17:38:00 +02:00
for ( Token * tok = tokens ; tok ; tok = tok - > next ( ) ) {
if ( tok - > str ( ) = = " auto " & & ! tok - > valueType ( ) )
debugMessage ( tok , " auto token with no type. " ) ;
}
}
2017-03-24 12:19:14 +01:00
// Update functions with new type information.
createSymbolDatabaseSetFunctionPointers ( false ) ;
2017-03-23 03:09:40 +01:00
// Update auto variables with new type information.
createSymbolDatabaseSetVariablePointers ( ) ;
2015-10-04 19:42:58 +02:00
}
2015-10-07 13:38:34 +02:00
2016-12-18 14:03:48 +01:00
ValueType ValueType : : parseDecl ( const Token * type , const Settings * settings )
{
ValueType vt ;
parsedecl ( type , & vt , settings - > defaultSign = = ' u ' ? Sign : : UNSIGNED : Sign : : SIGNED , settings ) ;
return vt ;
}
2017-03-01 18:09:50 +01:00
ValueType : : Type ValueType : : typeFromString ( const std : : string & typestr , bool longType )
{
if ( typestr = = " void " )
return ValueType : : Type : : VOID ;
2017-03-04 11:13:28 +01:00
if ( typestr = = " bool " | | typestr = = " _Bool " )
2017-03-01 18:09:50 +01:00
return ValueType : : Type : : BOOL ;
if ( typestr = = " char " )
return ValueType : : Type : : CHAR ;
if ( typestr = = " short " )
return ValueType : : Type : : SHORT ;
2019-05-01 16:34:28 +02:00
if ( typestr = = " wchar_t " )
return ValueType : : Type : : WCHAR_T ;
2017-03-01 18:09:50 +01:00
if ( typestr = = " int " )
return ValueType : : Type : : INT ;
if ( typestr = = " long " )
return longType ? ValueType : : Type : : LONGLONG : ValueType : : Type : : LONG ;
if ( typestr = = " float " )
return ValueType : : Type : : FLOAT ;
if ( typestr = = " double " )
return longType ? ValueType : : Type : : LONGDOUBLE : ValueType : : Type : : DOUBLE ;
return ValueType : : Type : : UNKNOWN_TYPE ;
}
2016-07-31 19:47:34 +02:00
bool ValueType : : fromLibraryType ( const std : : string & typestr , const Settings * settings )
{
const Library : : PodType * podtype = settings - > library . podtype ( typestr ) ;
if ( podtype & & ( podtype - > sign = = ' s ' | | podtype - > sign = = ' u ' ) ) {
if ( podtype - > size = = 1 )
type = ValueType : : Type : : CHAR ;
else if ( podtype - > size = = settings - > sizeof_int )
type = ValueType : : Type : : INT ;
else if ( podtype - > size = = settings - > sizeof_short )
type = ValueType : : Type : : SHORT ;
else if ( podtype - > size = = settings - > sizeof_long )
type = ValueType : : Type : : LONG ;
else if ( podtype - > size = = settings - > sizeof_long_long )
type = ValueType : : Type : : LONGLONG ;
else
type = ValueType : : Type : : UNKNOWN_INT ;
sign = ( podtype - > sign = = ' u ' ) ? ValueType : : UNSIGNED : ValueType : : SIGNED ;
return true ;
}
const Library : : PlatformType * platformType = settings - > library . platform_type ( typestr , settings - > platformString ( ) ) ;
if ( platformType ) {
2018-06-16 20:25:54 +02:00
if ( platformType - > mType = = " char " )
2016-07-31 19:47:34 +02:00
type = ValueType : : Type : : CHAR ;
2018-06-16 20:25:54 +02:00
else if ( platformType - > mType = = " short " )
2016-07-31 19:47:34 +02:00
type = ValueType : : Type : : SHORT ;
2019-05-01 16:34:28 +02:00
else if ( platformType - > mType = = " wchar_t " )
type = ValueType : : Type : : WCHAR_T ;
2018-06-16 20:25:54 +02:00
else if ( platformType - > mType = = " int " )
2016-07-31 19:47:34 +02:00
type = platformType - > _long ? ValueType : : Type : : LONG : ValueType : : Type : : INT ;
2018-06-16 20:25:54 +02:00
else if ( platformType - > mType = = " long " )
2016-07-31 19:47:34 +02:00
type = platformType - > _long ? ValueType : : Type : : LONGLONG : ValueType : : Type : : LONG ;
if ( platformType - > _signed )
sign = ValueType : : SIGNED ;
else if ( platformType - > _unsigned )
sign = ValueType : : UNSIGNED ;
if ( platformType - > _pointer )
pointer = 1 ;
if ( platformType - > _ptr_ptr )
pointer = 2 ;
if ( platformType - > _const_ptr )
constness = 1 ;
return true ;
2017-03-05 18:19:49 +01:00
} else if ( ! podtype & & ( typestr = = " size_t " | | typestr = = " std::size_t " ) ) {
originalTypeName = " size_t " ;
sign = ValueType : : UNSIGNED ;
if ( settings - > sizeof_size_t = = settings - > sizeof_long )
type = ValueType : : Type : : LONG ;
else if ( settings - > sizeof_size_t = = settings - > sizeof_long_long )
type = ValueType : : Type : : LONGLONG ;
else if ( settings - > sizeof_size_t = = settings - > sizeof_int )
type = ValueType : : Type : : INT ;
else
type = ValueType : : Type : : UNKNOWN_INT ;
return true ;
2016-07-31 19:47:34 +02:00
}
return false ;
}
2017-04-16 09:11:20 +02:00
std : : string ValueType : : dump ( ) const
{
std : : ostringstream ret ;
switch ( type ) {
case UNKNOWN_TYPE :
return " " ;
case NONSTD :
ret < < " valueType-type= \" nonstd \" " ;
break ;
case RECORD :
ret < < " valueType-type= \" record \" " ;
break ;
case CONTAINER :
ret < < " valueType-type= \" container \" " ;
break ;
case ITERATOR :
ret < < " valueType-type= \" iterator \" " ;
break ;
case VOID :
ret < < " valueType-type= \" void \" " ;
break ;
case BOOL :
ret < < " valueType-type= \" bool \" " ;
break ;
case CHAR :
ret < < " valueType-type= \" char \" " ;
break ;
case SHORT :
ret < < " valueType-type= \" short \" " ;
break ;
2019-05-01 16:34:28 +02:00
case WCHAR_T :
ret < < " valueType-type= \" wchar_t \" " ;
break ;
2017-04-16 09:11:20 +02:00
case INT :
ret < < " valueType-type= \" int \" " ;
break ;
case LONG :
ret < < " valueType-type= \" long \" " ;
break ;
case LONGLONG :
ret < < " valueType-type= \" long long \" " ;
break ;
case UNKNOWN_INT :
ret < < " valueType-type= \" unknown int \" " ;
break ;
case FLOAT :
ret < < " valueType-type= \" float \" " ;
break ;
case DOUBLE :
ret < < " valueType-type= \" double \" " ;
break ;
case LONGDOUBLE :
ret < < " valueType-type= \" long double \" " ;
break ;
} ;
switch ( sign ) {
case Sign : : UNKNOWN_SIGN :
break ;
case Sign : : SIGNED :
ret < < " valueType-sign= \" signed \" " ;
break ;
case Sign : : UNSIGNED :
ret < < " valueType-sign= \" unsigned \" " ;
break ;
} ;
2018-05-02 20:55:11 +02:00
if ( bits > 0 )
ret < < " valueType-bits= \" " < < bits < < ' \" ' ;
2017-04-16 09:11:20 +02:00
if ( pointer > 0 )
ret < < " valueType-pointer= \" " < < pointer < < ' \" ' ;
if ( constness > 0 )
ret < < " valueType-constness= \" " < < constness < < ' \" ' ;
if ( typeScope )
ret < < " valueType-typeScope= \" " < < typeScope < < ' \" ' ;
if ( ! originalTypeName . empty ( ) )
ret < < " valueType-originalTypeName= \" " < < originalTypeName < < ' \" ' ;
return ret . str ( ) ;
}
2019-03-17 13:09:15 +01:00
MathLib : : bigint ValueType : : typeSize ( const cppcheck : : Platform & platform ) const
{
switch ( type ) {
case ValueType : : Type : : BOOL :
return platform . sizeof_bool ;
case ValueType : : Type : : CHAR :
return 1 ;
case ValueType : : Type : : SHORT :
return platform . sizeof_short ;
2019-05-01 16:34:28 +02:00
case ValueType : : Type : : WCHAR_T :
return platform . sizeof_wchar_t ;
2019-03-17 13:09:15 +01:00
case ValueType : : Type : : INT :
return platform . sizeof_int ;
case ValueType : : Type : : LONG :
return platform . sizeof_long ;
case ValueType : : Type : : LONGLONG :
return platform . sizeof_long_long ;
case ValueType : : Type : : FLOAT :
return platform . sizeof_float ;
case ValueType : : Type : : DOUBLE :
return platform . sizeof_double ;
case ValueType : : Type : : LONGDOUBLE :
return platform . sizeof_long_double ;
default :
return 0 ;
} ;
}
2015-10-07 13:38:34 +02:00
std : : string ValueType : : str ( ) const
{
std : : string ret ;
2015-10-07 19:08:26 +02:00
if ( constness & 1 )
ret = " const " ;
2015-12-29 19:58:51 +01:00
if ( type = = VOID )
ret + = " void " ;
else if ( isIntegral ( ) ) {
2015-10-07 13:38:34 +02:00
if ( sign = = SIGNED )
2015-10-07 19:08:26 +02:00
ret + = " signed " ;
2015-10-07 13:38:34 +02:00
else if ( sign = = UNSIGNED )
2015-10-07 19:08:26 +02:00
ret + = " unsigned " ;
2015-10-07 13:38:34 +02:00
if ( type = = BOOL )
2015-10-07 19:08:26 +02:00
ret + = " bool " ;
2015-10-07 13:38:34 +02:00
else if ( type = = CHAR )
2015-10-07 19:08:26 +02:00
ret + = " char " ;
2015-10-07 13:38:34 +02:00
else if ( type = = SHORT )
2015-10-07 19:08:26 +02:00
ret + = " short " ;
2019-05-01 16:34:28 +02:00
else if ( type = = WCHAR_T )
ret + = " wchar_t " ;
2015-10-07 13:38:34 +02:00
else if ( type = = INT )
2015-10-07 19:08:26 +02:00
ret + = " int " ;
2015-10-07 13:38:34 +02:00
else if ( type = = LONG )
2015-10-07 19:08:26 +02:00
ret + = " long " ;
2015-10-07 13:38:34 +02:00
else if ( type = = LONGLONG )
2015-10-07 19:08:26 +02:00
ret + = " long long " ;
2016-05-04 15:39:56 +02:00
else if ( type = = UNKNOWN_INT )
ret + = " unknown_int " ;
2015-10-07 13:38:34 +02:00
} else if ( type = = FLOAT )
2015-10-08 19:50:10 +02:00
ret + = " float " ;
2015-10-07 13:38:34 +02:00
else if ( type = = DOUBLE )
2015-10-08 19:50:10 +02:00
ret + = " double " ;
else if ( type = = LONGDOUBLE )
ret + = " long double " ;
2017-03-05 14:53:32 +01:00
else if ( ( type = = ValueType : : Type : : NONSTD | | type = = ValueType : : Type : : RECORD ) & & typeScope ) {
2016-05-08 13:15:20 +02:00
std : : string className ( typeScope - > className ) ;
2018-09-24 06:40:20 +02:00
const Scope * scope = typeScope - > definedType ? typeScope - > definedType - > enclosingScope : typeScope - > nestedIn ;
2016-05-08 17:42:53 +02:00
while ( scope & & scope - > type ! = Scope : : eGlobal ) {
if ( scope - > type = = Scope : : eClass | | scope - > type = = Scope : : eStruct | | scope - > type = = Scope : : eNamespace )
className = scope - > className + " :: " + className ;
2018-09-24 06:40:20 +02:00
scope = scope - > definedType ? scope - > definedType - > enclosingScope : scope - > nestedIn ;
2016-05-08 13:15:20 +02:00
}
ret + = ' ' + className ;
2017-03-05 14:53:32 +01:00
} else if ( type = = ValueType : : Type : : CONTAINER & & container ) {
2017-03-05 02:09:52 +01:00
ret + = " container( " + container - > startPattern + ' ) ' ;
2017-03-05 14:53:32 +01:00
} else if ( type = = ValueType : : Type : : ITERATOR & & container ) {
ret + = " iterator( " + container - > startPattern + ' ) ' ;
2019-07-07 21:52:49 +02:00
} else if ( smartPointerType ) {
ret + = " smart-pointer< " + smartPointerType - > name ( ) + " > " ;
2016-05-08 13:15:20 +02:00
}
2016-05-06 15:22:45 +02:00
for ( unsigned int p = 0 ; p < pointer ; p + + ) {
2015-10-07 19:08:26 +02:00
ret + = " * " ;
if ( constness & ( 2 < < p ) )
2015-10-07 19:50:50 +02:00
ret + = " const " ;
}
2016-01-01 15:13:50 +01:00
return ret . empty ( ) ? ret : ret . substr ( 1 ) ;
2015-10-07 13:38:34 +02:00
}
2019-07-29 18:14:06 +02:00
ValueType : : MatchResult ValueType : : matchParameter ( const ValueType * call , const ValueType * func )
{
if ( ! call | | ! func )
return ValueType : : MatchResult : : UNKNOWN ;
2019-07-31 12:38:36 +02:00
if ( call - > pointer ! = func - > pointer ) {
2019-07-31 16:23:50 +02:00
if ( call - > pointer > 1 & & func - > pointer = = 1 & & func - > type = = ValueType : : Type : : VOID )
return ValueType : : MatchResult : : FALLBACK1 ;
2019-08-03 10:10:22 +02:00
if ( call - > pointer = = 1 & & call - > type = = ValueType : : Type : : CHAR & & func - > pointer = = 0 & & func - > container & & func - > container - > stdStringLike )
return ValueType : : MatchResult : : FALLBACK2 ;
2019-07-31 18:55:55 +02:00
return ValueType : : MatchResult : : NOMATCH ; // TODO
2019-07-31 12:38:36 +02:00
}
2019-07-31 18:24:15 +02:00
if ( call - > pointer > 0 & & ( ( call - > constness | func - > constness ) ! = func - > constness ) )
2019-07-31 12:38:36 +02:00
return ValueType : : MatchResult : : NOMATCH ;
2019-07-29 21:53:39 +02:00
if ( call - > type ! = func - > type ) {
2019-07-31 12:12:17 +02:00
if ( call - > type = = ValueType : : Type : : VOID | | func - > type = = ValueType : : Type : : VOID )
2019-07-30 21:02:12 +02:00
return ValueType : : MatchResult : : FALLBACK1 ;
2019-07-31 12:12:17 +02:00
if ( call - > pointer > 0 & & func - > pointer > 0 )
2019-09-11 19:25:09 +02:00
return func - > type = = ValueType : : UNKNOWN_TYPE ? ValueType : : MatchResult : : UNKNOWN : ValueType : : MatchResult : : NOMATCH ;
2019-07-29 21:53:39 +02:00
if ( call - > isIntegral ( ) & & func - > isIntegral ( ) )
2019-07-30 07:48:14 +02:00
return call - > type < func - > type ?
ValueType : : MatchResult : : FALLBACK1 :
ValueType : : MatchResult : : FALLBACK2 ;
2019-07-29 21:53:39 +02:00
else if ( call - > isFloat ( ) & & func - > isFloat ( ) )
return ValueType : : MatchResult : : FALLBACK1 ;
else if ( call - > isIntegral ( ) & & func - > isFloat ( ) )
return ValueType : : MatchResult : : FALLBACK2 ;
else if ( call - > isFloat ( ) & & func - > isIntegral ( ) )
return ValueType : : MatchResult : : FALLBACK2 ;
2019-07-29 18:14:06 +02:00
return ValueType : : MatchResult : : UNKNOWN ; // TODO
2019-07-29 21:53:39 +02:00
}
2019-07-31 18:35:56 +02:00
if ( call - > typeScope ! = nullptr | | func - > typeScope ! = nullptr )
return call - > typeScope = = func - > typeScope ? ValueType : : MatchResult : : SAME : ValueType : : MatchResult : : NOMATCH ;
2019-08-03 10:10:22 +02:00
if ( call - > container ! = nullptr | | func - > container ! = nullptr ) {
if ( call - > container ! = func - > container )
return ValueType : : MatchResult : : NOMATCH ;
}
2019-08-02 15:59:22 +02:00
2019-08-03 10:10:22 +02:00
else if ( func - > type < ValueType : : Type : : VOID | | func - > type = = ValueType : : Type : : UNKNOWN_INT )
2019-07-29 18:14:06 +02:00
return ValueType : : MatchResult : : UNKNOWN ;
2019-07-30 21:02:12 +02:00
if ( call - > isIntegral ( ) & & func - > isIntegral ( ) & & call - > sign ! = ValueType : : Sign : : UNKNOWN_SIGN & & func - > sign ! = ValueType : : Sign : : UNKNOWN_SIGN & & call - > sign ! = func - > sign )
2019-07-29 21:53:39 +02:00
return ValueType : : MatchResult : : UNKNOWN ; // TODO
2019-07-29 18:14:06 +02:00
return ValueType : : MatchResult : : SAME ;
}
2019-08-03 10:10:22 +02:00
ValueType : : MatchResult ValueType : : matchParameter ( const ValueType * call , const Variable * callVar , const Variable * funcVar )
{
ValueType : : MatchResult res = ValueType : : matchParameter ( call , funcVar - > valueType ( ) ) ;
if ( res = = ValueType : : MatchResult : : SAME & & callVar & & call - > container ) {
const std : : string type1 = getTypeString ( callVar - > typeStartToken ( ) ) ;
const std : : string type2 = getTypeString ( funcVar - > typeStartToken ( ) ) ;
if ( type1 ! = type2 )
return ValueType : : MatchResult : : NOMATCH ;
}
return res ;
}