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
* Copyright ( C ) 2007 - 2009 Daniel Marjamäki , Reijo Tomperi , Nicolas Le Cam ,
2009-03-01 20:52:33 +01:00
* Leandro Penz , Kimmo Varis , Vesa Pikki
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
* along with this program . If not , see < http : //www.gnu.org/licenses/
*/
// The preprocessor that c++check uses is a bit special. Instead of generating
// the code for a known configuration, it generates the code for each configuration.
# include "testsuite.h"
2009-01-06 15:18:36 +01:00
# include "../src/preprocessor.h"
2009-03-08 08:45:53 +01:00
# include "../src/tokenize.h"
2008-12-18 22:28:57 +01:00
# include <map>
# include <string>
2009-04-27 21:29:03 +02:00
# include <sstream>
# include <stdexcept>
2008-12-18 22:28:57 +01:00
2009-04-03 21:09:12 +02:00
extern std : : ostringstream errout ;
2008-12-18 22:28:57 +01:00
class TestPreprocessor : public TestFixture
{
public :
TestPreprocessor ( ) : TestFixture ( " TestPreprocessor " )
{ }
2009-02-07 21:06:00 +01:00
class OurPreprocessor : public Preprocessor
{
public :
static std : : string replaceIfDefined ( const std : : string & str )
{
return Preprocessor : : replaceIfDefined ( str ) ;
}
2009-04-03 21:09:12 +02:00
static std : : string expandMacros ( std : : string code , ErrorLogger * errorLogger = 0 )
2009-02-07 21:06:00 +01:00
{
2009-04-03 21:09:12 +02:00
return Preprocessor : : expandMacros ( code , " file.cpp " , errorLogger ) ;
2009-02-07 21:06:00 +01:00
}
2009-05-22 22:59:07 +02:00
2009-05-22 23:18:48 +02:00
static int getHeaderFileName ( std : : string & str )
2009-05-22 22:59:07 +02:00
{
return Preprocessor : : getHeaderFileName ( str ) ;
}
2009-02-07 21:06:00 +01:00
} ;
2008-12-18 22:28:57 +01:00
private :
void run ( )
{
// Just read the code into a string. Perform simple cleanup of the code
TEST_CASE ( readCode ) ;
// 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
2009-01-05 16:49:57 +01:00
TEST_CASE ( test1 ) ;
TEST_CASE ( test2 ) ;
TEST_CASE ( test3 ) ;
TEST_CASE ( test4 ) ;
TEST_CASE ( test5 ) ;
2009-01-24 20:28:30 +01:00
TEST_CASE ( test6 ) ;
2008-12-18 22:28:57 +01:00
2009-01-22 19:19:17 +01:00
// Handling include guards (don't create extra configuration for it)
TEST_CASE ( includeguard ) ;
2009-01-12 07:43:56 +01:00
TEST_CASE ( newlines ) ;
2009-01-12 07:33:06 +01:00
2009-01-05 16:49:57 +01:00
TEST_CASE ( comments1 ) ;
2008-12-18 22:28:57 +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 ) ;
2008-12-18 22:28:57 +01:00
2009-01-11 08:19:28 +01:00
TEST_CASE ( multiline1 ) ;
TEST_CASE ( multiline2 ) ;
2009-01-11 09:16:15 +01:00
TEST_CASE ( multiline3 ) ;
2009-05-11 20:12:29 +02:00
TEST_CASE ( multiline4 ) ;
2009-01-02 19:27:50 +01:00
2009-01-05 16:49:57 +01:00
TEST_CASE ( if_defined ) ; // "#if defined(AAA)" => "#ifdef AAA"
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-01-06 09:49:54 +01:00
TEST_CASE ( macro_mismatch ) ;
2009-03-09 20:29:25 +01:00
TEST_CASE ( macro_linenumbers ) ;
2009-01-18 17:58:57 +01:00
TEST_CASE ( string1 ) ;
TEST_CASE ( string2 ) ;
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 ) ;
2009-02-13 14:31:40 +01:00
TEST_CASE ( fmt1 ) ;
2009-02-13 14:34:24 +01:00
TEST_CASE ( fmt2 ) ;
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-03-08 08:45:53 +01:00
TEST_CASE ( ifdefwithfile ) ;
2009-03-15 13:23:12 +01:00
TEST_CASE ( pragma ) ;
2009-03-18 00:10:26 +01:00
TEST_CASE ( endifsemicolon ) ;
2009-04-03 21:09:12 +02:00
TEST_CASE ( missing_doublequote ) ;
2009-04-27 21:29:03 +02:00
TEST_CASE ( unicode1 ) ;
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-12 23:01:53 +02:00
TEST_CASE ( multiline_comment ) ;
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-05-22 22:59:07 +02:00
TEST_CASE ( includes ) ;
2008-12-18 22:28:57 +01:00
}
void readCode ( )
{
const char code [ ] = " \t a // \n "
" #aa \t /* remove this */ \t b \r \n " ;
Preprocessor p ;
std : : istringstream istr ( code ) ;
2009-01-05 16:49:57 +01:00
std : : string codestr ( p . read ( istr ) ) ;
ASSERT_EQUALS ( " a \n #aa b \n " , codestr ) ;
2008-12-18 22:28:57 +01:00
}
void Bug2190219 ( )
{
const char filedata [ ] = " int main() \n "
" { \n "
" #ifdef __cplusplus \n "
" int* flags = new int[10]; \n "
" #else \n "
" int* flags = (int*)malloc((10)*sizeof(int)); \n "
" #endif \n "
" \n "
" #ifdef __cplusplus \n "
" delete [] flags; \n "
" #else \n "
" free(flags); \n "
" #endif \n "
" } \n " ;
// Expected result..
std : : map < std : : string , std : : string > expected ;
expected [ " " ] = " int main() \n "
" { \n "
" \n "
" \n "
" \n "
" int* flags = (int*)malloc((10)*sizeof(int)); \n "
" \n "
" \n "
" \n "
" \n "
" \n "
" free(flags); \n "
" \n "
" } \n " ;
expected [ " __cplusplus " ] = " int main() \n "
2009-01-05 16:49:57 +01:00
" { \n "
" \n "
" int* flags = new int[10]; \n "
" \n "
" \n "
" \n "
" \n "
" \n "
" delete [] flags; \n "
" \n "
" \n "
" \n "
" } \n " ;
2008-12-18 22:28:57 +01:00
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
2009-01-21 22:03:46 +01:00
preprocessor . preprocess ( istr , actual , " file.c " ) ;
2008-12-18 22:28:57 +01:00
// Compare results..
2009-01-06 10:43:26 +01:00
ASSERT_EQUALS ( expected [ " " ] , actual [ " " ] ) ;
ASSERT_EQUALS ( expected [ " __cplusplus " ] , actual [ " __cplusplus " ] ) ;
2009-02-07 21:55:25 +01:00
ASSERT_EQUALS ( 2 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
2008-12-18 22:28:57 +01:00
}
void test1 ( )
{
const char filedata [ ] = " #ifdef WIN32 \n "
" abcdef \n "
" #else \n "
" qwerty \n "
" #endif \n " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
2009-01-21 22:03:46 +01:00
preprocessor . preprocess ( istr , actual , " file.c " ) ;
2008-12-18 22:28:57 +01:00
// Compare results..
2009-01-06 10:43:26 +01:00
ASSERT_EQUALS ( " \n \n \n qwerty \n \n " , actual [ " " ] ) ;
ASSERT_EQUALS ( " \n abcdef \n \n \n \n " , actual [ " WIN32 " ] ) ;
2009-02-07 21:55:25 +01:00
ASSERT_EQUALS ( 2 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
2008-12-18 22:28:57 +01:00
}
void test2 ( )
{
const char filedata [ ] = " # ifndef WIN32 \n "
" \" # ifdef WIN32 \" // a comment \n "
" # else \n "
" qwerty \n "
" # endif \n " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
2009-01-21 22:03:46 +01:00
preprocessor . preprocess ( istr , actual , " file.c " ) ;
2008-12-18 22:28:57 +01:00
// Compare results..
2009-05-13 21:18:02 +02:00
ASSERT_EQUALS ( " \n \" #ifdef WIN32 \" \n \n \n \n " , actual [ " " ] ) ;
2009-01-06 10:43:26 +01:00
ASSERT_EQUALS ( " \n \n \n qwerty \n \n " , actual [ " WIN32 " ] ) ;
2009-02-07 21:55:25 +01:00
ASSERT_EQUALS ( 2 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
2008-12-18 22:28:57 +01:00
}
void test3 ( )
{
const char filedata [ ] = " #ifdef ABC \n "
" a \n "
" #ifdef DEF \n "
" b \n "
" #endif \n "
" c \n "
" #endif \n " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
2009-01-21 22:03:46 +01:00
preprocessor . preprocess ( istr , actual , " file.c " ) ;
2008-12-18 22:28:57 +01:00
// Compare results..
2009-01-06 10:43:26 +01:00
ASSERT_EQUALS ( " \n \n \n \n \n \n \n " , actual [ " " ] ) ;
ASSERT_EQUALS ( " \n a \n \n \n \n c \n \n " , actual [ " ABC " ] ) ;
ASSERT_EQUALS ( " \n a \n \n b \n \n c \n \n " , actual [ " ABC;DEF " ] ) ;
2009-02-07 21:55:25 +01:00
ASSERT_EQUALS ( 3 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
2008-12-18 22:28:57 +01:00
}
void test4 ( )
{
const char filedata [ ] = " #ifdef ABC \n "
" A \n "
" #endif \t \n "
" #ifdef ABC \n "
" A \n "
" #endif \n " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
2009-01-21 22:03:46 +01:00
preprocessor . preprocess ( istr , actual , " file.c " ) ;
2008-12-18 22:28:57 +01:00
// Compare results..
2009-01-06 10:43:26 +01:00
ASSERT_EQUALS ( " \n \n \n \n \n \n " , actual [ " " ] ) ;
ASSERT_EQUALS ( " \n A \n \n \n A \n \n " , actual [ " ABC " ] ) ;
2009-02-07 21:55:25 +01:00
ASSERT_EQUALS ( 2 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
2008-12-18 22:28:57 +01:00
}
void test5 ( )
{
const char filedata [ ] = " #ifdef ABC \n "
" A \n "
" #else \n "
" B \n "
" #ifdef DEF \n "
" C \n "
" #endif \n "
" #endif \n " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
2009-01-21 22:03:46 +01:00
preprocessor . preprocess ( istr , actual , " file.c " ) ;
2008-12-18 22:28:57 +01:00
// Compare results..
2009-01-06 10:43:26 +01:00
ASSERT_EQUALS ( " \n \n \n B \n \n \n \n \n " , actual [ " " ] ) ;
ASSERT_EQUALS ( " \n A \n \n \n \n \n \n \n " , actual [ " ABC " ] ) ;
ASSERT_EQUALS ( " \n \n \n B \n \n C \n \n \n " , actual [ " DEF " ] ) ;
2009-02-07 21:55:25 +01:00
ASSERT_EQUALS ( 3 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
2008-12-18 22:28:57 +01:00
}
2009-01-24 20:28:30 +01:00
void test6 ( )
{
const char filedata [ ] = " #if(AAA) \n "
" #if(AAA) \n " ;
std : : istringstream istr ( filedata ) ;
const std : : string actual ( Preprocessor : : read ( istr ) ) ;
// Compare results..
ASSERT_EQUALS ( " #if (AAA) \n #if (AAA) \n " , actual ) ;
}
2008-12-18 22:28:57 +01:00
2009-01-22 19:19:17 +01:00
void includeguard ( )
{
// Handling include guards..
const char filedata [ ] = " #file \" abc.h \" \n "
" #ifndef abcH \n "
" #define abcH \n "
" #endif \n "
" #endfile \n "
" #ifdef ABC \n "
" #endif " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
preprocessor . preprocess ( istr , actual , " file.c " ) ;
// Expected configurations: "" and "ABC"
2009-02-07 21:55:25 +01:00
ASSERT_EQUALS ( 2 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
2009-01-22 19:19:17 +01:00
}
2009-03-08 08:45:53 +01:00
void ifdefwithfile ( )
{
// 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 : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
preprocessor . preprocess ( istr , actual , " file.c " ) ;
Tokenizer tok ;
2009-03-08 08:49:04 +01:00
std : : istringstream codeStream ( actual [ " " ] ) ;
tok . tokenize ( codeStream , " main.cpp " ) ;
2009-03-08 08:45:53 +01:00
2009-03-08 08:49:04 +01:00
ASSERT_EQUALS ( " \n \n ##file 0 \n 1: \n 2: \n 3: \n 4: int main ( ) { } \n " , tok . tokens ( ) - > stringifyList ( ) ) ;
2009-03-08 08:45:53 +01:00
// Expected configurations: "" and "ABC"
ASSERT_EQUALS ( 2 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
ASSERT_EQUALS ( " \n #file \" abc.h \" \n \n \n \n \n \n \n \n \n #endfile \n \n int main() {} \n " , actual [ " " ] ) ;
ASSERT_EQUALS ( " \n #file \" abc.h \" \n class A{}; \n \n \n \n \n \n \n \n #endfile \n \n int main() {} \n " , actual [ " ABC " ] ) ;
}
2008-12-18 22:28:57 +01:00
2009-01-12 07:33:06 +01:00
void newlines ( )
{
const char filedata [ ] = " \r \r \n \n " ;
// Preprocess
std : : istringstream istr ( filedata ) ;
Preprocessor preprocessor ;
ASSERT_EQUALS ( " \n \n \n " , preprocessor . read ( istr ) ) ;
}
2008-12-18 22:28:57 +01:00
void comments1 ( )
{
2009-05-13 21:18:02 +02:00
{
const char filedata [ ] = " /* \n "
" #ifdef WIN32 \n "
" #endif \n "
" */ \n " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
preprocessor . preprocess ( istr , actual , " file.c " ) ;
// Compare results..
ASSERT_EQUALS ( " \n \n \n \n " , actual [ " " ] ) ;
ASSERT_EQUALS ( 1 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
}
2008-12-18 22:28:57 +01:00
2009-05-13 21:18:02 +02:00
{
const char filedata [ ] = " /* \n "
" \x080 #ifdef WIN32 \n "
" #endif \n "
" */ \n " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
preprocessor . preprocess ( istr , actual , " file.c " ) ;
// Compare results..
ASSERT_EQUALS ( " \n \n \n \n " , actual [ " " ] ) ;
ASSERT_EQUALS ( 1 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
}
2009-05-14 21:53:49 +02:00
{
const char filedata [ ] = " void f() \n "
" { \n "
" *p = a / *b / *c; \n "
" } \n " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
preprocessor . preprocess ( istr , actual , " file.c " ) ;
// Compare results..
ASSERT_EQUALS ( " void f() \n { \n *p = a / *b / *c; \n } \n " , actual [ " " ] ) ;
ASSERT_EQUALS ( 1 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
}
2008-12-18 22:28:57 +01:00
}
void if0 ( )
{
const char filedata [ ] = " # if /* comment */ 0 // comment \n "
" #ifdef WIN32 \n "
" #endif \n "
" #endif \n " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
2009-01-21 22:03:46 +01:00
preprocessor . preprocess ( istr , actual , " file.c " ) ;
2008-12-18 22:28:57 +01:00
// Compare results..
2009-01-06 10:43:26 +01:00
ASSERT_EQUALS ( " \n \n \n \n " , actual [ " " ] ) ;
2009-02-07 21:55:25 +01:00
ASSERT_EQUALS ( 1 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
2008-12-18 22:28:57 +01:00
}
void if1 ( )
{
const char filedata [ ] = " # if /* comment */ 1 // comment \n "
" ABC \n "
" # endif \n " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
2009-01-21 22:03:46 +01:00
preprocessor . preprocess ( istr , actual , " file.c " ) ;
2008-12-18 22:28:57 +01:00
// Compare results..
2009-01-06 10:43:26 +01:00
ASSERT_EQUALS ( " \n ABC \n \n " , actual [ " " ] ) ;
2009-02-07 21:55:25 +01:00
ASSERT_EQUALS ( 1 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
2008-12-18 22:28:57 +01:00
}
void elif ( )
{
const char filedata [ ] = " #if DEF1 \n "
" ABC \n "
" #elif DEF2 \n "
" DEF \n "
" #endif \n " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
2009-01-21 22:03:46 +01:00
preprocessor . preprocess ( istr , actual , " file.c " ) ;
2008-12-18 22:28:57 +01:00
// Compare results..
2009-01-06 10:43:26 +01:00
ASSERT_EQUALS ( " \n \n \n \n \n " , actual [ " " ] ) ;
ASSERT_EQUALS ( " \n ABC \n \n \n \n " , actual [ " DEF1 " ] ) ;
ASSERT_EQUALS ( " \n \n \n DEF \n \n " , actual [ " DEF2 " ] ) ;
2009-02-07 21:55:25 +01:00
ASSERT_EQUALS ( 3 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
2008-12-18 22:28:57 +01:00
}
void if_cond1 ( )
{
const char filedata [ ] = " #if LIBVER>100 \n "
" A \n "
" #else \n "
" B \n "
" #endif \n " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
2009-01-21 22:03:46 +01:00
preprocessor . preprocess ( istr , actual , " file.c " ) ;
2008-12-18 22:28:57 +01:00
// Compare results..
2009-01-06 10:43:26 +01:00
ASSERT_EQUALS ( " \n \n \n B \n \n " , actual [ " " ] ) ;
ASSERT_EQUALS ( " \n A \n \n \n \n " , actual [ " LIBVER>100 " ] ) ;
2009-02-07 21:55:25 +01:00
ASSERT_EQUALS ( 2 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
2008-12-18 22:28:57 +01:00
}
2009-01-11 08:19:28 +01:00
void multiline1 ( )
2008-12-18 22:28:57 +01:00
{
2009-01-11 08:19:28 +01:00
const char filedata [ ] = " #define str \" abc \" \\ \n "
2009-01-06 10:43:26 +01:00
" \" def \" \n "
" abcdef = str; \n " ;
2008-12-18 22:28:57 +01:00
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
Preprocessor preprocessor ;
2009-05-14 21:53:49 +02:00
ASSERT_EQUALS ( " #define str \" abc \" \" def \" \n \n abcdef = str; \n " , preprocessor . read ( istr ) ) ;
2009-01-11 08:19:28 +01:00
}
2008-12-18 22:28:57 +01:00
2009-01-11 08:19:28 +01:00
void multiline2 ( )
{
const char filedata [ ] = " #define sqr(aa) aa * \\ \n "
" aa \n "
" sqr(5); \n " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
Preprocessor preprocessor ;
2009-05-14 21:53:49 +02:00
ASSERT_EQUALS ( " #define sqr(aa) aa * aa \n \n sqr(5); \n " , preprocessor . read ( istr ) ) ;
2008-12-18 22:28:57 +01:00
}
2009-01-11 09:16:15 +01:00
void multiline3 ( )
{
const char filedata [ ] = " const char *str = \" abc \\ \n "
" def \\ \n "
" ghi \" \n " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
Preprocessor preprocessor ;
ASSERT_EQUALS ( " const char *str = \" abcdefghi \" \n \n \n " , preprocessor . read ( istr ) ) ;
}
2009-05-11 20:12:29 +02:00
void multiline4 ( )
{
errout . str ( " " ) ;
const char filedata [ ] = " #define A int a = 4; \\ \n "
" int b = 5; \n "
" A \n " ;
2009-01-11 09:16:15 +01:00
2009-05-11 20:12:29 +02:00
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
preprocessor . preprocess ( istr , actual , " file.c " ) ;
// Compare results..
ASSERT_EQUALS ( 1 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
ASSERT_EQUALS ( " \n \n int a = 4; int b = 5; \n " , actual [ " " ] ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-01-02 19:27:50 +01:00
void if_defined ( )
{
const char filedata [ ] = " #if defined(AAA) \n "
" #endif \n " ;
2009-01-11 08:19:28 +01:00
2009-01-02 19:27:50 +01:00
// Expected result..
2009-01-05 16:49:57 +01:00
std : : string expected ( " #ifdef AAA \n #endif \n " ) ;
2009-01-02 19:27:50 +01:00
// Compare result..
2009-02-07 21:06:00 +01:00
ASSERT_EQUALS ( expected , OurPreprocessor : : replaceIfDefined ( filedata ) ) ;
2009-01-02 19:27:50 +01:00
}
2009-01-18 11:54:07 +01:00
2009-01-06 09:49:54 +01:00
void macro_simple1 ( )
2009-01-05 10:26:00 +01:00
{
2009-01-05 21:41:34 +01:00
const char filedata [ ] = " #define AAA(aa) f(aa) \n "
" AAA(5); \n " ;
2009-02-07 21:06:00 +01:00
ASSERT_EQUALS ( " \n f(5); \n " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-05 21:41:34 +01:00
}
2009-01-06 09:49:54 +01:00
void macro_simple2 ( )
2009-01-05 21:41:34 +01:00
{
const char filedata [ ] = " #define min(x,y) x<y?x:y \n "
" min(a(),b()); \n " ;
2009-02-07 21:06:00 +01:00
ASSERT_EQUALS ( " \n a()<b()?a():b(); \n " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-05 21:41:34 +01:00
}
2009-01-11 16:07:13 +01:00
void macro_simple3 ( )
{
const char filedata [ ] = " #define A 4 \n "
" A AA \n " ;
2009-02-07 21:06:00 +01:00
ASSERT_EQUALS ( " \n 4 AA \n " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-11 16:07:13 +01:00
}
2009-01-11 16:51:46 +01:00
void macro_simple4 ( )
{
const char filedata [ ] = " #define TEMP_1 if( temp > 0 ) return 1; \n "
" TEMP_1 \n " ;
2009-02-07 21:06:00 +01:00
ASSERT_EQUALS ( " \n if( temp > 0 ) return 1; \n " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-11 16:51:46 +01:00
}
2009-01-11 17:06:37 +01:00
void macro_simple5 ( )
{
const char filedata [ ] = " #define ABC if( temp > 0 ) return 1; \n "
" \n "
" void foo() \n "
" { \n "
" int temp = 0; \n "
" ABC \n "
" } \n " ;
2009-02-07 21:06:00 +01:00
ASSERT_EQUALS ( " \n \n void foo() \n { \n int temp = 0; \n if( temp > 0 ) return 1; \n } \n " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-11 17:06:37 +01:00
}
2009-01-18 17:56:12 +01:00
void macro_simple6 ( )
{
const char filedata [ ] = " #define ABC (a+b+c) \n "
" ABC " ;
2009-02-07 21:06:00 +01:00
ASSERT_EQUALS ( " \n (a+b+c) " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-18 17:56:12 +01:00
}
2009-01-21 18:11:24 +01:00
void macro_simple7 ( )
{
const char filedata [ ] = " #define ABC(str) str \n "
" ABC( \" ( \" ) " ;
2009-02-07 21:06:00 +01:00
ASSERT_EQUALS ( " \n \" ( \" " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-23 18:14:42 +01:00
}
void macro_simple8 ( )
{
const char filedata [ ] = " #define ABC 123 \n "
" #define ABCD 1234 \n "
" ABC ABCD " ;
2009-02-07 21:06:00 +01:00
ASSERT_EQUALS ( " \n \n 123 1234 " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-21 18:11:24 +01:00
}
2009-01-06 09:49:54 +01:00
void macro_mismatch ( )
2009-01-05 21:41:34 +01:00
{
const char filedata [ ] = " #define AAA(aa,bb) f(aa) \n "
" AAA(5); \n " ;
2009-02-07 21:06:00 +01:00
ASSERT_EQUALS ( " \n AAA(5); \n " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-05 10:26:00 +01:00
}
2009-03-08 21:28:12 +01:00
void macro_linenumbers ( )
{
const char filedata [ ] = " #define AAA(a) \n "
" AAA(5 \n "
" \n "
" ) \n "
" int a; \n " ;
2009-03-10 23:49:16 +01:00
ASSERT_EQUALS ( " \n "
" \n "
" \n "
" \n "
" int a; \n " ,
OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-03-08 21:28:12 +01:00
}
2009-01-18 17:58:57 +01:00
void string1 ( )
2009-01-08 23:28:54 +01:00
{
const char filedata [ ] = " int main() "
" { "
" const char *a = \" #define A \n \" ; "
" } " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
2009-01-21 22:03:46 +01:00
preprocessor . preprocess ( istr , actual , " file.c " ) ;
2009-01-05 10:26:00 +01:00
2009-01-08 23:28:54 +01:00
// Compare results..
2009-02-07 21:55:25 +01:00
ASSERT_EQUALS ( 1 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
2009-01-08 23:28:54 +01:00
ASSERT_EQUALS ( " int main(){ const char *a = \" #define A \n \" ;} \n " , actual [ " " ] ) ;
}
2009-01-12 19:23:53 +01:00
2009-01-18 17:58:57 +01:00
void string2 ( )
{
const char filedata [ ] = " #define AAA 123 \n "
" str = \" AAA \" " ;
// Compare results..
2009-02-07 21:06:00 +01:00
ASSERT_EQUALS ( " \n str = \" AAA \" " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-18 17:58:57 +01:00
}
2009-01-12 19:23:53 +01:00
void preprocessor_undef ( )
{
const char filedata [ ] = " #define AAA int a; \n "
" #undef AAA \n "
" #define AAA char b=0; \n "
" AAA \n " ;
// Compare results..
2009-02-07 21:06:00 +01:00
ASSERT_EQUALS ( " \n \n \n char b=0; \n " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-12 19:23:53 +01:00
}
2009-01-19 20:24:41 +01:00
2009-01-22 21:19:07 +01:00
void defdef ( )
{
const char filedata [ ] = " #define AAA 123 \n "
" #define AAA 456 \n "
" #define AAA 789 \n "
" AAA \n " ;
// Compare results..
2009-02-07 21:06:00 +01:00
ASSERT_EQUALS ( " \n \n \n 789 \n " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-22 21:19:07 +01:00
}
2009-01-19 22:45:59 +01:00
void preprocessor_doublesharp ( )
{
const char filedata [ ] = " #define TEST(var,val) var = val \n "
" TEST(foo,20); \n " ;
// Compare results..
2009-02-07 21:06:00 +01:00
ASSERT_EQUALS ( " \n foo=20; \n " , OurPreprocessor : : expandMacros ( filedata ) ) ;
2009-01-19 22:45:59 +01:00
const char filedata2 [ ] = " #define TEST(var,val) var##_##val = val \n "
" TEST(foo,20); \n " ;
// Compare results..
2009-02-07 21:06:00 +01:00
ASSERT_EQUALS ( " \n foo_20=20; \n " , OurPreprocessor : : expandMacros ( filedata2 ) ) ;
2009-01-19 22:45:59 +01:00
}
2009-01-19 20:24:41 +01:00
void preprocessor_include_in_str ( )
{
const char filedata [ ] = " int main() \n "
" { \n "
" const char *a = \" #include <string> \n \" ; \n "
" return 0; \n "
" } \n " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
2009-01-21 22:03:46 +01:00
preprocessor . preprocess ( istr , actual , " file.c " ) ;
2009-01-19 20:24:41 +01:00
// Compare results..
2009-02-07 21:55:25 +01:00
ASSERT_EQUALS ( 1 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
2009-01-19 20:24:41 +01:00
ASSERT_EQUALS ( " int main() \n { \n const char *a = \" #include <string> \n \" ; \n return 0; \n } \n " , actual [ " " ] ) ;
}
2009-01-21 08:22:44 +01:00
2009-01-22 21:19:07 +01:00
2009-01-28 21:19:46 +01:00
void fmt1 ( )
2009-01-21 08:22:44 +01:00
{
2009-01-21 18:11:24 +01:00
const char filedata [ ] = " #define DBG(fmt...) printf(fmt) \n "
2009-01-21 08:22:44 +01:00
" DBG( \" [0x%lx-0x%lx) \" , pstart, pend); " ;
// Preprocess..
2009-02-07 21:06:00 +01:00
std : : string actual = OurPreprocessor : : expandMacros ( filedata ) ;
2009-01-21 18:11:24 +01:00
2009-03-16 22:20:55 +01:00
ASSERT_EQUALS ( " \n printf( \" [0x%lx-0x%lx) \" ,pstart,pend); " , actual ) ;
2009-01-21 08:22:44 +01:00
}
2009-01-28 21:19:46 +01:00
void fmt2 ( )
{
const char filedata [ ] = " #define DBG(fmt, args...) printf(fmt, ## args) \n "
" DBG( \" hello \" ); " ;
// Preprocess..
2009-02-07 21:06:00 +01:00
std : : string actual = OurPreprocessor : : expandMacros ( filedata ) ;
2009-01-28 21:19:46 +01:00
ASSERT_EQUALS ( " \n printf( \" hello \" ); " , actual ) ;
}
2009-01-21 20:12:28 +01:00
void multi_character_character ( )
{
const char filedata [ ] = " #define FOO 'ABCD' \n "
" int main() \n "
" { \n "
" if( FOO == 0 ); \n "
" return 0; \n "
" } \n " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
2009-01-21 22:03:46 +01:00
preprocessor . preprocess ( istr , actual , " file.c " ) ;
2009-01-21 20:12:28 +01:00
// Compare results..
2009-02-07 21:55:25 +01:00
ASSERT_EQUALS ( 1 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
2009-01-21 22:45:17 +01:00
ASSERT_EQUALS ( " \n int main() \n { \n if( 'ABCD' == 0 ); \n return 0; \n } \n " , actual [ " " ] ) ;
2009-01-21 20:12:28 +01:00
}
2009-01-22 21:19:07 +01:00
2009-01-25 14:30:15 +01:00
void stringify ( )
{
const char filedata [ ] = " #define STRINGIFY(x) #x \n "
" STRINGIFY(abc) " ;
// expand macros..
2009-02-07 21:06:00 +01:00
std : : string actual = OurPreprocessor : : expandMacros ( filedata ) ;
2009-01-25 14:30:15 +01:00
ASSERT_EQUALS ( " \n \" abc \" " , actual ) ;
}
2009-03-15 15:05:23 +01:00
void stringify2 ( )
{
const char filedata [ ] = " #define A(x) g(#x) \n "
" A(abc); " ;
// expand macros..
std : : string actual = OurPreprocessor : : expandMacros ( filedata ) ;
ASSERT_EQUALS ( " \n g( \" abc \" ); " , actual ) ;
}
2009-03-15 22:39:58 +01:00
void stringify3 ( )
{
const char filedata [ ] = " #define A(x) g(#x) \n "
" A( abc); " ;
// expand macros..
std : : string actual = OurPreprocessor : : expandMacros ( filedata ) ;
ASSERT_EQUALS ( " \n g( \" abc \" ); " , actual ) ;
}
2009-05-05 17:19:06 +02:00
void stringify4 ( )
{
const char filedata [ ] = " #define A(x) #x \n "
" 1 A( \n "
" abc \n "
" ) 2 " ;
// expand macros..
std : : string actual = OurPreprocessor : : expandMacros ( filedata ) ;
ASSERT_EQUALS ( " \n 1 \n \n \" abc \" 2 " , actual ) ;
}
2009-03-15 13:23:12 +01:00
void pragma ( )
{
const char filedata [ ] = " #pragma once \n "
" void f() \n "
" { \n "
" } \n " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
preprocessor . preprocess ( istr , actual , " file.c " ) ;
// Compare results..
ASSERT_EQUALS ( 1 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
ASSERT_EQUALS ( " \n void f() \n { \n } \n " , actual [ " " ] ) ;
}
2009-03-18 00:10:26 +01:00
void endifsemicolon ( )
{
const char filedata [ ] = " void f() \n "
" { \n "
" #ifdef A \n "
" #endif; \n "
" } \n " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
preprocessor . preprocess ( istr , actual , " file.c " ) ;
// Compare results..
ASSERT_EQUALS ( 2 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
ASSERT_EQUALS ( " void f() \n "
" { \n "
" \n "
" \n "
" } \n " , actual [ " " ] ) ;
}
2009-04-03 21:09:12 +02: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 ) ) ;
ASSERT_EQUALS ( " \n \n int a = 1; \n " , actual ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-04-03 21:09:12 +02:00
}
2009-04-27 21:29:03 +02:00
void unicode1 ( )
{
const char filedata [ ] = { ' a ' , ( char ) 200 , 0 } ;
std : : istringstream istr ( filedata ) ;
ASSERT_THROW ( Preprocessor : : read ( istr ) , std : : runtime_error ) ;
}
2009-05-09 21:32:29 +02:00
void define_part_of_func ( )
{
2009-05-11 20:12:29 +02:00
errout . str ( " " ) ;
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 : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
preprocessor . preprocess ( istr , actual , " file.c " ) ;
// Compare results..
ASSERT_EQUALS ( 1 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
ASSERT_EQUALS ( " \n void f() { \n g( ); \n } \n " , actual [ " " ] ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-05-13 21:38:57 +02:00
void conditionalDefine ( )
{
const char filedata [ ] = " #ifdef A \n "
" #define N 10 \n "
" #else \n "
" #define N 20 \n "
" #endif \n "
" N " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
preprocessor . preprocess ( istr , actual , " file.c " ) ;
// Compare results..
ASSERT_EQUALS ( 2 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
ASSERT_EQUALS ( " \n \n \n \n \n 20 \n " , actual [ " " ] ) ;
2009-05-17 18:51:29 +02:00
ASSERT_EQUALS ( " \n \n \n \n \n 10 \n " , actual [ " A " ] ) ;
2009-05-13 21:38:57 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-05-12 23:01:53 +02:00
void multiline_comment ( )
{
errout . str ( " " ) ;
const char filedata [ ] = " #define ABC {// \\ \n "
" } \n "
" void f() ABC } \n " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
preprocessor . preprocess ( istr , actual , " file.c " ) ;
// Compare results..
ASSERT_EQUALS ( 1 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
2009-05-13 21:18:02 +02:00
ASSERT_EQUALS ( " \n \n void f() { } \n " , actual [ " " ] ) ;
2009-05-12 23:01:53 +02:00
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-05-18 22:32:04 +02:00
void macro_parameters ( )
{
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 : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
preprocessor . preprocess ( istr , actual , " file.c " , std : : list < std : : string > ( ) , this ) ;
// Compare results..
ASSERT_EQUALS ( 1 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
ASSERT_EQUALS ( " " , actual [ " " ] ) ;
ASSERT_EQUALS ( " [file.c:6]: (error) Syntax error. Not enough parameters for macro 'BC'. \n " , errout . str ( ) ) ;
}
2009-05-12 23:01:53 +02:00
2009-05-20 20:36:59 +02:00
void newline_in_macro ( )
{
errout . str ( " " ) ;
const char filedata [ ] = " #define ABC(str) printf( str ) \n "
" void f() \n "
" { \n "
" ABC( \" \\ n \" ); \n "
" } \n " ;
// Preprocess => actual result..
std : : istringstream istr ( filedata ) ;
std : : map < std : : string , std : : string > actual ;
Preprocessor preprocessor ;
preprocessor . preprocess ( istr , actual , " file.c " , std : : list < std : : string > ( ) , this ) ;
// Compare results..
ASSERT_EQUALS ( 1 , static_cast < unsigned int > ( actual . size ( ) ) ) ;
ASSERT_EQUALS ( " \n void f() \n { \n printf( \" \\ n \" ); \n } \n " , actual [ " " ] ) ;
ASSERT_EQUALS ( " " , errout . str ( ) ) ;
}
2009-05-22 22:59:07 +02:00
void includes ( )
{
2009-05-22 23:18:48 +02:00
{
std : : string src = " #include a.h " ;
ASSERT_EQUALS ( 0 , OurPreprocessor : : getHeaderFileName ( src ) ) ;
ASSERT_EQUALS ( " " , src ) ;
}
{
std : : string src = " #include \" b.h \" " ;
ASSERT_EQUALS ( 1 , OurPreprocessor : : getHeaderFileName ( src ) ) ;
ASSERT_EQUALS ( " b.h " , src ) ;
}
{
std : : string src = " #include <c.h> " ;
ASSERT_EQUALS ( 2 , OurPreprocessor : : getHeaderFileName ( src ) ) ;
ASSERT_EQUALS ( " c.h " , src ) ;
}
2009-05-22 22:59:07 +02:00
}
2008-12-18 22:28:57 +01:00
} ;
2009-01-05 16:49:57 +01:00
REGISTER_TEST ( TestPreprocessor )