2008-12-18 22:28:57 +01:00
/*
2009-01-21 21:04:20 +01:00
* Cppcheck - A tool for static C / C + + code analysis
2022-02-05 11:45:17 +01:00
* Copyright ( C ) 2007 - 2022 Cppcheck team .
2008-12-18 22:28:57 +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
2009-09-27 17:08:31 +02:00
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
2008-12-18 22:28:57 +01:00
*/
2009-07-05 22:16:43 +02:00
// The preprocessor that Cppcheck uses is a bit special. Instead of generating
2008-12-18 22:28:57 +01:00
// the code for a known configuration, it generates the code for each configuration.
2022-01-27 19:03:20 +01:00
# include "errortypes.h"
2017-05-27 04:33:47 +02:00
# include "platform.h"
2009-10-25 12:49:06 +01:00
# include "preprocessor.h"
2010-07-26 22:05:17 +02:00
# include "settings.h"
2022-08-14 12:44:19 +02:00
# include "suppressions.h"
2017-05-27 04:33:47 +02:00
# include "testsuite.h"
2022-07-09 23:21:11 +02:00
# include "testutils.h"
2017-05-18 22:25:49 +02:00
2022-01-27 19:03:20 +01:00
# include <atomic>
2016-08-21 13:53:44 +02:00
# include <cstring>
2022-01-27 19:03:20 +01:00
# include <iosfwd>
2017-05-27 04:33:47 +02:00
# include <list>
2008-12-18 22:28:57 +01:00
# include <map>
2022-01-27 19:03:20 +01:00
# include <memory>
2013-10-27 10:33:37 +01:00
# include <set>
2017-05-27 04:33:47 +02:00
# include <string>
# include <vector>
2008-12-18 22:28:57 +01:00
2022-01-27 19:03:20 +01:00
# include <simplecpp.h>
2017-05-27 04:33:47 +02:00
class ErrorLogger ;
2009-04-03 21:09:12 +02:00
2011-10-13 20:53:06 +02:00
class TestPreprocessor : public TestFixture {
2008-12-18 22:28:57 +01:00
public :
2015-10-09 12:27:39 +02:00
TestPreprocessor ( )
: TestFixture ( " TestPreprocessor " )
, preprocessor0 ( settings0 , this ) {
2021-02-24 22:00:06 +01:00
settings0 . severity . enable ( Severity : : information ) ;
2012-03-27 19:35:41 +02:00
}
2008-12-18 22:28:57 +01:00
2011-10-13 20:53:06 +02:00
class OurPreprocessor : public Preprocessor {
2009-02-07 21:06:00 +01:00
public :
2019-06-30 21:39:22 +02:00
static std : : string expandMacros ( const char code [ ] , ErrorLogger * errorLogger = nullptr ) {
2016-07-20 12:21:00 +02:00
std : : istringstream istr ( code ) ;
simplecpp : : OutputList outputList ;
std : : vector < std : : string > files ;
const simplecpp : : TokenList tokens1 = simplecpp : : TokenList ( istr , files , " file.cpp " , & outputList ) ;
2016-11-10 20:04:05 +01:00
std : : map < std : : string , simplecpp : : TokenList * > filedata ;
2016-07-21 19:42:26 +02:00
simplecpp : : TokenList tokens2 ( files ) ;
simplecpp : : preprocess ( tokens2 , tokens1 , files , filedata , simplecpp : : DUI ( ) , & outputList ) ;
2016-07-20 12:21:00 +02:00
if ( errorLogger ) {
2016-12-06 22:11:40 +01:00
static Settings settings ;
2016-08-06 13:28:24 +02:00
Preprocessor p ( settings , errorLogger ) ;
p . reportOutput ( outputList , true ) ;
2016-07-20 12:21:00 +02:00
}
return tokens2 . stringify ( ) ;
2009-02-07 21:06:00 +01:00
}
} ;
2008-12-18 22:28:57 +01:00
private :
2015-10-07 18:33:57 +02:00
Settings settings0 ;
2015-10-09 12:27:39 +02:00
Preprocessor preprocessor0 ;
2008-12-18 22:28:57 +01:00
2022-02-10 23:02:24 +01:00
void run ( ) override {
2012-09-30 09:35:32 +02:00
2008-12-18 22:28:57 +01:00
// The bug that started the whole work with the new preprocessor
2009-01-05 16:49:57 +01:00
TEST_CASE ( Bug2190219 ) ;
2008-12-18 22:28:57 +01:00
2014-06-18 17:26:51 +02:00
TEST_CASE ( error1 ) ; // #error => don't extract any code
2017-04-02 10:06:39 +02:00
TEST_CASE ( error2 ) ; // #error if symbol is not defined
2010-09-12 21:30:47 +02:00
TEST_CASE ( error3 ) ;
2011-08-03 07:28:37 +02:00
TEST_CASE ( error4 ) ; // #2919 - wrong filename is reported
2014-06-18 17:26:51 +02:00
TEST_CASE ( error5 ) ;
2017-03-22 10:53:21 +01:00
TEST_CASE ( error6 ) ;
2017-05-24 11:16:41 +02:00
TEST_CASE ( error7 ) ;
2021-02-06 12:48:52 +01:00
TEST_CASE ( error8 ) ; // #10170 -> previous #if configurations
2010-09-12 21:30:47 +02:00
2016-07-25 14:52:23 +02:00
TEST_CASE ( setPlatformInfo ) ;
2009-01-22 19:19:17 +01:00
// Handling include guards (don't create extra configuration for it)
2010-02-06 09:30:48 +01:00
TEST_CASE ( includeguard1 ) ;
TEST_CASE ( includeguard2 ) ;
2009-01-22 19:19:17 +01:00
2009-01-05 16:49:57 +01:00
TEST_CASE ( if0 ) ;
TEST_CASE ( if1 ) ;
2008-12-18 22:28:57 +01:00
2009-01-05 16:49:57 +01:00
TEST_CASE ( elif ) ;
2008-12-18 22:28:57 +01:00
2009-01-05 16:49:57 +01:00
TEST_CASE ( if_cond1 ) ;
2009-06-26 13:19:55 +02:00
TEST_CASE ( if_cond2 ) ;
TEST_CASE ( if_cond3 ) ;
2009-07-22 20:11:27 +02:00
TEST_CASE ( if_cond4 ) ;
2009-08-29 23:00:54 +02:00
TEST_CASE ( if_cond5 ) ;
2009-11-20 19:18:57 +01:00
TEST_CASE ( if_cond6 ) ;
2009-12-15 20:18:32 +01:00
TEST_CASE ( if_cond8 ) ;
2010-01-09 21:54:20 +01:00
TEST_CASE ( if_cond9 ) ;
2010-08-17 20:06:20 +02:00
TEST_CASE ( if_cond10 ) ;
2010-09-02 23:01:12 +02:00
TEST_CASE ( if_cond11 ) ;
2011-02-20 20:11:51 +01:00
TEST_CASE ( if_cond12 ) ;
2011-11-03 20:01:31 +01:00
TEST_CASE ( if_cond13 ) ;
2012-03-26 19:01:45 +02:00
TEST_CASE ( if_cond14 ) ;
2008-12-18 22:28:57 +01:00
2010-08-26 21:33:45 +02:00
TEST_CASE ( if_or_1 ) ;
TEST_CASE ( if_or_2 ) ;
2009-12-13 17:18:27 +01:00
2012-03-15 20:04:34 +01:00
TEST_CASE ( if_macro_eq_macro ) ; // #3536
2012-03-23 00:45:47 +01:00
TEST_CASE ( ticket_3675 ) ;
2012-04-22 06:49:42 +02:00
TEST_CASE ( ticket_3699 ) ;
2013-08-04 14:34:28 +02:00
TEST_CASE ( ticket_4922 ) ; // #4922
2012-03-15 20:04:34 +01:00
2009-01-05 10:26:00 +01:00
// Macros..
2009-01-06 09:49:54 +01:00
TEST_CASE ( macro_simple1 ) ;
TEST_CASE ( macro_simple2 ) ;
2009-01-11 16:07:13 +01:00
TEST_CASE ( macro_simple3 ) ;
2009-01-11 16:51:46 +01:00
TEST_CASE ( macro_simple4 ) ;
2009-01-11 17:06:37 +01:00
TEST_CASE ( macro_simple5 ) ;
2009-01-18 17:56:12 +01:00
TEST_CASE ( macro_simple6 ) ;
2009-01-21 18:11:24 +01:00
TEST_CASE ( macro_simple7 ) ;
2009-01-23 18:14:42 +01:00
TEST_CASE ( macro_simple8 ) ;
2009-06-05 22:45:31 +02:00
TEST_CASE ( macro_simple9 ) ;
2009-08-01 14:55:45 +02:00
TEST_CASE ( macro_simple10 ) ;
2009-11-26 17:32:18 +01:00
TEST_CASE ( macro_simple11 ) ;
2009-12-09 17:13:48 +01:00
TEST_CASE ( macro_simple12 ) ;
2010-01-02 20:54:52 +01:00
TEST_CASE ( macro_simple13 ) ;
2011-02-11 06:30:42 +01:00
TEST_CASE ( macro_simple14 ) ;
2011-02-11 18:01:27 +01:00
TEST_CASE ( macro_simple15 ) ;
2013-08-10 23:28:02 +02:00
TEST_CASE ( macro_simple16 ) ; // #4703: Macro parameters not trimmed
2013-10-13 17:42:06 +02:00
TEST_CASE ( macro_simple17 ) ; // #5074: isExpandedMacro not set
2013-12-29 21:51:01 +01:00
TEST_CASE ( macro_simple18 ) ; // (1e-7)
2011-04-07 16:53:42 +02:00
TEST_CASE ( macroInMacro1 ) ;
TEST_CASE ( macroInMacro2 ) ;
2009-03-09 20:29:25 +01:00
TEST_CASE ( macro_linenumbers ) ;
2009-06-19 16:42:47 +02:00
TEST_CASE ( macro_nopar ) ;
2015-12-29 06:54:44 +01:00
TEST_CASE ( macro_incdec ) ; // separate ++ and -- with space when expanding such macro: '#define M(X) A-X'
2010-04-15 22:21:00 +02:00
TEST_CASE ( macro_switchCase ) ;
2013-01-13 15:01:31 +01:00
TEST_CASE ( macro_NULL ) ; // skip #define NULL .. it is replaced in the tokenizer
2009-01-18 17:58:57 +01:00
TEST_CASE ( string1 ) ;
TEST_CASE ( string2 ) ;
2009-12-09 17:13:48 +01:00
TEST_CASE ( string3 ) ;
2009-01-18 17:37:40 +01:00
TEST_CASE ( preprocessor_undef ) ;
2009-01-22 21:19:07 +01:00
TEST_CASE ( defdef ) ; // Defined multiple times
2009-01-20 19:28:24 +01:00
TEST_CASE ( preprocessor_doublesharp ) ;
2009-01-19 20:24:41 +01:00
TEST_CASE ( preprocessor_include_in_str ) ;
2011-01-02 10:09:50 +01:00
TEST_CASE ( va_args_1 ) ;
2016-07-20 12:21:00 +02:00
//TEST_CASE(va_args_2); invalid code
2011-01-02 10:09:50 +01:00
TEST_CASE ( va_args_3 ) ;
TEST_CASE ( va_args_4 ) ;
2016-05-28 11:27:45 +02:00
TEST_CASE ( va_args_5 ) ;
2009-01-21 22:45:17 +01:00
TEST_CASE ( multi_character_character ) ;
2009-01-25 14:30:15 +01:00
TEST_CASE ( stringify ) ;
2009-03-15 22:09:27 +01:00
TEST_CASE ( stringify2 ) ;
2009-03-16 22:20:55 +01:00
TEST_CASE ( stringify3 ) ;
2009-05-05 17:19:06 +02:00
TEST_CASE ( stringify4 ) ;
2009-10-14 20:40:17 +02:00
TEST_CASE ( stringify5 ) ;
2009-03-08 08:45:53 +01:00
TEST_CASE ( ifdefwithfile ) ;
2009-03-15 13:23:12 +01:00
TEST_CASE ( pragma ) ;
2010-02-12 18:15:15 +01:00
TEST_CASE ( pragma_asm_1 ) ;
TEST_CASE ( pragma_asm_2 ) ;
2009-03-18 00:10:26 +01:00
TEST_CASE ( endifsemicolon ) ;
2009-04-03 21:09:12 +02:00
TEST_CASE ( missing_doublequote ) ;
2009-08-13 23:22:51 +02:00
TEST_CASE ( handle_error ) ;
2011-01-30 09:09:12 +01:00
TEST_CASE ( dup_defines ) ;
2009-04-27 21:29:03 +02:00
2009-05-09 21:32:29 +02:00
TEST_CASE ( define_part_of_func ) ;
2009-05-13 21:38:57 +02:00
TEST_CASE ( conditionalDefine ) ;
2009-05-18 22:32:04 +02:00
TEST_CASE ( macro_parameters ) ;
2009-05-20 20:36:59 +02:00
TEST_CASE ( newline_in_macro ) ;
2009-06-14 22:37:18 +02:00
TEST_CASE ( ifdef_ifdefined ) ;
2009-07-22 18:47:50 +02:00
// define and then ifdef
2011-07-18 21:44:23 +02:00
TEST_CASE ( define_if1 ) ;
TEST_CASE ( define_if2 ) ;
2011-11-17 19:19:43 +01:00
TEST_CASE ( define_if3 ) ;
2012-11-28 07:33:24 +01:00
TEST_CASE ( define_if4 ) ; // #4079 - #define X +123
2013-01-26 12:37:46 +01:00
TEST_CASE ( define_if5 ) ; // #4516 - #define B (A & 0x00f0)
2013-06-19 21:29:39 +02:00
TEST_CASE ( define_if6 ) ; // #4863 - #define B (A?-1:1)
2009-07-22 18:47:50 +02:00
TEST_CASE ( define_ifdef ) ;
2010-09-14 17:45:37 +02:00
TEST_CASE ( define_ifndef1 ) ;
TEST_CASE ( define_ifndef2 ) ;
2012-05-04 17:53:47 +02:00
TEST_CASE ( ifndef_define ) ;
2012-01-24 07:43:26 +01:00
TEST_CASE ( undef_ifdef ) ;
2009-10-10 22:23:48 +02:00
TEST_CASE ( endfile ) ;
2010-04-15 18:37:51 +02:00
TEST_CASE ( redundant_config ) ;
2011-02-11 06:30:42 +01:00
2012-09-05 20:50:25 +02:00
TEST_CASE ( invalid_define_1 ) ; // #2605 - hang for: '#define ='
TEST_CASE ( invalid_define_2 ) ; // #4036 - hang for: '#define () {(int f(x) }'
2011-04-22 20:25:17 +02:00
2022-07-09 23:21:11 +02:00
// inline suppression, missingInclude/missingIncludeSystem
2011-04-22 20:25:17 +02:00
TEST_CASE ( inline_suppression_for_missing_include ) ;
2022-07-09 23:21:11 +02:00
TEST_CASE ( inline_suppression_for_missing_include_check_config ) ;
2011-07-16 09:24:27 +02:00
// Using -D to predefine symbols
TEST_CASE ( predefine1 ) ;
TEST_CASE ( predefine2 ) ;
2011-07-16 16:59:06 +02:00
TEST_CASE ( predefine3 ) ;
2012-02-05 20:48:28 +01:00
TEST_CASE ( predefine4 ) ;
2012-05-08 20:49:43 +02:00
TEST_CASE ( predefine5 ) ; // automatically define __cplusplus
2022-04-15 16:17:36 +02:00
TEST_CASE ( predefine6 ) ; // automatically define __STDC_VERSION__
2011-07-20 23:50:57 +02:00
2011-08-02 21:06:27 +02:00
TEST_CASE ( invalidElIf ) ; // #2942 segfault
2011-10-17 20:12:46 +02:00
2016-08-21 08:06:20 +02:00
// Preprocessor::getConfigs
TEST_CASE ( getConfigs1 ) ;
TEST_CASE ( getConfigs2 ) ;
TEST_CASE ( getConfigs3 ) ;
TEST_CASE ( getConfigs4 ) ;
TEST_CASE ( getConfigs5 ) ;
TEST_CASE ( getConfigs7 ) ;
TEST_CASE ( getConfigs7a ) ;
TEST_CASE ( getConfigs7b ) ;
TEST_CASE ( getConfigs7c ) ;
TEST_CASE ( getConfigs7d ) ;
TEST_CASE ( getConfigs7e ) ;
TEST_CASE ( getConfigs8 ) ; // #if A==1 => cfg: A=1
TEST_CASE ( getConfigs10 ) ; // #5139
2021-03-12 18:16:09 +01:00
TEST_CASE ( getConfigs11 ) ; // #9832 - include guards
2016-12-03 11:59:48 +01:00
TEST_CASE ( getConfigsError ) ;
2016-08-21 08:06:20 +02:00
2016-08-21 13:53:44 +02:00
TEST_CASE ( getConfigsD1 ) ;
2016-08-21 08:06:20 +02:00
TEST_CASE ( getConfigsU1 ) ;
TEST_CASE ( getConfigsU2 ) ;
TEST_CASE ( getConfigsU3 ) ;
TEST_CASE ( getConfigsU4 ) ;
TEST_CASE ( getConfigsU5 ) ;
TEST_CASE ( getConfigsU6 ) ;
2016-10-11 18:46:46 +02:00
TEST_CASE ( getConfigsU7 ) ;
2016-07-07 23:45:42 +02:00
2018-09-26 12:17:14 +02:00
TEST_CASE ( validateCfg1 ) ;
TEST_CASE ( validateCfg2 ) ;
2012-08-22 17:28:06 +02:00
TEST_CASE ( if_sizeof ) ;
2014-04-23 20:50:16 +02:00
2015-05-12 14:00:43 +02:00
TEST_CASE ( invalid_ifs ) ; // #5909
TEST_CASE ( garbage ) ;
2015-11-30 19:27:15 +01:00
TEST_CASE ( wrongPathOnErrorDirective ) ;
2015-12-07 19:54:41 +01:00
TEST_CASE ( testDirectiveIncludeTypes ) ;
TEST_CASE ( testDirectiveIncludeLocations ) ;
TEST_CASE ( testDirectiveIncludeComments ) ;
2022-07-09 23:21:11 +02:00
TEST_CASE ( testMissingInclude ) ;
TEST_CASE ( testMissingIncludeCheckConfig ) ;
2008-12-18 22:28:57 +01:00
}
2016-02-29 07:34:06 +01:00
void preprocess ( const char * code , std : : map < std : : string , std : : string > & actual , const char filename [ ] = " file.c " ) {
2015-10-09 12:27:39 +02:00
errout . str ( " " ) ;
std : : istringstream istr ( code ) ;
2016-07-20 12:21:00 +02:00
simplecpp : : OutputList outputList ;
std : : vector < std : : string > files ;
2016-07-21 07:48:17 +02:00
simplecpp : : TokenList tokens ( istr , files , filename , & outputList ) ;
tokens . removeComments ( ) ;
2017-05-17 21:58:46 +02:00
preprocessor0 . simplifyPragmaAsm ( & tokens ) ;
2016-07-20 12:21:00 +02:00
const std : : set < std : : string > configs ( preprocessor0 . getConfigs ( tokens ) ) ;
2016-07-24 14:02:21 +02:00
preprocessor0 . setDirectives ( tokens ) ;
2019-09-19 20:29:33 +02:00
for ( const std : : string & config : configs ) {
2016-07-20 12:21:00 +02:00
try {
2019-09-19 20:29:33 +02:00
const std : : string & cfgcode = preprocessor0 . getcode ( tokens , config , files , std : : string ( code ) . find ( " #file " ) ! = std : : string : : npos ) ;
actual [ config ] = cfgcode ;
2018-05-29 11:54:07 +02:00
} catch ( const simplecpp : : Output & ) {
2019-09-19 20:29:33 +02:00
actual [ config ] = " " ;
2021-08-07 20:51:18 +02:00
} catch ( . . . ) { }
2012-06-10 11:00:27 +02:00
}
}
2019-06-30 21:39:22 +02:00
std : : string getConfigsStr ( const char filedata [ ] , const char * arg = nullptr ) {
2016-07-30 20:22:07 +02:00
Settings settings ;
2016-08-21 13:53:44 +02:00
if ( arg & & std : : strncmp ( arg , " -D " , 2 ) = = 0 )
settings . userDefines = arg + 2 ;
if ( arg & & std : : strncmp ( arg , " -U " , 2 ) = = 0 )
settings . userUndefs . insert ( arg + 2 ) ;
2016-07-30 20:22:07 +02:00
Preprocessor preprocessor ( settings , this ) ;
std : : vector < std : : string > files ;
std : : istringstream istr ( filedata ) ;
simplecpp : : TokenList tokens ( istr , files ) ;
tokens . removeComments ( ) ;
const std : : set < std : : string > configs = preprocessor . getConfigs ( tokens ) ;
std : : string ret ;
2019-09-19 20:29:33 +02:00
for ( const std : : string & config : configs )
ret + = config + ' \n ' ;
2016-07-30 20:22:07 +02:00
return ret ;
}
2014-11-20 14:20:09 +01:00
void Bug2190219 ( ) {
2016-02-29 07:34:06 +01:00
const char filedata [ ] = " #ifdef __cplusplus \n "
" cpp \n "
2008-12-18 22:28:57 +01:00
" #else \n "
2016-02-29 07:34:06 +01:00
" c \n "
" #endif " ;
2008-12-18 22:28:57 +01:00
2016-02-29 07:34:06 +01:00
{
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
preprocess ( filedata , actual , " file.cpp " ) ;
2008-12-18 22:28:57 +01:00
2016-02-29 07:34:06 +01:00
// Compare results..
ASSERT_EQUALS ( 1U , actual . size ( ) ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n cpp " , actual [ " " ] ) ;
2016-02-29 07:34:06 +01:00
}
{
// Ticket #7102 - skip __cplusplus in C code
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
preprocess ( filedata , actual , " file.c " ) ;
// Compare results..
ASSERT_EQUALS ( 1U , actual . size ( ) ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n \n c " , actual [ " " ] ) ;
2016-02-29 07:34:06 +01:00
}
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +01:00
void error1 ( ) {
2009-11-13 22:12:29 +01:00
const char filedata [ ] = " #ifdef A \n "
" ; \n "
" #else \n "
" #error abcd \n "
" #endif \n " ;
2016-07-30 20:22:07 +02:00
ASSERT_EQUALS ( " \n A \n " , getConfigsStr ( filedata ) ) ;
2009-12-22 20:38:12 +01:00
}
2017-04-02 10:06:39 +02:00
void error2 ( ) {
const char filedata1 [ ] = " #ifndef A \n "
" #error \n "
" #endif \n " ;
2017-04-02 12:15:53 +02:00
ASSERT_EQUALS ( " A \n " , getConfigsStr ( filedata1 ) ) ;
2017-04-02 10:06:39 +02:00
const char filedata2 [ ] = " #if !A \n "
" #error \n "
" #endif \n " ;
2017-04-02 12:15:53 +02:00
ASSERT_EQUALS ( " A \n " , getConfigsStr ( filedata2 ) ) ;
2017-04-02 10:06:39 +02:00
}
2014-11-20 14:20:09 +01:00
void error3 ( ) {
2011-08-03 07:28:37 +02:00
errout . str ( " " ) ;
2010-09-12 21:30:47 +02:00
Settings settings ;
settings . userDefines = " __cplusplus " ;
2015-07-24 13:30:41 +02:00
Preprocessor preprocessor ( settings , this ) ;
2010-09-12 21:30:47 +02:00
const std : : string code ( " #error hello world! \n " ) ;
2012-01-06 08:01:50 +01:00
preprocessor . getcode ( code , " X " , " test.c " ) ;
2010-09-12 21:30:47 +02:00
ASSERT_EQUALS ( " [test.c:1]: (error) #error hello world! \n " , errout . str ( ) ) ;
}
2011-08-03 07:28:37 +02:00
// Ticket #2919 - wrong filename reported for #error
2014-11-20 14:20:09 +01:00
void error4 ( ) {
2011-08-03 07:28:37 +02:00
// In included file
{
errout . str ( " " ) ;
Settings settings ;
settings . userDefines = " TEST " ;
2015-07-24 13:30:41 +02:00
Preprocessor preprocessor ( settings , this ) ;
2011-08-03 07:28:37 +02:00
const std : : string code ( " #file \" ab.h \" \n #error hello world! \n #endfile " ) ;
2012-01-06 08:01:50 +01:00
preprocessor . getcode ( code , " TEST " , " test.c " ) ;
2011-08-03 07:28:37 +02:00
ASSERT_EQUALS ( " [ab.h:1]: (error) #error hello world! \n " , errout . str ( ) ) ;
}
// After including a file
{
errout . str ( " " ) ;
Settings settings ;
settings . userDefines = " TEST " ;
2015-07-24 13:30:41 +02:00
Preprocessor preprocessor ( settings , this ) ;
2011-08-03 07:28:37 +02:00
const std : : string code ( " #file \" ab.h \" \n \n #endfile \n #error aaa " ) ;
2012-01-06 08:01:50 +01:00
preprocessor . getcode ( code , " TEST " , " test.c " ) ;
2011-08-03 07:28:37 +02:00
ASSERT_EQUALS ( " [test.c:2]: (error) #error aaa \n " , errout . str ( ) ) ;
}
}
2014-11-20 14:20:09 +01:00
void error5 ( ) {
2014-06-18 17:26:51 +02:00
errout . str ( " " ) ;
Settings settings ;
settings . userDefines = " FOO " ;
2016-01-03 16:18:17 +01:00
settings . force = true ; // No message if --force is given
2015-07-24 13:30:41 +02:00
Preprocessor preprocessor ( settings , this ) ;
2014-06-18 17:26:51 +02:00
const std : : string code ( " #error hello world! \n " ) ;
preprocessor . getcode ( code , " X " , " test.c " ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2017-03-22 10:53:21 +01:00
void error6 ( ) {
2017-04-22 12:44:57 +02:00
const char filedata1 [ ] = " #ifdef A \n "
" #else \n "
" #error 1 \n "
" #endif \n "
" #ifdef B \n "
" #else \n "
" #error 2 \n "
" #endif \n " ;
ASSERT_EQUALS ( " \n A \n A;B \n B \n " , getConfigsStr ( filedata1 ) ) ;
const char filedata2 [ ] = " #ifndef A \n "
" #error 1 \n "
" #endif \n "
" #ifndef B \n "
" #error 2 \n "
" #endif \n " ;
ASSERT_EQUALS ( " A;B \n " , getConfigsStr ( filedata2 ) ) ;
const char filedata3 [ ] = " #if !A \n "
" #error 1 \n "
" #endif \n "
" #if !B \n "
" #error 2 \n "
" #endif \n " ;
ASSERT_EQUALS ( " A;B \n " , getConfigsStr ( filedata3 ) ) ;
2017-03-22 10:53:21 +01:00
}
2017-05-24 11:16:41 +02:00
void error7 ( ) { // #8074
const char filedata [ ] = " #define A \n "
" \n "
" #if defined(B) \n "
" #else \n "
" #error \" 1 \" \n "
" #endif \n "
" \n "
" #if defined(A) \n "
" #else \n "
" #error \" 2 \" \n "
" #endif \n " ;
ASSERT_EQUALS ( " \n B \n " , getConfigsStr ( filedata ) ) ;
}
2021-02-06 12:48:52 +01:00
void error8 ( ) {
const char filedata [ ] = " #ifdef A \n "
" #ifdef B \n "
" #endif \n "
" #else \n "
" #endif \n "
" \n "
" #ifndef C \n "
" #error aa \n "
" #endif " ;
ASSERT_EQUALS ( " A;B;C \n A;C \n C \n " , getConfigsStr ( filedata ) ) ;
}
2016-07-25 14:52:23 +02:00
void setPlatformInfo ( ) {
Settings settings ;
Preprocessor preprocessor ( settings , this ) ;
// read code with simplecpp..
const char filedata [ ] = " #if sizeof(long) == 4 \n "
" 1 \n "
" #else \n "
" 2 \n "
" #endif \n " ;
std : : istringstream istr ( filedata ) ;
std : : vector < std : : string > files ;
simplecpp : : TokenList tokens ( istr , files , " test.c " ) ;
// preprocess code with unix32 platform..
settings . platform ( Settings : : PlatformType : : Unix32 ) ;
preprocessor . setPlatformInfo ( & tokens ) ;
ASSERT_EQUALS ( " \n 1 " , preprocessor . getcode ( tokens , " " , files , false ) ) ;
// preprocess code with unix64 platform..
settings . platform ( Settings : : PlatformType : : Unix64 ) ;
preprocessor . setPlatformInfo ( & tokens ) ;
ASSERT_EQUALS ( " \n \n \n 2 " , preprocessor . getcode ( tokens , " " , files , false ) ) ;
}
2014-11-20 14:20:09 +01:00
void includeguard1 ( ) {
2009-01-22 19:19:17 +01:00
// Handling include guards..
const char filedata [ ] = " #file \" abc.h \" \n "
" #ifndef abcH \n "
" #define abcH \n "
" #endif \n "
" #endfile \n "
" #ifdef ABC \n "
" #endif " ;
2016-07-30 20:22:07 +02:00
ASSERT_EQUALS ( " \n ABC \n " , getConfigsStr ( filedata ) ) ;
2009-01-22 19:19:17 +01:00
}
2014-11-20 14:20:09 +01:00
void includeguard2 ( ) {
2010-02-06 09:30:48 +01:00
// Handling include guards..
const char filedata [ ] = " #file \" abc.h \" \n "
" foo \n "
" #ifdef ABC \n "
" \n "
" #endif \n "
" #endfile \n " ;
2016-07-30 20:22:07 +02:00
ASSERT_EQUALS ( " \n ABC \n " , getConfigsStr ( filedata ) ) ;
2010-02-06 09:30:48 +01:00
}
2014-11-20 14:20:09 +01:00
void ifdefwithfile ( ) {
2009-03-08 08:45:53 +01:00
// Handling include guards..
const char filedata [ ] = " #ifdef ABC \n "
" #file \" abc.h \" \n "
" class A{};/* \n \n \n \n \n \n \n */ \n "
" #endfile \n "
" #endif \n "
" int main() {} \n " ;
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2009-03-08 08:45:53 +01:00
// Expected configurations: "" and "ABC"
2019-07-16 09:14:44 +02:00
ASSERT_EQUALS ( 2 , actual . size ( ) ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n \n int main ( ) { } " , actual [ " " ] ) ;
ASSERT_EQUALS ( " \n #line 1 \" abc.h \" \n class A { } ; \n #line 4 \" file.c \" \n int main ( ) { } " , actual [ " ABC " ] ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +01:00
void if0 ( ) {
2008-12-18 22:28:57 +01:00
const char filedata [ ] = " # if /* comment */ 0 // comment \n "
" #ifdef WIN32 \n "
" #endif \n "
" #endif \n " ;
2016-07-30 20:22:07 +02:00
ASSERT_EQUALS ( " \n " , getConfigsStr ( filedata ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +01:00
void if1 ( ) {
2008-12-18 22:28:57 +01:00
const char filedata [ ] = " # if /* comment */ 1 // comment \n "
" ABC \n "
" # endif \n " ;
2016-07-30 20:22:07 +02:00
ASSERT_EQUALS ( " \n " , getConfigsStr ( filedata ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +01:00
void elif ( ) {
2010-03-28 14:15:25 +02:00
{
const char filedata [ ] = " #if DEF1 \n "
" ABC \n "
" #elif DEF2 \n "
" DEF \n "
" #endif \n " ;
2016-07-30 20:22:07 +02:00
ASSERT_EQUALS ( " \n DEF1 \n DEF2 \n " , getConfigsStr ( filedata ) ) ;
2010-03-28 14:15:25 +02:00
}
{
const char filedata [ ] = " #if(defined DEF1) \n "
" ABC \n "
" #elif(defined DEF2) \n "
" DEF \n "
" #else \n "
" GHI \n "
" #endif \n " ;
2016-07-30 20:22:07 +02:00
ASSERT_EQUALS ( " \n DEF1 \n DEF2 \n " , getConfigsStr ( filedata ) ) ;
2009-07-30 10:10:34 +02:00
}
2009-07-25 16:22:42 +02:00
}
2014-11-20 14:20:09 +01:00
void if_cond1 ( ) {
2008-12-18 22:28:57 +01:00
const char filedata [ ] = " #if LIBVER>100 \n "
" A \n "
" #else \n "
" B \n "
" #endif \n " ;
2016-07-30 20:22:07 +02:00
TODO_ASSERT_EQUALS ( " \n LIBVER=101 \n " , " \n " , getConfigsStr ( filedata ) ) ;
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +01:00
void if_cond2 ( ) {
2009-06-26 13:19:55 +02:00
const char filedata [ ] = " #ifdef A \n "
" a \n "
" #endif \n "
" #if defined(A) && defined(B) \n "
" ab \n "
" #endif \n " ;
2016-07-30 20:22:07 +02:00
ASSERT_EQUALS ( " \n A \n A;B \n " , getConfigsStr ( filedata ) ) ;
2009-06-26 13:19:55 +02:00
2010-03-19 16:13:45 +01:00
if_cond2b ( ) ;
if_cond2c ( ) ;
if_cond2d ( ) ;
2011-01-31 00:33:44 +01:00
if_cond2e ( ) ;
2010-03-19 16:13:45 +01:00
}
2014-11-20 14:20:09 +01:00
void if_cond2b ( ) {
2010-03-19 16:13:45 +01:00
const char filedata [ ] = " #ifndef A \n "
" !a \n "
" #ifdef B \n "
" b \n "
" #endif \n "
" #else \n "
" a \n "
" #endif \n " ;
2016-07-30 20:22:07 +02:00
TODO_ASSERT_EQUALS ( " \n A;B \n " , " \n A \n B \n " , getConfigsStr ( filedata ) ) ;
2010-03-19 16:13:45 +01:00
}
2014-11-20 14:20:09 +01:00
void if_cond2c ( ) {
2010-03-19 16:13:45 +01:00
const char filedata [ ] = " #ifndef A \n "
" !a \n "
" #ifdef B \n "
" b \n "
" #else \n "
" !b \n "
" #endif \n "
" #else \n "
" a \n "
" #endif \n " ;
2016-07-30 20:22:07 +02:00
TODO_ASSERT_EQUALS ( " \n A \n A;B \n " , " \n A \n B \n " , getConfigsStr ( filedata ) ) ;
2010-03-19 16:13:45 +01:00
}
2014-11-20 14:20:09 +01:00
void if_cond2d ( ) {
2010-03-19 16:13:45 +01:00
const char filedata [ ] = " #ifndef A \n "
" !a \n "
" #ifdef B \n "
" b \n "
" #else \n "
" !b \n "
" #endif \n "
" #else \n "
" a \n "
" #ifdef B \n "
" b \n "
" #else \n "
" !b \n "
" #endif \n "
" #endif \n " ;
2016-07-30 20:22:07 +02:00
ASSERT_EQUALS ( " \n A \n A;B \n B \n " , getConfigsStr ( filedata ) ) ;
2009-06-26 13:19:55 +02:00
}
2014-11-20 14:20:09 +01:00
void if_cond2e ( ) {
2011-01-31 00:33:44 +01:00
const char filedata [ ] = " #if !defined(A) \n "
" !a \n "
" #elif !defined(B) \n "
" !b \n "
" #endif \n " ;
2017-04-02 09:03:43 +02:00
ASSERT_EQUALS ( " \n A \n B \n " , getConfigsStr ( filedata ) ) ;
2011-01-31 00:33:44 +01:00
}
2014-11-20 14:20:09 +01:00
void if_cond3 ( ) {
2009-06-26 13:19:55 +02:00
const char filedata [ ] = " #ifdef A \n "
" a \n "
" #if defined(B) && defined(C) \n "
" abc \n "
" #endif \n "
" #endif \n " ;
2016-07-30 20:22:07 +02:00
ASSERT_EQUALS ( " \n A \n A;B;C \n " , getConfigsStr ( filedata ) ) ;
2009-06-26 13:19:55 +02:00
}
2014-11-20 14:20:09 +01:00
void if_cond4 ( ) {
2009-10-06 10:47:36 +02:00
{
const char filedata [ ] = " #define A \n "
" #define B \n "
" #if defined A || defined B \n "
" ab \n "
" #endif \n " ;
2016-07-30 20:22:07 +02:00
ASSERT_EQUALS ( " \n " , getConfigsStr ( filedata ) ) ;
2009-10-06 10:47:36 +02:00
}
{
const char filedata [ ] = " #if A \n "
" { \n "
" #if (defined(B)) \n "
" foo(); \n "
" #endif \n "
" } \n "
" #endif \n " ;
2016-07-30 20:22:07 +02:00
ASSERT_EQUALS ( " \n A \n A;B \n " , getConfigsStr ( filedata ) ) ;
2009-10-06 10:47:36 +02:00
}
{
const char filedata [ ] = " #define A \n "
" #define B \n "
" #if (defined A) || defined (B) \n "
" ab \n "
" #endif \n " ;
2016-07-30 20:22:07 +02:00
ASSERT_EQUALS ( " \n " , getConfigsStr ( filedata ) ) ;
2009-10-06 10:47:36 +02:00
}
{
const char filedata [ ] = " #if (A) \n "
" foo(); \n "
" #endif \n " ;
2016-07-30 20:22:07 +02:00
ASSERT_EQUALS ( " \n A \n " , getConfigsStr ( filedata ) ) ;
2009-10-06 10:47:36 +02:00
}
2010-03-04 18:51:25 +01:00
{
const char filedata [ ] = " #if! A \n "
" foo(); \n "
" #endif \n " ;
2017-04-02 09:03:43 +02:00
ASSERT_EQUALS ( " \n A=0 \n " , getConfigsStr ( filedata ) ) ;
2010-03-04 18:51:25 +01:00
}
2009-07-22 20:11:27 +02:00
}
2009-06-26 13:19:55 +02:00
2014-11-20 14:20:09 +01:00
void if_cond5 ( ) {
2009-08-29 23:00:54 +02:00
const char filedata [ ] = " #if defined(A) && defined(B) \n "
" ab \n "
" #endif \n "
" cd \n "
" #if defined(B) && defined(A) \n "
" ef \n "
" #endif \n " ;
2016-07-30 20:22:07 +02:00
ASSERT_EQUALS ( " \n A;B \n " , getConfigsStr ( filedata ) ) ;
2009-08-29 23:00:54 +02:00
}
2009-06-26 13:19:55 +02:00
2014-11-20 14:20:09 +01:00
void if_cond6 ( ) {
2009-11-20 19:18:57 +01:00
const char filedata [ ] = " \n "
" #if defined(A) && defined(B)) \n "
" #endif \n " ;
2016-07-30 20:22:07 +02:00
ASSERT_EQUALS ( " \n A;B \n " , getConfigsStr ( filedata ) ) ;
2009-11-20 19:18:57 +01:00
}
2014-11-20 14:20:09 +01:00
void if_cond8 ( ) {
2009-12-15 20:18:32 +01:00
const char filedata [ ] = " #if defined(A) + defined(B) + defined(C) != 1 \n "
" #endif \n " ;
2016-07-30 20:22:07 +02:00
TODO_ASSERT_EQUALS ( " \n A \n " , " \n A;B;C \n " , getConfigsStr ( filedata ) ) ;
2009-12-15 20:18:32 +01:00
}
2014-11-20 14:20:09 +01:00
void if_cond9 ( ) {
2010-01-09 21:54:20 +01:00
const char filedata [ ] = " #if !defined _A \n "
" abc \n "
" #endif \n " ;
2017-04-02 09:03:43 +02:00
ASSERT_EQUALS ( " \n _A \n " , getConfigsStr ( filedata ) ) ;
2010-01-09 21:54:20 +01:00
}
2014-11-20 14:20:09 +01:00
void if_cond10 ( ) {
2010-08-17 20:06:20 +02:00
const char filedata [ ] = " #if !defined(a) && !defined(b) \n "
" #if defined(and) \n "
" #endif \n "
" #endif \n " ;
// Preprocess => don't crash..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2010-08-17 20:06:20 +02:00
}
2014-11-20 14:20:09 +01:00
void if_cond11 ( ) {
2010-09-02 23:01:12 +02:00
const char filedata [ ] = " #if defined(L_fixunssfdi) && LIBGCC2_HAS_SF_MODE \n "
" #if LIBGCC2_HAS_DF_MODE \n "
" #elif FLT_MANT_DIG < W_TYPE_SIZE \n "
" #endif \n "
" #endif \n " ;
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2010-09-02 23:01:12 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void if_cond12 ( ) {
2011-02-20 20:11:51 +01:00
const char filedata [ ] = " #define A (1) \n "
" #if A == 1 \n "
" ; \n "
" #endif \n " ;
2016-07-30 20:22:07 +02:00
ASSERT_EQUALS ( " \n " , getConfigsStr ( filedata ) ) ;
2011-02-20 20:11:51 +01:00
}
2014-11-20 14:20:09 +01:00
void if_cond13 ( ) {
2011-11-03 20:01:31 +01:00
const char filedata [ ] = " #if ('A' == 0x41) \n "
" 123 \n "
" #endif \n " ;
2016-07-30 20:22:07 +02:00
ASSERT_EQUALS ( " \n " , getConfigsStr ( filedata ) ) ;
2012-03-26 19:01:45 +02:00
}
2014-11-20 14:20:09 +01:00
void if_cond14 ( ) {
2012-03-26 19:01:45 +02:00
const char filedata [ ] = " #if !(A) \n "
" 123 \n "
" #endif \n " ;
2016-07-30 20:22:07 +02:00
ASSERT_EQUALS ( " \n " , getConfigsStr ( filedata ) ) ;
2013-01-03 08:44:32 +01:00
}
2010-01-09 21:54:20 +01:00
2009-12-15 20:18:32 +01:00
2014-11-20 14:20:09 +01:00
void if_or_1 ( ) {
2009-12-13 17:18:27 +01:00
const char filedata [ ] = " #if defined(DEF_10) || defined(DEF_11) \n "
" a1; \n "
" #endif \n " ;
2016-07-30 20:22:07 +02:00
ASSERT_EQUALS ( " \n DEF_10;DEF_11 \n " , getConfigsStr ( filedata ) ) ;
2009-12-13 17:18:27 +01:00
}
2014-11-20 14:20:09 +01:00
void if_or_2 ( ) {
2016-07-30 20:22:07 +02:00
const char filedata [ ] = " #if X || Y \n "
" a1; \n "
" #endif \n " ;
TODO_ASSERT_EQUALS ( " \n X;Y \n " , " \n " , getConfigsStr ( filedata ) ) ;
2010-08-26 21:33:45 +02:00
}
2014-11-20 14:20:09 +01:00
void if_macro_eq_macro ( ) {
2016-07-30 20:22:07 +02:00
const char * code = " #define A B \n "
2015-10-09 12:27:39 +02:00
" #define B 1 \n "
" #define C 1 \n "
" #if A == C \n "
" Wilma \n "
" #else \n "
" Betty \n "
" #endif \n " ;
2016-07-30 20:22:07 +02:00
ASSERT_EQUALS ( " \n " , getConfigsStr ( code ) ) ;
2012-03-15 20:04:34 +01:00
}
2009-12-13 17:18:27 +01:00
2014-11-20 14:20:09 +01:00
void ticket_3675 ( ) {
2015-10-09 12:27:39 +02:00
const char * code = " #ifdef YYSTACKSIZE \n "
" #define YYMAXDEPTH YYSTACKSIZE \n "
" #else \n "
" #define YYSTACKSIZE YYMAXDEPTH \n "
" #endif \n "
" #if YYDEBUG \n "
" #endif \n " ;
2012-03-23 00:45:47 +01:00
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( code , actual ) ;
2012-03-23 00:45:47 +01:00
// There's nothing to assert. It just needs to not hang.
}
2014-11-20 14:20:09 +01:00
void ticket_3699 ( ) {
2015-10-09 12:27:39 +02:00
const char * code = " #define INLINE __forceinline \n "
" #define inline __forceinline \n "
" #define __forceinline inline \n "
" #if !defined(_WIN32) \n "
" #endif \n "
" INLINE inline __forceinline \n " ;
2012-04-22 06:49:42 +02:00
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( code , actual ) ;
2012-04-22 06:49:42 +02:00
// First, it must not hang. Second, inline must becomes inline, and __forceinline must become __forceinline.
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n \n \n \n $__forceinline $inline $__forceinline " , actual [ " " ] ) ;
2012-04-22 06:49:42 +02:00
}
2014-11-20 14:20:09 +01:00
void ticket_4922 ( ) { // #4922
2015-10-09 12:27:39 +02:00
const char * code = " __asm__ \n "
" { int extern __value) 0; (double return ( \" \" } extern \n "
" __typeof __finite (__finite) __finite __inline \" __GI___finite \" ); " ;
2013-08-04 14:34:28 +02:00
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( code , actual ) ;
2013-08-04 14:34:28 +02:00
}
2015-01-19 18:00:05 +01:00
void macro_simple1 ( ) const {
2009-05-24 22:57:12 +02:00
{
const char filedata [ ] = " #define AAA(aa) f(aa) \n "
" AAA(5); \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n f ( 5 ) ; " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-05-24 22:57:12 +02:00
}
{
const char filedata [ ] = " #define AAA(aa) f(aa) \n "
" AAA (5); \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n f ( 5 ) ; " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-05-24 22:57:12 +02:00
}
2009-01-05 21:41:34 +01:00
}
2015-01-19 18:00:05 +01:00
void macro_simple2 ( ) const {
2009-01-05 21:41:34 +01:00
const char filedata [ ] = " #define min(x,y) x<y?x:y \n "
" min(a(),b()); \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n a ( ) < b ( ) ? a ( ) : b ( ) ; " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-05 21:41:34 +01:00
}
2015-01-19 18:00:05 +01:00
void macro_simple3 ( ) const {
2009-01-11 16:07:13 +01:00
const char filedata [ ] = " #define A 4 \n "
" A AA \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n 4 AA " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-11 16:07:13 +01:00
}
2015-01-19 18:00:05 +01:00
void macro_simple4 ( ) const {
2009-01-11 16:51:46 +01:00
const char filedata [ ] = " #define TEMP_1 if( temp > 0 ) return 1; \n "
" TEMP_1 \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n if ( temp > 0 ) return 1 ; " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-11 16:51:46 +01:00
}
2015-01-19 18:00:05 +01:00
void macro_simple5 ( ) const {
2009-01-11 17:06:37 +01:00
const char filedata [ ] = " #define ABC if( temp > 0 ) return 1; \n "
" \n "
" void foo() \n "
" { \n "
" int temp = 0; \n "
" ABC \n "
" } \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n void foo ( ) \n { \n int temp = 0 ; \n if ( temp > 0 ) return 1 ; \n } " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-11 17:06:37 +01:00
}
2015-01-19 18:00:05 +01:00
void macro_simple6 ( ) const {
2009-01-18 17:56:12 +01:00
const char filedata [ ] = " #define ABC (a+b+c) \n "
2009-12-09 17:13:48 +01:00
" ABC \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n ( a + b + c ) " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-18 17:56:12 +01:00
}
2015-01-19 18:00:05 +01:00
void macro_simple7 ( ) const {
2009-01-21 18:11:24 +01:00
const char filedata [ ] = " #define ABC(str) str \n "
2009-12-09 17:13:48 +01:00
" ABC( \" ( \" ) \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \" ( \" " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-23 18:14:42 +01:00
}
2015-01-19 18:00:05 +01:00
void macro_simple8 ( ) const {
2009-01-23 18:14:42 +01:00
const char filedata [ ] = " #define ABC 123 \n "
" #define ABCD 1234 \n "
2009-12-09 17:13:48 +01:00
" ABC ABCD \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n 123 1234 " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-21 18:11:24 +01:00
}
2015-01-19 18:00:05 +01:00
void macro_simple9 ( ) const {
2009-06-05 22:45:31 +02:00
const char filedata [ ] = " #define ABC(a) f(a) \n "
" ABC( \" \\ \" \" ); \n "
2009-12-09 17:13:48 +01:00
" ABC( \" g \" ); \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n f ( \" \\ \" \" ) ; \n f ( \" g \" ) ; " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-06-05 22:45:31 +02:00
}
2015-01-19 18:00:05 +01:00
void macro_simple10 ( ) const {
2009-08-01 14:55:45 +02:00
const char filedata [ ] = " #define ABC(t) t x \n "
2009-12-09 17:13:48 +01:00
" ABC(unsigned long); \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n unsigned long x ; " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-08-01 14:55:45 +02:00
}
2015-01-19 18:00:05 +01:00
void macro_simple11 ( ) const {
2009-11-26 17:32:18 +01:00
const char filedata [ ] = " #define ABC(x) delete x \n "
2009-12-09 17:13:48 +01:00
" ABC(a); \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n delete a ; " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-12-09 17:13:48 +01:00
}
2015-01-19 18:00:05 +01:00
void macro_simple12 ( ) const {
2009-12-09 17:13:48 +01:00
const char filedata [ ] = " #define AB ab.AB \n "
" AB.CD \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n ab . AB . CD " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-11-26 17:32:18 +01:00
}
2015-01-19 18:00:05 +01:00
void macro_simple13 ( ) const {
2010-01-02 20:54:52 +01:00
const char filedata [ ] = " #define TRACE(x) \n "
" TRACE(;if(a)) \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2010-01-02 20:54:52 +01:00
}
2015-01-19 18:00:05 +01:00
void macro_simple14 ( ) const {
2011-02-11 06:30:42 +01:00
const char filedata [ ] = " #define A \" a \" \n "
" printf(A); \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n printf ( \" a \" ) ; " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2011-02-11 06:30:42 +01:00
}
2015-01-19 18:00:05 +01:00
void macro_simple15 ( ) const {
2011-02-11 18:01:27 +01:00
const char filedata [ ] = " #define FOO \" foo \" \n "
" FOO \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \" foo \" " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2011-02-11 18:01:27 +01:00
}
2015-01-19 18:00:05 +01:00
void macro_simple16 ( ) const { // # 4703
2013-08-10 23:28:02 +02:00
const char filedata [ ] = " #define MACRO( A, B, C ) class A##B##C##Creator {}; \n "
" MACRO( B \t , U , G ) " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n class BUGCreator { } ; " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2013-10-13 17:42:06 +02:00
}
2015-01-19 18:00:05 +01:00
void macro_simple17 ( ) const { // # 5074 - the Token::isExpandedMacro() doesn't always indicate properly if token comes from macro
2013-10-13 17:42:06 +02:00
// It would probably be OK if the generated code was
// "\n123+$123" since the first 123 comes from the source code
const char filedata [ ] = " #define MACRO(A) A+123 \n "
" MACRO(123) " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n 123 + 123 " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2013-08-10 23:28:02 +02:00
}
2015-01-19 18:00:05 +01:00
void macro_simple18 ( ) const { // (1e-7)
2013-12-30 18:03:24 +01:00
const char filedata1 [ ] = " #define A (1e-7) \n "
" a=A; " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n a = ( 1e-7 ) ; " , OurPreprocessor : : expandMacros ( filedata1 ) ) ;
2013-12-30 18:03:24 +01:00
const char filedata2 [ ] = " #define A (1E-7) \n "
" a=A; " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n a = ( 1E-7 ) ; " , OurPreprocessor : : expandMacros ( filedata2 ) ) ;
2013-12-30 18:03:24 +01:00
const char filedata3 [ ] = " #define A (1e+7) \n "
" a=A; " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n a = ( 1e+7 ) ; " , OurPreprocessor : : expandMacros ( filedata3 ) ) ;
2013-12-31 10:24:14 +01:00
const char filedata4 [ ] = " #define A (1.e+7) \n "
" a=A; " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n a = ( 1.e+7 ) ; " , OurPreprocessor : : expandMacros ( filedata4 ) ) ;
2013-12-31 10:24:14 +01:00
const char filedata5 [ ] = " #define A (1.7f) \n "
" a=A; " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n a = ( 1.7f ) ; " , OurPreprocessor : : expandMacros ( filedata5 ) ) ;
2014-01-02 11:21:23 +01:00
const char filedata6 [ ] = " #define A (.1) \n "
" a=A; " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n a = ( .1 ) ; " , OurPreprocessor : : expandMacros ( filedata6 ) ) ;
2014-01-02 11:21:23 +01:00
const char filedata7 [ ] = " #define A (1.) \n "
" a=A; " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n a = ( 1. ) ; " , OurPreprocessor : : expandMacros ( filedata7 ) ) ;
2014-01-08 18:05:14 +01:00
const char filedata8 [ ] = " #define A (8.0E+007) \n "
" a=A; " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n a = ( 8.0E+007 ) ; " , OurPreprocessor : : expandMacros ( filedata8 ) ) ;
2013-12-29 21:51:01 +01:00
}
2015-01-19 18:00:05 +01:00
void macroInMacro1 ( ) const {
2009-09-14 21:53:57 +02:00
{
const char filedata [ ] = " #define A(m) long n = m; n++; \n "
" #define B(n) A(n) \n "
2009-12-09 17:13:48 +01:00
" B(0) \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n long n = 0 ; n ++ ; " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-09-14 21:53:57 +02:00
}
{
const char filedata [ ] = " #define A B \n "
" #define B 3 \n "
2009-12-09 17:13:48 +01:00
" A \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n 3 " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-09-14 21:53:57 +02:00
}
2009-09-21 22:27:06 +02:00
2010-03-24 19:24:53 +01:00
{
const char filedata [ ] = " #define BC(b, c...) 0##b * 0##c \n "
" #define ABC(a, b...) a + BC(b) \n "
" \n "
2016-07-20 12:21:00 +02:00
" ABC(1); \n " // <- too few parameters
2010-03-24 19:24:53 +01:00
" ABC(2,3); \n "
" ABC(4,5,6); \n " ;
2010-03-24 19:55:02 +01:00
2021-02-20 13:02:14 +01:00
ASSERT_EQUALS ( " \n \n \n 1 + 0 * 0 ; \n 2 + 03 * 0 ; \n 4 + 05 * 06 ; " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2010-03-24 19:24:53 +01:00
}
2009-09-21 22:27:06 +02:00
{
const char filedata [ ] = " #define A 4 \n "
" #define B(a) a,A \n "
2009-12-09 17:13:48 +01:00
" B(2); \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n 2 , 4 ; " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-09-21 22:27:06 +02:00
}
2009-11-17 23:21:21 +01:00
{
const char filedata [ ] = " #define A(x) (x) \n "
" #define B )A( \n "
" #define C )A( \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-11-17 23:21:21 +01:00
}
{
const char filedata [ ] = " #define A(x) (x*2) \n "
" #define B A( \n "
" foo B(i)); \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n foo ( ( i ) * 2 ) ; " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-11-18 23:34:00 +01:00
}
{
const char filedata [ ] = " #define foo foo \n "
" foo \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n foo " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-11-17 23:21:21 +01:00
}
2009-12-13 21:36:42 +01:00
{
const char filedata [ ] =
" #define B(A1, A2) } while (0) \n "
" #define A(name) void foo##name() { do { B(1, 2); } \n "
" A(0) \n "
" A(1) \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n void foo0 ( ) { do { } while ( 0 ) ; } \n void foo1 ( ) { do { } while ( 0 ) ; } " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-12-14 23:06:05 +01:00
}
{
const char filedata [ ] =
" #define B(x) ( \n "
" #define A() B(xx) \n "
" B(1) A() ) ) \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n ( ( ) ) " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-12-13 21:36:42 +01:00
}
2009-12-20 22:50:57 +01:00
{
const char filedata [ ] =
" #define PTR1 ( \n "
" #define PTR2 PTR1 PTR1 \n "
" int PTR2 PTR2 foo )))) = 0; \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n int ( ( ( ( foo ) ) ) ) = 0 ; " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-12-20 22:50:57 +01:00
}
{
const char filedata [ ] =
" #define PTR1 ( \n "
" PTR1 PTR1 \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n ( ( " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-12-20 22:50:57 +01:00
}
2009-08-22 13:03:52 +02:00
}
2015-01-19 18:00:05 +01:00
void macroInMacro2 ( ) const {
2011-04-07 16:53:42 +02:00
const char filedata [ ] = " #define A(x) a##x \n "
" #define B 0 \n "
" A(B) \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n aB " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-05 10:26:00 +01:00
}
2015-01-19 18:00:05 +01:00
void macro_linenumbers ( ) const {
2009-03-08 21:28:12 +01:00
const char filedata [ ] = " #define AAA(a) \n "
" AAA(5 \n "
" \n "
" ) \n "
" int a; \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n "
2009-03-10 23:49:16 +01:00
" \n "
" \n "
" \n "
2016-07-20 12:21:00 +02:00
" int a ; " ,
2009-03-10 23:49:16 +01:00
OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-03-08 21:28:12 +01:00
}
2015-01-19 18:00:05 +01:00
void macro_nopar ( ) const {
2009-06-19 16:42:47 +02:00
const char filedata [ ] = " #define AAA( ) { NULL } \n "
2009-12-09 17:13:48 +01:00
" AAA() \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n { NULL } " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-06-19 16:42:47 +02:00
}
2015-12-29 06:54:44 +01:00
void macro_incdec ( ) const {
const char filedata [ ] = " #define M1(X) 1+X \n "
" #define M2(X) 2-X \n "
" M1(+1) M2(-1) \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n 1 + + 1 2 - - 1 " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2015-12-29 06:54:44 +01:00
}
2015-01-19 18:00:05 +01:00
void macro_switchCase ( ) const {
2010-04-15 22:21:00 +02:00
{
// Make sure "case 2" doesn't become "case2"
const char filedata [ ] = " #define A( b ) "
" switch( a ){ "
" case 2: "
" break; "
" } \n "
" A( 5 ); \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n switch ( a ) { case 2 : break ; } ; " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2010-04-15 22:21:00 +02:00
}
{
// Make sure "2 BB" doesn't become "2BB"
const char filedata [ ] = " #define A() AA : 2 BB \n "
" A(); \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n AA : 2 BB ; " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2010-04-15 22:21:00 +02:00
}
{
const char filedata [ ] = " #define A } \n "
" #define B() A \n "
" #define C( a ) B() break; \n "
" {C( 2 ); \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n \n { } break ; ; " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2010-04-15 22:21:00 +02:00
}
{
const char filedata [ ] = " #define A } \n "
" #define B() A \n "
" #define C( a ) B() _break; \n "
" {C( 2 ); \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n \n { } _break ; ; " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2010-04-15 22:21:00 +02:00
}
{
const char filedata [ ] = " #define A } \n "
" #define B() A \n "
" #define C( a ) B() 5; \n "
" {C( 2 ); \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n \n { } 5 ; ; " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2010-04-15 22:21:00 +02:00
}
}
2009-06-19 16:42:47 +02:00
2015-01-19 18:00:05 +01:00
void macro_NULL ( ) const {
2013-01-14 06:44:52 +01:00
// See ticket #4482 - UB when passing NULL to variadic function
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n 0 " , OurPreprocessor : : expandMacros ( " #define null 0 \n null " ) ) ;
2021-02-20 13:02:14 +01:00
TODO_ASSERT_EQUALS ( " \n NULL " , " \n 0 " , OurPreprocessor : : expandMacros ( " #define NULL 0 \n NULL " ) ) ; // TODO: Let the tokenizer handle NULL?
2013-01-13 15:01:31 +01:00
}
2014-11-20 14:20:09 +01:00
void string1 ( ) {
2009-01-08 23:28:54 +01:00
const char filedata [ ] = " int main() "
" { "
2016-07-20 12:21:00 +02:00
" const char *a = \" #define A \" ; "
2009-12-09 17:13:48 +01:00
" } \n " ;
2009-01-08 23:28:54 +01:00
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2009-01-05 10:26:00 +01:00
2009-01-08 23:28:54 +01:00
// Compare results..
2019-07-16 09:14:44 +02:00
ASSERT_EQUALS ( 1 , actual . size ( ) ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " int main ( ) { const char * a = \" #define A \" ; } " , actual [ " " ] ) ;
2009-01-08 23:28:54 +01:00
}
2009-01-12 19:23:53 +01:00
2015-01-19 18:00:05 +01:00
void string2 ( ) const {
2009-01-18 17:58:57 +01:00
const char filedata [ ] = " #define AAA 123 \n "
2009-12-09 17:13:48 +01:00
" str = \" AAA \" \n " ;
// Compare results..
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n str = \" AAA \" " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-12-09 17:13:48 +01:00
}
2015-01-19 18:00:05 +01:00
void string3 ( ) const {
2009-12-09 17:13:48 +01:00
const char filedata [ ] = " str( \" ; \" ); \n " ;
2009-01-18 17:58:57 +01:00
// Compare results..
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " str ( \" ; \" ) ; " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-18 17:58:57 +01:00
}
2014-11-20 14:20:09 +01:00
void preprocessor_undef ( ) {
2009-06-14 06:21:20 +02:00
{
const char filedata [ ] = " #define AAA int a; \n "
" #undef AAA \n "
" #define AAA char b=0; \n "
" AAA \n " ;
2009-01-12 19:23:53 +01:00
2009-06-14 06:21:20 +02:00
// Compare results..
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n \n char b = 0 ; " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-06-14 06:21:20 +02:00
}
{
// ticket #403
const char filedata [ ] = " #define z p[2] \n "
" #undef z \n "
" int z; \n "
" z = 0; \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n int z ; \n z = 0 ; " , preprocessor0 . getcode ( filedata , " " , " " ) ) ;
2009-06-14 06:21:20 +02:00
}
2009-01-12 19:23:53 +01:00
}
2009-01-19 20:24:41 +01:00
2015-01-19 18:00:05 +01:00
void defdef ( ) const {
2009-01-22 21:19:07 +01:00
const char filedata [ ] = " #define AAA 123 \n "
" #define AAA 456 \n "
" #define AAA 789 \n "
" AAA \n " ;
// Compare results..
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n \n 789 " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-22 21:19:07 +01:00
}
2015-01-19 18:00:05 +01:00
void preprocessor_doublesharp ( ) const {
2010-06-19 12:03:39 +02:00
// simple testcase without ##
const char filedata1 [ ] = " #define TEST(var,val) var = val \n "
" TEST(foo,20); \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n foo = 20 ; " , OurPreprocessor : : expandMacros ( filedata1 ) ) ;
2009-01-19 22:45:59 +01:00
2010-06-19 12:03:39 +02:00
// simple testcase with ##
2009-01-19 22:45:59 +01:00
const char filedata2 [ ] = " #define TEST(var,val) var##_##val = val \n "
" TEST(foo,20); \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n foo_20 = 20 ; " , OurPreprocessor : : expandMacros ( filedata2 ) ) ;
2009-12-09 19:14:07 +01:00
2010-06-19 12:03:39 +02:00
// concat macroname
2009-12-09 19:14:07 +01:00
const char filedata3 [ ] = " #define ABCD 123 \n "
" #define A(B) A##B \n "
" A(BCD) \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n 123 " , OurPreprocessor : : expandMacros ( filedata3 ) ) ;
2010-06-19 12:03:39 +02:00
// Ticket #1802 - inner ## must be expanded before outer macro
const char filedata4 [ ] = " #define A(B) A##B \n "
" #define a(B) A(B) \n "
" a(A(B)) \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n AAB " , OurPreprocessor : : expandMacros ( filedata4 ) ) ;
2010-06-19 12:03:39 +02:00
// Ticket #1802 - inner ## must be expanded before outer macro
const char filedata5 [ ] = " #define AB(A,B) A##B \n "
" #define ab(A,B) AB(A,B) \n "
" ab(a,AB(b,c)) \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n abc " , OurPreprocessor : : expandMacros ( filedata5 ) ) ;
2010-09-18 22:20:01 +02:00
// Ticket #1802
const char filedata6 [ ] = " #define AB_(A,B) A ## B \n "
" #define AB(A,B) AB_(A,B) \n "
" #define ab(suf) AB(X, AB_(_, suf)) \n "
" #define X x \n "
" ab(y) \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n \n \n x_y " , OurPreprocessor : : expandMacros ( filedata6 ) ) ;
2009-01-19 22:45:59 +01:00
}
2014-11-20 14:20:09 +01:00
void preprocessor_include_in_str ( ) {
2009-01-19 20:24:41 +01:00
const char filedata [ ] = " int main() \n "
" { \n "
2016-07-20 12:21:00 +02:00
" const char *a = \" #include <string> \" ; \n "
2009-01-19 20:24:41 +01:00
" return 0; \n "
" } \n " ;
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2009-01-19 20:24:41 +01:00
// Compare results..
2019-07-16 09:14:44 +02:00
ASSERT_EQUALS ( 1 , actual . size ( ) ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " int main ( ) \n { \n const char * a = \" #include <string> \" ; \n return 0 ; \n } " , actual [ " " ] ) ;
2009-01-19 20:24:41 +01:00
}
2009-01-21 08:22:44 +01:00
2009-01-22 21:19:07 +01:00
2015-01-19 18:00:05 +01:00
void va_args_1 ( ) const {
2009-01-21 18:11:24 +01:00
const char filedata [ ] = " #define DBG(fmt...) printf(fmt) \n "
2009-12-09 17:13:48 +01:00
" DBG( \" [0x%lx-0x%lx) \" , pstart, pend); \n " ;
2009-01-21 08:22:44 +01:00
// Preprocess..
2009-02-07 21:06:00 +01:00
std : : string actual = OurPreprocessor : : expandMacros ( filedata ) ;
2009-01-21 18:11:24 +01:00
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n printf ( \" [0x%lx-0x%lx) \" , pstart , pend ) ; " , actual ) ;
2009-01-21 08:22:44 +01:00
}
2016-07-20 12:21:00 +02:00
/*
void va_args_2 ( ) const {
const char filedata [ ] = " #define DBG(fmt, args...) printf(fmt, ## args) \n "
" DBG( \" hello \" ); \n " ;
2009-01-21 08:22:44 +01:00
2016-07-20 12:21:00 +02:00
// Preprocess..
std : : string actual = OurPreprocessor : : expandMacros ( filedata ) ;
2009-01-28 21:19:46 +01:00
2016-07-20 12:21:00 +02:00
// invalid code ASSERT_EQUALS("\nprintf ( \"hello\" ) ;", actual);
}
2021-08-07 20:51:18 +02:00
*/
2015-01-19 18:00:05 +01:00
void va_args_3 ( ) const {
2009-06-18 23:09:11 +02:00
const char filedata [ ] = " #define FRED(...) { fred(__VA_ARGS__); } \n "
2009-12-09 17:13:48 +01:00
" FRED(123) \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n { fred ( 123 ) ; } " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-06-18 23:09:11 +02:00
}
2009-01-28 21:19:46 +01:00
2015-01-19 18:00:05 +01:00
void va_args_4 ( ) const {
2011-01-02 11:19:37 +01:00
const char filedata [ ] = " #define FRED(name, ...) name (__VA_ARGS__) \n "
" FRED(abc, 123) \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n abc ( 123 ) " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2011-01-02 10:09:50 +01:00
}
2017-01-07 14:13:22 +01:00
void va_args_5 ( ) const {
2016-05-28 11:27:45 +02:00
const char filedata1 [ ] = " #define A(...) #__VA_ARGS__ \n "
" A(123) \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \" 123 \" " , OurPreprocessor : : expandMacros ( filedata1 ) ) ;
2016-05-28 11:27:45 +02:00
const char filedata2 [ ] = " #define A(X,...) X(#__VA_ARGS__) \n "
" A(f,123) \n " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n f ( \" 123 \" ) " , OurPreprocessor : : expandMacros ( filedata2 ) ) ;
2016-05-28 11:27:45 +02:00
}
2009-01-28 21:19:46 +01:00
2014-11-20 14:20:09 +01:00
void multi_character_character ( ) {
2009-01-21 20:12:28 +01:00
const char filedata [ ] = " #define FOO 'ABCD' \n "
" int main() \n "
" { \n "
" if( FOO == 0 ); \n "
" return 0; \n "
" } \n " ;
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2009-01-21 20:12:28 +01:00
// Compare results..
2019-07-16 09:14:44 +02:00
ASSERT_EQUALS ( 1 , actual . size ( ) ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n int main ( ) \n { \n if ( $'ABCD' == 0 ) ; \n return 0 ; \n } " , actual [ " " ] ) ;
2009-01-21 20:12:28 +01:00
}
2009-01-22 21:19:07 +01:00
2015-01-19 18:00:05 +01:00
void stringify ( ) const {
2009-01-25 14:30:15 +01:00
const char filedata [ ] = " #define STRINGIFY(x) #x \n "
2009-12-09 17:13:48 +01:00
" STRINGIFY(abc) \n " ;
2009-01-25 14:30:15 +01:00
// expand macros..
2009-02-07 21:06:00 +01:00
std : : string actual = OurPreprocessor : : expandMacros ( filedata ) ;
2009-01-25 14:30:15 +01:00
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \" abc \" " , actual ) ;
2009-01-25 14:30:15 +01:00
}
2015-01-19 18:00:05 +01:00
void stringify2 ( ) const {
2009-03-15 15:05:23 +01:00
const char filedata [ ] = " #define A(x) g(#x) \n "
2009-12-09 17:13:48 +01:00
" A(abc); \n " ;
2009-03-15 15:05:23 +01:00
// expand macros..
std : : string actual = OurPreprocessor : : expandMacros ( filedata ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n g ( \" abc \" ) ; " , actual ) ;
2009-03-15 15:05:23 +01:00
}
2015-01-19 18:00:05 +01:00
void stringify3 ( ) const {
2009-03-15 22:39:58 +01:00
const char filedata [ ] = " #define A(x) g(#x) \n "
2009-12-09 17:13:48 +01:00
" A( abc); \n " ;
2009-03-15 22:39:58 +01:00
// expand macros..
std : : string actual = OurPreprocessor : : expandMacros ( filedata ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n g ( \" abc \" ) ; " , actual ) ;
2009-03-15 22:39:58 +01:00
}
2015-01-19 18:00:05 +01:00
void stringify4 ( ) const {
2009-05-05 17:19:06 +02:00
const char filedata [ ] = " #define A(x) #x \n "
" 1 A( \n "
" abc \n "
2009-12-09 17:13:48 +01:00
" ) 2 \n " ;
2009-05-05 17:19:06 +02:00
// expand macros..
std : : string actual = OurPreprocessor : : expandMacros ( filedata ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n 1 \" abc \" \n \n 2 " , actual ) ;
2009-05-05 17:19:06 +02:00
}
2015-01-19 18:00:05 +01:00
void stringify5 ( ) const {
2009-10-14 20:40:17 +02:00
const char filedata [ ] = " #define A(x) a(#x,x) \n "
" A(foo( \" \\ \" \" )) \n " ;
2016-08-04 22:53:10 +02:00
ASSERT_EQUALS ( " \n a ( \" foo( \\ \" \\ \\ \\ \" \\ \" ) \" , foo ( \" \\ \" \" ) ) " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-10-14 20:40:17 +02:00
}
2014-11-20 14:20:09 +01:00
void pragma ( ) {
2009-03-15 13:23:12 +01:00
const char filedata [ ] = " #pragma once \n "
" void f() \n "
" { \n "
" } \n " ;
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2009-03-15 13:23:12 +01:00
// Compare results..
2019-07-16 09:14:44 +02:00
ASSERT_EQUALS ( 1 , actual . size ( ) ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n void f ( ) \n { \n } " , actual [ " " ] ) ;
2009-03-15 13:23:12 +01:00
}
2009-03-18 00:10:26 +01:00
2014-11-20 14:20:09 +01:00
void pragma_asm_1 ( ) {
2009-08-10 20:07:55 +02:00
const char filedata [ ] = " #pragma asm \n "
" mov r1, 11 \n "
" #pragma endasm \n "
2009-08-26 21:54:43 +02:00
" aaa \n "
" #pragma asm foo \n "
" mov r1, 11 \n "
" #pragma endasm bar \n "
" bbb " ;
2009-08-10 20:07:55 +02:00
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2009-08-10 20:07:55 +02:00
// Compare results..
2019-07-16 09:14:44 +02:00
ASSERT_EQUALS ( 1 , actual . size ( ) ) ;
2017-05-17 10:25:37 +02:00
ASSERT_EQUALS ( " asm ( ) \n ; \n \n aaa \n asm ( ) ; \n \n \n bbb " , actual [ " " ] ) ;
2009-08-10 20:07:55 +02:00
}
2014-11-20 14:20:09 +01:00
void pragma_asm_2 ( ) {
2010-02-12 18:15:15 +01:00
const char filedata [ ] = " #pragma asm \n "
" mov @w1, 11 \n "
" #pragma endasm ( temp=@w1 ) \n "
" bbb " ;
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2010-02-12 18:15:15 +01:00
// Compare results..
2019-07-16 09:14:44 +02:00
ASSERT_EQUALS ( 1 , actual . size ( ) ) ;
2017-05-17 10:25:37 +02:00
ASSERT_EQUALS ( " asm ( ) \n ; \n \n bbb " , actual [ " " ] ) ;
2013-08-18 18:04:06 +02:00
}
2014-11-20 14:20:09 +01:00
void endifsemicolon ( ) {
2011-12-17 15:23:55 +01:00
const char filedata [ ] = " void f() { \n "
2009-03-18 00:10:26 +01:00
" #ifdef A \n "
" #endif; \n "
" } \n " ;
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2009-03-18 00:10:26 +01:00
// Compare results..
2019-07-16 09:14:44 +02:00
ASSERT_EQUALS ( 2 , actual . size ( ) ) ;
2016-07-20 12:21:00 +02:00
const std : : string expected ( " void f ( ) { \n \n \n } " ) ;
2011-12-17 15:23:55 +01:00
ASSERT_EQUALS ( expected , actual [ " " ] ) ;
ASSERT_EQUALS ( expected , actual [ " A " ] ) ;
2009-03-18 00:10:26 +01:00
}
2009-04-03 21:09:12 +02:00
2014-11-20 14:20:09 +01:00
void handle_error ( ) {
2009-08-13 23:22:51 +02:00
{
const char filedata [ ] = " #define A \n "
2009-11-13 22:12:29 +01:00
" #define B don't want to \\ \n "
2009-08-13 23:22:51 +02:00
" more text \n "
" void f() \n "
" { \n "
" char a = 'a'; // ' \n "
" } \n " ;
2015-10-09 12:27:39 +02:00
2009-08-13 23:22:51 +02:00
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2009-08-13 23:22:51 +02:00
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " " , actual [ " " ] ) ;
2016-07-07 23:45:42 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2009-08-13 23:22:51 +02:00
}
}
2014-11-20 14:20:09 +01:00
void missing_doublequote ( ) {
2009-04-26 11:05:32 +02:00
{
const char filedata [ ] = " #define a \n "
" #ifdef 1 \n "
" \" \n "
" #endif \n " ;
2009-04-03 21:09:12 +02:00
2009-04-26 11:05:32 +02:00
// expand macros..
errout . str ( " " ) ;
const std : : string actual ( OurPreprocessor : : expandMacros ( filedata , this ) ) ;
ASSERT_EQUALS ( " " , actual ) ;
ASSERT_EQUALS ( " [file.cpp:3]: (error) No pair for character ( \" ). Can't process file. File is either invalid or unicode, which is currently not supported. \n " , errout . str ( ) ) ;
}
2009-04-03 21:09:12 +02:00
2009-04-26 11:05:32 +02:00
{
2009-05-19 21:19:15 +02:00
const char filedata [ ] = " #file \" abc.h \" \n "
2009-04-26 11:05:32 +02:00
" #define a \n "
" \" \n "
" #endfile \n " ;
// expand macros..
errout . str ( " " ) ;
const std : : string actual ( OurPreprocessor : : expandMacros ( filedata , this ) ) ;
ASSERT_EQUALS ( " " , actual ) ;
ASSERT_EQUALS ( " [abc.h:2]: (error) No pair for character ( \" ). Can't process file. File is either invalid or unicode, which is currently not supported. \n " , errout . str ( ) ) ;
}
2009-04-26 21:19:08 +02:00
2009-05-19 21:19:15 +02:00
{
const char filedata [ ] = " #file \" abc.h \" \n "
" #define a \n "
" #endfile \n "
" \" \n " ;
// expand macros..
errout . str ( " " ) ;
const std : : string actual ( OurPreprocessor : : expandMacros ( filedata , this ) ) ;
ASSERT_EQUALS ( " " , actual ) ;
ASSERT_EQUALS ( " [file.cpp:2]: (error) No pair for character ( \" ). Can't process file. File is either invalid or unicode, which is currently not supported. \n " , errout . str ( ) ) ;
}
2009-04-26 21:19:08 +02:00
{
const char filedata [ ] = " #define A 1 \n "
" #define B \" \n "
" int a = A; \n " ;
// expand macros..
errout . str ( " " ) ;
const std : : string actual ( OurPreprocessor : : expandMacros ( filedata , this ) ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " " , actual ) ;
ASSERT_EQUALS ( " [file.cpp:2]: (error) No pair for character ( \" ). Can't process file. File is either invalid or unicode, which is currently not supported. \n " , errout . str ( ) ) ;
2009-04-26 21:19:08 +02:00
}
2010-02-26 22:11:23 +01:00
{
const char filedata [ ] = " void foo() \n "
" { \n "
" \n "
" \n "
" \n "
" int a = 0; \n "
" printf(Text \" ); \n "
" } \n " ;
// expand macros..
errout . str ( " " ) ;
2014-03-28 18:55:16 +01:00
OurPreprocessor : : expandMacros ( filedata , this ) ;
2010-02-26 22:11:23 +01:00
ASSERT_EQUALS ( " [file.cpp:7]: (error) No pair for character ( \" ). Can't process file. File is either invalid or unicode, which is currently not supported. \n " , errout . str ( ) ) ;
}
2009-04-03 21:09:12 +02:00
}
2009-04-27 21:29:03 +02:00
2009-06-19 15:43:46 +02:00
2014-11-20 14:20:09 +01:00
void define_part_of_func ( ) {
2009-05-09 21:32:29 +02:00
const char filedata [ ] = " #define A g( \n "
" void f() { \n "
" A ); \n "
" } \n " ;
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2009-05-09 21:32:29 +02:00
// Compare results..
2019-07-16 09:14:44 +02:00
ASSERT_EQUALS ( 1 , actual . size ( ) ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n void f ( ) { \n $g $( ) ; \n } " , actual [ " " ] ) ;
2009-05-09 21:32:29 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void conditionalDefine ( ) {
2009-05-13 21:38:57 +02:00
const char filedata [ ] = " #ifdef A \n "
" #define N 10 \n "
" #else \n "
" #define N 20 \n "
" #endif \n "
" N " ;
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2009-05-13 21:38:57 +02:00
// Compare results..
2019-07-16 09:14:44 +02:00
ASSERT_EQUALS ( 2 , actual . size ( ) ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n \n \n \n $20 " , actual [ " " ] ) ;
ASSERT_EQUALS ( " \n \n \n \n \n $10 " , actual [ " A " ] ) ;
2009-05-12 23:01:53 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void macro_parameters ( ) {
2009-05-18 22:32:04 +02:00
errout . str ( " " ) ;
const char filedata [ ] = " #define BC(a, b, c, arg...) \\ \n "
" AB(a, b, c, ## arg) \n "
" \n "
" void f() \n "
" { \n "
" BC(3); \n "
" } \n " ;
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2009-05-18 22:32:04 +02:00
// Compare results..
2019-07-16 09:14:44 +02:00
ASSERT_EQUALS ( 1 , actual . size ( ) ) ;
2009-05-18 22:32:04 +02:00
ASSERT_EQUALS ( " " , actual [ " " ] ) ;
2016-09-03 12:29:45 +02:00
ASSERT_EQUALS ( " [file.c:6]: (error) failed to expand 'BC', Wrong number of parameters for macro 'BC'. \n " , errout . str ( ) ) ;
2009-05-18 22:32:04 +02:00
}
2009-05-12 23:01:53 +02:00
2014-11-20 14:20:09 +01:00
void newline_in_macro ( ) {
2009-05-20 20:36:59 +02:00
const char filedata [ ] = " #define ABC(str) printf( str ) \n "
" void f() \n "
" { \n "
" ABC( \" \\ n \" ); \n "
" } \n " ;
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2009-05-20 20:36:59 +02:00
// Compare results..
2019-07-16 09:14:44 +02:00
ASSERT_EQUALS ( 1 , actual . size ( ) ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n void f ( ) \n { \n $printf $( \" \\ n \" $) ; \n } " , actual [ " " ] ) ;
2009-05-20 20:36:59 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void ifdef_ifdefined ( ) {
2009-06-14 22:37:18 +02:00
const char filedata [ ] = " #ifdef ABC \n "
" A \n "
" #endif \t \n "
" #if defined ABC \n "
" A \n "
" #endif \n " ;
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2009-06-14 22:37:18 +02:00
// Compare results..
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " " , actual [ " " ] ) ;
ASSERT_EQUALS ( " \n A \n \n \n A " , actual [ " ABC " ] ) ;
2019-07-16 09:14:44 +02:00
ASSERT_EQUALS ( 2 , actual . size ( ) ) ;
2009-06-14 22:37:18 +02:00
}
2009-07-22 18:47:50 +02:00
2014-11-20 14:20:09 +01:00
void define_if1 ( ) {
2011-02-23 22:08:24 +01:00
{
const char filedata [ ] = " #define A 0 \n "
" #if A \n "
" FOO \n "
" #endif " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " " , preprocessor0 . getcode ( filedata , " " , " " ) ) ;
2011-02-23 22:08:24 +01:00
}
{
const char filedata [ ] = " #define A 1 \n "
" #if A==1 \n "
" FOO \n "
" #endif " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n FOO " , preprocessor0 . getcode ( filedata , " " , " " ) ) ;
2011-02-23 22:08:24 +01:00
}
}
2014-11-20 14:20:09 +01:00
void define_if2 ( ) {
2011-07-18 21:44:23 +02:00
const char filedata [ ] = " #define A 22 \n "
" #define B A \n "
" #if (B==A) || (B==C) \n "
" FOO \n "
" #endif " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n \n FOO " , preprocessor0 . getcode ( filedata , " " , " " ) ) ;
2011-07-18 21:44:23 +02:00
}
2014-11-20 14:20:09 +01:00
void define_if3 ( ) {
2011-11-17 19:19:43 +01:00
const char filedata [ ] = " #define A 0 \n "
" #if (A==0) \n "
" FOO \n "
" #endif " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n FOO " , preprocessor0 . getcode ( filedata , " " , " " ) ) ;
2011-11-17 19:19:43 +01:00
}
2014-11-20 14:20:09 +01:00
void define_if4 ( ) {
2012-11-28 07:33:24 +01:00
const char filedata [ ] = " #define X +123 \n "
2012-11-28 08:48:00 +01:00
" #if X==123 \n "
" FOO \n "
" #endif " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n FOO " , preprocessor0 . getcode ( filedata , " " , " " ) ) ;
2012-11-28 07:33:24 +01:00
}
2014-11-20 14:20:09 +01:00
void define_if5 ( ) { // #4516 - #define B (A & 0x00f0)
2013-01-26 16:21:33 +01:00
{
const char filedata [ ] = " #define A 0x0010 \n "
" #define B (A & 0x00f0) \n "
" #if B==0x0010 \n "
" FOO \n "
" #endif " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n \n FOO " , preprocessor0 . getcode ( filedata , " " , " " ) ) ;
2013-01-26 16:21:33 +01:00
}
{
const char filedata [ ] = " #define A 0x00f0 \n "
" #define B (16) \n "
" #define C (B & A) \n "
" #if C==0x0010 \n "
" FOO \n "
" #endif " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n \n \n FOO " , preprocessor0 . getcode ( filedata , " " , " " ) ) ;
2013-01-26 16:21:33 +01:00
}
2013-01-27 02:53:29 +01:00
{
const char filedata [ ] = " #define A (1+A) \n " // don't hang for recursive macros
" #if A==1 \n "
" FOO \n "
" #endif " ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n FOO " , preprocessor0 . getcode ( filedata , " " , " " ) ) ;
2013-01-27 02:53:29 +01:00
}
2013-01-26 12:37:46 +01:00
}
2014-11-20 14:20:09 +01:00
void define_if6 ( ) { // #4516 - #define B (A?1:-1)
2013-06-19 21:29:39 +02:00
const char filedata [ ] = " #ifdef A \n "
" #define B (A?1:-1) \n "
" #endif \n "
" \n "
" #if B < 0 \n "
" 123 \n "
" #endif \n "
" \n "
" #if B >= 0 \n "
" 456 \n "
" #endif \n " ;
2015-10-09 12:27:39 +02:00
const std : : string actualA0 = preprocessor0 . getcode ( filedata , " A=0 " , " test.c " ) ;
2013-06-19 21:29:39 +02:00
ASSERT_EQUALS ( true , actualA0 . find ( " 123 " ) ! = std : : string : : npos ) ;
ASSERT_EQUALS ( false , actualA0 . find ( " 456 " ) ! = std : : string : : npos ) ;
2015-10-09 12:27:39 +02:00
const std : : string actualA1 = preprocessor0 . getcode ( filedata , " A=1 " , " test.c " ) ;
2013-06-19 21:29:39 +02:00
ASSERT_EQUALS ( false , actualA1 . find ( " 123 " ) ! = std : : string : : npos ) ;
ASSERT_EQUALS ( true , actualA1 . find ( " 456 " ) ! = std : : string : : npos ) ;
}
2014-11-20 14:20:09 +01:00
void define_ifdef ( ) {
2009-07-25 13:58:34 +02:00
{
const char filedata [ ] = " #define ABC \n "
" #ifndef ABC \n "
" A \n "
" #else \n "
" B \n "
" #endif \n " ;
2009-07-22 18:47:50 +02:00
2009-07-25 13:58:34 +02:00
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2009-07-22 18:47:50 +02:00
2009-07-25 13:58:34 +02:00
// Compare results..
2011-01-01 09:16:31 +01:00
ASSERT_EQUALS ( 1 , ( int ) actual . size ( ) ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n \n \n B " , actual [ " " ] ) ;
2009-07-25 13:58:34 +02:00
}
{
const char filedata [ ] = " #define A 1 \n "
" #ifdef A \n "
" A \n "
" #endif \n " ;
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2009-07-25 13:58:34 +02:00
// Compare results..
2011-01-01 09:16:31 +01:00
ASSERT_EQUALS ( 1 , ( int ) actual . size ( ) ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n $1 " , actual [ " " ] ) ;
2009-07-25 13:58:34 +02:00
}
{
const char filedata [ ] = " #define A 1 \n "
" #if A==1 \n "
" A \n "
" #endif \n " ;
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2009-07-25 13:58:34 +02:00
// Compare results..
2011-01-01 09:16:31 +01:00
ASSERT_EQUALS ( 1 , ( int ) actual . size ( ) ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n $1 " , actual [ " " ] ) ;
2009-07-25 13:58:34 +02:00
}
2009-08-31 20:36:25 +02:00
{
const char filedata [ ] = " #define A 1 \n "
2013-06-19 21:29:39 +02:00
" #if A>0 \n "
2009-08-31 20:36:25 +02:00
" A \n "
" #endif \n " ;
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2009-08-31 20:36:25 +02:00
// Compare results..
2011-01-01 09:16:31 +01:00
ASSERT_EQUALS ( 1 , ( int ) actual . size ( ) ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n $1 " , actual [ " " ] ) ;
2009-08-31 20:36:25 +02:00
}
2011-02-11 18:51:22 +01:00
{
const char filedata [ ] = " #define A 1 \n "
" #if 0 \n "
" #undef A \n "
" #endif \n "
" A \n " ;
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2011-02-11 18:51:22 +01:00
// Compare results..
ASSERT_EQUALS ( 1 , ( int ) actual . size ( ) ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n \n \n $1 " , actual [ " " ] ) ;
2011-02-11 18:51:22 +01:00
}
2009-07-22 18:47:50 +02:00
}
2009-10-10 22:23:48 +02:00
2014-11-20 14:20:09 +01:00
void define_ifndef1 ( ) {
2010-07-25 15:19:25 +02:00
const char filedata [ ] = " #define A(x) (x) \n "
" #ifndef A \n "
" ; \n "
" #endif \n " ;
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2010-07-25 15:19:25 +02:00
// Compare results..
2012-05-04 17:53:47 +02:00
ASSERT_EQUALS ( 1U , actual . size ( ) ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " " , actual [ " " ] ) ;
2010-07-25 15:19:25 +02:00
}
2014-11-20 14:20:09 +01:00
void define_ifndef2 ( ) {
2010-09-14 17:45:37 +02:00
const char filedata [ ] = " #ifdef A \n "
" #define B char \n "
" #endif \n "
" #ifndef B \n "
" #define B int \n "
" #endif \n "
" B me; \n " ;
// Preprocess => actual result..
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n \n \n \n \n $int me ; " , preprocessor0 . getcode ( filedata , " " , " a.cpp " ) ) ;
ASSERT_EQUALS ( " \n \n \n \n \n \n $char me ; " , preprocessor0 . getcode ( filedata , " A " , " a.cpp " ) ) ;
2010-09-14 17:45:37 +02:00
}
2014-11-20 14:20:09 +01:00
void ifndef_define ( ) {
2012-05-04 17:53:47 +02:00
const char filedata [ ] = " #ifndef A \n "
" #define A(x) x \n "
" #endif \n "
" A(123); " ;
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2012-05-04 17:53:47 +02:00
ASSERT_EQUALS ( 1U , actual . size ( ) ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n \n 123 ; " , actual [ " " ] ) ;
2012-05-04 17:53:47 +02:00
}
2014-11-20 14:20:09 +01:00
void undef_ifdef ( ) {
2012-01-24 07:43:26 +01:00
const char filedata [ ] = " #undef A \n "
" #ifdef A \n "
" 123 \n "
" #endif \n " ;
// Preprocess => actual result..
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " " , preprocessor0 . getcode ( filedata , " " , " a.cpp " ) ) ;
ASSERT_EQUALS ( " " , preprocessor0 . getcode ( filedata , " A " , " a.cpp " ) ) ;
2012-01-24 07:43:26 +01:00
}
2014-11-20 14:20:09 +01:00
void redundant_config ( ) {
2010-04-15 18:37:51 +02:00
const char filedata [ ] = " int main() { \n "
" #ifdef FOO \n "
" #ifdef BAR \n "
" std::cout << 1; \n "
" #endif \n "
" #endif \n "
" \n "
" #ifdef BAR \n "
" #ifdef FOO \n "
" std::cout << 2; \n "
" #endif \n "
" #endif \n "
" } \n " ;
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2010-04-15 18:37:51 +02:00
// Compare results..
2011-01-01 09:16:31 +01:00
ASSERT_EQUALS ( 4 , ( int ) actual . size ( ) ) ;
2010-04-15 18:37:51 +02:00
ASSERT ( actual . find ( " " ) ! = actual . end ( ) ) ;
ASSERT ( actual . find ( " BAR " ) ! = actual . end ( ) ) ;
ASSERT ( actual . find ( " FOO " ) ! = actual . end ( ) ) ;
ASSERT ( actual . find ( " BAR;FOO " ) ! = actual . end ( ) ) ;
}
2014-11-20 14:20:09 +01:00
void endfile ( ) {
2009-10-10 22:23:48 +02:00
const char filedata [ ] = " char a[] = \" #endfile \" ; \n "
" char b[] = \" #endfile \" ; \n "
" #include \" notfound.h \" \n " ;
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2009-10-10 22:23:48 +02:00
// Compare results..
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " char a [ ] = \" #endfile \" ; \n char b [ ] = \" #endfile \" ; " , actual [ " " ] ) ;
2011-01-01 09:16:31 +01:00
ASSERT_EQUALS ( 1 , ( int ) actual . size ( ) ) ;
2009-10-10 22:23:48 +02:00
}
2011-01-30 09:09:12 +01:00
2014-11-20 14:20:09 +01:00
void dup_defines ( ) {
2011-01-30 09:09:12 +01:00
const char filedata [ ] = " #ifdef A \n "
" #define B \n "
" #if defined(B) && defined(A) \n "
" a \n "
" #else \n "
" b \n "
" #endif \n "
" #endif \n " ;
// Preprocess => actual result..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2011-01-30 09:09:12 +01:00
// B will always be defined if A is defined; the following test
2011-01-30 12:54:19 +01:00
// cases should be fixed whenever this other bug is fixed
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( 2U , actual . size ( ) ) ;
2011-01-30 09:09:12 +01:00
2020-03-27 17:11:38 +01:00
ASSERT_EQUALS_MSG ( true , ( actual . find ( " A " ) ! = actual . end ( ) ) , " A is expected to be checked but it was not checked " ) ;
2011-01-30 12:54:19 +01:00
2020-03-27 17:11:38 +01:00
ASSERT_EQUALS_MSG ( true , ( actual . find ( " A;A;B " ) = = actual . end ( ) ) , " A;A;B is expected to NOT be checked but it was checked " ) ;
2011-01-30 09:09:12 +01:00
}
2011-02-11 06:30:42 +01:00
2014-11-20 14:20:09 +01:00
void invalid_define_1 ( ) {
2015-10-09 12:27:39 +02:00
std : : map < std : : string , std : : string > actual ;
preprocess ( " #define = \n " , actual ) ; // don't hang
2012-08-25 13:24:17 +02:00
}
2015-10-09 12:27:39 +02:00
void invalid_define_2 ( ) { // #4036
std : : map < std : : string , std : : string > actual ;
preprocess ( " #define () {(int f(x) } \n " , actual ) ; // don't hang
2011-02-22 19:55:02 +01:00
}
2011-04-22 20:25:17 +02:00
2022-07-09 23:21:11 +02:00
void inline_suppression_for_missing_include_internal ( bool checkConfig ) {
2012-05-16 11:59:45 +02:00
Preprocessor : : missingIncludeFlag = false ;
2022-07-09 23:21:11 +02:00
Preprocessor : : missingSystemIncludeFlag = false ;
2011-04-22 20:25:17 +02:00
Settings settings ;
2022-07-09 23:21:11 +02:00
settings . checkConfiguration = checkConfig ;
2016-01-03 16:18:17 +01:00
settings . inlineSuppressions = true ;
2022-07-09 23:21:11 +02:00
settings . severity . clear ( ) ;
// --check-config needs to report this regardless of the emanled checks
if ( ! checkConfig )
settings . checks . enable ( Checks : : missingInclude ) ;
2015-07-24 13:30:41 +02:00
Preprocessor preprocessor ( settings , this ) ;
2011-04-22 20:25:17 +02:00
2022-07-09 23:21:11 +02:00
const std : : string code ( " // cppcheck-suppress missingInclude \n "
2011-04-22 20:25:17 +02:00
" #include \" missing.h \" \n "
2022-07-09 23:21:11 +02:00
" // cppcheck-suppress missingIncludeSystem \n "
" #include <missing2.h> \n " ) ;
2011-04-22 20:25:17 +02:00
// Don't report that the include is missing
errout . str ( " " ) ;
2022-07-09 23:21:11 +02:00
preprocessor . getcode ( code , " " , " test.c " ) ;
2011-04-22 20:25:17 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
2012-05-16 11:59:45 +02:00
ASSERT_EQUALS ( false , Preprocessor : : missingIncludeFlag ) ;
2022-07-09 23:21:11 +02:00
ASSERT_EQUALS ( false , Preprocessor : : missingSystemIncludeFlag ) ;
auto suppressions = settings . nomsg . getSuppressions ( ) ;
ASSERT_EQUALS ( 2 , suppressions . size ( ) ) ;
auto suppr = suppressions . front ( ) ;
suppressions . pop_front ( ) ;
ASSERT_EQUALS ( " missingInclude " , suppr . errorId ) ;
ASSERT_EQUALS ( " test.c " , suppr . fileName ) ;
ASSERT_EQUALS ( 2 , suppr . lineNumber ) ;
ASSERT_EQUALS ( true , suppr . checked ) ;
ASSERT_EQUALS ( true , suppr . matched ) ;
suppr = suppressions . front ( ) ;
suppressions . pop_front ( ) ;
ASSERT_EQUALS ( " missingIncludeSystem " , suppr . errorId ) ;
ASSERT_EQUALS ( " test.c " , suppr . fileName ) ;
ASSERT_EQUALS ( 4 , suppr . lineNumber ) ;
ASSERT_EQUALS ( true , suppr . checked ) ;
ASSERT_EQUALS ( true , suppr . matched ) ;
}
void inline_suppression_for_missing_include ( ) {
inline_suppression_for_missing_include_internal ( false ) ;
}
void inline_suppression_for_missing_include_check_config ( ) {
inline_suppression_for_missing_include_internal ( true ) ;
2011-04-22 20:25:17 +02:00
}
2011-07-16 09:24:27 +02:00
2014-11-20 14:20:09 +01:00
void predefine1 ( ) {
2013-06-19 21:29:39 +02:00
const std : : string src ( " #if defined X || Y \n "
2011-07-16 09:24:27 +02:00
" Fred & Wilma \n "
" #endif \n " ) ;
2015-10-09 12:27:39 +02:00
std : : string actual = preprocessor0 . getcode ( src , " X=1 " , " test.c " ) ;
2011-07-16 09:24:27 +02:00
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n Fred & Wilma " , actual ) ;
2011-07-16 09:24:27 +02:00
}
2014-11-20 14:20:09 +01:00
void predefine2 ( ) {
2013-06-19 21:29:39 +02:00
const std : : string src ( " #if defined(X) && Y \n "
2011-07-16 09:24:27 +02:00
" Fred & Wilma \n "
" #endif \n " ) ;
{
2015-10-09 12:27:39 +02:00
std : : string actual = preprocessor0 . getcode ( src , " X=1 " , " test.c " ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " " , actual ) ;
2011-07-16 09:24:27 +02:00
}
{
2015-10-09 12:27:39 +02:00
std : : string actual = preprocessor0 . getcode ( src , " X=1;Y=2 " , " test.c " ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n Fred & Wilma " , actual ) ;
2012-01-02 12:10:53 +01:00
}
}
2014-11-20 14:20:09 +01:00
void predefine3 ( ) {
2012-01-02 12:10:53 +01:00
// #2871 - define in source is not used if -D is used
const char code [ ] = " #define X 1 \n "
" #define Y X \n "
" #if (X == Y) \n "
" Fred & Wilma \n "
" #endif \n " ;
2015-10-09 12:27:39 +02:00
const std : : string actual = preprocessor0 . getcode ( code , " TEST " , " test.c " ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n \n \n Fred & Wilma " , actual ) ;
2012-01-02 12:10:53 +01:00
}
2014-11-20 14:20:09 +01:00
void predefine4 ( ) {
2012-02-05 20:48:28 +01:00
// #3577
const char code [ ] = " char buf[X]; \n " ;
2015-10-09 12:27:39 +02:00
const std : : string actual = preprocessor0 . getcode ( code , " X=123 " , " test.c " ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " char buf [ $123 ] ; " , actual ) ;
2012-02-05 20:48:28 +01:00
}
2014-11-20 14:20:09 +01:00
void predefine5 ( ) { // #3737, #5119 - automatically define __cplusplus
2013-11-15 19:21:21 +01:00
// #3737...
2012-05-08 20:49:43 +02:00
const char code [ ] = " #ifdef __cplusplus \n 123 \n #endif " ;
2022-04-15 16:17:36 +02:00
ASSERT_EQUALS ( " " , preprocessor0 . getcode ( code , " " , " test.c " ) ) ;
ASSERT_EQUALS ( " \n 123 " , preprocessor0 . getcode ( code , " " , " test.cpp " ) ) ;
}
void predefine6 ( ) { // automatically define __STDC_VERSION__
const char code [ ] = " #ifdef __STDC_VERSION__ \n 123 \n #endif " ;
ASSERT_EQUALS ( " \n 123 " , preprocessor0 . getcode ( code , " " , " test.c " ) ) ;
ASSERT_EQUALS ( " " , preprocessor0 . getcode ( code , " " , " test.cpp " ) ) ;
2012-01-02 12:10:53 +01:00
}
2014-11-20 14:20:09 +01:00
void invalidElIf ( ) {
2012-01-02 12:10:53 +01:00
// #2942 - segfault
const char code [ ] = " #elif (){ \n " ;
2015-10-09 12:27:39 +02:00
const std : : string actual = preprocessor0 . getcode ( code , " TEST " , " test.c " ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " " , actual ) ;
2012-01-21 12:51:54 +01:00
}
2016-08-21 08:06:20 +02:00
void getConfigs1 ( ) {
const char filedata [ ] = " #ifdef WIN32 \n "
" abcdef \n "
" #else \n "
" qwerty \n "
" #endif \n " ;
ASSERT_EQUALS ( " \n WIN32 \n " , getConfigsStr ( filedata ) ) ;
}
void getConfigs2 ( ) {
const char filedata [ ] = " # ifndef WIN32 \n "
" \" # ifdef WIN32 \" // a comment \n "
" # else \n "
" qwerty \n "
" # endif \n " ;
ASSERT_EQUALS ( " \n WIN32 \n " , getConfigsStr ( filedata ) ) ;
}
void getConfigs3 ( ) {
const char filedata [ ] = " #ifdef ABC \n "
" a \n "
" #ifdef DEF \n "
" b \n "
" #endif \n "
" c \n "
" #endif \n " ;
ASSERT_EQUALS ( " \n ABC \n ABC;DEF \n " , getConfigsStr ( filedata ) ) ;
}
void getConfigs4 ( ) {
const char filedata [ ] = " #ifdef ABC \n "
" A \n "
" #endif \t \n "
" #ifdef ABC \n "
" A \n "
" #endif \n " ;
ASSERT_EQUALS ( " \n ABC \n " , getConfigsStr ( filedata ) ) ;
}
void getConfigs5 ( ) {
const char filedata [ ] = " #ifdef ABC \n "
" A \n "
" #else \n "
" B \n "
" #ifdef DEF \n "
" C \n "
" #endif \n "
" #endif \n " ;
ASSERT_EQUALS ( " \n ABC \n DEF \n " , getConfigsStr ( filedata ) ) ;
}
void getConfigs7 ( ) {
const char filedata [ ] = " #ifdef ABC \n "
" A \n "
" #ifdef ABC \n "
" B \n "
" #endif \n "
" #endif \n " ;
ASSERT_EQUALS ( " \n ABC \n " , getConfigsStr ( filedata ) ) ;
}
void getConfigs7a ( ) {
const char filedata [ ] = " #ifndef ABC \n "
" A \n "
" #ifndef ABC \n "
" B \n "
" #endif \n "
" #endif \n " ;
ASSERT_EQUALS ( " \n " , getConfigsStr ( filedata ) ) ;
}
void getConfigs7b ( ) {
const char filedata [ ] = " #ifndef ABC \n "
" A \n "
" #ifdef ABC \n "
" B \n "
" #endif \n "
" #endif \n " ;
ASSERT_EQUALS ( " \n ABC \n " , getConfigsStr ( filedata ) ) ;
}
void getConfigs7c ( ) {
const char filedata [ ] = " #ifdef ABC \n "
" A \n "
" #ifndef ABC \n "
" B \n "
" #endif \n "
" #endif \n " ;
ASSERT_EQUALS ( " \n ABC \n " , getConfigsStr ( filedata ) ) ;
}
void getConfigs7d ( ) {
const char filedata [ ] = " #if defined(ABC) \n "
" A \n "
" #if defined(ABC) \n "
" B \n "
" #endif \n "
" #endif \n " ;
ASSERT_EQUALS ( " \n ABC \n " , getConfigsStr ( filedata ) ) ;
}
void getConfigs7e ( ) {
const char filedata [ ] = " #ifdef ABC \n "
" #file \" test.h \" \n "
" #ifndef test_h \n "
" #define test_h \n "
" #ifdef ABC \n "
" #endif \n "
" #endif \n "
" #endfile \n "
" #endif \n " ;
ASSERT_EQUALS ( " \n ABC \n " , getConfigsStr ( filedata ) ) ;
}
void getConfigs8 ( ) {
const char filedata [ ] = " #if A == 1 \n "
" 1 \n "
" #endif \n " ;
ASSERT_EQUALS ( " \n A=1 \n " , getConfigsStr ( filedata ) ) ;
}
void getConfigs10 ( ) { // Ticket #5139
const char filedata [ ] = " #define foo a.foo \n "
" #define bar foo \n "
" #define baz bar+0 \n "
" #if 0 \n "
" #endif " ;
ASSERT_EQUALS ( " \n " , getConfigsStr ( filedata ) ) ;
2021-03-12 18:16:09 +01:00
}
void getConfigs11 ( ) { // #9832 - include guards
const char filedata [ ] = " #file \" test.h \" \n "
" #if !defined(test_h) \n "
" #define test_h \n "
" 123 \n "
" #endif \n "
" #endfile \n " ;
ASSERT_EQUALS ( " \n " , getConfigsStr ( filedata ) ) ;
2016-08-21 08:06:20 +02:00
}
2016-12-03 11:59:48 +01:00
void getConfigsError ( ) {
const char filedata1 [ ] = " #ifndef X \n "
" #error \" !X \" \n "
" #endif \n " ;
2017-04-02 12:15:53 +02:00
ASSERT_EQUALS ( " X \n " , getConfigsStr ( filedata1 ) ) ;
2016-12-03 11:59:48 +01:00
const char filedata2 [ ] = " #ifdef X \n "
" #ifndef Y \n "
" #error \" !Y \" \n "
" #endif \n "
" #endif \n " ;
2021-02-06 12:48:52 +01:00
ASSERT_EQUALS ( " \n X;Y \n Y \n " , getConfigsStr ( filedata2 ) ) ;
2016-12-03 11:59:48 +01:00
}
2016-08-21 13:53:44 +02:00
void getConfigsD1 ( ) {
const char filedata [ ] = " #ifdef X \n "
" #else \n "
" #ifdef Y \n "
" #endif \n "
" #endif \n " ;
ASSERT_EQUALS ( " \n " , getConfigsStr ( filedata , " -DX " ) ) ;
ASSERT_EQUALS ( " \n X \n Y \n " , getConfigsStr ( filedata ) ) ;
}
2016-08-21 08:06:20 +02:00
void getConfigsU1 ( ) {
2012-01-02 12:10:53 +01:00
const char filedata [ ] = " #ifdef X \n "
" #endif \n " ;
2016-08-21 13:53:44 +02:00
ASSERT_EQUALS ( " \n " , getConfigsStr ( filedata , " -UX " ) ) ;
2016-07-28 19:22:59 +02:00
ASSERT_EQUALS ( " \n X \n " , getConfigsStr ( filedata ) ) ;
2012-01-02 12:10:53 +01:00
}
2016-08-21 08:06:20 +02:00
void getConfigsU2 ( ) {
2012-01-02 12:10:53 +01:00
const char filedata [ ] = " #ifndef X \n "
" #endif \n " ;
2016-08-21 13:53:44 +02:00
ASSERT_EQUALS ( " \n " , getConfigsStr ( filedata , " -UX " ) ) ;
2016-07-28 19:22:59 +02:00
ASSERT_EQUALS ( " \n " , getConfigsStr ( filedata ) ) ; // no #else
2012-01-02 12:10:53 +01:00
}
2016-08-21 08:06:20 +02:00
void getConfigsU3 ( ) {
2016-07-28 19:22:59 +02:00
const char filedata [ ] = " #ifndef X \n "
2012-01-02 12:10:53 +01:00
" Fred & Wilma \n "
" #else \n "
" Barney & Betty \n "
" #endif \n " ;
2016-08-21 13:53:44 +02:00
ASSERT_EQUALS ( " \n " , getConfigsStr ( filedata , " -UX " ) ) ;
2016-07-28 19:22:59 +02:00
ASSERT_EQUALS ( " \n X \n " , getConfigsStr ( filedata ) ) ;
2016-07-07 23:45:42 +02:00
}
2016-08-21 08:06:20 +02:00
void getConfigsU4 ( ) {
2016-08-21 07:45:15 +02:00
const char filedata [ ] = " #if defined(X) || defined(Y) || defined(Z) \n "
" #else \n "
" #endif \n " ;
2016-08-21 15:01:04 +02:00
ASSERT_EQUALS ( " \n Y;Z \n " , getConfigsStr ( filedata , " -UX " ) ) ;
2016-08-21 07:45:15 +02:00
ASSERT_EQUALS ( " \n X;Y;Z \n " , getConfigsStr ( filedata ) ) ;
}
2016-08-21 08:06:20 +02:00
void getConfigsU5 ( ) {
2016-08-21 07:45:15 +02:00
const char filedata [ ] = " #if X==1 \n "
" #endif \n " ;
2016-08-21 13:53:44 +02:00
ASSERT_EQUALS ( " \n " , getConfigsStr ( filedata , " -UX " ) ) ;
2016-08-21 07:45:15 +02:00
ASSERT_EQUALS ( " \n X=1 \n " , getConfigsStr ( filedata ) ) ;
}
2016-08-21 08:06:20 +02:00
void getConfigsU6 ( ) {
2016-08-21 07:45:15 +02:00
const char filedata [ ] = " #if X==0 \n "
" #endif \n " ;
2016-08-21 13:53:44 +02:00
ASSERT_EQUALS ( " \n X=0 \n " , getConfigsStr ( filedata , " -UX " ) ) ;
2016-08-21 07:45:15 +02:00
ASSERT_EQUALS ( " \n X=0 \n " , getConfigsStr ( filedata ) ) ;
}
2016-10-11 18:46:46 +02:00
void getConfigsU7 ( ) {
const char code [ ] = " #ifndef Y \n "
" #else \n "
" #endif \n " ;
ASSERT_EQUALS ( " \n Y \n " , getConfigsStr ( code , " -DX " ) ) ;
}
2018-09-26 12:17:14 +02:00
void validateCfg1 ( ) {
2016-12-06 22:11:40 +01:00
Preprocessor preprocessor ( settings0 , this ) ;
2012-07-10 20:29:04 +02:00
2016-12-06 22:11:40 +01:00
std : : vector < std : : string > files ( 1 , " test.c " ) ;
2018-09-26 12:17:14 +02:00
simplecpp : : MacroUsage macroUsage ( files , false ) ;
2016-08-01 20:09:41 +02:00
macroUsage . useLocation . fileIndex = 0 ;
macroUsage . useLocation . line = 1 ;
macroUsage . macroName = " X " ;
2018-04-09 09:41:24 +02:00
std : : list < simplecpp : : MacroUsage > macroUsageList ( 1 , macroUsage ) ;
2016-08-01 20:09:41 +02:00
ASSERT_EQUALS ( true , preprocessor . validateCfg ( " " , macroUsageList ) ) ;
ASSERT_EQUALS ( false , preprocessor . validateCfg ( " X " , macroUsageList ) ) ;
ASSERT_EQUALS ( false , preprocessor . validateCfg ( " A=42;X " , macroUsageList ) ) ;
ASSERT_EQUALS ( true , preprocessor . validateCfg ( " X=1 " , macroUsageList ) ) ;
ASSERT_EQUALS ( true , preprocessor . validateCfg ( " Y " , macroUsageList ) ) ;
2018-09-26 12:17:14 +02:00
macroUsageList . front ( ) . macroValueKnown = true ; // #8404
ASSERT_EQUALS ( true , preprocessor . validateCfg ( " X " , macroUsageList ) ) ;
}
void validateCfg2 ( ) {
const char filedata [ ] = " #ifdef ABC \n "
" #endif \n "
" int i = ABC; " ;
std : : map < std : : string , std : : string > actual ;
preprocess ( filedata , actual , " file.cpp " ) ;
ASSERT_EQUALS ( " [file.cpp:3]: (information) Skipping configuration 'ABC' since the value of 'ABC' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly. \n " , errout . str ( ) ) ;
2012-07-10 20:29:04 +02:00
}
2014-11-20 14:20:09 +01:00
void if_sizeof ( ) { // #4071
2012-08-25 11:45:18 +02:00
static const char * code = " #if sizeof(unsigned short) == 2 \n "
2012-08-22 17:28:06 +02:00
" Fred & Wilma \n "
2012-08-25 11:45:18 +02:00
" #elif sizeof(unsigned short) == 4 \n "
2012-08-22 17:28:06 +02:00
" Fred & Wilma \n "
" #else \n "
" #endif " ;
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( code , actual ) ;
2016-07-20 12:21:00 +02:00
ASSERT_EQUALS ( " \n Fred & Wilma " , actual [ " " ] ) ;
2014-04-23 20:50:16 +02:00
}
2014-06-08 10:02:16 +02:00
2014-11-20 14:20:09 +01:00
void invalid_ifs ( ) {
2014-06-08 10:02:16 +02:00
const char filedata [ ] = " #ifdef \n "
" #endif \n "
" #ifdef ! \n "
" #endif \n "
" #if defined \n "
" #endif \n "
" #define f(x) x \n "
" #if f(2 \n "
" #endif \n "
" int x; \n " ;
// Preprocess => don't crash..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2015-05-12 14:00:43 +02:00
}
void garbage ( ) {
const char filedata [ ] = " V \n "
" #define X b #endif #line 0 \" x \" ; \n "
" #if ! defined ( Y ) #endif " ;
2014-06-08 10:02:16 +02:00
2015-05-12 14:00:43 +02:00
// Preprocess => don't crash..
std : : map < std : : string , std : : string > actual ;
2015-10-09 12:27:39 +02:00
preprocess ( filedata , actual ) ;
2014-06-08 10:02:16 +02:00
}
2015-11-30 19:27:15 +01:00
void wrongPathOnErrorDirective ( ) {
errout . str ( " " ) ;
Settings settings ;
settings . userDefines = " foo " ;
Preprocessor preprocessor ( settings , this ) ;
const std : : string code ( " #error hello world! \n " ) ;
preprocessor . getcode ( code , " X " , " ./././test.c " ) ;
ASSERT_EQUALS ( " [test.c:1]: (error) #error hello world! \n " , errout . str ( ) ) ;
}
2015-12-07 19:54:41 +01:00
void testDirectiveIncludeTypes ( ) {
const char filedata [ ] = " #define macro some definition \n "
" #undef macro \n "
" #ifdef macro \n "
" #elif some (complex) condition \n "
" #else \n "
" #endif \n "
" #if some other condition \n "
" #pragma some proprietary content \n "
" # \n " /* may appear in old C code */
" #ident some text \n " /* may appear in old C code */
" #unknownmacro some unpredictable text \n "
" #warning some warning message \n "
" #error some error message \n " ;
const char dumpdata [ ] = " <directivelist> \n "
" <directive file= \" test.c \" linenr= \" 1 \" str= \" #define macro some definition \" /> \n "
" <directive file= \" test.c \" linenr= \" 2 \" str= \" #undef macro \" /> \n "
" <directive file= \" test.c \" linenr= \" 3 \" str= \" #ifdef macro \" /> \n "
" <directive file= \" test.c \" linenr= \" 4 \" str= \" #elif some (complex) condition \" /> \n "
" <directive file= \" test.c \" linenr= \" 5 \" str= \" #else \" /> \n "
" <directive file= \" test.c \" linenr= \" 6 \" str= \" #endif \" /> \n "
" <directive file= \" test.c \" linenr= \" 7 \" str= \" #if some other condition \" /> \n "
" <directive file= \" test.c \" linenr= \" 8 \" str= \" #pragma some proprietary content \" /> \n "
" <directive file= \" test.c \" linenr= \" 9 \" str= \" # \" /> \n "
" <directive file= \" test.c \" linenr= \" 10 \" str= \" #ident some text \" /> \n "
" <directive file= \" test.c \" linenr= \" 11 \" str= \" #unknownmacro some unpredictable text \" /> \n "
" <directive file= \" test.c \" linenr= \" 12 \" str= \" #warning some warning message \" /> \n "
" <directive file= \" test.c \" linenr= \" 13 \" str= \" #error some error message \" /> \n "
" </directivelist> \n " ;
std : : ostringstream ostr ;
2016-12-06 22:11:40 +01:00
Preprocessor preprocessor ( settings0 , this ) ;
2015-12-07 19:54:41 +01:00
preprocessor . getcode ( filedata , " " , " test.c " ) ;
preprocessor . dump ( ostr ) ;
ASSERT_EQUALS ( dumpdata , ostr . str ( ) ) ;
}
void testDirectiveIncludeLocations ( ) {
const char filedata [ ] = " #define macro1 val \n "
" #file \" inc1.h \" \n "
" #define macro2 val \n "
" #file \" inc2.h \" \n "
" #define macro3 val \n "
" #endfile \n "
" #define macro4 val \n "
" #endfile \n "
" #define macro5 val \n " ;
const char dumpdata [ ] = " <directivelist> \n "
" <directive file= \" test.c \" linenr= \" 1 \" str= \" #define macro1 val \" /> \n "
" <directive file= \" test.c \" linenr= \" 2 \" str= \" #include "inc1.h" \" /> \n "
" <directive file= \" inc1.h \" linenr= \" 1 \" str= \" #define macro2 val \" /> \n "
" <directive file= \" inc1.h \" linenr= \" 2 \" str= \" #include "inc2.h" \" /> \n "
" <directive file= \" inc2.h \" linenr= \" 1 \" str= \" #define macro3 val \" /> \n "
" <directive file= \" inc1.h \" linenr= \" 3 \" str= \" #define macro4 val \" /> \n "
" <directive file= \" test.c \" linenr= \" 3 \" str= \" #define macro5 val \" /> \n "
" </directivelist> \n " ;
std : : ostringstream ostr ;
2016-12-06 22:11:40 +01:00
Preprocessor preprocessor ( settings0 , this ) ;
2015-12-07 19:54:41 +01:00
preprocessor . getcode ( filedata , " " , " test.c " ) ;
preprocessor . dump ( ostr ) ;
ASSERT_EQUALS ( dumpdata , ostr . str ( ) ) ;
}
void testDirectiveIncludeComments ( ) {
const char filedata [ ] = " #ifdef macro2 /* this will be removed */ \n "
" #else /* this will be removed too */ \n "
" #endif /* this will also be removed */ \n " ;
const char dumpdata [ ] = " <directivelist> \n "
" <directive file= \" test.c \" linenr= \" 1 \" str= \" #ifdef macro2 \" /> \n "
" <directive file= \" test.c \" linenr= \" 2 \" str= \" #else \" /> \n "
" <directive file= \" test.c \" linenr= \" 3 \" str= \" #endif \" /> \n "
" </directivelist> \n " ;
std : : ostringstream ostr ;
2016-12-06 22:11:40 +01:00
Preprocessor preprocessor ( settings0 , this ) ;
2015-12-07 19:54:41 +01:00
preprocessor . getcode ( filedata , " " , " test.c " ) ;
preprocessor . dump ( ostr ) ;
ASSERT_EQUALS ( dumpdata , ostr . str ( ) ) ;
}
2022-07-09 23:21:11 +02:00
void testMissingInclude ( ) {
Preprocessor : : missingIncludeFlag = false ;
Preprocessor : : missingSystemIncludeFlag = false ;
Settings settings ;
settings . severity . clear ( ) ;
settings . checks . enable ( Checks : : missingInclude ) ;
Preprocessor preprocessor ( settings , this ) ;
ScopedFile header ( " header.h " , " " ) ;
ScopedFile header2 ( " header2.h " , " " ) ;
std : : string code ( " #include \" missing.h \" \n "
" #include <header.h> \n "
" #include <missing2.h> \n "
" #include \" header2.h \" " ) ;
errout . str ( " " ) ;
preprocessor . getcode ( code , " " , " test.c " ) ;
ASSERT_EQUALS ( true , Preprocessor : : missingIncludeFlag ) ;
ASSERT_EQUALS ( true , Preprocessor : : missingSystemIncludeFlag ) ;
// the expected messages are emited outside of the Preprocessor
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
Preprocessor : : missingIncludeFlag = false ;
Preprocessor : : missingSystemIncludeFlag = false ;
}
void testMissingIncludeCheckConfig ( ) {
Preprocessor : : missingIncludeFlag = false ;
Preprocessor : : missingSystemIncludeFlag = false ;
Settings settings ;
settings . checkConfiguration = true ;
settings . severity . clear ( ) ;
// needs to be reported regardless of enabled checks
Preprocessor preprocessor ( settings , this ) ;
ScopedFile header ( " header.h " , " " ) ;
ScopedFile header2 ( " header2.h " , " " ) ;
std : : string code ( " #include \" missing.h \" \n "
" #include <header.h> \n "
" #include <missing2.h> \n "
" #include \" header2.h \" " ) ;
errout . str ( " " ) ;
preprocessor . getcode ( code , " " , " test.c " ) ;
ASSERT_EQUALS ( true , Preprocessor : : missingIncludeFlag ) ;
ASSERT_EQUALS ( true , Preprocessor : : missingSystemIncludeFlag ) ;
ASSERT_EQUALS ( " [test.c:1]: (information) Include file: \" missing.h \" not found. \n "
" [test.c:3]: (information) Include file: <missing2.h> not found. Please note: Cppcheck does not need standard library headers to get proper results. \n " , errout . str ( ) ) ;
Preprocessor : : missingIncludeFlag = false ;
Preprocessor : : missingSystemIncludeFlag = false ;
}
2012-01-02 12:10:53 +01:00
} ;
REGISTER_TEST ( TestPreprocessor )