/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2021 Cppcheck team. * * 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 . */ #include "config.h" #include "platform.h" #include "preprocessor.h" // usually tests here should not use preprocessor... #include "settings.h" #include "standards.h" #include "testsuite.h" #include "token.h" #include "tokenize.h" #include "tokenlist.h" #include #include #include #include struct InternalError; class TestTokenizer : public TestFixture { public: TestTokenizer() : TestFixture("TestTokenizer") { } private: Settings settings0; Settings settings1; Settings settings2; Settings settings_windows; void run() OVERRIDE { LOAD_LIB_2(settings_windows.library, "windows.cfg"); // If there are unused templates, keep those settings0.checkUnusedTemplates = true; settings1.checkUnusedTemplates = true; settings2.checkUnusedTemplates = true; settings_windows.checkUnusedTemplates = true; TEST_CASE(tokenize1); TEST_CASE(tokenize2); TEST_CASE(tokenize4); TEST_CASE(tokenize5); TEST_CASE(tokenize7); TEST_CASE(tokenize8); TEST_CASE(tokenize9); TEST_CASE(tokenize11); TEST_CASE(tokenize13); // bailout if the code contains "@" - that is not handled well. TEST_CASE(tokenize14); // tokenize "0X10" => 16 TEST_CASE(tokenizeHexWithSuffix); // tokenize 0xFFFFFFul TEST_CASE(tokenize15); // tokenize ".123" TEST_CASE(tokenize17); // #2759 TEST_CASE(tokenize18); // tokenize "(X&&Y)" into "( X && Y )" instead of "( X & & Y )" TEST_CASE(tokenize19); // #3006 (segmentation fault) TEST_CASE(tokenize21); // tokenize 0x0E-7 TEST_CASE(tokenize22); // special marker $ from preprocessor TEST_CASE(tokenize25); // #4239 (segmentation fault) TEST_CASE(tokenize26); // #4245 (segmentation fault) TEST_CASE(tokenize27); // #4525 (segmentation fault) TEST_CASE(tokenize31); // #3503 (Wrong handling of member function taking function pointer as argument) TEST_CASE(tokenize32); // #5884 (fsanitize=undefined: left shift of negative value -10000 in lib/templatesimplifier.cpp:852:46) TEST_CASE(tokenize33); // #5780 Various crashes on valid template code TEST_CASE(tokenize34); // #8031 TEST_CASE(tokenize35); // #8361 TEST_CASE(tokenize36); // #8436 TEST_CASE(tokenize37); // #8550 TEST_CASE(tokenize38); // #9569 TEST_CASE(tokenize39); // #9771 TEST_CASE(validate); TEST_CASE(objectiveC); // Syntax error should be written for objective C/C++ code. TEST_CASE(syntax_case_default); TEST_CASE(removePragma); TEST_CASE(foreach); // #3690 TEST_CASE(ifconstexpr); TEST_CASE(combineOperators); TEST_CASE(concatenateNegativeNumber); TEST_CASE(longtok); TEST_CASE(simplifyHeadersAndUnusedTemplates1); TEST_CASE(simplifyHeadersAndUnusedTemplates2); TEST_CASE(simplifyAt); TEST_CASE(inlineasm); TEST_CASE(simplifyAsm2); // #4725 (writing asm() around "^{}") TEST_CASE(ifAddBraces1); TEST_CASE(ifAddBraces2); TEST_CASE(ifAddBraces3); TEST_CASE(ifAddBraces4); TEST_CASE(ifAddBraces5); TEST_CASE(ifAddBraces7); TEST_CASE(ifAddBraces9); TEST_CASE(ifAddBraces11); TEST_CASE(ifAddBraces12); TEST_CASE(ifAddBraces13); TEST_CASE(ifAddBraces15); // #2616 - unknown macro before if TEST_CASE(ifAddBraces16); TEST_CASE(ifAddBraces17); // '} else' should be in the same line TEST_CASE(ifAddBraces18); // #3424 - if if { } else else TEST_CASE(ifAddBraces19); // #3928 - if for if else TEST_CASE(ifAddBraces20); // #5012 - syntax error 'else }' TEST_CASE(ifAddBracesLabels); // #5332 - if (x) label: {} .. TEST_CASE(switchAddBracesLabels); TEST_CASE(whileAddBraces); TEST_CASE(whileAddBracesLabels); TEST_CASE(doWhileAddBraces); TEST_CASE(doWhileAddBracesLabels); TEST_CASE(forAddBraces1); TEST_CASE(forAddBraces2); // #5088 TEST_CASE(forAddBracesLabels); TEST_CASE(simplifyExternC); TEST_CASE(simplifyKeyword); // #5842 - remove C99 static keyword between [] TEST_CASE(isZeroNumber); TEST_CASE(isOneNumber); TEST_CASE(isTwoNumber); TEST_CASE(simplifyFunctionParameters); TEST_CASE(simplifyFunctionParameters1); // #3721 TEST_CASE(simplifyFunctionParameters2); // #4430 TEST_CASE(simplifyFunctionParameters3); // #4436 TEST_CASE(simplifyFunctionParameters4); // #9421 TEST_CASE(simplifyFunctionParametersMultiTemplate); TEST_CASE(simplifyFunctionParametersErrors); TEST_CASE(simplifyFunctionTryCatch); TEST_CASE(removeParentheses1); // Ticket #61 TEST_CASE(removeParentheses3); TEST_CASE(removeParentheses4); // Ticket #390 TEST_CASE(removeParentheses5); // Ticket #392 TEST_CASE(removeParentheses6); TEST_CASE(removeParentheses7); TEST_CASE(removeParentheses8); // Ticket #1865 TEST_CASE(removeParentheses9); // Ticket #1962 TEST_CASE(removeParentheses10); // Ticket #2320 TEST_CASE(removeParentheses11); // Ticket #2505 TEST_CASE(removeParentheses12); // Ticket #2760 ',(b)=' TEST_CASE(removeParentheses13); TEST_CASE(removeParentheses14); // Ticket #3309 TEST_CASE(removeParentheses15); // Ticket #4142 TEST_CASE(removeParentheses16); // Ticket #4423 '*(x.y)=' TEST_CASE(removeParentheses17); // Don't remove parentheses in 'a ? b : (c>0 ? d : e);' TEST_CASE(removeParentheses18); // 'float(*a)[2]' => 'float *a[2]' TEST_CASE(removeParentheses19); // ((typeof(x) *)0) TEST_CASE(removeParentheses20); // Ticket #5479: a>(2); TEST_CASE(removeParentheses21); // Don't "simplify" casts TEST_CASE(removeParentheses22); TEST_CASE(removeParentheses23); // Ticket #6103 - Infinite loop upon valid input TEST_CASE(removeParentheses24); // Ticket #7040 TEST_CASE(removeParentheses25); // daca@home - a=(b,c) TEST_CASE(removeParentheses26); // Ticket #8875 a[0](0) TEST_CASE(tokenize_double); TEST_CASE(tokenize_strings); TEST_CASE(simplifyMulAndParens); // Ticket #2784 + #3184 TEST_CASE(simplifyStructDecl); TEST_CASE(vardecl1); TEST_CASE(vardecl2); TEST_CASE(vardecl3); TEST_CASE(vardecl4); TEST_CASE(vardecl5); // #7048 TEST_CASE(vardec_static); TEST_CASE(vardecl6); TEST_CASE(vardecl7); TEST_CASE(vardecl8); TEST_CASE(vardecl9); TEST_CASE(vardecl10); TEST_CASE(vardecl11); TEST_CASE(vardecl12); TEST_CASE(vardecl13); TEST_CASE(vardecl14); TEST_CASE(vardecl15); TEST_CASE(vardecl16); TEST_CASE(vardecl17); TEST_CASE(vardecl18); TEST_CASE(vardecl19); TEST_CASE(vardecl20); // #3700 - register const int H = 0; TEST_CASE(vardecl21); // #4042 - a::b const *p = 0; TEST_CASE(vardecl22); // #4211 - segmentation fault TEST_CASE(vardecl23); // #4276 - segmentation fault TEST_CASE(vardecl24); // #4187 - variable declaration within lambda function TEST_CASE(vardecl25); // #4799 - segmentation fault TEST_CASE(vardecl26); // #5907 - incorrect handling of extern declarations TEST_CASE(vardecl27); // #7850 - crash on valid C code TEST_CASE(vardecl_stl_1); TEST_CASE(vardecl_stl_2); TEST_CASE(vardecl_template_1); TEST_CASE(vardecl_template_2); TEST_CASE(vardecl_union); TEST_CASE(vardecl_par); // #2743 - set links if variable type contains parentheses TEST_CASE(vardecl_par2); // #3912 - set correct links TEST_CASE(vardecl_par3); // #6556 - Fred x1(a), x2(b); TEST_CASE(vardecl_class_ref); TEST_CASE(volatile_variables); // unsigned i; => unsigned int i; TEST_CASE(unsigned1); TEST_CASE(unsigned2); TEST_CASE(unsigned3); // template arguments TEST_CASE(simplifyStdType); // #4947, #4950, #4951 TEST_CASE(createLinks); TEST_CASE(createLinks2); TEST_CASE(signed1); TEST_CASE(simplifyString); TEST_CASE(simplifyConst); TEST_CASE(switchCase); TEST_CASE(simplifyPointerToStandardType); TEST_CASE(simplifyFunctionPointers1); TEST_CASE(simplifyFunctionPointers2); TEST_CASE(simplifyFunctionPointers3); TEST_CASE(simplifyFunctionPointers4); TEST_CASE(simplifyFunctionPointers5); TEST_CASE(simplifyFunctionPointers6); TEST_CASE(simplifyFunctionPointers7); TEST_CASE(simplifyFunctionPointers8); // #7410 - throw TEST_CASE(simplifyFunctionPointers9); // #6113 - function call with function pointer TEST_CASE(removedeclspec); TEST_CASE(removeattribute); TEST_CASE(functionAttributeBefore); TEST_CASE(functionAttributeAfter); TEST_CASE(functionAttributeListBefore); TEST_CASE(functionAttributeListAfter); TEST_CASE(splitTemplateRightAngleBrackets); TEST_CASE(cpp03template1); TEST_CASE(cpp0xtemplate1); TEST_CASE(cpp0xtemplate2); TEST_CASE(cpp0xtemplate3); TEST_CASE(cpp0xtemplate4); // Ticket #6181: Mishandled C++11 syntax TEST_CASE(cpp0xtemplate5); // Ticket #9154 change >> to > > TEST_CASE(cpp14template); // Ticket #6708 TEST_CASE(arraySize); TEST_CASE(labels); TEST_CASE(simplifyInitVar); TEST_CASE(simplifyInitVar2); TEST_CASE(simplifyInitVar3); TEST_CASE(bitfields1); TEST_CASE(bitfields2); TEST_CASE(bitfields3); TEST_CASE(bitfields4); // ticket #1956 TEST_CASE(bitfields5); // ticket #1956 TEST_CASE(bitfields6); // ticket #2595 TEST_CASE(bitfields7); // ticket #1987 TEST_CASE(bitfields8); TEST_CASE(bitfields9); // ticket #2706 TEST_CASE(bitfields10); TEST_CASE(bitfields12); // ticket #3485 (segmentation fault) TEST_CASE(bitfields13); // ticket #3502 (segmentation fault) TEST_CASE(bitfields14); // ticket #4561 (segfault for 'class a { signals: };') TEST_CASE(bitfields15); // ticket #7747 (enum Foo {A,B}:4;) TEST_CASE(bitfields16); // Save bitfield bit count TEST_CASE(simplifyNamespaceStd); TEST_CASE(microsoftMemory); TEST_CASE(microsoftString); TEST_CASE(borland); TEST_CASE(simplifyQtSignalsSlots1); TEST_CASE(simplifyQtSignalsSlots2); TEST_CASE(simplifySQL); TEST_CASE(simplifyCAlternativeTokens); // x = ({ 123; }); => { x = 123; } TEST_CASE(simplifyRoundCurlyParentheses); TEST_CASE(simplifyOperatorName1); TEST_CASE(simplifyOperatorName2); TEST_CASE(simplifyOperatorName3); TEST_CASE(simplifyOperatorName4); TEST_CASE(simplifyOperatorName5); TEST_CASE(simplifyOperatorName6); // ticket #3194 TEST_CASE(simplifyOperatorName7); // ticket #4619 TEST_CASE(simplifyOperatorName8); // ticket #5706 TEST_CASE(simplifyOperatorName9); // ticket #5709 - comma operator not properly tokenized TEST_CASE(simplifyOperatorName10); // #8746 - using a::operator= TEST_CASE(simplifyOperatorName11); // #8889 TEST_CASE(simplifyOperatorName12); // #9110 TEST_CASE(simplifyOperatorName13); // user defined literal TEST_CASE(simplifyOperatorName14); // std::complex operator "" if TEST_CASE(simplifyOperatorName15); // ticket #9468 syntaxError TEST_CASE(simplifyOperatorName16); // ticket #9472 TEST_CASE(simplifyOperatorName17); TEST_CASE(simplifyOperatorName18); // global namespace TEST_CASE(simplifyOperatorName19); TEST_CASE(simplifyOperatorName20); TEST_CASE(simplifyOperatorName21); TEST_CASE(simplifyOperatorName22); TEST_CASE(simplifyOperatorName23); TEST_CASE(simplifyOperatorName24); TEST_CASE(simplifyOperatorName25); TEST_CASE(simplifyOperatorName26); TEST_CASE(simplifyOperatorName27); TEST_CASE(simplifyOperatorName28); TEST_CASE(simplifyOperatorName29); // spaceship operator TEST_CASE(simplifyOverloadedOperators1); TEST_CASE(simplifyOverloadedOperators2); // (*this)(123) TEST_CASE(simplifyOverloadedOperators3); // #9881 - hang TEST_CASE(simplifyNullArray); // Some simple cleanups of unhandled macros in the global scope TEST_CASE(removeMacrosInGlobalScope); TEST_CASE(removeMacroInVarDecl); TEST_CASE(addSemicolonAfterUnknownMacro); // a = b = 0; TEST_CASE(multipleAssignment); TEST_CASE(platformWin32A); TEST_CASE(platformWin32W); TEST_CASE(platformWin32AStringCat); // ticket #5015 TEST_CASE(platformWin32WStringCat); // ticket #5015 TEST_CASE(platformWinWithNamespace); TEST_CASE(simplifyStaticConst); TEST_CASE(simplifyCPPAttribute); TEST_CASE(simplifyCaseRange); TEST_CASE(simplifyEmptyNamespaces); TEST_CASE(compileLimits); // #5592 crash: gcc: testsuit: gcc.c-torture/compile/limits-declparen.c TEST_CASE(prepareTernaryOpForAST); // AST data TEST_CASE(astexpr); TEST_CASE(astexpr2); // limit large expressions TEST_CASE(astpar); TEST_CASE(astnewdelete); TEST_CASE(astbrackets); TEST_CASE(astunaryop); TEST_CASE(astfunction); TEST_CASE(asttemplate); TEST_CASE(astcast); TEST_CASE(astlambda); TEST_CASE(astcase); TEST_CASE(astrefqualifier); TEST_CASE(astvardecl); TEST_CASE(astnewscoped); TEST_CASE(startOfExecutableScope); TEST_CASE(removeMacroInClassDef); // #6058 TEST_CASE(sizeofAddParentheses); TEST_CASE(reportUnknownMacros); // Make sure the Tokenizer::findGarbageCode() does not have false positives // The TestGarbage ensures that there are true positives TEST_CASE(findGarbageCode); TEST_CASE(checkEnableIf); TEST_CASE(checkTemplates); TEST_CASE(checkNamespaces); TEST_CASE(checkLambdas); TEST_CASE(checkIfCppCast); TEST_CASE(checkRefQualifiers); TEST_CASE(checkConditionBlock); // #9052 TEST_CASE(noCrash1); TEST_CASE(noCrash2); TEST_CASE(noCrash3); // --check-config TEST_CASE(checkConfiguration); TEST_CASE(unknownType); // #8952 TEST_CASE(unknownMacroBeforeReturn); TEST_CASE(cppcast); TEST_CASE(checkHeader1); TEST_CASE(removeExtraTemplateKeywords); TEST_CASE(removeAlignas1); TEST_CASE(removeAlignas2); // Do not remove alignof in the same way TEST_CASE(simplifyCoroutines); TEST_CASE(simplifySpaceshipOperator); TEST_CASE(simplifyIfSwitchForInit1); TEST_CASE(simplifyIfSwitchForInit2); TEST_CASE(simplifyIfSwitchForInit3); TEST_CASE(simplifyIfSwitchForInit4); } std::string tokenizeAndStringify(const char code[], bool expand = true, Settings::PlatformType platform = Settings::Native, const char* filename = "test.cpp", bool cpp11 = true) { errout.str(""); settings1.debugwarnings = true; settings1.platform(platform); settings1.standards.cpp = cpp11 ? Standards::CPP11 : Standards::CPP03; // tokenize.. Tokenizer tokenizer(&settings1, this); std::istringstream istr(code); tokenizer.tokenize(istr, filename); // filter out ValueFlow messages.. const std::string debugwarnings = errout.str(); errout.str(""); std::istringstream istr2(debugwarnings); std::string line; while (std::getline(istr2,line)) { if (line.find("valueflow.cpp") == std::string::npos) errout << line << "\n"; } if (tokenizer.tokens()) return tokenizer.tokens()->stringifyList(false, expand, false, true, false, nullptr, nullptr); else return ""; } std::string tokenizeAndStringifyWindows(const char code[], bool expand = true, Settings::PlatformType platform = Settings::Native, const char* filename = "test.cpp", bool cpp11 = true) { errout.str(""); settings_windows.debugwarnings = true; settings_windows.platform(platform); settings_windows.standards.cpp = cpp11 ? Standards::CPP11 : Standards::CPP03; // tokenize.. Tokenizer tokenizer(&settings_windows, this); std::istringstream istr(code); tokenizer.tokenize(istr, filename); // filter out ValueFlow messages.. const std::string debugwarnings = errout.str(); errout.str(""); std::istringstream istr2(debugwarnings); std::string line; while (std::getline(istr2,line)) { if (line.find("valueflow.cpp") == std::string::npos) errout << line << "\n"; } if (tokenizer.tokens()) return tokenizer.tokens()->stringifyList(false, expand, false, true, false, nullptr, nullptr); else return ""; } std::string tokenizeAndStringify(const char code[], const Settings &settings, const char filename[] = "test.cpp") { errout.str(""); // tokenize.. Tokenizer tokenizer(&settings, this); std::istringstream istr(code); tokenizer.tokenize(istr, filename); if (!tokenizer.tokens()) return ""; return tokenizer.tokens()->stringifyList(false, true, false, true, false, nullptr, nullptr); } std::string tokenizeDebugListing(const char code[], const char filename[] = "test.cpp") { errout.str(""); settings2.standards.c = Standards::C89; settings2.standards.cpp = Standards::CPP03; Tokenizer tokenizer(&settings2, this); std::istringstream istr(code); tokenizer.tokenize(istr, filename); // result.. return tokenizer.tokens()->stringifyList(true,true,true,true,false); } void tokenize1() { const char code[] = "void f ( )\n" "{ if ( p . y ( ) > yof ) { } }"; ASSERT_EQUALS(code, tokenizeAndStringify(code)); } void tokenize2() { const char code[] = "{ sizeof a, sizeof b }"; ASSERT_EQUALS("{ sizeof ( a ) , sizeof ( b ) }", tokenizeAndStringify(code)); } void tokenize4() { const char code[] = "class foo\n" "{\n" "public:\n" " const int i;\n" "}"; ASSERT_EQUALS("class foo\n" "{\n" "public:\n" "const int i ;\n" "}", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } void tokenize5() { // Tokenize values ASSERT_EQUALS("; + 1E3 ;", tokenizeAndStringify("; +1E3 ;")); ASSERT_EQUALS("; 1E-2 ;", tokenizeAndStringify("; 1E-2 ;")); } void tokenize7() { const char code[] = "void f() {\n" " int x1 = 1;\n" " int x2(x1);\n" "}\n"; ASSERT_EQUALS("void f ( ) {\nint x1 ; x1 = 1 ;\nint x2 ; x2 = x1 ;\n}", tokenizeAndStringify(code)); } void tokenize8() { const char code[] = "void f() {\n" " int x1(g());\n" " int x2(x1);\n" "}\n"; ASSERT_EQUALS("1: void f ( ) {\n" "2: int x1@1 ; x1@1 = g ( ) ;\n" "3: int x2@2 ; x2@2 = x1@1 ;\n" "4: }\n", tokenizeDebugListing(code)); } void tokenize9() { const char code[] = "typedef void (*fp)();\n" "typedef fp (*fpp)();\n" "void f() {\n" " fpp x = (fpp)f();\n" "}"; tokenizeAndStringify(code); ASSERT_EQUALS("", errout.str()); } void tokenize11() { ASSERT_EQUALS("X * sizeof ( Y ( ) ) ;", tokenizeAndStringify("X * sizeof(Y());")); } // bailout if there is "@" - it is not handled well void tokenize13() { const char code[] = "@implementation\n" "-(Foo *)foo: (Bar *)bar\n" "{ }\n" "@end\n"; ASSERT_THROW(tokenizeAndStringify(code), InternalError); } // Ticket #2361: 0X10 => 16 void tokenize14() { ASSERT_EQUALS("; 0x10 ;", tokenizeAndStringify(";0x10;")); ASSERT_EQUALS("; 0X10 ;", tokenizeAndStringify(";0X10;")); ASSERT_EQUALS("; 0444 ;", tokenizeAndStringify(";0444;")); } // Ticket #8050 void tokenizeHexWithSuffix() { ASSERT_EQUALS("; 0xFFFFFF ;", tokenizeAndStringify(";0xFFFFFF;")); ASSERT_EQUALS("; 0xFFFFFFu ;", tokenizeAndStringify(";0xFFFFFFu;")); ASSERT_EQUALS("; 0xFFFFFFul ;", tokenizeAndStringify(";0xFFFFFFul;")); // Number of digits decides about internal representation... ASSERT_EQUALS("; 0xFFFFFFFF ;", tokenizeAndStringify(";0xFFFFFFFF;")); ASSERT_EQUALS("; 0xFFFFFFFFu ;", tokenizeAndStringify(";0xFFFFFFFFu;")); ASSERT_EQUALS("; 0xFFFFFFFFul ;", tokenizeAndStringify(";0xFFFFFFFFul;")); } // Ticket #2429: 0.125 void tokenize15() { ASSERT_EQUALS("0.125 ;", tokenizeAndStringify(".125;")); ASSERT_EQUALS("005.125 ;", tokenizeAndStringify("005.125;")); // Don't confuse with octal values } void tokenize17() { // #2759 ASSERT_EQUALS("class B : private :: A { } ;", tokenizeAndStringify("class B : private ::A { };")); } void tokenize18() { // tokenize "(X&&Y)" into "( X && Y )" instead of "( X & & Y )" ASSERT_EQUALS("( X && Y ) ;", tokenizeAndStringify("(X&&Y);")); } void tokenize19() { // #3006 - added hasComplicatedSyntaxErrorsInTemplates to avoid segmentation fault ASSERT_THROW(tokenizeAndStringify("x < () <"), InternalError); // #3496 - make sure hasComplicatedSyntaxErrorsInTemplates works ASSERT_EQUALS("void a ( Fred * f ) { for ( ; n < f . x ( ) ; ) { } }", tokenizeAndStringify("void a(Fred* f) MACRO { for (;n < f->x();) {} }")); // #6216 - make sure hasComplicatedSyntaxErrorsInTemplates works ASSERT_EQUALS("C :: C ( )\n" ": v { }\n" "{\n" "for ( int dim = 0 ; dim < v . size ( ) ; ++ dim ) {\n" "v [ dim ] . f ( ) ;\n" "}\n" "} ;", tokenizeAndStringify("C::C()\n" ":v{}\n" "{\n" " for (int dim = 0; dim < v.size(); ++dim) {\n" " v[dim]->f();\n" " }\n" "};")); } void tokenize21() { // tokenize 0x0E-7 ASSERT_EQUALS("0x0E - 7 ;", tokenizeAndStringify("0x0E-7;")); } void tokenize22() { // tokenize special marker $ from preprocessor ASSERT_EQUALS("a$b", tokenizeAndStringify("a$b")); ASSERT_EQUALS("a $b\nc", tokenizeAndStringify("a $b\nc")); ASSERT_EQUALS("a = $0 ;", tokenizeAndStringify("a = $0;")); ASSERT_EQUALS("a$ ++ ;", tokenizeAndStringify("a$++;")); ASSERT_EQUALS("$if ( ! p )", tokenizeAndStringify("$if(!p)")); } // #4239 - segfault for "f ( struct { int typedef T x ; } ) { }" void tokenize25() { ASSERT_THROW(tokenizeAndStringify("f ( struct { int typedef T x ; } ) { }"), InternalError); } // #4245 - segfault void tokenize26() { ASSERT_THROW(tokenizeAndStringify("class x { protected : template < int y = } ;"), InternalError); // Garbage code } void tokenize27() { // #4525 - segfault tokenizeAndStringify("struct except_spec_d_good : except_spec_a, except_spec_b {\n" "~except_spec_d_good();\n" "};\n" "struct S { S(); };\n" "S::S() __attribute((pure)) = default;" ); // original code: glibc-2.18/posix/bug-regex20.c tokenizeAndStringify("static unsigned int re_string_context_at (const re_string_t *input, int idx, int eflags) internal_function __attribute__ ((pure));"); } // #3503 - don't "simplify" SetFunction member function to a variable void tokenize31() { ASSERT_EQUALS("struct TTestClass { TTestClass ( ) { }\n" "void SetFunction ( Other ( * m_f ) ( ) ) { }\n" "} ;", tokenizeAndStringify("struct TTestClass { TTestClass() { }\n" " void SetFunction(Other(*m_f)()) { }\n" "};")); ASSERT_EQUALS("struct TTestClass { TTestClass ( ) { }\n" "void SetFunction ( Other ( * m_f ) ( ) ) ;\n" "} ;", tokenizeAndStringify("struct TTestClass { TTestClass() { }\n" " void SetFunction(Other(*m_f)());\n" "};")); } // #5884 - Avoid left shift of negative integer value. void tokenize32() { // Do not simplify negative integer left shifts. const char * code = "void f ( ) { int max_x ; max_x = -10000 << 16 ; }"; ASSERT_EQUALS(code, tokenizeAndStringify(code)); } // #5780 Various crashes on valid template code in Tokenizer::setVarId() void tokenize33() { const char * code = "template> struct vector {};\n" "void z() {\n" " vector VI;\n" "}\n"; tokenizeAndStringify(code); } void tokenize34() { // #8031 { const char code[] = "struct Container {\n" " Container();\n" " int* mElements;\n" "};\n" "Container::Container() : mElements(nullptr) {}\n" "Container intContainer;"; const char exp [] = "1: struct Container {\n" "2: Container ( ) ;\n" "3: int * mElements@1 ;\n" "4: } ;\n" "5: Container :: Container ( ) : mElements@1 ( nullptr ) { }\n" "6: Container intContainer@2 ;\n"; ASSERT_EQUALS(exp, tokenizeDebugListing(code)); } { const char code[] = "template struct Container {\n" " Container();\n" " int* mElements;\n" "};\n" "template Container::Container() : mElements(nullptr) {}\n" "Container intContainer;"; const char exp [] = "1: struct Container ;\n" "2:\n" "|\n" "5:\n" "6: Container intContainer@1 ;\n" "1: struct Container {\n" "2: Container ( ) ;\n" "3: int * mElements@2 ;\n" "4: } ;\n" "5: Container :: Container ( ) : mElements@2 ( nullptr ) { }\n"; ASSERT_EQUALS(exp, tokenizeDebugListing(code)); } } void tokenize35() { // #8361 tokenizeAndStringify("typedef int CRCWord; " "template ::CRCWord const Compute(T const t) { return 0; }"); } void tokenize36() { // #8436 const char code[] = "int foo ( int i ) { return i ? * new int { 5 } : int { i ? 0 : 1 } ; }"; ASSERT_EQUALS(code, tokenizeAndStringify(code)); } void tokenize37() { // #8550 const char codeC[] = "class name { public: static void init ( ) {} } ; " "typedef class name N; " "void foo ( ) { return N :: init ( ) ; }"; const char expC [] = "class name { public: static void init ( ) { } } ; " "void foo ( ) { return name :: init ( ) ; }"; ASSERT_EQUALS(expC, tokenizeAndStringify(codeC)); const char codeS[] = "class name { public: static void init ( ) {} } ; " "typedef struct name N; " "void foo ( ) { return N :: init ( ) ; }"; const char expS [] = "class name { public: static void init ( ) { } } ; " "void foo ( ) { return name :: init ( ) ; }"; ASSERT_EQUALS(expS, tokenizeAndStringify(codeS)); } void tokenize38() { // #9569 const char code[] = "using Binary = std::vector; enum Type { Binary };"; const char exp[] = "enum Type { Binary } ;"; ASSERT_EQUALS(exp, tokenizeAndStringify(code)); } void tokenize39() { // #9771 const char code[] = "template class Foo;" "template bool operator!=(const Foo &, const Foo &);" "template class Foo { friend bool operator!= <> (const Foo &, const Foo &); };"; const char exp[] = "template < typename T > class Foo ; " "template < typename T > bool operator!= ( const Foo < T > & , const Foo < T > & ) ; " "template < typename T > class Foo { friend bool operator!= < > ( const Foo < T > & , const Foo < T > & ) ; } ;"; ASSERT_EQUALS(exp, tokenizeAndStringify(code)); } void validate() { // C++ code in C file ASSERT_THROW(tokenizeAndStringify(";using namespace std;",false,Settings::Native,"test.c"), InternalError); ASSERT_THROW(tokenizeAndStringify(";std::map m;",false,Settings::Native,"test.c"), InternalError); ASSERT_THROW(tokenizeAndStringify(";template class X { };",false,Settings::Native,"test.c"), InternalError); ASSERT_THROW(tokenizeAndStringify("int X() {};",false,Settings::Native,"test.c"), InternalError); ASSERT_THROW(tokenizeAndStringify("void foo(int i) { reinterpret_cast(i) };",false,Settings::Native,"test.h"), InternalError); } void objectiveC() { ASSERT_THROW(tokenizeAndStringify("void f() { [foo bar]; }"), InternalError); } void syntax_case_default() { // correct syntax tokenizeAndStringify("void f() {switch (n) { case 0: z(); break;}}"); ASSERT_EQUALS("", errout.str()); tokenizeAndStringify("void f() {switch (n) { case 0:; break;}}"); ASSERT_EQUALS("", errout.str()); // TODO: Do not throw AST validation exception TODO_ASSERT_THROW(tokenizeAndStringify("void f() {switch (n) { case 0?1:2 : z(); break;}}"), InternalError); //ASSERT_EQUALS("", errout.str()); // TODO: Do not throw AST validation exception TODO_ASSERT_THROW(tokenizeAndStringify("void f() {switch (n) { case 0?(1?3:4):2 : z(); break;}}"), InternalError); ASSERT_EQUALS("", errout.str()); //allow GCC '({ %name%|%num%|%bool% ; })' statement expression extension // TODO: Do not throw AST validation exception TODO_ASSERT_THROW(tokenizeAndStringify("void f() {switch (n) { case 0?({0;}):1: z(); break;}}"), InternalError); ASSERT_EQUALS("", errout.str()); //'b' can be or a macro or an undefined enum tokenizeAndStringify("void f() {switch (n) { case b: z(); break;}}"); ASSERT_EQUALS("", errout.str()); //valid, when there's this declaration: 'constexpr int g() { return 2; }' tokenizeAndStringify("void f() {switch (n) { case g(): z(); break;}}"); ASSERT_EQUALS("", errout.str()); //valid, when there's also this declaration: 'constexpr int g[1] = {0};' tokenizeAndStringify("void f() {switch (n) { case g[0]: z(); break;}}"); ASSERT_EQUALS("", errout.str()); //valid, similar to above case tokenizeAndStringify("void f() {switch (n) { case *g: z(); break;}}"); ASSERT_EQUALS("", errout.str()); //valid, when 'x' and 'y' are constexpr. tokenizeAndStringify("void f() {switch (n) { case sqrt(x+y): z(); break;}}"); ASSERT_EQUALS("", errout.str()); } void removePragma() { const char code[] = "_Pragma(\"abc\") int x;"; Settings s; s.standards.c = Standards::C89; ASSERT_EQUALS("_Pragma ( \"abc\" ) int x ;", tokenizeAndStringify(code, s, "test.c")); s.standards.c = Standards::CLatest; ASSERT_EQUALS("int x ;", tokenizeAndStringify(code, s, "test.c")); s.standards.cpp = Standards::CPP03; ASSERT_EQUALS("_Pragma ( \"abc\" ) int x ;", tokenizeAndStringify(code, s, "test.cpp")); s.standards.cpp = Standards::CPPLatest; ASSERT_EQUALS("int x ;", tokenizeAndStringify(code, s, "test.cpp")); } void foreach () { // #3690,#5154 const char code[] ="void f() { for each ( char c in MyString ) { Console::Write(c); } }"; ASSERT_EQUALS("void f ( ) { asm ( \"char c in MyString\" ) { Console :: Write ( c ) ; } }", tokenizeAndStringify(code)); } void ifconstexpr() { ASSERT_EQUALS("void f ( ) { if ( FOO ) { bar ( c ) ; } }", tokenizeAndStringify("void f() { if constexpr ( FOO ) { bar(c); } }")); } void combineOperators() { ASSERT_EQUALS("; private: ;", tokenizeAndStringify(";private:;")); ASSERT_EQUALS("; protected: ;", tokenizeAndStringify(";protected:;")); ASSERT_EQUALS("; public: ;", tokenizeAndStringify(";public:;")); ASSERT_EQUALS("; __published: ;", tokenizeAndStringify(";__published:;")); ASSERT_EQUALS("a . public : ;", tokenizeAndStringify("a.public:;")); ASSERT_EQUALS("void f ( x & = 2 ) ;", tokenizeAndStringify("void f(x &= 2);")); ASSERT_EQUALS("const_cast < a * > ( & e )", tokenizeAndStringify("const_cast(&e)")); } void concatenateNegativeNumber() { ASSERT_EQUALS("i = -12 ;", tokenizeAndStringify("i = -12;")); ASSERT_EQUALS("1 - 2 ;", tokenizeAndStringify("1-2;")); ASSERT_EQUALS("foo ( -1 ) - 2 ;", tokenizeAndStringify("foo(-1)-2;")); ASSERT_EQUALS("int f ( ) { return -2 ; }", tokenizeAndStringify("int f(){return -2;}")); ASSERT_EQUALS("int x [ 2 ] = { -2 , 1 }", tokenizeAndStringify("int x[2] = {-2,1}")); ASSERT_EQUALS("f ( 123 )", tokenizeAndStringify("f(+123)")); } void longtok() { const std::string filedata(10000, 'a'); ASSERT_EQUALS(filedata, tokenizeAndStringify(filedata.c_str())); } void simplifyHeadersAndUnusedTemplates1() { Settings s; s.checkUnusedTemplates = false; ASSERT_EQUALS(";", tokenizeAndStringify("; template uint8_t b(std::tuple d) {\n" " std::tuple c{std::move(d)};\n" " return std::get<0>(c);\n" "}", s)); ASSERT_EQUALS("int g ( int ) ;", tokenizeAndStringify("int g(int);\n" "template auto h(F f, Ts... xs) {\n" " auto e = f(g(xs)...);\n" " return e;\n" "}", s)); } void simplifyHeadersAndUnusedTemplates2() { const char code[] = "; template< typename T, u_int uBAR = 0 >\n" "class Foo {\n" "public:\n" " void FooBar() {\n" " new ( (uBAR ? uBAR : sizeof(T))) T;\n" " }\n" "};"; Settings s; s.checkUnusedTemplates = false; ASSERT_EQUALS(";", tokenizeAndStringify(code, s)); s.checkUnusedTemplates = true; ASSERT_EQUALS("; template < typename T , u_int uBAR = 0 >\n" "class Foo {\n" "public:\n" "void FooBar ( ) {\n" "new ( uBAR ? uBAR : sizeof ( T ) ) T ;\n" "}\n" "} ;", tokenizeAndStringify(code, s)); } void simplifyAt() { ASSERT_EQUALS("int x ;", tokenizeAndStringify("int x@123;")); ASSERT_EQUALS("bool x ;", tokenizeAndStringify("bool x@123:1;")); ASSERT_EQUALS("char PORTB ; bool PB3 ;", tokenizeAndStringify("char PORTB @ 0x10; bool PB3 @ PORTB:3;\n")); ASSERT_EQUALS("int x ;", tokenizeAndStringify("int x @ (0x1000 + 18);")); ASSERT_EQUALS("int x [ 10 ] ;", tokenizeAndStringify("int x[10]@0x100;")); ASSERT_EQUALS("interrupt@ f ( ) { }", tokenizeAndStringify("@interrupt f() {}")); } void inlineasm() { ASSERT_EQUALS("asm ( \"mov ax , bx\" ) ;", tokenizeAndStringify("asm { mov ax,bx };")); ASSERT_EQUALS("asm ( \"mov ax , bx\" ) ;", tokenizeAndStringify("_asm { mov ax,bx };")); ASSERT_EQUALS("asm ( \"mov ax , bx\" ) ;", tokenizeAndStringify("_asm mov ax,bx")); ASSERT_EQUALS("asm ( \"mov ax , bx\" ) ;", tokenizeAndStringify("__asm { mov ax,bx };")); ASSERT_EQUALS("asm ( \"\"mov ax,bx\"\" ) ;", tokenizeAndStringify("__asm__ __volatile__ ( \"mov ax,bx\" );")); ASSERT_EQUALS("asm ( \"_emit 12h\" ) ;", tokenizeAndStringify("__asm _emit 12h ;")); ASSERT_EQUALS("asm ( \"mov a , b\" ) ;", tokenizeAndStringify("__asm mov a, b ;")); ASSERT_EQUALS("asm ( \"\"fnstcw %0\" : \"= m\" ( old_cw )\" ) ;", tokenizeAndStringify("asm volatile (\"fnstcw %0\" : \"= m\" (old_cw));")); ASSERT_EQUALS("asm ( \"\"fnstcw %0\" : \"= m\" ( old_cw )\" ) ;", tokenizeAndStringify(" __asm__ (\"fnstcw %0\" : \"= m\" (old_cw));")); ASSERT_EQUALS("asm ( \"\"ddd\"\" ) ;", tokenizeAndStringify(" __asm __volatile__ (\"ddd\") ;")); ASSERT_EQUALS("asm ( \"\"ddd\"\" ) ;", tokenizeAndStringify(" __asm __volatile (\"ddd\") ;")); ASSERT_EQUALS("asm ( \"\"mov ax,bx\"\" ) ;", tokenizeAndStringify("__asm__ volatile ( \"mov ax,bx\" );")); ASSERT_EQUALS("asm ( \"mov ax , bx\" ) ; int a ;", tokenizeAndStringify("asm { mov ax,bx } int a;")); ASSERT_EQUALS("asm\n\n( \"mov ax , bx\" ) ;", tokenizeAndStringify("__asm\nmov ax,bx\n__endasm;")); ASSERT_EQUALS("asm\n\n( \"push b ; for if\" ) ;", tokenizeAndStringify("__asm\npush b ; for if\n__endasm;")); // 'asm ( ) ;' should be in the same line ASSERT_EQUALS(";\n\nasm ( \"\"mov ax,bx\"\" ) ;", tokenizeAndStringify(";\n\n__asm__ volatile ( \"mov ax,bx\" );")); } // #4725 - ^{} void simplifyAsm2() { ASSERT_THROW(ASSERT_EQUALS("void f ( ) { asm ( \"^{}\" ) ; }", tokenizeAndStringify("void f() { ^{} }")), InternalError); ASSERT_THROW(ASSERT_EQUALS("void f ( ) { x ( asm ( \"^{}\" ) ) ; }", tokenizeAndStringify("void f() { x(^{}); }")), InternalError); ASSERT_THROW(ASSERT_EQUALS("void f ( ) { foo ( A ( ) , asm ( \"^{bar();}\" ) ) ; }", tokenizeAndStringify("void f() { foo(A(), ^{ bar(); }); }")), InternalError); ASSERT_THROW(ASSERT_EQUALS("int f0 ( Args args ) { asm ( \"asm(\"return^{returnsizeof...(Args);}()\")+^{returnsizeof...(args);}()\" )\n" "2:\n" "|\n" "5:\n" "6: ;\n" "} ;", tokenizeAndStringify("int f0(Args args) {\n" " return ^{\n" " return sizeof...(Args);\n" " }() + ^ {\n" " return sizeof...(args);\n" " }();\n" "};")), InternalError); ASSERT_THROW(ASSERT_EQUALS("int ( ^ block ) ( void ) = asm ( \"^{staticinttest=0;returntest;}\" )\n\n\n;", tokenizeAndStringify("int(^block)(void) = ^{\n" " static int test = 0;\n" " return test;\n" "};")), InternalError); ASSERT_THROW(ASSERT_EQUALS("; return f ( a [ b = c ] , asm ( \"^{}\" ) ) ;", tokenizeAndStringify("; return f(a[b=c],^{});")), InternalError); // #7185 ASSERT_EQUALS("{ return f ( asm ( \"^(void){somecode}\" ) ) ; }", tokenizeAndStringify("{ return f(^(void){somecode}); }")); ASSERT_THROW(ASSERT_EQUALS("; asm ( \"a?(b?(c,asm(\"^{}\")):0):^{}\" ) ;", tokenizeAndStringify(";a?(b?(c,^{}):0):^{};")), InternalError); ASSERT_EQUALS("template < typename T > " "CImg < T > operator| ( const char * const expression , const CImg < T > & img ) { " "return img | expression ; " "} " "template < typename T > " "CImg < T > operator^ ( const char * const expression , const CImg < T > & img ) { " "return img ^ expression ; " "} " "template < typename T > " "CImg < T > operator== ( const char * const expression , const CImg < T > & img ) { " "return img == expression ; " "}", tokenizeAndStringify("template < typename T >" "inline CImg operator|(const char *const expression, const CImg& img) {" " return img | expression ;" "}" "template" "inline CImg operator^(const char *const expression, const CImg& img) {" " return img ^ expression;" "}" "template" "inline CImg operator==(const char *const expression, const CImg& img) {" " return img == expression;" "}")); } void ifAddBraces1() { const char code[] = "void f()\n" "{\n" " if (a);\n" " else ;\n" "}\n"; ASSERT_EQUALS("void f ( )\n" "{\n" "if ( a ) { ; }\n" "else { ; }\n" "}", tokenizeAndStringify(code)); } void ifAddBraces2() { const char code[] = "void f()\n" "{\n" " if (a) if (b) { }\n" "}\n"; ASSERT_EQUALS("void f ( )\n" "{\n" "if ( a ) { if ( b ) { } }\n" "}", tokenizeAndStringify(code)); } void ifAddBraces3() { const char code[] = "void f()\n" "{\n" " if (a) for (;;) { }\n" "}\n"; ASSERT_EQUALS("void f ( )\n" "{\n" "if ( a ) { for ( ; ; ) { } }\n" "}", tokenizeAndStringify(code)); } void ifAddBraces4() { const char code[] = "char * foo ()\n" "{\n" " char *str = malloc(10);\n" " if (somecondition)\n" " for ( ; ; )\n" " { }\n" " return str;\n" "}\n"; ASSERT_EQUALS("char * foo ( )\n" "{\n" "char * str ; str = malloc ( 10 ) ;\n" "if ( somecondition ) {\n" "for ( ; ; )\n" "{ } }\n" "return str ;\n" "}", tokenizeAndStringify(code)); } void ifAddBraces5() { const char code[] = "void f()\n" "{\n" "for(int i = 0; i < 2; i++)\n" "if(true)\n" "return;\n" "\n" "return;\n" "}\n"; ASSERT_EQUALS("void f ( )\n" "{\n" "for ( int i = 0 ; i < 2 ; i ++ ) {\n" "if ( true ) {\n" "return ; } }\n\n" "return ;\n" "}", tokenizeAndStringify(code)); } void ifAddBraces7() { const char code[] = "void f()\n" "{\n" "int a;\n" "if( a )\n" " ({a=4;}),({a=5;});\n" "}\n"; ASSERT_EQUALS("void f ( )\n" "{\n" "int a ;\n" "if ( a ) {\n" "( { a = 4 ; } ) , ( { a = 5 ; } ) ; }\n" "}", tokenizeAndStringify(code)); } void ifAddBraces9() { // ticket #990 const char code[] = "void f() {" " for (int k=0; k 0 ) ;\n" " return 0 ;\n" "}\n"; const char result[] = "void foo ( int c , int d ) {\n" "do {\n" "if ( c ) {\n" "while ( c ) { c -- ; }\n" "} }\n" "while ( -- d > 0 ) ;\n" "return 0 ;\n" "}"; ASSERT_EQUALS(result, tokenizeAndStringify(code)); } { const char code[] = "void foo ( int c , int d ) {\n" " do\n" " do c -- ; while ( c ) ;\n" " while ( -- d > 0 ) ;\n" " return 0 ;\n" "}\n"; const char result[] = "void foo ( int c , int d ) {\n" "do {\n" "do { c -- ; } while ( c ) ; }\n" "while ( -- d > 0 ) ;\n" "return 0 ;\n" "}"; ASSERT_EQUALS(result, tokenizeAndStringify(code)); } { // #8148 - while inside the do-while body const char code[] = "void foo() {\n" " do { while (x) f(); } while (y);\n" "}"; const char result[] = "void foo ( ) {\n" "do { while ( x ) { f ( ) ; } } while ( y ) ;\n" "}"; ASSERT_EQUALS(result, tokenizeAndStringify(code)); } } void doWhileAddBracesLabels() { // Labels before statement ASSERT_EQUALS("void f ( int x ) {\n" "do {\n" "l1 : ; l2 : ; -- x ; }\n" "while ( x ) ;\n" "}", tokenizeAndStringify("void f(int x) {\n" " do\n" " l1: l2: --x;\n" " while (x);\n" "}")); // Labels before { ASSERT_EQUALS("void f ( int x ) {\n" "do\n" "{ l1 : ; l2 : ; -- x ; }\n" "while ( x ) ;\n" "}", tokenizeAndStringify("void f(int x) {\n" " do\n" " l1: l2: { -- x; }\n" " while (x);\n" "}")); // Labels before try/catch ASSERT_EQUALS("void f ( int x ) {\n" "do {\n" "l1 : ; l2 : ;\n" "try { throw 1 ; }\n" "catch ( ... ) { -- x ; } }\n" "while ( x ) ;\n" "}", tokenizeAndStringify("void f(int x) {\n" " do\n" " l1: l2:\n" " try { throw 1; }\n" " catch(...) { --x; }\n" " while (x);\n" "}")); } void forAddBraces1() { { const char code[] = "void f() {\n" " for(;;)\n" " if (a) { }\n" " else { }\n" "}"; const char expected[] = "void f ( ) {\n" "for ( ; ; ) {\n" "if ( a ) { }\n" "else { } }\n" "}"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "void f() {\n" " for(;;)\n" " if (a) { }\n" " else if (b) { }\n" " else { }\n" "}"; const char expected[] = "void f ( ) {\n" "for ( ; ; ) {\n" "if ( a ) { }\n" "else { if ( b ) { }\n" "else { } } }\n" "}"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } } void forAddBraces2() { // #5088 const char code[] = "void f() {\n" " for(;;) try { } catch (...) { }\n" "}"; const char expected[] = "void f ( ) {\n" "for ( ; ; ) { try { } catch ( ... ) { } }\n" "}"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } void forAddBracesLabels() { // Labels before statement ASSERT_EQUALS("void f ( int x ) {\n" "for ( ; x ; ) {\n" "l1 : ; l2 : ; -- x ; }\n" "}", tokenizeAndStringify("void f(int x) {\n" " for ( ; x; )\n" " l1: l2: --x;\n" "}")); // Labels before { ASSERT_EQUALS("void f ( int x ) {\n" "for ( ; x ; )\n" "{ l1 : ; l2 : ; -- x ; }\n" "}", tokenizeAndStringify("void f(int x) {\n" " for ( ; x; )\n" " l1: l2: { -- x; }\n" "}")); // Labels before try/catch ASSERT_EQUALS("void f ( int x ) {\n" "for ( ; x ; ) {\n" "l1 : ; l2 : ;\n" "try { throw 1 ; }\n" "catch ( ... ) { -- x ; } }\n" "}", tokenizeAndStringify("void f(int x) {\n" " for ( ; x; )\n" " l1: l2:\n" " try { throw 1; }\n" " catch(...) { --x; }\n" "}")); } void simplifyExternC() { ASSERT_EQUALS("int foo ( ) ;", tokenizeAndStringify("extern \"C\" int foo();")); ASSERT_EQUALS("int foo ( ) ;", tokenizeAndStringify("extern \"C\" { int foo(); }")); } void simplifyFunctionParameters() { { const char code[] = "char a [ ABC ( DEF ) ] ;"; ASSERT_EQUALS(code, tokenizeAndStringify(code)); } { const char code[] = "module ( a , a , sizeof ( a ) , 0444 ) ;"; ASSERT_EQUALS("module ( a , a , sizeof ( a ) , 0444 ) ;", tokenizeAndStringify(code)); } ASSERT_EQUALS("void f ( int x ) { }", tokenizeAndStringify("void f(x) int x; { }")); ASSERT_EQUALS("void f ( int x , char y ) { }", tokenizeAndStringify("void f(x,y) int x; char y; { }")); ASSERT_EQUALS("int main ( int argc , char * argv [ ] ) { }", tokenizeAndStringify("int main(argc,argv) int argc; char *argv[]; { }")); ASSERT_EQUALS("int f ( int p , int w , float d ) { }", tokenizeAndStringify("int f(p,w,d) float d; { }")); // #1067 - Not simplified. Feel free to fix so it is simplified correctly but this syntax is obsolescent. ASSERT_EQUALS("int ( * d ( a , b , c ) ) ( ) int a ; int b ; int c ; { }", tokenizeAndStringify("int (*d(a,b,c))()int a,b,c; { }")); { // This is not a function but the pattern is similar.. const char code[] = "void foo()" "{" " if (x)" " int x;" " { }" "}"; ASSERT_EQUALS("void foo ( ) { if ( x ) { int x ; } { } }", tokenizeAndStringify(code)); } } void simplifyFunctionParameters1() { // ticket #3721 const char code[] = "typedef float ufloat;\n" "typedef short ftnlen;\n" "int f(p,w,d,e,len) ufloat *p; ftnlen len;\n" "{\n" "}\n"; ASSERT_EQUALS("int f ( float * p , int w , int d , int e , short len )\n" "{\n" "}", tokenizeAndStringify(code)); } void simplifyFunctionParameters2() { // #4430 const char code[] = "class Item { " "int i ; " "public: " "Item ( int i ) ; " "} ; " "Item :: Item ( int i ) : i ( i ) { }"; ASSERT_EQUALS(code, tokenizeAndStringify(code)); } void simplifyFunctionParameters3() { // #4436 const char code[] = "class Item { " "int i ; " "int j ; " "public: " "Item ( int i , int j ) ; " "} ; " "Item :: Item ( int i , int j ) : i ( i ) , j ( j ) { }"; ASSERT_EQUALS(code, tokenizeAndStringify(code)); } void simplifyFunctionParameters4() { // #9421 const char code[] = "int foo :: bar ( int , int ) const ;"; ASSERT_EQUALS(code, tokenizeAndStringify(code)); } void simplifyFunctionParametersMultiTemplate() { const char code[] = "template < typename T1 > template < typename T2 > " "void A < T1 > :: foo ( T2 ) { }"; ASSERT_EQUALS(code, tokenizeAndStringify(code)); } void simplifyFunctionParametersErrors() { //same parameters... ASSERT_THROW(tokenizeAndStringify("void foo(x, x)\n" " int x;\n" " int x;\n" "{}\n"), InternalError); ASSERT_THROW(tokenizeAndStringify("void foo(x, y)\n" " int x;\n" " int x;\n" "{}\n"), InternalError); tokenizeAndStringify("void foo(int, int)\n" "{}"); ASSERT_EQUALS("", errout.str()); // #3848 - Don't hang tokenizeAndStringify("sal_Bool ShapeHasText(sal_uLong, sal_uLong) const {\n" " return sal_True;\n" "}\n" "void CreateSdrOLEFromStorage() {\n" " comphelper::EmbeddedObjectContainer aCnt( xDestStorage );\n" " { }\n" "}"); ASSERT_EQUALS("", errout.str()); } void simplifyFunctionTryCatch() { ASSERT_EQUALS("void foo ( ) { try {\n" "} catch ( int ) {\n" "} catch ( char ) {\n" "} }", tokenizeAndStringify("void foo() try {\n" "} catch (int) {\n" "} catch (char) {\n" "}")); ASSERT_EQUALS("void foo ( ) { try {\n" "struct S {\n" "void bar ( ) { try {\n" "} catch ( int ) {\n" "} catch ( char ) {\n" "} }\n" "} ;\n" "} catch ( long ) {\n" "} }", tokenizeAndStringify("void foo() try {\n" " struct S {\n" " void bar() try {\n" " } catch (int) {\n" " } catch (char) {\n" " }\n" " };\n" "} catch (long) {\n" "}")); } // Simplify "((..))" into "(..)" void removeParentheses1() { const char code[] = "void foo()" "{" " free(((void*)p));" "}"; ASSERT_EQUALS("void foo ( ) { free ( ( void * ) p ) ; }", tokenizeAndStringify(code)); } void removeParentheses3() { { const char code[] = "void foo()" "{" " if (( true )==(true)){}" "}"; ASSERT_EQUALS("void foo ( ) { if ( true == true ) { } }", tokenizeAndStringify(code)); } { const char code[] = "void foo()" "{" " if (( 2 )==(2)){}" "}"; ASSERT_EQUALS("void foo ( ) { if ( 2 == 2 ) { } }", tokenizeAndStringify(code)); } { const char code[] = "void foo()" "{" " if( g(10)){}" "}"; ASSERT_EQUALS("void foo ( ) { if ( g ( 10 ) ) { } }", tokenizeAndStringify(code)); } } // Simplify "( function (..))" into "function (..)" void removeParentheses4() { const char code[] = "void foo()" "{" " (free(p));" "}"; ASSERT_EQUALS("void foo ( ) { free ( p ) ; }", tokenizeAndStringify(code)); } void removeParentheses5() { // Simplify "( delete x )" into "delete x" { const char code[] = "void foo()" "{" " (delete p);" "}"; ASSERT_EQUALS("void foo ( ) { delete p ; }", tokenizeAndStringify(code)); } // Simplify "( delete [] x )" into "delete [] x" { const char code[] = "void foo()" "{" " (delete [] p);" "}"; ASSERT_EQUALS("void foo ( ) { delete [ ] p ; }", tokenizeAndStringify(code)); } } // "!(abc.a)" => "!abc.a" void removeParentheses6() { { const char code[] = "(!(abc.a));"; ASSERT_EQUALS("( ! abc . a ) ;", tokenizeAndStringify(code)); } //handle more complex member selections { const char code[] = "(!(a.b.c.d));"; ASSERT_EQUALS("( ! a . b . c . d ) ;", tokenizeAndStringify(code)); } } void removeParentheses7() { const char code[] = ";char *p; (delete(p), (p)=0);"; ASSERT_EQUALS("; char * p ; delete ( p ) , p = 0 ;", tokenizeAndStringify(code)); } void removeParentheses8() { const char code[] = "struct foo {\n" " void operator delete(void *obj, size_t sz);\n" "}\n"; const std::string actual(tokenizeAndStringify(code, true, Settings::Win32A)); const char expected[] = "struct foo {\n" "void operatordelete ( void * obj , unsigned long sz ) ;\n" "}"; ASSERT_EQUALS(expected, actual); } void removeParentheses9() { ASSERT_EQUALS("void delete ( double num ) ;", tokenizeAndStringify("void delete(double num);")); } void removeParentheses10() { ASSERT_EQUALS("p = buf + 8 ;", tokenizeAndStringify("p = (buf + 8);")); } void removeParentheses11() { // #2502 ASSERT_EQUALS("{ } x ( ) ;", tokenizeAndStringify("{}(x());")); } void removeParentheses12() { // #2760 ASSERT_EQUALS(", x = 0 ;", tokenizeAndStringify(",(x)=0;")); } void removeParentheses13() { ASSERT_EQUALS("; f ( a + b , c ) ;", tokenizeAndStringify(";f((a+b),c);")); ASSERT_EQUALS("; x = y [ a + b ] ;", tokenizeAndStringify(";x=y[(a+b)];")); } void removeParentheses14() { ASSERT_EQUALS("{ if ( ( i & 1 ) == 0 ) { ; } }", tokenizeAndStringify("{ if ( (i & 1) == 0 ); }")); } void removeParentheses15() { ASSERT_EQUALS("a = b ? c : 123 ;", tokenizeAndStringify("a = b ? c : (123);")); ASSERT_EQUALS("a = b ? c : ( 123 + 456 ) ;", tokenizeAndStringify("a = b ? c : ((123)+(456));")); ASSERT_EQUALS("a = b ? 123 : c ;", tokenizeAndStringify("a = b ? (123) : c;")); // #4316 ASSERT_EQUALS("a = b ? c : ( d = 1 , 0 ) ;", tokenizeAndStringify("a = b ? c : (d=1,0);")); } void removeParentheses16() { // *(x.y)= // #4423 ASSERT_EQUALS("; * x = 0 ;", tokenizeAndStringify(";*(x)=0;")); ASSERT_EQUALS("; * x . y = 0 ;", tokenizeAndStringify(";*(x.y)=0;")); } void removeParentheses17() { // a ? b : (c > 0 ? d : e) ASSERT_EQUALS("a ? b : ( c > 0 ? d : e ) ;", tokenizeAndStringify("a?b:(c>0?d:e);")); } void removeParentheses18() { ASSERT_EQUALS("float ( * a ) [ 2 ] ;", tokenizeAndStringify("float(*a)[2];")); } void removeParentheses19() { ASSERT_EQUALS("( ( ( typeof ( X ) ) * ) 0 ) ;", tokenizeAndStringify("(((typeof(X))*)0);")); } void removeParentheses20() { ASSERT_EQUALS("a < b < int > > ( 2 ) ;", tokenizeAndStringify("a>(2);")); } void removeParentheses21() { ASSERT_EQUALS("a = ( int ) - b ;", tokenizeAndStringify("a = ((int)-b);")); } void removeParentheses22() { static char code[] = "struct S { " "char *(a); " "char &(b); " "const static char *(c); " "} ;"; static char exp[] = "struct S { " "char * a ; " "char & b ; " "static const char * c ; " "} ;"; ASSERT_EQUALS(exp, tokenizeAndStringify(code)); } void removeParentheses23() { // Ticket #6103 // Reported case { static char code[] = "; * * p f ( ) int = { new int ( * [ 2 ] ) ; void }"; static char exp[] = "; * * p f ( ) int = { new int ( * [ 2 ] ) ; void }"; ASSERT_EQUALS(exp, tokenizeAndStringify(code)); } // Various valid cases { static char code[] = "int * f [ 1 ] = { new ( int ) } ;"; static char exp[] = "int * f [ 1 ] = { new int } ;"; ASSERT_EQUALS(exp, tokenizeAndStringify(code)); } { static char code[] = "int * * f [ 1 ] = { new ( int ) [ 1 ] } ;"; static char exp[] = "int * * f [ 1 ] = { new int [ 1 ] } ;"; ASSERT_EQUALS(exp, tokenizeAndStringify(code)); } { static char code[] = "list < int > * f [ 1 ] = { new ( list < int > ) } ;"; static char exp[] = "list < int > * f [ 1 ] = { new list < int > } ;"; ASSERT_EQUALS(exp, tokenizeAndStringify(code)); } // don't remove parentheses in operator new overload { static char code[] = "void *operator new(__SIZE_TYPE__, int);"; static char exp[] = "void * operatornew ( __SIZE_TYPE__ , int ) ;"; ASSERT_EQUALS(exp, tokenizeAndStringify(code)); } } void removeParentheses24() { // Ticket #7040 static char code[] = "std::hash()(t._data);"; static char exp[] = "std :: hash < decltype ( t . _data ) > ( ) ( t . _data ) ;"; ASSERT_EQUALS(exp, tokenizeAndStringify(code)); } void removeParentheses25() { // daca@home - a=(b,c) static char code[] = "a=(b,c);"; static char exp[] = "a = ( b , c ) ;"; ASSERT_EQUALS(exp, tokenizeAndStringify(code)); } void removeParentheses26() { // Ticket #8875 a[0](0) static char code[] = "a[0](0);"; static char exp[] = "a [ 0 ] ( 0 ) ;"; ASSERT_EQUALS(exp, tokenizeAndStringify(code)); } void tokenize_double() { const char code[] = "void f() {\n" " double a = 4.2;\n" " float b = 4.2f;\n" " double c = 4.2e+10;\n" " double d = 4.2e-10;\n" " int e = 4+2;\n" "}"; ASSERT_EQUALS("void f ( ) {\n" "double a ; a = 4.2 ;\n" "float b ; b = 4.2f ;\n" "double c ; c = 4.2e+10 ;\n" "double d ; d = 4.2e-10 ;\n" "int e ; e = 4 + 2 ;\n" "}", tokenizeAndStringify(code)); } void tokenize_strings() { const char code[] = "void f() {\n" "const char *a =\n" "{\n" "\"hello \"\n" "\"more \"\n" "\"world\"\n" "};\n" "}"; ASSERT_EQUALS("void f ( ) {\n" "const char * a ; a =\n" "{\n" "\"hello more world\"\n" "\n" "\n" "} ;\n" "}", tokenizeAndStringify(code)); } void simplifyMulAndParens() { // (error) Resource leak const char code[] = "void f() {" " *&n1=open();" " *&(n2)=open();" " *(&n3)=open();" " *&*&n4=open();" " *&*&*&(n5)=open();" " *&*&(*&n6)=open();" " *&*(&*&n7)=open();" " *(&*&n8)=open();" " *&(*&*&(*&n9))=open();" " (n10) = open();" " ((n11)) = open();" " ((*&n12))=open();" " *(&(*&n13))=open();" " ((*&(*&n14)))=open();" " ((*&(*&n15)))+=10;" "}"; const char expected[] = "void f ( ) {" " n1 = open ( ) ;" " n2 = open ( ) ;" " n3 = open ( ) ;" " n4 = open ( ) ;" " n5 = open ( ) ;" " n6 = open ( ) ;" " n7 = open ( ) ;" " n8 = open ( ) ;" " n9 = open ( ) ;" " n10 = open ( ) ;" " n11 = open ( ) ;" " n12 = open ( ) ;" " n13 = open ( ) ;" " n14 = open ( ) ;" " n15 += 10 ; " "}"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } void simplifyStructDecl() { const char code[] = "const struct A { int a; int b; } a;"; ASSERT_EQUALS("struct A { int a ; int b ; } ; const struct A a ;", tokenizeAndStringify(code)); // #9519 const char code2[] = "enum A {} (a);"; const char expected2[] = "enum A { } ; enum A a ;"; ASSERT_EQUALS(expected2, tokenizeAndStringify(code2)); } void vardecl1() { const char code[] = "unsigned int a, b;"; const std::string actual(tokenizeAndStringify(code)); ASSERT_EQUALS("unsigned int a ; unsigned int b ;", actual); } void vardecl2() { const char code[] = "void foo(a,b) unsigned int a, b; { }"; const std::string actual(tokenizeAndStringify(code)); ASSERT_EQUALS("void foo ( unsigned int a , unsigned int b ) { }", actual); } void vardecl3() { const char code[] = "void f() { char * p = foo<10,char>(); }"; const std::string actual(tokenizeAndStringify(code)); ASSERT_EQUALS("void f ( ) { char * p ; p = foo < 10 , char > ( ) ; }", actual); } void vardecl4() { // ticket #346 const char code1[] = "void *p = NULL;"; const char res1[] = "void * p ; p = NULL ;"; ASSERT_EQUALS(res1, tokenizeAndStringify(code1)); const char code2[] = "const void *p = NULL;"; const char res2[] = "const void * p ; p = NULL ;"; ASSERT_EQUALS(res2, tokenizeAndStringify(code2)); const char code3[] = "void * const p = NULL;"; const char res3[] = "void * const p ; p = NULL ;"; ASSERT_EQUALS(res3, tokenizeAndStringify(code3)); const char code4[] = "const void * const p = NULL;"; const char res4[] = "const void * const p ; p = NULL ;"; ASSERT_EQUALS(res4, tokenizeAndStringify(code4)); const char code5[] = "const void * volatile p = NULL;"; const char res5[] = "const void * volatile p ; p = NULL ;"; ASSERT_EQUALS(res5, tokenizeAndStringify(code5)); } void vardecl5() { ASSERT_EQUALS("void foo ( int nX ) {\n" "int addI ; addI = frontPoint == 2 || frontPoint == 1 ? ( i = 0 , 1 ) : ( i = nX - 2 , -1 ) ;\n" "}", tokenizeAndStringify("void foo(int nX) {\n" " int addI = frontPoint == 2 || frontPoint == 1 ? i = 0, 1 : (i = nX - 2, -1);\n" "}")); } void vardecl_stl_1() { // ticket #520 const char code1[] = "std::vectora, b;"; const char res1[] = "std :: vector < std :: string > a ; std :: vector < std :: string > b ;"; ASSERT_EQUALS(res1, tokenizeAndStringify(code1)); const char code2[] = "std::vector::const_iterator it, cit;"; const char res2[] = "std :: vector < std :: string > :: const_iterator it ; std :: vector < std :: string > :: const_iterator cit ;"; ASSERT_EQUALS(res2, tokenizeAndStringify(code2)); const char code3[] = "std::vector > *c, d;"; const char res3[] = "std :: vector < std :: pair < std :: string , std :: string > > * c ; std :: vector < std :: pair < std :: string , std :: string > > d ;"; ASSERT_EQUALS(res3, tokenizeAndStringify(code3)); } void vardecl_stl_2() { const char code1[] = "{ std::string x = \"abc\"; }"; ASSERT_EQUALS("{ std :: string x ; x = \"abc\" ; }", tokenizeAndStringify(code1)); const char code2[] = "{ std::vector x = y; }"; ASSERT_EQUALS("{ std :: vector < int > x ; x = y ; }", tokenizeAndStringify(code2)); } void vardecl_template_1() { // ticket #1046 const char code1[] = "b<(1<<24),10,24> u, v;"; const char res1[] = "b < 16777216 , 10 , 24 > u ; b < 16777216 , 10 , 24 > v ;"; ASSERT_EQUALS(res1, tokenizeAndStringify(code1)); // ticket #3571 (segmentation fault) tokenizeAndStringify("template 4) > class X4 {};"); } void vardecl_template_2() { // ticket #3650 const char code[] = "const string str = x<8,int>();"; const char expected[] = "const string str = x < 8 , int > ( ) ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } void vardecl_union() { // ticket #1976 const char code1[] = "class Fred { public: union { int a ; int b ; } ; } ;"; ASSERT_EQUALS(code1, tokenizeAndStringify(code1)); // ticket #2039 const char code2[] = "void f() {\n" " union {\n" " int x;\n" " long y;\n" " };\n" "}"; ASSERT_EQUALS("void f ( ) {\n\nint x ;\nlong & y = x ;\n\n}", tokenizeAndStringify(code2)); // ticket #3927 const char code3[] = "union xy *p = NULL;"; ASSERT_EQUALS("union xy * p ; p = NULL ;", tokenizeAndStringify(code3)); } void vardecl_par() { // ticket #2743 - set links if variable type contains parentheses const char code[] = "Fred fred1=a, fred2=b;"; ASSERT_EQUALS("Fred < int ( * ) ( ) > fred1 ; fred1 = a ; Fred < int ( * ) ( ) > fred2 ; fred2 = b ;", tokenizeAndStringify(code)); } void vardecl_par2() { // ticket #3912 - set correct links const char code[] = "function)> v;"; ASSERT_EQUALS("function < void ( shared_ptr < MyClass > ) > v ;", tokenizeAndStringify(code)); } void vardecl_par3() { // ticket #6556- Fred x1(a), x2(b); const char code[] = "Fred x1(a), x2(b);"; ASSERT_EQUALS("Fred x1 ( a ) ; Fred x2 ( b ) ;", tokenizeAndStringify(code)); } void vardecl_class_ref() { const char code[] = "class A { B &b1,&b2; };"; ASSERT_EQUALS("class A { B & b1 ; B & b2 ; } ;", tokenizeAndStringify(code)); } void vardec_static() { { // don't simplify declarations of static variables // "static int i = 0;" is not the same as "static int i; i = 0;" const char code[] = "static int i = 0 ;"; ASSERT_EQUALS(code, tokenizeAndStringify(code)); } { const char code[] = "static int a, b;"; ASSERT_EQUALS("static int a ; static int b ;", tokenizeAndStringify(code)); } { const char code[] = "static unsigned int a, b;"; ASSERT_EQUALS("static unsigned int a ; static unsigned int b ;", tokenizeAndStringify(code)); } { const char code[] = "static int a=1, b=1;"; ASSERT_EQUALS("static int a = 1 ; static int b = 1 ;", tokenizeAndStringify(code)); } { const char code[] = "static int *a, *b;"; ASSERT_EQUALS("static int * a ; static int * b ;", tokenizeAndStringify(code)); } { const char code[] = "static unsigned int *a=0, *b=0;"; ASSERT_EQUALS("static unsigned int * a = 0 ; static unsigned int * b = 0 ;", tokenizeAndStringify(code)); } { // Ticket #4450 const char code[] = "static int large_eeprom_type = (13 | (5)), " "default_flash_type = 42;"; ASSERT_EQUALS("static int large_eeprom_type = 13 | 5 ; static int default_flash_type = 42 ;", tokenizeAndStringify(code)); } { // Ticket #5121 const char code[] = "unsigned int x;" "static const unsigned int A = 1, B = A, C = 0, D = (A), E = 0;" "void f() {" " unsigned int *foo = &x;" "}"; ASSERT_EQUALS("unsigned int x ; " "static const unsigned int A = 1 ; " "static const unsigned int B = A ; " "static const unsigned int C = 0 ; " "static const unsigned int D = A ; " "static const unsigned int E = 0 ; " "void f ( ) { " "unsigned int * foo ; " "foo = & x ; " "}", tokenizeAndStringify(code)); } { // Ticket #5266 const char code[] = "class Machine {\n" " static int const STACK_ORDER = 10, STACK_MAX = 1 << STACK_ORDER," " STACK_GUARD = 2;\n" "};"; ASSERT_EQUALS("class Machine {\n" "static const int STACK_ORDER = 10 ; static const int STACK_MAX = 1 << STACK_ORDER ; " "static const int STACK_GUARD = 2 ;\n" "} ;", tokenizeAndStringify(code)); } } void vardecl6() { // ticket #565 const char code1[] = "int z = x >> 16;"; const char res1[] = "int z ; z = x >> 16 ;"; ASSERT_EQUALS(res1, tokenizeAndStringify(code1)); } void vardecl7() { // ticket #603 const char code[] = "void f() {\n" " for (int c = 0; c < 0; ++c) {}\n" " int t;\n" " D(3 > t, \"T\");\n" "}"; const char res[] = "void f ( ) {\n" "for ( int c = 0 ; c < 0 ; ++ c ) { }\n" "int t ;\n" "D ( 3 > t , \"T\" ) ;\n" "}"; ASSERT_EQUALS(res, tokenizeAndStringify(code)); } void vardecl8() { // ticket #696 const char code[] = "char a[10]={'\\0'}, b[10]={'\\0'};"; const char res[] = "char a [ 10 ] = { '\\0' } ; char b [ 10 ] = { '\\0' } ;"; ASSERT_EQUALS(res, tokenizeAndStringify(code)); } void vardecl9() { const char code[] = "char a[2] = {'A', '\\0'}, b[2] = {'B', '\\0'};"; const char res[] = "char a [ 2 ] = { 'A' , '\\0' } ; char b [ 2 ] = { 'B' , '\\0' } ;"; ASSERT_EQUALS(res, tokenizeAndStringify(code)); } void vardecl10() { // ticket #732 const char code[] = "char a [ 2 ] = { '-' } ; memset ( a , '-' , sizeof ( a ) ) ;"; ASSERT_EQUALS(code, tokenizeAndStringify(code)); } void vardecl11() { // ticket #1684 const char code[] = "char a[5][8], b[5][8];"; ASSERT_EQUALS("char a [ 5 ] [ 8 ] ; char b [ 5 ] [ 8 ] ;", tokenizeAndStringify(code)); } void vardecl12() { const char code[] = "struct A { public: B a, b, c, d; };"; ASSERT_EQUALS("struct A { public: B a ; B b ; B c ; B d ; } ;", tokenizeAndStringify(code)); } void vardecl13() { const char code[] = "void f() {\n" " int a = (x < y) ? 1 : 0;\n" "}"; ASSERT_EQUALS("void f ( ) {\nint a ; a = ( x < y ) ? 1 : 0 ;\n}", tokenizeAndStringify(code)); } void vardecl14() { const char code[] = "::std::tr1::shared_ptr pNum1, pNum2;\n"; ASSERT_EQUALS(":: std :: tr1 :: shared_ptr < int > pNum1 ; :: std :: tr1 :: shared_ptr < int > pNum2 ;", tokenizeAndStringify(code, false, Settings::Native, "test.cpp", false)); } void vardecl15() { const char code[] = "const char x[] = \"foo\", y[] = \"bar\";\n"; ASSERT_EQUALS("const char x [ 4 ] = \"foo\" ; const char y [ 4 ] = \"bar\" ;", tokenizeAndStringify(code)); } void vardecl16() { { const char code[] = "const a::b::g::h::l *x [] = foo(),y [][] = bar();\n"; ASSERT_EQUALS("const a :: b < c , d ( e ) , f > :: g :: h < i > :: l * x [ ] = foo ( ) ; " "const a :: b < c , d ( e ) , f > :: g :: h < i > :: l y [ ] [ ] = bar ( ) ;", tokenizeAndStringify(code)); } { const char code[] = "const ::b::g::h::l *x [] = foo(),y [][] = bar();\n"; ASSERT_EQUALS("const :: b < c , d ( e ) , f > :: g :: h < i > :: l * x [ ] = foo ( ) ; " "const :: b < c , d ( e ) , f > :: g :: h < i > :: l y [ ] [ ] = bar ( ) ;", tokenizeAndStringify(code)); } } void vardecl17() { const char code[] = "a < b > :: c :: d :: e < f > x = foo(), y = bar();\n"; ASSERT_EQUALS("a < b > :: c :: d :: e < f > x ; x = foo ( ) ; " "a < b > :: c :: d :: e < f > y ; y = bar ( ) ;", tokenizeAndStringify(code)); } void vardecl18() { const char code[] = "void f() {\n" " g((double)v1*v2, v3, v4);\n" "}\n"; ASSERT_EQUALS("void f ( ) {\n" "g ( ( double ) v1 * v2 , v3 , v4 ) ;\n" "}", tokenizeAndStringify(code)); } void vardecl19() { { const char code[] = "void func(in, r, m)\n" "int in;" "int r,m;" "{\n" "}\n"; ASSERT_EQUALS("void func (\n" "int in , int r , int m\n" ")\n" "{\n" "}", tokenizeAndStringify(code)); } { const char code[] = "void f(r,f)\n" "char *r;\n" "{\n" "}\n"; ASSERT_EQUALS("void f (\n" "char * r\n" ")\n" "\n" "{\n" "}", tokenizeAndStringify(code)); } { const char code[] = "void f(f)\n" "{\n" "}\n"; ASSERT_EQUALS("void f ( )\n" "{\n" "}", tokenizeAndStringify(code)); } { const char code[] = "void f(f,r)\n" "char *r;\n" "{\n" "}\n"; ASSERT_EQUALS("void f (\n" "char * r\n" ")\n" "\n" "{\n" "}", tokenizeAndStringify(code)); } { const char code[] = "void f(r,f,s)\n" "char *r;\n" "char *s;\n" "{\n" "}\n"; ASSERT_EQUALS("void f (\n" "char * r ,\n" "char * s\n" ")\n" "\n" "\n" "{\n" "}", tokenizeAndStringify(code)); } { const char code[] = "void f(r,s,t)\n" "char *r,*s,*t;\n" "{\n" "}\n"; ASSERT_EQUALS("void f (\n" "char * r , char * s , char * t\n" ")\n" "\n" "{\n" "}", tokenizeAndStringify(code)); } { const char code[] = "void f(a, b) register char *a, *b;\n" "{\n" "}\n"; ASSERT_EQUALS("void f ( char * a , char * b )\n" "{\n" "}", tokenizeAndStringify(code)); } } void vardecl20() { // #3700 const char code[] = "void a::b() const\n" "{\n" " register const int X = 0;\n" "}\n"; ASSERT_EQUALS("void a :: b ( ) const\n" "{\n" "const int X = 0 ;\n" "}", tokenizeAndStringify(code)); } void vardecl21() { // type in namespace // #4042 - a::b const *p = 0; const char code1[] = "void f() {\n" " a::b const *p = 0;\n" "}\n"; ASSERT_EQUALS("void f ( ) {\n" "const a :: b * p ; p = 0 ;\n" "}" , tokenizeAndStringify(code1)); // #4226 - ::a::b const *p = 0; const char code2[] = "void f() {\n" " ::a::b const *p = 0;\n" "}\n"; ASSERT_EQUALS("void f ( ) {\n" "const :: a :: b * p ; p = 0 ;\n" "}" , tokenizeAndStringify(code2)); } void vardecl22() { // #4211 - segmentation fault tokenizeAndStringify("A> >* p = 0;"); } void vardecl23() { // #4276 - segmentation fault ASSERT_THROW(tokenizeAndStringify("class a { protected : template < class int x = 1 ; public : int f ( ) ; }"), InternalError); } void vardecl24() { // #4187 - variable declaration within lambda function const char code1[] = "void f() {\n" " std::for_each(ints.begin(), ints.end(), [](int val)\n" " {\n" " int temp = 0;\n" " });\n" "}"; const char expected1[] = "void f ( ) {\n" "std :: for_each ( ints . begin ( ) , ints . end ( ) , [ ] ( int val )\n" "{\n" "int temp ; temp = 0 ;\n" "} ) ;\n" "}"; ASSERT_EQUALS(expected1, tokenizeAndStringify(code1)); const char code2[] = "void f(int j) {\n" " g( [](){int temp = 0;} , j );\n" "}"; const char expected2[] = "void f ( int j ) {\n" "g ( [ ] ( ) { int temp ; temp = 0 ; } , j ) ;\n" "}"; ASSERT_EQUALS(expected2, tokenizeAndStringify(code2)); } void vardecl25() { // #4799 - segmentation fault tokenizeAndStringify("void A::func(P g) const {}\n" "void A::a() {\n" " b = new d( [this]( const P & p) -> double { return this->func(p);} );\n" "}"); } void vardecl26() { // #5907 const char code[] = "extern int *new, obj, player;"; const char expected[] = "extern int * new ; extern int obj ; extern int player ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, Settings::Native, "test.c")); ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } void vardecl27() { // #7850 const char code[] = "extern int foo(char);\n" "void* class(char c) {\n" " if (foo(c))\n" " return 0;\n" " return 0;\n" "}"; tokenizeAndStringify(code, /*expand=*/true, Settings::Native, "test.c"); } void volatile_variables() { const char code[] = "volatile int a=0;\n" "volatile int b=0;\n" "volatile int c=0;\n"; const std::string actual(tokenizeAndStringify(code)); ASSERT_EQUALS("volatile int a ; a = 0 ;\nvolatile int b ; b = 0 ;\nvolatile int c ; c = 0 ;", actual); } void simplifyKeyword() { { const char code[] = "void f (int a [ static 5] );"; ASSERT_EQUALS("void f ( int a [ 5 ] ) ;", tokenizeAndStringify(code)); } { const char in4 [] = "struct B final : A { void foo(); };"; const char out4 [] = "struct B : A { void foo ( ) ; } ;"; ASSERT_EQUALS(out4, tokenizeAndStringify(in4)); const char in5 [] = "struct ArrayItemsValidator final {\n" " SchemaError validate() const override {\n" " for (; pos < value.size(); ++pos) {\n" " }\n" " return none;\n" " }\n" "};\n"; const char out5 [] = "struct ArrayItemsValidator {\n" "SchemaError validate ( ) const override {\n" "for ( ; pos < value . size ( ) ; ++ pos ) {\n" "}\n" "return none ;\n" "}\n" "} ;"; ASSERT_EQUALS(out5, tokenizeAndStringify(in5)); } { // Ticket #8679 const char code[] = "thread_local void *thread_local_var; " "__thread void *thread_local_var_2;"; ASSERT_EQUALS("static void * thread_local_var ; " "void * thread_local_var_2 ;", tokenizeAndStringify(code)); } } /** * tokenize "signed i" => "signed int i" */ void signed1() { { const char code1[] = "void foo ( signed int , float ) ;"; ASSERT_EQUALS(code1, tokenizeAndStringify(code1)); } { const char code1[] = "signed i ;"; const char code2[] = "signed int i ;"; ASSERT_EQUALS(code2, tokenizeAndStringify(code1)); } { const char code1[] = "signed int i ;"; ASSERT_EQUALS(code1, tokenizeAndStringify(code1)); } { const char code1[] = "int signed i ;"; const char code2[] = "signed int i ;"; ASSERT_EQUALS(code2, tokenizeAndStringify(code1)); } { const char code1[] = "void f() { for (signed i=0; i<10; i++) {} }"; const char code2[] = "void f ( ) { for ( signed int i = 0 ; i < 10 ; i ++ ) { } }"; ASSERT_EQUALS(code2, tokenizeAndStringify(code1)); } } /** * tokenize "unsigned i" => "unsigned int i" * tokenize "unsigned" => "unsigned int" */ void unsigned1() { // No changes.. { const char code[] = "void foo ( unsigned int , float ) ;"; ASSERT_EQUALS(code, tokenizeAndStringify(code)); } // insert "int" after "unsigned".. { const char code1[] = "unsigned i ;"; const char code2[] = "unsigned int i ;"; ASSERT_EQUALS(code2, tokenizeAndStringify(code1)); } { const char code1[] = "int unsigned i ;"; const char code2[] = "unsigned int i ;"; ASSERT_EQUALS(code2, tokenizeAndStringify(code1)); } // insert "int" after "unsigned".. { const char code1[] = "void f() { for (unsigned i=0; i<10; i++) {} }"; const char code2[] = "void f ( ) { for ( unsigned int i = 0 ; i < 10 ; i ++ ) { } }"; ASSERT_EQUALS(code2, tokenizeAndStringify(code1)); } // "extern unsigned x;" => "extern int x;" { const char code1[] = "; extern unsigned x;"; const char code2[] = "; extern unsigned int x ;"; ASSERT_EQUALS(code2, tokenizeAndStringify(code1)); } } void unsigned2() { const char code[] = "i = (unsigned)j;"; const char expected[] = "i = ( unsigned int ) j ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } // simplify "unsigned" when using templates.. void unsigned3() { { const char code[] = "; foo();"; const char expected[] = "; foo < unsigned int > ( ) ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "; foo();"; const char expected[] = "; foo < unsigned int > ( ) ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } } void simplifyStdType() { // #4947, #4950, #4951 // usigned long long { const char code[] = "long long unsigned int x;"; const char expected[] = "unsigned long long x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "long long int unsigned x;"; const char expected[] = "unsigned long long x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "unsigned long long int x;"; const char expected[] = "unsigned long long x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "unsigned int long long x;"; const char expected[] = "unsigned long long x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "int unsigned long long x;"; const char expected[] = "unsigned long long x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "int long long unsigned x;"; const char expected[] = "unsigned long long x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } // signed long long { const char code[] = "long long signed int x;"; const char expected[] = "signed long long x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "long long int signed x;"; const char expected[] = "signed long long x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "signed long long int x;"; const char expected[] = "signed long long x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "signed int long long x;"; const char expected[] = "signed long long x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "int signed long long x;"; const char expected[] = "signed long long x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "int long long signed x;"; const char expected[] = "signed long long x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } // usigned short { const char code[] = "short unsigned int x;"; const char expected[] = "unsigned short x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "short int unsigned x;"; const char expected[] = "unsigned short x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "unsigned short int x;"; const char expected[] = "unsigned short x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "unsigned int short x;"; const char expected[] = "unsigned short x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "int unsigned short x;"; const char expected[] = "unsigned short x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "int short unsigned x;"; const char expected[] = "unsigned short x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } // signed short { const char code[] = "short signed int x;"; const char expected[] = "signed short x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "short int signed x;"; const char expected[] = "signed short x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "signed short int x;"; const char expected[] = "signed short x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "signed int short x;"; const char expected[] = "signed short x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "int signed short x;"; const char expected[] = "signed short x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "int short signed x;"; const char expected[] = "signed short x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "unsigned static short const int i;"; const char expected[] = "static const unsigned short i ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "float complex x;"; const char expected[] = "_Complex float x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "complex float x;"; const char expected[] = "_Complex float x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "complex long double x;"; const char expected[] = "_Complex long double x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "long double complex x;"; const char expected[] = "_Complex long double x ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } { const char code[] = "double complex;"; const char expected[] = "double complex ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } } void createLinks() { { const char code[] = "class A{\n" " void f() {}\n" "};"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok = tokenizer.tokens(); // A body {} ASSERT_EQUALS(true, tok->linkAt(2) == tok->tokAt(9)); ASSERT_EQUALS(true, tok->linkAt(9) == tok->tokAt(2)); // f body {} ASSERT_EQUALS(true, tok->linkAt(7) == tok->tokAt(8)); ASSERT_EQUALS(true, tok->linkAt(8) == tok->tokAt(7)); // f () ASSERT_EQUALS(true, tok->linkAt(5) == tok->tokAt(6)); ASSERT_EQUALS(true, tok->linkAt(6) == tok->tokAt(5)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "void f(){\n" " char a[10];\n" " char *b ; b = new char[a[0]];\n" "};"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok = tokenizer.tokens(); // a[10] ASSERT_EQUALS(true, tok->linkAt(7) == tok->tokAt(9)); ASSERT_EQUALS(true, tok->linkAt(9) == tok->tokAt(7)); // new char[] ASSERT_EQUALS(true, tok->linkAt(19) == tok->tokAt(24)); ASSERT_EQUALS(true, tok->linkAt(24) == tok->tokAt(19)); // a[0] ASSERT_EQUALS(true, tok->linkAt(21) == tok->tokAt(23)); ASSERT_EQUALS(true, tok->linkAt(23) == tok->tokAt(21)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "void f(){\n" " foo(g());\n" "};"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok = tokenizer.tokens(); // foo( ASSERT_EQUALS(true, tok->linkAt(6) == tok->tokAt(10)); ASSERT_EQUALS(true, tok->linkAt(10) == tok->tokAt(6)); // g( ASSERT_EQUALS(true, tok->linkAt(8) == tok->tokAt(9)); ASSERT_EQUALS(true, tok->linkAt(9) == tok->tokAt(8)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "bool foo(C a, bar>& f, int b) {\n" " return(af);\n" "}"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok = tokenizer.tokens(); // template< ASSERT_EQUALS(true, tok->tokAt(6) == tok->linkAt(4)); ASSERT_EQUALS(true, tok->tokAt(4) == tok->linkAt(6)); // bar< ASSERT_EQUALS(true, tok->tokAt(17) == tok->linkAt(10)); ASSERT_EQUALS(true, tok->tokAt(10) == tok->linkAt(17)); // x< ASSERT_EQUALS(true, tok->tokAt(16) == tok->linkAt(14)); ASSERT_EQUALS(true, tok->tokAt(14) == tok->linkAt(16)); // af ASSERT_EQUALS(true, nullptr == tok->linkAt(28)); ASSERT_EQUALS(true, nullptr == tok->linkAt(32)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "void foo() {\n" " return static_cast(a);\n" "}"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok = tokenizer.tokens(); // static_cast< ASSERT_EQUALS(true, tok->tokAt(9) == tok->linkAt(7)); ASSERT_EQUALS(true, tok->tokAt(7) == tok->linkAt(9)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "void foo() {\n" " nvwa<(x > y)> ERROR_nnn;\n" "}"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok = tokenizer.tokens(); // nvwa<(x > y)> ASSERT_EQUALS(true, tok->tokAt(12) == tok->linkAt(6)); ASSERT_EQUALS(true, tok->tokAt(6) == tok->linkAt(12)); ASSERT_EQUALS("", errout.str()); } { // #4860 const char code[] = "class A : public B {};"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok = tokenizer.tokens(); // B<..> ASSERT_EQUALS(true, tok->tokAt(5) == tok->linkAt(7)); ASSERT_EQUALS(true, tok->linkAt(5) == tok->tokAt(7)); ASSERT_EQUALS("", errout.str()); } { // #4860 const char code[] = "Bar>>>::set(1, 2, 3);"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok = tokenizer.tokens(); ASSERT_EQUALS(true, tok->tokAt(1) == tok->linkAt(18)); ASSERT_EQUALS(true, tok->tokAt(3) == tok->linkAt(17)); ASSERT_EQUALS(true, tok->tokAt(7) == tok->linkAt(16)); ASSERT_EQUALS(true, tok->tokAt(11) == tok->linkAt(15)); ASSERT_EQUALS("", errout.str()); } { // #5627 const char code[] = "new Foo[10];"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok = tokenizer.tokens(); ASSERT_EQUALS(true, tok->tokAt(2) == tok->linkAt(4)); ASSERT_EQUALS(true, tok->tokAt(4) == tok->linkAt(2)); ASSERT_EQUALS(true, tok->tokAt(5) == tok->linkAt(7)); ASSERT_EQUALS(true, tok->tokAt(7) == tok->linkAt(5)); ASSERT_EQUALS("", errout.str()); } { // #6242 const char code[] = "func = integral_;"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok = tokenizer.tokens(); ASSERT_EQUALS(true, tok->tokAt(3) == tok->linkAt(9)); ASSERT_EQUALS(true, tok->linkAt(3) == tok->tokAt(9)); ASSERT_EQUALS("", errout.str()); } { // if (a < b || c > d) { } const char code[] = "{ if (a < b || c > d); }"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok = tokenizer.tokens(); ASSERT_EQUALS(true, tok->linkAt(3) == nullptr); } { // bool f = a < b || c > d const char code[] = "bool f = a < b || c > d;"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok = tokenizer.tokens(); ASSERT_EQUALS(true, tok->linkAt(4) == nullptr); } { // template const char code[] = "a < b || c > d;"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok = tokenizer.tokens(); ASSERT_EQUALS(true, tok->linkAt(1) == tok->tokAt(5)); } { // if (a < ... > d) { } const char code[] = "{ if (a < b || c == 3 || d > e); }"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok = tokenizer.tokens(); ASSERT_EQUALS(true, tok->linkAt(3) == nullptr); } { // template const char code[] = "a d;"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok = tokenizer.tokens(); ASSERT_EQUALS(true, tok->linkAt(1) == tok->tokAt(7)); } { // template const char code[] = "a d;"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok = tokenizer.tokens(); ASSERT_EQUALS(true, tok->linkAt(1) == tok->tokAt(7)); } { const char code[] = "template < f = b || c > struct S;"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok = tokenizer.tokens(); ASSERT_EQUALS(true, tok->linkAt(1) == tok->tokAt(7)); ASSERT_EQUALS(true, tok->tokAt(1) == tok->linkAt(7)); } { const char code[] = "struct A : B {};"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok = tokenizer.tokens(); ASSERT_EQUALS(true, tok->linkAt(4) == tok->tokAt(8)); ASSERT_EQUALS(true, tok->tokAt(4) == tok->linkAt(8)); } { const char code[] = "Data;"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok = tokenizer.tokens(); ASSERT_EQUALS(true, tok->linkAt(1) == tok->tokAt(4)); ASSERT_EQUALS(true, tok->tokAt(1) == tok->linkAt(4)); } { // #6601 const char code[] = "template struct FuncType : FuncType { };"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok = tokenizer.tokens(); ASSERT_EQUALS(true, tok->linkAt(1) == tok->tokAt(4)); // ASSERT_EQUALS(true, tok->linkAt(7) == tok->tokAt(14)); // ASSERT_EQUALS(true, tok->linkAt(9) == tok->tokAt(11)); // (&) ASSERT_EQUALS(true, tok->linkAt(12) == tok->tokAt(13)); // () ASSERT_EQUALS(true, tok->linkAt(17) == tok->tokAt(21)); // ASSERT_EQUALS(true, tok->linkAt(19) == tok->tokAt(20)); // () ASSERT_EQUALS(true, tok->linkAt(22) == tok->tokAt(23)); // {} } } void createLinks2() { { // #7158 const char code[] = "enum { value = boost::mpl::at_c };"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok = Token::findsimplematch(tokenizer.tokens(), "<"); ASSERT_EQUALS(true, tok->link() == tok->tokAt(4)); ASSERT_EQUALS(true, tok->linkAt(4) == tok); } { // #7865 const char code[] = "template \n" "struct CheckedDivOp< T, U, typename std::enable_if::value || std::is_floating_point::value>::type> {\n" "};\n"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok1 = Token::findsimplematch(tokenizer.tokens(), "struct")->tokAt(2); const Token *tok2 = Token::findsimplematch(tokenizer.tokens(), "{")->previous(); ASSERT_EQUALS(true, tok1->link() == tok2); ASSERT_EQUALS(true, tok2->link() == tok1); } { // #7975 const char code[] = "template X copy() {};\n"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok1 = Token::findsimplematch(tokenizer.tokens(), "< Y"); const Token *tok2 = Token::findsimplematch(tok1, "> copy"); ASSERT_EQUALS(true, tok1->link() == tok2); ASSERT_EQUALS(true, tok2->link() == tok1); } { // #8006 const char code[] = "C && a = b;"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok1 = tokenizer.tokens()->next(); const Token *tok2 = tok1->tokAt(2); ASSERT_EQUALS(true, tok1->link() == tok2); ASSERT_EQUALS(true, tok2->link() == tok1); } { // #8115 const char code[] = "void Test(C && c);"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *tok1 = Token::findsimplematch(tokenizer.tokens(), "<"); const Token *tok2 = tok1->tokAt(2); ASSERT_EQUALS(true, tok1->link() == tok2); ASSERT_EQUALS(true, tok2->link() == tok1); } { // #8654 const char code[] = "template struct A {}; " "template struct foo : A... {};"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *A = Token::findsimplematch(tokenizer.tokens(), "A <"); ASSERT_EQUALS(true, A->next()->link() == A->tokAt(3)); } { // #8851 const char code[] = "template::type>" "void basic_json() {}"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); ASSERT_EQUALS(true, Token::simpleMatch(tokenizer.tokens()->next()->link(), "> void")); } { // #9094 - template usage or comparison? const char code[] = "a = f(x%x<--a==x>x);"; Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); ASSERT(nullptr == Token::findsimplematch(tokenizer.tokens(), "<")->link()); } { // #9131 - template usage or comparison? const char code[] = "using std::list; list l;"; Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); ASSERT(nullptr != Token::findsimplematch(tokenizer.tokens(), "<")->link()); } { const char code[] = "using std::set;\n" "void foo()\n" "{\n" " for (set::iterator i = sources.begin(); i != sources.end(); ++i) {}\n" "}"; Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); ASSERT(nullptr != Token::findsimplematch(tokenizer.tokens(), "<")->link()); } { // #8890 const char code[] = "void f() {\n" " a<> b;\n" " b.a<>::c();\n" "}\n"; Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); ASSERT(nullptr != Token::findsimplematch(tokenizer.tokens(), "> ::")->link()); } { // #9136 const char code[] = "template char * a;\n" "template struct c {\n" " void d() { a[0]; }\n" "};\n"; Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); ASSERT(nullptr != Token::findsimplematch(tokenizer.tokens(), "> [")->link()); } { // #9057 const char code[] = "template struct a;\n" "template using c = typename a::d;\n" "template using f = c;\n" "template > struct g {};\n" "template using baz = g;\n"; Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); ASSERT(nullptr != Token::findsimplematch(tokenizer.tokens(), "> ;")->link()); } { // #9141 const char code[] = "struct a {\n" " typedef int b;\n" " operator b();\n" "};\n" "template using c = a;\n" "template c e;\n" "auto f = -e<1> == 0;\n"; Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); ASSERT(nullptr != Token::findsimplematch(tokenizer.tokens(), "> ==")->link()); } { // #9145 const char code[] = "template struct b {\n" " template constexpr void operator()(c &&) const;\n" "};\n" "template struct e { b f; };\n" "template using h = e;\n" "template h i;\n" "template \n" "template \n" "constexpr void b::operator()(c &&) const {\n" " i<3>.f([] {});\n" "}\n"; Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); ASSERT(nullptr != Token::findsimplematch(tokenizer.tokens(), "> . f (")->link()); } } void simplifyString() { errout.str(""); Tokenizer tokenizer(&settings0, this); ASSERT_EQUALS("\"abc\"", tokenizer.simplifyString("\"abc\"")); ASSERT_EQUALS("\"\n\"", tokenizer.simplifyString("\"\\xa\"")); ASSERT_EQUALS("\"3\"", tokenizer.simplifyString("\"\\x33\"")); ASSERT_EQUALS("\"33\"", tokenizer.simplifyString("\"\\x333\"")); ASSERT_EQUALS("\"a\"", tokenizer.simplifyString("\"\\x61\"")); ASSERT_EQUALS("\"\n1\"", tokenizer.simplifyString("\"\\0121\"")); ASSERT_EQUALS("\"3\"", tokenizer.simplifyString("\"\\x33\"")); ASSERT_EQUALS("\" 0\"", tokenizer.simplifyString("\"\\0400\"")); ASSERT_EQUALS("\"\\nhello\"", tokenizer.simplifyString("\"\\nhello\"")); ASSERT_EQUALS("\"aaa\"", tokenizer.simplifyString("\"\\x61\\x61\\x61\"")); ASSERT_EQUALS("\"\n1\n1\n1\"", tokenizer.simplifyString("\"\\0121\\0121\\0121\"")); ASSERT_EQUALS("\"\\\\x61\"", tokenizer.simplifyString("\"\\\\x61\"")); ASSERT_EQUALS("\"b\"", tokenizer.simplifyString("\"\\x62\"")); ASSERT_EQUALS("\" 7\"", tokenizer.simplifyString("\"\\0407\"")); // terminate a string at null character. ASSERT_EQUALS(std::string("\"a") + '\0' + "\"", tokenizer.simplifyString("\"a\\0\"")); } void simplifyConst() { ASSERT_EQUALS("void foo ( ) { const int x ; }", tokenizeAndStringify("void foo(){ int const x;}")); ASSERT_EQUALS("void foo ( ) { { } const long x ; }", tokenizeAndStringify("void foo(){ {} long const x;}")); ASSERT_EQUALS("void foo ( int b , const unsigned int x ) { }", tokenizeAndStringify("void foo(int b,unsigned const x){}")); ASSERT_EQUALS("void foo ( ) { bar ( ) ; const char x ; }", tokenizeAndStringify("void foo(){ bar(); char const x;}")); ASSERT_EQUALS("void foo ( const char x ) { }", tokenizeAndStringify("void foo(char const x){}")); ASSERT_EQUALS("void foo ( int b , const char x ) { }", tokenizeAndStringify("void foo(int b,char const x){}")); ASSERT_EQUALS("void foo ( ) { int * const x ; }", tokenizeAndStringify("void foo(){ int * const x;}")); ASSERT_EQUALS("const int foo ( ) ;", tokenizeAndStringify("int const foo ();")); ASSERT_EQUALS("const int x ;", tokenizeAndStringify("int const x;")); ASSERT_EQUALS("const unsigned int x ;", tokenizeAndStringify("unsigned const x;")); ASSERT_EQUALS("const struct X x ;", tokenizeAndStringify("struct X const x;")); } void switchCase() { ASSERT_EQUALS("void foo ( int i ) { switch ( i ) { case -1 : ; break ; } }", tokenizeAndStringify("void foo (int i) { switch(i) { case -1: break; } }")); //ticket #3227 ASSERT_EQUALS("void foo ( ) { switch ( n ) { label : ; case 1 : ; label1 : ; label2 : ; break ; } }", tokenizeAndStringify("void foo(){ switch (n){ label: case 1: label1: label2: break; }}")); //ticket #8345 ASSERT_EQUALS("void foo ( ) { switch ( 0 ) { case 0 : ; default : ; } }", tokenizeAndStringify("void foo () { switch(0) case 0 : default : ; }")); //ticket #8477 ASSERT_EQUALS("void foo ( ) { enum Anonymous0 : int { Six = 6 } ; return Six ; }", tokenizeAndStringify("void foo () { enum : int { Six = 6 } ; return Six ; }")); // ticket #8281 tokenizeAndStringify("void lzma_decode(int i) { " " bool state; " " switch (i) " " while (true) { " " state=false; " " case 1: " " ; " " }" "}"); // ticket #8417 tokenizeAndStringify("void printOwnedAttributes(int mode) { " " switch(mode) case 0: { break; } " "}"); ASSERT_THROW(tokenizeAndStringify("void printOwnedAttributes(int mode) { " " switch(mode) case 0: { break; } case 1: ; " "}"), InternalError); } void simplifyPointerToStandardType() { // Pointer to standard type ASSERT_EQUALS("char buf [ 100 ] ; readlink ( path , buf , 99 ) ;", tokenizeAndStringify("char buf[100] ; readlink(path, &buf[0], 99);", true, Settings::Native, "test.c")); ASSERT_EQUALS("void foo ( char * c ) { if ( 1 == ( 1 & c [ 0 ] ) ) { } }", tokenizeAndStringify("void foo(char *c) { if (1==(1 & c[0])) {} }", true, Settings::Native, "test.c")); // Simplification of unknown type - C only ASSERT_EQUALS("foo data [ 100 ] ; something ( foo ) ;", tokenizeAndStringify("foo data[100]; something(&foo[0]);", true, Settings::Native, "test.c")); // C++: No pointer simplification ASSERT_EQUALS("foo data [ 100 ] ; something ( & foo [ 0 ] ) ;", tokenizeAndStringify("foo data[100]; something(&foo[0]);")); } void simplifyFunctionPointers1() { ASSERT_EQUALS("void ( * f ) ( ) ;", tokenizeAndStringify("void (*f)();")); ASSERT_EQUALS("void * ( * f ) ( ) ;", tokenizeAndStringify("void *(*f)();")); ASSERT_EQUALS("unsigned int ( * f ) ( ) ;", tokenizeAndStringify("unsigned int (*f)();")); ASSERT_EQUALS("unsigned int * ( * f ) ( ) ;", tokenizeAndStringify("unsigned int * (*f)();")); } void simplifyFunctionPointers2() { const char code[] = "typedef void (* PF)();" "void f1 ( ) { }" "PF pf = &f1;" "PF pfs[] = { &f1, &f1 };"; const char expected[] = "void f1 ( ) { } " "void ( * pf ) ( ) ; pf = & f1 ; " "void ( * pfs [ ] ) ( ) = { & f1 , & f1 } ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } void simplifyFunctionPointers3() { // Related with ticket #2873 const char code[] = "void f() {\n" "(void)(xy(*p)(0);)" "\n}"; const char expected[] = "void f ( ) {\n" "( void ) ( xy ( * p ) ( 0 ) ; )\n" "}"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); } void simplifyFunctionPointers4() { const char code[] = "struct S\n" "{\n" " typedef void (*FP)();\n" " virtual FP getFP();\n" "};"; const char expected[] = "1: struct S\n" "2: {\n" "3:\n" "4: virtual void * getFP ( ) ;\n" "5: } ;\n"; ASSERT_EQUALS(expected, tokenizeDebugListing(code)); } void simplifyFunctionPointers5() { const char code[] = ";void (*fp[])(int a) = {0,0,0};"; const char expected[] = "1: ; void ( * fp@1 [ ] ) ( ) = { 0 , 0 , 0 } ;\n"; // TODO: Array dimension ASSERT_EQUALS(expected, tokenizeDebugListing(code)); } void simplifyFunctionPointers6() { const char code1[] = "void (*fp(void))(int) {}"; const char expected1[] = "1: void * fp ( void ) { }\n"; ASSERT_EQUALS(expected1, tokenizeDebugListing(code1)); const char code2[] = "std::string (*fp(void))(int);"; const char expected2[] = "1: std :: string * fp ( void ) ;\n"; ASSERT_EQUALS(expected2, tokenizeDebugListing(code2)); } void simplifyFunctionPointers7() { const char code1[] = "void (X::*y)();"; const char expected1[] = "1: void ( * y@1 ) ( ) ;\n"; ASSERT_EQUALS(expected1, tokenizeDebugListing(code1)); } void simplifyFunctionPointers8() { const char code1[] = "int (*f)() throw(int);"; const char expected1[] = "1: int ( * f@1 ) ( ) ;\n"; ASSERT_EQUALS(expected1, tokenizeDebugListing(code1)); } void simplifyFunctionPointers9() { // function call with function pointer const char code1[] = "int f() { (*f)(); }"; const char expected1[] = "1: int f ( ) { ( * f ) ( ) ; }\n"; ASSERT_EQUALS(expected1, tokenizeDebugListing(code1)); const char code2[] = "int f() { return (*f)(); }"; const char expected2[] = "1: int f ( ) { return ( * f ) ( ) ; }\n"; ASSERT_EQUALS(expected2, tokenizeDebugListing(code2)); const char code3[] = "int f() { throw (*f)(); }"; const char expected3[] = "1: int f ( ) { throw ( * f ) ( ) ; }\n"; ASSERT_EQUALS(expected3, tokenizeDebugListing(code3)); } void removedeclspec() { ASSERT_EQUALS("a b", tokenizeAndStringify("a __declspec ( dllexport ) b")); ASSERT_EQUALS("a b", tokenizeAndStringify("a _declspec ( dllexport ) b")); ASSERT_EQUALS("int a ;", tokenizeAndStringify("__declspec(thread) __declspec(align(32)) int a;")); ASSERT_EQUALS("int i ;", tokenizeAndStringify("__declspec(allocate(\"mycode\")) int i;")); ASSERT_EQUALS("struct IUnknown ;", tokenizeAndStringify("struct __declspec(uuid(\"00000000-0000-0000-c000-000000000046\")) IUnknown;")); ASSERT_EQUALS("__property int x [ ] ;", tokenizeAndStringify("__declspec(property(get=GetX, put=PutX)) int x[];")); } void removeattribute() { ASSERT_EQUALS("short array [ 3 ] ;", tokenizeAndStringify("short array[3] __attribute__ ((aligned));")); ASSERT_EQUALS("int x [ 2 ] ;", tokenizeAndStringify("int x[2] __attribute__ ((packed));")); ASSERT_EQUALS("int vecint ;", tokenizeAndStringify("int __attribute__((mode(SI))) __attribute__((vector_size (16))) vecint;")); // alternate spelling #5328 ASSERT_EQUALS("short array [ 3 ] ;", tokenizeAndStringify("short array[3] __attribute ((aligned));")); ASSERT_EQUALS("int x [ 2 ] ;", tokenizeAndStringify("int x[2] __attribute ((packed));")); ASSERT_EQUALS("int vecint ;", tokenizeAndStringify("int __attribute((mode(SI))) __attribute((vector_size (16))) vecint;")); ASSERT_EQUALS("struct Payload_IR_config { uint8_t tap [ 16 ] ; } ;", tokenizeAndStringify("struct __attribute__((packed, gcc_struct)) Payload_IR_config { uint8_t tap[16]; };")); } void functionAttributeBefore() { const char code[] = "void __attribute__((pure)) __attribute__((nothrow)) __attribute__((const)) func1();\n" "void __attribute__((__pure__)) __attribute__((__nothrow__)) __attribute__((__const__)) func2();\n" "void __attribute__((nothrow)) __attribute__((pure)) __attribute__((const)) func3();\n" "void __attribute__((__nothrow__)) __attribute__((__pure__)) __attribute__((__const__)) func4();\n" "void __attribute__((noreturn)) func5();"; const char expected[] = "void func1 ( ) ; void func2 ( ) ; void func3 ( ) ; void func4 ( ) ; void func5 ( ) ;"; errout.str(""); // tokenize.. Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); // Expected result.. ASSERT_EQUALS(expected, tokenizer.tokens()->stringifyList(nullptr, false)); const Token * func1 = Token::findsimplematch(tokenizer.tokens(), "func1"); const Token * func2 = Token::findsimplematch(tokenizer.tokens(), "func2"); const Token * func3 = Token::findsimplematch(tokenizer.tokens(), "func3"); const Token * func4 = Token::findsimplematch(tokenizer.tokens(), "func4"); const Token * func5 = Token::findsimplematch(tokenizer.tokens(), "func5"); ASSERT(func1 && func1->isAttributePure() && func1->isAttributeNothrow() && func1->isAttributeConst()); ASSERT(func2 && func2->isAttributePure() && func2->isAttributeNothrow() && func2->isAttributeConst()); ASSERT(func3 && func3->isAttributePure() && func3->isAttributeNothrow() && func3->isAttributeConst()); ASSERT(func4 && func4->isAttributePure() && func4->isAttributeNothrow() && func4->isAttributeConst()); ASSERT(func5 && func5->isAttributeNoreturn()); } void functionAttributeAfter() { const char code[] = "void func1() __attribute__((pure)) __attribute__((nothrow)) __attribute__((const));\n" "void func2() __attribute__((__pure__)) __attribute__((__nothrow__)) __attribute__((__const__));\n" "void func3() __attribute__((nothrow)) __attribute__((pure)) __attribute__((const));\n" "void func4() __attribute__((__nothrow__)) __attribute__((__pure__)) __attribute__((__const__));" "void func5() __attribute__((noreturn));"; const char expected[] = "void func1 ( ) ; void func2 ( ) ; void func3 ( ) ; void func4 ( ) ; void func5 ( ) ;"; errout.str(""); // tokenize.. Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); // Expected result.. ASSERT_EQUALS(expected, tokenizer.tokens()->stringifyList(nullptr, false)); const Token * func1 = Token::findsimplematch(tokenizer.tokens(), "func1"); const Token * func2 = Token::findsimplematch(tokenizer.tokens(), "func2"); const Token * func3 = Token::findsimplematch(tokenizer.tokens(), "func3"); const Token * func4 = Token::findsimplematch(tokenizer.tokens(), "func4"); const Token * func5 = Token::findsimplematch(tokenizer.tokens(), "func5"); ASSERT(func1 && func1->isAttributePure() && func1->isAttributeNothrow() && func1->isAttributeConst()); ASSERT(func2 && func2->isAttributePure() && func2->isAttributeNothrow() && func2->isAttributeConst()); ASSERT(func3 && func3->isAttributePure() && func3->isAttributeNothrow() && func3->isAttributeConst()); ASSERT(func4 && func4->isAttributePure() && func4->isAttributeNothrow() && func4->isAttributeConst()); ASSERT(func5 && func5->isAttributeNoreturn()); } void functionAttributeListBefore() { const char code[] = "void __attribute__((pure,nothrow,const)) func1();\n" "void __attribute__((__pure__,__nothrow__,__const__)) func2();\n" "void __attribute__((nothrow,pure,const)) func3();\n" "void __attribute__((__nothrow__,__pure__,__const__)) func4();\n" "void __attribute__((noreturn,format(printf,1,2))) func5();\n" "void __attribute__((__nothrow__)) __attribute__((__pure__,__const__)) func6();\n" "void __attribute__((__nothrow__,__pure__)) __attribute__((__const__)) func7();\n" "void __attribute__((noreturn)) __attribute__(()) __attribute__((nothrow,pure,const)) func8();"; const char expected[] = "void func1 ( ) ; void func2 ( ) ; void func3 ( ) ; void func4 ( ) ; void func5 ( ) ; " "void func6 ( ) ; void func7 ( ) ; void func8 ( ) ;"; errout.str(""); // tokenize.. Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); // Expected result.. ASSERT_EQUALS(expected, tokenizer.tokens()->stringifyList(nullptr, false)); const Token * func1 = Token::findsimplematch(tokenizer.tokens(), "func1"); const Token * func2 = Token::findsimplematch(tokenizer.tokens(), "func2"); const Token * func3 = Token::findsimplematch(tokenizer.tokens(), "func3"); const Token * func4 = Token::findsimplematch(tokenizer.tokens(), "func4"); const Token * func5 = Token::findsimplematch(tokenizer.tokens(), "func5"); const Token * func6 = Token::findsimplematch(tokenizer.tokens(), "func6"); const Token * func7 = Token::findsimplematch(tokenizer.tokens(), "func7"); const Token * func8 = Token::findsimplematch(tokenizer.tokens(), "func8"); ASSERT(func1 && func1->isAttributePure() && func1->isAttributeNothrow() && func1->isAttributeConst()); ASSERT(func2 && func2->isAttributePure() && func2->isAttributeNothrow() && func2->isAttributeConst()); ASSERT(func3 && func3->isAttributePure() && func3->isAttributeNothrow() && func3->isAttributeConst()); ASSERT(func4 && func4->isAttributePure() && func4->isAttributeNothrow() && func4->isAttributeConst()); ASSERT(func5 && func5->isAttributeNoreturn()); ASSERT(func6 && func6->isAttributePure() && func6->isAttributeNothrow() && func6->isAttributeConst()); ASSERT(func7 && func7->isAttributePure() && func7->isAttributeNothrow() && func7->isAttributeConst()); ASSERT(func8 && func8->isAttributeNoreturn() && func8->isAttributePure() && func8->isAttributeNothrow() && func8->isAttributeConst()); } void functionAttributeListAfter() { const char code[] = "void func1() __attribute__((pure,nothrow,const));\n" "void func2() __attribute__((__pure__,__nothrow__,__const__));\n" "void func3() __attribute__((nothrow,pure,const));\n" "void func4() __attribute__((__nothrow__,__pure__,__const__));\n" "void func5() __attribute__((noreturn,format(printf,1,2)));\n" "void func6() __attribute__((__nothrow__)) __attribute__((__pure__,__const__));\n" "void func7() __attribute__((__nothrow__,__pure__)) __attribute__((__const__));\n" "void func8() __attribute__((noreturn)) __attribute__(()) __attribute__((nothrow,pure,const));"; const char expected[] = "void func1 ( ) ; void func2 ( ) ; void func3 ( ) ; void func4 ( ) ; void func5 ( ) ; " "void func6 ( ) ; void func7 ( ) ; void func8 ( ) ;"; errout.str(""); // tokenize.. Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); // Expected result.. ASSERT_EQUALS(expected, tokenizer.tokens()->stringifyList(nullptr, false)); const Token * func1 = Token::findsimplematch(tokenizer.tokens(), "func1"); const Token * func2 = Token::findsimplematch(tokenizer.tokens(), "func2"); const Token * func3 = Token::findsimplematch(tokenizer.tokens(), "func3"); const Token * func4 = Token::findsimplematch(tokenizer.tokens(), "func4"); const Token * func5 = Token::findsimplematch(tokenizer.tokens(), "func5"); const Token * func6 = Token::findsimplematch(tokenizer.tokens(), "func6"); const Token * func7 = Token::findsimplematch(tokenizer.tokens(), "func7"); const Token * func8 = Token::findsimplematch(tokenizer.tokens(), "func8"); ASSERT(func1 && func1->isAttributePure() && func1->isAttributeNothrow() && func1->isAttributeConst()); ASSERT(func2 && func2->isAttributePure() && func2->isAttributeNothrow() && func2->isAttributeConst()); ASSERT(func3 && func3->isAttributePure() && func3->isAttributeNothrow() && func3->isAttributeConst()); ASSERT(func4 && func4->isAttributePure() && func4->isAttributeNothrow() && func4->isAttributeConst()); ASSERT(func5 && func5->isAttributeNoreturn()); ASSERT(func6 && func6->isAttributePure() && func6->isAttributeNothrow() && func6->isAttributeConst()); ASSERT(func7 && func7->isAttributePure() && func7->isAttributeNothrow() && func7->isAttributeConst()); ASSERT(func8 && func8->isAttributeNoreturn() && func8->isAttributePure() && func8->isAttributeNothrow() && func8->isAttributeConst()); } void splitTemplateRightAngleBrackets() { { const char code[] = "; z = x < 0 ? x >> y : x >> y;"; ASSERT_EQUALS("; z = x < 0 ? x >> y : x >> y ;", tokenizeAndStringify(code)); } { // ftp://ftp.de.debian.org/debian/pool/main/f/ffmpeg/ffmpeg_4.3.1.orig.tar.xz // ffmpeg-4.3.1/libavcodec/mpeg4videodec.c:376 const char code[] = "void f ( ) {\n" " int shift_y = ctx->sprite_shift[0];\n" " int shift_c = ctx->sprite_shift[1];\n" " if ( shift_c < 0 || shift_y < 0 ||\n" " FFABS ( sprite_offset [ 0 ] [ i ] ) >= INT_MAX >> shift_y ||\n" " FFABS ( sprite_offset [ 1 ] [ i ] ) >= INT_MAX >> shift_c ||\n" " FFABS ( sprite_delta [ 0 ] [ i ] ) >= INT_MAX >> shift_y ||\n" " FFABS ( sprite_delta [ 1 ] [ i ] ) >= INT_MAX >> shift_y ) ;\n" "}"; ASSERT_EQUALS(std::string::npos, tokenizeAndStringify(code).find("> >")); } } void cpp03template1() { { const char *code = "template struct extent {};"; ASSERT_EQUALS("template < typename > struct extent { } ;", tokenizeAndStringify(code)); } { const char *code = "template struct extent;"; ASSERT_EQUALS("template < typename > struct extent ;", tokenizeAndStringify(code)); } { const char *code = "template struct extent;"; ASSERT_EQUALS("template < typename , unsigned int = 0 > struct extent ;", tokenizeAndStringify(code)); } } void cpp0xtemplate1() { const char *code = "template \n" "void fn2 (T t = []{return 1;}())\n" "{}\n" "int main()\n" "{\n" " fn2();\n" "}\n"; ASSERT_EQUALS("void fn2 ( int t = [ ] { return 1 ; } ( ) ) ;\n" "\n" "int main ( )\n" "{\n" "fn2 ( ) ;\n" "}\n" "void fn2 ( int t = [ ] { return 1 ; } ( ) )\n" "{ }", tokenizeAndStringify(code)); } void cpp0xtemplate2() { // tokenize ">>" into "> >" const char *code = "list> ints;\n"; ASSERT_EQUALS("list < list < int > > ints ;", tokenizeAndStringify(code)); } void cpp0xtemplate3() { // #2549 const char *code = "template\n" "struct S\n" "{};\n" "S s;\n"; ASSERT_EQUALS("struct S ;\n" "\n" "\n" "S s ;\n" "struct S\n" "{ } ;", tokenizeAndStringify(code)); } void cpp0xtemplate4() { // #6181, #6354, #6414 tokenizeAndStringify("class A; " "template class Disposer; " "template > class Shim {}; " "class B : public Shim {};"); tokenizeAndStringify("template class ELFObjectImage {}; " "ObjectImage *createObjectImage() { " " return new ELFObjectImage>(Obj); " "} " "void resolveX86_64Relocation() { " " reinterpret_cast(0); " "}"); tokenizeAndStringify("template " "value_type Base(const value_type x, const value_type dx, function_type func, int type_deriv) { " " return 0.0; " "}; " "namespace { " " template class C { " " void Fun(int G, const double x); " " }; " " template void C::Fun(int G, const double x) {" " Base>(2, 2, f, 0); " " }; " " template class C2 {}; " "}"); } void cpp0xtemplate5() { // #9154 { const char *code = "struct s>;"; ASSERT_EQUALS("struct s < x < u ... > > ;", tokenizeAndStringify(code)); } { const char *code = "template using c = e,b...>>;"; ASSERT_EQUALS("template < class f > using c = e < i < q < f , r > , b ... > > ;", tokenizeAndStringify(code)); } { const char *code = "struct s> { };"; ASSERT_EQUALS("struct s < x < u ... > > { } ;", tokenizeAndStringify(code)); } { const char *code = "struct q : s> { };"; ASSERT_EQUALS("struct q : s < x < u ... > > { } ;", tokenizeAndStringify(code)); } { const char *code = "struct q : private s> { };"; ASSERT_EQUALS("struct q : private s < x < u ... > > { } ;", tokenizeAndStringify(code)); } } void cpp14template() { // Ticket #6708 tokenizeAndStringify("template " "decltype(auto) forward(T& t) { return 0; }"); } void arraySize() { ASSERT_EQUALS("; int a [ 3 ] = { 1 , 2 , 3 } ;", tokenizeAndStringify(";int a[]={1,2,3};")); ASSERT_EQUALS("; int a [ 3 ] = { 1 , 2 , 3 } ;", tokenizeAndStringify(";int a[]={1,2,3,};")); ASSERT_EQUALS("; foo a [ 3 ] = { { 1 , 2 } , { 3 , 4 } , { 5 , 6 } } ;", tokenizeAndStringify(";foo a[]={{1,2},{3,4},{5,6}};")); ASSERT_EQUALS("; int a [ 1 ] = { foo < bar1 , bar2 > ( 123 , 4 ) } ;", tokenizeAndStringify(";int a[]={foo(123,4)};")); ASSERT_EQUALS("; int a [ 2 ] = { b > c ? 1 : 2 , 3 } ;", tokenizeAndStringify(";int a[]={ b>c?1:2,3};")); ASSERT_EQUALS("int main ( ) { int a [ 2 ] = { b < c ? 1 : 2 , 3 } }", tokenizeAndStringify("int main(){int a[]={bx)=0; }")); //with '(' parentheses ASSERT_EQUALS("void f ( ) { ab : ; * ( * b ) . x = 0 ; }", tokenizeAndStringify("void f() { ab: *(* b)->x=0; }")); ASSERT_EQUALS("void f ( ) { ab : ; ( * * b ) . x = 0 ; }", tokenizeAndStringify("void f() { ab: (** b).x=0; }")); ASSERT_EQUALS("void f ( ) { ab : ; & ( * b . x ) = 0 ; }", tokenizeAndStringify("void f() { ab: &(*b.x)=0; }")); //with '{' parentheses ASSERT_EQUALS("void f ( ) { ab : ; { b = 0 ; } }", tokenizeAndStringify("void f() { ab: {b=0;} }")); ASSERT_EQUALS("void f ( ) { ab : ; { * b = 0 ; } }", tokenizeAndStringify("void f() { ab: { *b=0;} }")); ASSERT_EQUALS("void f ( ) { ab : ; { & b = 0 ; } }", tokenizeAndStringify("void f() { ab: { &b=0;} }")); ASSERT_EQUALS("void f ( ) { ab : ; { & ( * b . x ) = 0 ; } }", tokenizeAndStringify("void f() { ab: {&(*b.x)=0;} }")); //with unhandled MACRO() code ASSERT_THROW(tokenizeAndStringify("void f() { MACRO(ab: b=0;, foo)}"), InternalError); ASSERT_EQUALS("void f ( ) { MACRO ( bar , ab : { & ( * b . x ) = 0 ; } ) }", tokenizeAndStringify("void f() { MACRO(bar, ab: {&(*b.x)=0;})}")); } void simplifyInitVar() { { const char code[] = "int i ; int p(0);"; ASSERT_EQUALS("int i ; int p ; p = 0 ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "int i; int *p(0);"; ASSERT_EQUALS("int i ; int * p ; p = 0 ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "int p(0);"; ASSERT_EQUALS("int p ; p = 0 ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "int *p(0);"; ASSERT_EQUALS("int * p ; p = 0 ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "int i ; int p(i);"; ASSERT_EQUALS("int i ; int p ; p = i ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "int i; int *p(&i);"; ASSERT_EQUALS("int i ; int * p ; p = & i ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "int i; void *p(&i);"; ASSERT_EQUALS("int i ; void * p ; p = & i ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "struct S { }; struct S s; struct S *p(&s);"; ASSERT_EQUALS("struct S { } ; struct S s ; struct S * p ; p = & s ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "struct S { }; S s; S *p(&s);"; ASSERT_EQUALS("struct S { } ; S s ; S * p ; p = & s ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "union S { int i; float f; }; union S s; union S *p(&s);"; ASSERT_EQUALS("union S { int i ; float f ; } ; union S s ; union S * p ; p = & s ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "union S { int i; float f; }; S s; S *p(&s);"; ASSERT_EQUALS("union S { int i ; float f ; } ; S s ; S * p ; p = & s ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "class C { }; class C c; class C *p(&c);"; ASSERT_EQUALS("class C { } ; class C c ; class C * p ; p = & c ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "class C { }; C c; C *p(&c);"; ASSERT_EQUALS("class C { } ; C c ; C * p ; p = & c ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "struct S { }; struct S s; struct S s1(s);"; ASSERT_EQUALS("struct S { } ; struct S s ; struct S s1 ( s ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "struct S { }; S s; S s1(s);"; ASSERT_EQUALS("struct S { } ; S s ; S s1 ( s ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "struct S { }; struct S s; struct S s1(&s);"; ASSERT_EQUALS("struct S { } ; struct S s ; struct S s1 ( & s ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "struct S { }; S s; S s1(&s);"; ASSERT_EQUALS("struct S { } ; S s ; S s1 ( & s ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "class S { int function(); };"; ASSERT_EQUALS("class S { int function ( ) ; } ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "class S { int function(void); };"; ASSERT_EQUALS("class S { int function ( void ) ; } ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "class S { int function(int); };"; ASSERT_EQUALS("class S { int function ( int ) ; } ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "int function(void);"; ASSERT_EQUALS("int function ( void ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "int function(int);"; ASSERT_EQUALS("int function ( int ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "extern int function(void);"; ASSERT_EQUALS("extern int function ( void ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "int function1(void); int function2(void);"; ASSERT_EQUALS("int function1 ( void ) ; int function2 ( void ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "int function(A);"; // We can't tell if this a function prototype or a variable without knowing // what A is. Since A is undefined, just leave it alone. ASSERT_EQUALS("int function ( A ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "int i; int function(A);"; ASSERT_EQUALS("int i ; int function ( A ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "class A { } ; int foo(A);"; ASSERT_EQUALS("class A { } ; int foo ( A ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "class A { } ; A a; int foo(a);"; ASSERT_EQUALS("class A { } ; A a ; int foo ; foo = a ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "int x(f());"; ASSERT_EQUALS("int x ; x = f ( ) ;", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } { const char code[] = "{ return doSomething(X), 0; }"; ASSERT_EQUALS("{ return doSomething ( X ) , 0 ; }", tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } } void simplifyInitVar2() { // ticket #5131 - unsigned const char code[] = "void f() {\n" " unsigned int a(0),b(0);\n" "}"; ASSERT_EQUALS("void f ( ) {\n" "unsigned int a ; a = 0 ; unsigned int b ; b = 0 ;\n" "}", tokenizeAndStringify(code)); } void simplifyInitVar3() { const char code[] = "void f() {\n" " int *a(0),b(0);\n" "}"; ASSERT_EQUALS("void f ( ) {\n" "int * a ; a = 0 ; int b ; b = 0 ;\n" "}", tokenizeAndStringify(code)); } void bitfields1() { const char code1[] = "struct A { bool x : 1; };"; ASSERT_EQUALS("struct A { bool x ; } ;", tokenizeAndStringify(code1)); const char code2[] = "struct A { char x : 3; };"; ASSERT_EQUALS("struct A { char x ; } ;", tokenizeAndStringify(code2)); const char code3[] = "struct A { short x : 3; };"; ASSERT_EQUALS("struct A { short x ; } ;", tokenizeAndStringify(code3)); const char code4[] = "struct A { int x : 3; };"; ASSERT_EQUALS("struct A { int x ; } ;", tokenizeAndStringify(code4)); const char code5[] = "struct A { long x : 3; };"; ASSERT_EQUALS("struct A { long x ; } ;", tokenizeAndStringify(code5)); const char code6[] = "struct A { __int8 x : 3; };"; ASSERT_EQUALS("struct A { char x ; } ;", tokenizeAndStringifyWindows(code6, true, Settings::Win32A)); const char code7[] = "struct A { __int16 x : 3; };"; ASSERT_EQUALS("struct A { short x ; } ;", tokenizeAndStringifyWindows(code7, true, Settings::Win32A)); const char code8[] = "struct A { __int32 x : 3; };"; ASSERT_EQUALS("struct A { int x ; } ;", tokenizeAndStringifyWindows(code8, true, Settings::Win32A)); const char code9[] = "struct A { __int64 x : 3; };"; ASSERT_EQUALS("struct A { long long x ; } ;", tokenizeAndStringifyWindows(code9, true, Settings::Win32A)); const char code10[] = "struct A { unsigned char x : 3; };"; ASSERT_EQUALS("struct A { unsigned char x ; } ;", tokenizeAndStringify(code10)); const char code11[] = "struct A { unsigned short x : 3; };"; ASSERT_EQUALS("struct A { unsigned short x ; } ;", tokenizeAndStringify(code11)); const char code12[] = "struct A { unsigned int x : 3; };"; ASSERT_EQUALS("struct A { unsigned int x ; } ;", tokenizeAndStringify(code12)); const char code13[] = "struct A { unsigned long x : 3; };"; ASSERT_EQUALS("struct A { unsigned long x ; } ;", tokenizeAndStringify(code13)); const char code14[] = "struct A { unsigned __int8 x : 3; };"; ASSERT_EQUALS("struct A { unsigned char x ; } ;", tokenizeAndStringifyWindows(code14, true, Settings::Win32A)); const char code15[] = "struct A { unsigned __int16 x : 3; };"; ASSERT_EQUALS("struct A { unsigned short x ; } ;", tokenizeAndStringifyWindows(code15, true, Settings::Win32A)); const char code16[] = "struct A { unsigned __int32 x : 3; };"; ASSERT_EQUALS("struct A { unsigned int x ; } ;", tokenizeAndStringifyWindows(code16, true, Settings::Win32A)); const char code17[] = "struct A { unsigned __int64 x : 3; };"; ASSERT_EQUALS("struct A { unsigned long long x ; } ;", tokenizeAndStringifyWindows(code17, true, Settings::Win32A)); const char code18[] = "struct A { signed char x : 3; };"; ASSERT_EQUALS("struct A { signed char x ; } ;", tokenizeAndStringify(code18)); const char code19[] = "struct A { signed short x : 3; };"; ASSERT_EQUALS("struct A { signed short x ; } ;", tokenizeAndStringify(code19)); const char code20[] = "struct A { signed int x : 3; };"; ASSERT_EQUALS("struct A { signed int x ; } ;", tokenizeAndStringify(code20)); const char code21[] = "struct A { signed long x : 3; };"; ASSERT_EQUALS("struct A { signed long x ; } ;", tokenizeAndStringifyWindows(code21)); const char code22[] = "struct A { signed __int8 x : 3; };"; ASSERT_EQUALS("struct A { signed char x ; } ;", tokenizeAndStringifyWindows(code22, true, Settings::Win32A)); const char code23[] = "struct A { signed __int16 x : 3; };"; ASSERT_EQUALS("struct A { signed short x ; } ;", tokenizeAndStringifyWindows(code23, true, Settings::Win32A)); const char code24[] = "struct A { signed __int32 x : 3; };"; ASSERT_EQUALS("struct A { signed int x ; } ;", tokenizeAndStringifyWindows(code24, true, Settings::Win32A)); const char code25[] = "struct A { signed __int64 x : 3; };"; ASSERT_EQUALS("struct A { signed long long x ; } ;", tokenizeAndStringifyWindows(code25, true, Settings::Win32A)); } void bitfields2() { const char code1[] = "struct A { public: int x : 3; };"; ASSERT_EQUALS("struct A { public: int x ; } ;", tokenizeAndStringify(code1)); const char code2[] = "struct A { public: unsigned long x : 3; };"; ASSERT_EQUALS("struct A { public: unsigned long x ; } ;", tokenizeAndStringify(code2)); const char code3[] = "struct A { protected: int x : 3; };"; ASSERT_EQUALS("struct A { protected: int x ; } ;", tokenizeAndStringify(code3)); const char code4[] = "struct A { protected: unsigned long x : 3; };"; ASSERT_EQUALS("struct A { protected: unsigned long x ; } ;", tokenizeAndStringify(code4)); const char code5[] = "struct A { private: int x : 3; };"; ASSERT_EQUALS("struct A { private: int x ; } ;", tokenizeAndStringify(code5)); const char code6[] = "struct A { private: unsigned long x : 3; };"; ASSERT_EQUALS("struct A { private: unsigned long x ; } ;", tokenizeAndStringify(code6)); } void bitfields3() { const char code1[] = "struct A { const int x : 3; };"; ASSERT_EQUALS("struct A { const int x ; } ;", tokenizeAndStringify(code1)); const char code2[] = "struct A { const unsigned long x : 3; };"; ASSERT_EQUALS("struct A { const unsigned long x ; } ;", tokenizeAndStringify(code2)); const char code3[] = "struct A { public: const int x : 3; };"; ASSERT_EQUALS("struct A { public: const int x ; } ;", tokenizeAndStringify(code3)); const char code4[] = "struct A { public: const unsigned long x : 3; };"; ASSERT_EQUALS("struct A { public: const unsigned long x ; } ;", tokenizeAndStringify(code4)); } void bitfields4() { // ticket #1956 const char code1[] = "struct A { CHAR x : 3; };"; ASSERT_EQUALS("struct A { CHAR x ; } ;", tokenizeAndStringify(code1)); const char code2[] = "struct A { UCHAR x : 3; };"; ASSERT_EQUALS("struct A { UCHAR x ; } ;", tokenizeAndStringify(code2)); const char code3[] = "struct A { BYTE x : 3; };"; ASSERT_EQUALS("struct A { BYTE x ; } ;", tokenizeAndStringify(code3)); const char code4[] = "struct A { WORD x : 3; };"; ASSERT_EQUALS("struct A { WORD x ; } ;", tokenizeAndStringify(code4)); const char code5[] = "struct A { DWORD x : 3; };"; ASSERT_EQUALS("struct A { DWORD x ; } ;", tokenizeAndStringify(code5)); const char code6[] = "struct A { LONG x : 3; };"; ASSERT_EQUALS("struct A { LONG x ; } ;", tokenizeAndStringify(code6)); const char code7[] = "struct A { UINT8 x : 3; };"; ASSERT_EQUALS("struct A { UINT8 x ; } ;", tokenizeAndStringify(code7)); const char code8[] = "struct A { UINT16 x : 3; };"; ASSERT_EQUALS("struct A { UINT16 x ; } ;", tokenizeAndStringify(code8)); const char code9[] = "struct A { UINT32 x : 3; };"; ASSERT_EQUALS("struct A { UINT32 x ; } ;", tokenizeAndStringify(code9)); const char code10[] = "struct A { UINT64 x : 3; };"; ASSERT_EQUALS("struct A { UINT64 x ; } ;", tokenizeAndStringify(code10)); } void bitfields5() { // ticket #1956 const char code1[] = "struct RGB { unsigned int r : 3, g : 3, b : 2; };"; ASSERT_EQUALS("struct RGB { unsigned int r ; unsigned int g ; unsigned int b ; } ;", tokenizeAndStringify(code1)); const char code2[] = "struct A { int a : 3; int : 3; int c : 3; };"; ASSERT_EQUALS("struct A { int a ; int c ; } ;", tokenizeAndStringify(code2)); const char code3[] = "struct A { virtual void f() {} int f1 : 1; };"; ASSERT_EQUALS("struct A { virtual void f ( ) { } int f1 ; } ;", tokenizeAndStringify(code3)); } void bitfields6() { // ticket #2595 const char code1[] = "struct A { bool b : true; };"; ASSERT_EQUALS("struct A { bool b ; } ;", tokenizeAndStringify(code1)); const char code2[] = "struct A { bool b : true, c : true; };"; ASSERT_EQUALS("struct A { bool b ; bool c ; } ;", tokenizeAndStringify(code2)); const char code3[] = "struct A { bool : true; };"; ASSERT_EQUALS("struct A { } ;", tokenizeAndStringify(code3)); } void bitfields7() { // ticket #1987 const char code[] = "typedef struct Descriptor {" " unsigned element_size: 8* sizeof( unsigned );" "} Descriptor;"; const char expected[] = "struct Descriptor { " "unsigned int element_size ; " "} ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } void bitfields8() { const char code[] = "struct A;" "class B : virtual public C" "{" " int f();" "};"; const char expected[] = "struct A ; " "class B : virtual public C " "{ " "int f ( ) ; " "} ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); ASSERT_EQUALS("", errout.str()); } void bitfields9() { // ticket #2706 const char code[] = "void f() {\n" " goto half;\n" "half:\n" " {\n" " ;\n" " }\n" "};"; tokenizeAndStringify(code); ASSERT_EQUALS("", errout.str()); } void bitfields10() { // ticket #2737 const char code[] = "{}" "MACRO " "default: { }" ";"; ASSERT_EQUALS("{ } MACRO default : { } ;", tokenizeAndStringify(code)); } void bitfields12() { // ticket #3485 (segmentation fault) const char code[] = "{a:1;};\n"; ASSERT_EQUALS("{ } ;", tokenizeAndStringify(code)); } void bitfields13() { // ticket #3502 (segmentation fault) ASSERT_EQUALS("x y ;", tokenizeAndStringify("struct{x y:};\n")); } void bitfields14() { // #4561 - crash for 'signals:' ASSERT_EQUALS("class x { protected: } ;", tokenizeAndStringify("class x { signals: };\n")); } void bitfields15() { // #7747 - enum Foo {A,B}:4; ASSERT_EQUALS("struct AB {\n" "enum Foo { A , B } ; enum Foo Anonymous ;\n" "} ;", tokenizeAndStringify("struct AB {\n" " enum Foo {A,B} : 4;\n" "};")); ASSERT_EQUALS("struct AB {\n" "enum Foo { A , B } ; enum Foo foo ;\n" "} ;", tokenizeAndStringify("struct AB {\n" " enum Foo {A,B} foo : 4;\n" "};")); } void bitfields16() { const char code[] = "struct A { unsigned int x : 1; };"; errout.str(""); Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); const Token *x = Token::findsimplematch(tokenizer.tokens(), "x"); ASSERT_EQUALS(1, x->bits()); } void simplifyNamespaceStd() { const char *code, *expected; code = "map m;"; // namespace std is not used ASSERT_EQUALS("map < foo , bar > m ;", tokenizeAndStringify(code)); code = "using namespace std;\n" "map m;"; ASSERT_EQUALS("std :: map < foo , bar > m ;", tokenizeAndStringify(code)); code = "using namespace std;\n" "string s;"; ASSERT_EQUALS("std :: string s ;", tokenizeAndStringify(code)); code = "using namespace std;\n" "void foo() {swap(a, b); }"; ASSERT_EQUALS("void foo ( ) { std :: swap ( a , b ) ; }", tokenizeAndStringify(code)); code = "using namespace std;\n" "void search() {}"; ASSERT_EQUALS("void search ( ) { }", tokenizeAndStringify(code)); code = "using namespace std;\n" "void search();\n" "void dostuff() { search(); }"; ASSERT_EQUALS("void search ( ) ;\nvoid dostuff ( ) { search ( ) ; }", tokenizeAndStringify(code)); code = "using namespace std;\n" "void foo() {map(a, b); }"; // That's obviously not std::map<> ASSERT_EQUALS("void foo ( ) { map ( a , b ) ; }", tokenizeAndStringify(code)); code = "using namespace std;\n" "string s;"; // That's obviously not std::string ASSERT_EQUALS("string < wchar_t > s ;", tokenizeAndStringify(code)); code = "using namespace std;\n" "swap s;"; // That's obviously not std::swap ASSERT_EQUALS("swap s ;", tokenizeAndStringify(code)); code = "using namespace std;\n" "std::string s;"; ASSERT_EQUALS("std :: string s ;", tokenizeAndStringify(code)); code = "using namespace std;\n" "tr1::function f;"; ASSERT_EQUALS("tr1 :: function < void ( int ) > f ;", tokenizeAndStringify(code, true, Settings::Native, "test.cpp", false)); ASSERT_EQUALS("std :: function < void ( int ) > f ;", tokenizeAndStringify(code, true, Settings::Native, "test.cpp", true)); code = "std::tr1::function f;"; ASSERT_EQUALS("std :: tr1 :: function < void ( int ) > f ;", tokenizeAndStringify(code, true, Settings::Native, "test.cpp", false)); ASSERT_EQUALS("std :: function < void ( int ) > f ;", tokenizeAndStringify(code, true, Settings::Native, "test.cpp", true)); // #4042 (Do not add 'std ::' to variables) code = "using namespace std;\n" "const char * string = \"Hi\";"; ASSERT_EQUALS("const char * string ; string = \"Hi\" ;", tokenizeAndStringify(code)); code = "using namespace std;\n" "string f(const char * string) {\n" " cout << string << endl;\n" " return string;\n" "}"; expected = "std :: string f ( const char * string ) {\n" "std :: cout << string << std :: endl ;\n" "return string ;\n" "}"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); code = "using namespace std;\n" "void f() {\n" " try { }\n" " catch(std::exception &exception) { }\n" "}"; expected = "void f ( ) {\n" "try { }\n" "catch ( std :: exception & exception ) { }\n" "}"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); // #5773 (Don't prepend 'std ::' to function definitions) code = "using namespace std;\n" "class C {\n" " void search() {}\n" " void search() const {}\n" " void search() THROW_MACRO {}\n" "};"; expected = "class C {\n" "void search ( ) { }\n" "void search ( ) const { }\n" "void search ( ) { }\n" "} ;"; ASSERT_EQUALS(expected, tokenizeAndStringify(code)); // Ticket #8091 ASSERT_EQUALS("enum Anonymous0 { string } ;", tokenizeAndStringify("using namespace std; " "enum { string };")); ASSERT_EQUALS("enum Type { string } ;", tokenizeAndStringify("using namespace std; " "enum Type { string } ;")); ASSERT_EQUALS("enum class Type { string } ;", tokenizeAndStringify("using namespace std; " "enum class Type { string } ;")); ASSERT_EQUALS("enum struct Type { string } ;", tokenizeAndStringify("using namespace std; " "enum struct Type { string } ;")); ASSERT_EQUALS("enum struct Type : int { f = 0 , string } ;", tokenizeAndStringify("using namespace std; " "enum struct Type : int { f = 0 , string } ;")); ASSERT_EQUALS("enum Type { a , b } ; void foo ( enum Type , std :: string ) { }", tokenizeAndStringify("using namespace std; " "enum Type { a , b } ; void foo ( enum Type , string) {}")); ASSERT_EQUALS("struct T { } ; enum struct Type : int { f = 0 , string } ;", tokenizeAndStringify("using namespace std; " "struct T { typedef int type; } ; " "enum struct Type : T :: type { f = 0 , string } ;")); // Handle garbage enum code "well" ASSERT_EQUALS("enum E : int ; void foo ( ) { std :: string s ; }", tokenizeAndStringify("using namespace std; enum E : int ; void foo ( ) { string s ; }")); } void microsoftMemory() { const char code1a[] = "void foo() { int a[10], b[10]; CopyMemory(a, b, sizeof(a)); }"; ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; int b [ 10 ] ; memcpy ( a , b , sizeof ( a ) ) ; }", tokenizeAndStringify(code1a,true,Settings::Win32A)); const char code1b[] = "void foo() { int a[10], b[10]; RtlCopyMemory(a, b, sizeof(a)); }"; ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; int b [ 10 ] ; memcpy ( a , b , sizeof ( a ) ) ; }", tokenizeAndStringify(code1b,true,Settings::Win32A)); const char code1c[] = "void foo() { int a[10], b[10]; RtlCopyBytes(a, b, sizeof(a)); }"; ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; int b [ 10 ] ; memcpy ( a , b , sizeof ( a ) ) ; }", tokenizeAndStringify(code1c,true,Settings::Win32A)); const char code2a[] = "void foo() { int a[10]; FillMemory(a, sizeof(a), 255); }"; ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; memset ( a , 255 , sizeof ( a ) ) ; }", tokenizeAndStringify(code2a,true,Settings::Win32A)); const char code2b[] = "void foo() { int a[10]; RtlFillMemory(a, sizeof(a), 255); }"; ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; memset ( a , 255 , sizeof ( a ) ) ; }", tokenizeAndStringify(code2b,true,Settings::Win32A)); const char code2c[] = "void foo() { int a[10]; RtlFillBytes(a, sizeof(a), 255); }"; ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; memset ( a , 255 , sizeof ( a ) ) ; }", tokenizeAndStringify(code2c,true,Settings::Win32A)); const char code3a[] = "void foo() { int a[10], b[10]; MoveMemory(a, b, sizeof(a)); }"; ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; int b [ 10 ] ; memmove ( a , b , sizeof ( a ) ) ; }", tokenizeAndStringify(code3a,true,Settings::Win32A)); const char code3b[] = "void foo() { int a[10], b[10]; RtlMoveMemory(a, b, sizeof(a)); }"; ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; int b [ 10 ] ; memmove ( a , b , sizeof ( a ) ) ; }", tokenizeAndStringify(code3b,true,Settings::Win32A)); const char code4a[] = "void foo() { int a[10]; ZeroMemory(a, sizeof(a)); }"; ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; memset ( a , 0 , sizeof ( a ) ) ; }", tokenizeAndStringify(code4a,true,Settings::Win32A)); const char code4b[] = "void foo() { int a[10]; RtlZeroMemory(a, sizeof(a)); }"; ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; memset ( a , 0 , sizeof ( a ) ) ; }", tokenizeAndStringify(code4b,true,Settings::Win32A)); const char code4c[] = "void foo() { int a[10]; RtlZeroBytes(a, sizeof(a)); }"; ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; memset ( a , 0 , sizeof ( a ) ) ; }", tokenizeAndStringify(code4c,true,Settings::Win32A)); const char code4d[] = "void foo() { int a[10]; RtlSecureZeroMemory(a, sizeof(a)); }"; ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; memset ( a , 0 , sizeof ( a ) ) ; }", tokenizeAndStringify(code4d,true,Settings::Win32A)); const char code5[] = "void foo() { int a[10], b[10]; RtlCompareMemory(a, b, sizeof(a)); }"; ASSERT_EQUALS("void foo ( ) { int a [ 10 ] ; int b [ 10 ] ; memcmp ( a , b , sizeof ( a ) ) ; }", tokenizeAndStringify(code5,true,Settings::Win32A)); const char code6[] = "void foo() { ZeroMemory(f(1, g(a, b)), h(i, j(0, 1))); }"; ASSERT_EQUALS("void foo ( ) { memset ( f ( 1 , g ( a , b ) ) , 0 , h ( i , j ( 0 , 1 ) ) ) ; }", tokenizeAndStringify(code6,true,Settings::Win32A)); const char code7[] = "void foo() { FillMemory(f(1, g(a, b)), h(i, j(0, 1)), 255); }"; ASSERT_EQUALS("void foo ( ) { memset ( f ( 1 , g ( a , b ) ) , 255 , h ( i , j ( 0 , 1 ) ) ) ; }", tokenizeAndStringify(code7,true,Settings::Win32A)); } void microsoftString() { const char code1a[] = "void foo() { _tprintf (_T(\"test\") _T(\"1\")); }"; ASSERT_EQUALS("void foo ( ) { printf ( \"test1\" ) ; }", tokenizeAndStringify(code1a, true, Settings::Win32A)); const char code1b[] = "void foo() { _tprintf (_TEXT(\"test\") _TEXT(\"2\")); }"; ASSERT_EQUALS("void foo ( ) { printf ( \"test2\" ) ; }", tokenizeAndStringify(code1b, true, Settings::Win32A)); const char code1c[] = "void foo() { _tprintf (TEXT(\"test\") TEXT(\"3\")); }"; ASSERT_EQUALS("void foo ( ) { printf ( \"test3\" ) ; }", tokenizeAndStringify(code1c, true, Settings::Win32A)); const char code2a[] = "void foo() { _tprintf (_T(\"test\") _T(\"1\")); }"; ASSERT_EQUALS("void foo ( ) { wprintf ( L\"test1\" ) ; }", tokenizeAndStringify(code2a, true, Settings::Win32W)); ASSERT_EQUALS("void foo ( ) { wprintf ( L\"test1\" ) ; }", tokenizeAndStringify(code2a, true, Settings::Win64)); const char code2b[] = "void foo() { _tprintf (_TEXT(\"test\") _TEXT(\"2\")); }"; ASSERT_EQUALS("void foo ( ) { wprintf ( L\"test2\" ) ; }", tokenizeAndStringify(code2b, true, Settings::Win32W)); ASSERT_EQUALS("void foo ( ) { wprintf ( L\"test2\" ) ; }", tokenizeAndStringify(code2b, true, Settings::Win64)); const char code2c[] = "void foo() { _tprintf (TEXT(\"test\") TEXT(\"3\")); }"; ASSERT_EQUALS("void foo ( ) { wprintf ( L\"test3\" ) ; }", tokenizeAndStringify(code2c, true, Settings::Win32W)); ASSERT_EQUALS("void foo ( ) { wprintf ( L\"test3\" ) ; }", tokenizeAndStringify(code2c, true, Settings::Win64)); } void borland() { // __closure ASSERT_EQUALS("int ( * a ) ( ) ;", // TODO VarId tokenizeAndStringify("int (__closure *a)();", true, Settings::Win32A)); // __property ASSERT_EQUALS("class Fred { ; __property ; } ;", tokenizeAndStringify("class Fred { __property int x = { } };", true, Settings::Win32A)); } void simplifyQtSignalsSlots1() { const char code1[] = "class Counter : public QObject " "{ " " Q_OBJECT " "public: " " Counter() { m_value = 0; } " " int value() const { return m_value; } " "public slots: " " void setValue(int value); " "signals: " " void valueChanged(int newValue); " "private: " " int m_value; " "}; " "void Counter::setValue(int value) " "{ " " if (value != m_value) { " " m_value = value; " " emit valueChanged(value); " " } " "}"; const char result1 [] = "class Counter : public QObject " "{ " "public: " "Counter ( ) { m_value = 0 ; } " "int value ( ) const { return m_value ; } " "public: " "void setValue ( int value ) ; " "protected: " "void valueChanged ( int newValue ) ; " "private: " "int m_value ; " "} ; " "void Counter :: setValue ( int value ) " "{ " "if ( value != m_value ) { " "m_value = value ; " "valueChanged ( value ) ; " "} " "}"; ASSERT_EQUALS(result1, tokenizeAndStringify(code1)); const char code2[] = "class Counter : public QObject " "{ " " Q_OBJECT " "public: " " Counter() { m_value = 0; } " " int value() const { return m_value; } " "public Q_SLOTS: " " void setValue(int value); " "Q_SIGNALS: " " void valueChanged(int newValue); " "private: " " int m_value; " "};" "void Counter::setValue(int value) " "{ " " if (value != m_value) { " " m_value = value; " " emit valueChanged(value); " " } " "}"; const char result2 [] = "class Counter : public QObject " "{ " "public: " "Counter ( ) { m_value = 0 ; } " "int value ( ) const { return m_value ; } " "public: " "void setValue ( int value ) ; " "protected: " "void valueChanged ( int newValue ) ; " "private: " "int m_value ; " "} ; " "void Counter :: setValue ( int value ) " "{ " "if ( value != m_value ) { " "m_value = value ; " "valueChanged ( value ) ; " "} " "}"; ASSERT_EQUALS(result2, tokenizeAndStringify(code2)); const char code3[] = "class MyObject : public QObject {" " MyObject() {}" " ~MyObject() {}" " public slots:" " signals:" " void test() {}" "};"; const char result3 [] = "class MyObject : public QObject { " "MyObject ( ) { } " "~ MyObject ( ) { } " "public: " "protected: " "void test ( ) { } " "} ;"; ASSERT_EQUALS(result3, tokenizeAndStringify(code3)); ASSERT_EQUALS("", errout.str()); const char code4[] = "class MyObject : public QObject {" " Q_OBJECT " "public slots:" "};"; const char result4[] = "class MyObject : public QObject { " "public: " "} ;"; ASSERT_EQUALS(result4, tokenizeAndStringify(code4)); } void simplifyQtSignalsSlots2() { const char code1[] = "class Foo::Bar: public QObject { private slots: };"; const char result1[] = "class Foo :: Bar : public QObject { private: } ;"; ASSERT_EQUALS(result1, tokenizeAndStringify(code1)); } void simplifySQL() { // Oracle PRO*C extensions for inline SQL. Just replace the SQL with "asm()" to fix wrong error messages // ticket: #1959 ASSERT_EQUALS("asm ( \"\"__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL SELECT A FROM B\"\" ) ;", tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL SELECT A FROM B;")); ASSERT_THROW(tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL"), InternalError); ASSERT_EQUALS("asm ( \"\"__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL EXECUTE BEGIN Proc1 ( A ) ; END ; END - __CPPCHECK_EMBEDDED_SQL_EXEC__\"\" ) ; asm ( \"\"__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL COMMIT\"\" ) ;", tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL EXECUTE BEGIN Proc1(A); END; END-__CPPCHECK_EMBEDDED_SQL_EXEC__; __CPPCHECK_EMBEDDED_SQL_EXEC__ SQL COMMIT;")); ASSERT_EQUALS("asm ( \"\"__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL UPDATE A SET B = C\"\" ) ; asm ( \"\"__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL COMMIT\"\" ) ;", tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL UPDATE A SET B = C; __CPPCHECK_EMBEDDED_SQL_EXEC__ SQL COMMIT;")); ASSERT_EQUALS("asm ( \"\"__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL COMMIT\"\" ) ; asm ( \"\"__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL EXECUTE BEGIN Proc1 ( A ) ; END ; END - __CPPCHECK_EMBEDDED_SQL_EXEC__\"\" ) ;", tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL COMMIT; __CPPCHECK_EMBEDDED_SQL_EXEC__ SQL EXECUTE BEGIN Proc1(A); END; END-__CPPCHECK_EMBEDDED_SQL_EXEC__;")); ASSERT_THROW(tokenizeAndStringify("int f(){ __CPPCHECK_EMBEDDED_SQL_EXEC__ SQL } int a;"), InternalError); ASSERT_THROW(tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL int f(){"), InternalError); ASSERT_THROW(tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL END-__CPPCHECK_EMBEDDED_SQL_EXEC__ int a;"), InternalError); ASSERT_NO_THROW(tokenizeAndStringify("__CPPCHECK_EMBEDDED_SQL_EXEC__ SQL UPDATE A SET B = :&b->b1, C = :c::c1;")); } void simplifyCAlternativeTokens() { ASSERT_EQUALS("void or ( void ) ;", tokenizeAndStringify("void or(void);", true, Settings::Native, "test.c")); ASSERT_EQUALS("void f ( ) { if ( a && b ) { ; } }", tokenizeAndStringify("void f() { if (a and b); }", true, Settings::Native, "test.c")); ASSERT_EQUALS("void f ( ) { if ( a && b ) { ; } }", tokenizeAndStringify("void f() { if (a and b); }", true, Settings::Native, "test.cpp")); ASSERT_EQUALS("void f ( ) { if ( a || b ) { ; } }", tokenizeAndStringify("void f() { if (a or b); }", true, Settings::Native, "test.c")); ASSERT_EQUALS("void f ( ) { if ( a || b ) { ; } }", tokenizeAndStringify("void f() { if (a or b); }", true, Settings::Native, "test.cpp")); ASSERT_EQUALS("void f ( ) { if ( a & b ) { ; } }", tokenizeAndStringify("void f() { if (a bitand b); }", true, Settings::Native, "test.c")); ASSERT_EQUALS("void f ( ) { if ( a & b ) { ; } }", tokenizeAndStringify("void f() { if (a bitand b); }", true, Settings::Native, "test.cpp")); ASSERT_EQUALS("void f ( ) { if ( a | b ) { ; } }", tokenizeAndStringify("void f() { if (a bitor b); }", true, Settings::Native, "test.c")); ASSERT_EQUALS("void f ( ) { if ( a | b ) { ; } }", tokenizeAndStringify("void f() { if (a bitor b); }", true, Settings::Native, "test.cpp")); ASSERT_EQUALS("void f ( ) { if ( a ^ b ) { ; } }", tokenizeAndStringify("void f() { if (a xor b); }", true, Settings::Native, "test.c")); ASSERT_EQUALS("void f ( ) { if ( a ^ b ) { ; } }", tokenizeAndStringify("void f() { if (a xor b); }", true, Settings::Native, "test.cpp")); ASSERT_EQUALS("void f ( ) { if ( ~ b ) { ; } }", tokenizeAndStringify("void f() { if (compl b); }", true, Settings::Native, "test.c")); ASSERT_EQUALS("void f ( ) { if ( ~ b ) { ; } }", tokenizeAndStringify("void f() { if (compl b); }", true, Settings::Native, "test.cpp")); ASSERT_EQUALS("void f ( ) { if ( ! b ) { ; } }", tokenizeAndStringify("void f() { if (not b); }", true, Settings::Native, "test.c")); ASSERT_EQUALS("void f ( ) { if ( ! b ) { ; } }", tokenizeAndStringify("void f() { if (not b); }", true, Settings::Native, "test.cpp")); ASSERT_EQUALS("void f ( ) const { if ( ! b ) { ; } }", tokenizeAndStringify("void f() const { if (not b); }", true, Settings::Native, "test.cpp")); ASSERT_EQUALS("void f ( ) { if ( a != b ) { ; } }", tokenizeAndStringify("void f() { if (a not_eq b); }", true, Settings::Native, "test.c")); ASSERT_EQUALS("void f ( ) { if ( a != b ) { ; } }", tokenizeAndStringify("void f() { if (a not_eq b); }", true, Settings::Native, "test.cpp")); // #6201 ASSERT_EQUALS("void f ( ) { if ( ! c || ! memcmp ( a , b , s ) ) { ; } }", tokenizeAndStringify("void f() { if (!c or !memcmp(a, b, s)); }", true, Settings::Native, "test.c")); ASSERT_EQUALS("void f ( ) { if ( ! c || ! memcmp ( a , b , s ) ) { ; } }", tokenizeAndStringify("void f() { if (!c or !memcmp(a, b, s)); }", true, Settings::Native, "test.cpp")); // #6029 ASSERT_EQUALS("void f ( ) { if ( ! b ) { } }", tokenizeAndStringify("void f() { if (not b){} }", true, Settings::Native, "test.c")); ASSERT_EQUALS("void f ( ) { if ( ! b ) { } }", tokenizeAndStringify("void f() { if (not b){} }", true, Settings::Native, "test.cpp")); // #6207 ASSERT_EQUALS("void f ( ) { if ( not = x ) { } }", tokenizeAndStringify("void f() { if (not=x){} }", true, Settings::Native, "test.c")); ASSERT_EQUALS("void f ( ) { if ( not = x ) { } }", tokenizeAndStringify("void f() { if (not=x){} }", true, Settings::Native, "test.cpp")); // #8029 ASSERT_EQUALS("void f ( struct S * s ) { x = s . and + 1 ; }", tokenizeAndStringify("void f(struct S *s) { x = s->and + 1; }", true, Settings::Native, "test.c")); // #8745 ASSERT_EQUALS("void f ( ) { if ( x ) { or = 0 ; } }", tokenizeAndStringify("void f() { if (x) or = 0; }")); // #9324 ASSERT_EQUALS("void f ( const char * str ) { while ( * str == '!' || * str == '[' ) { } }", tokenizeAndStringify("void f(const char *str) { while (*str=='!' or *str=='['){} }")); // #9920 ASSERT_EQUALS("result = ch != s . end ( ) && * ch == ':' ;", tokenizeAndStringify("result = ch != s.end() and *ch == ':';", true, Settings::Native, "test.c")); // #8975 ASSERT_EQUALS("void foo ( ) {\n" "char * or ;\n" "while ( ( * or != 0 ) && ( * or != '|' ) ) { or ++ ; }\n" "}", tokenizeAndStringify( "void foo() {\n" " char *or;\n" " while ((*or != 0) && (*or != '|')) or++;\n" "}", true, Settings::Native, "test.c")); // #10013 ASSERT_EQUALS("void f ( ) { x = ! 123 ; }", tokenizeAndStringify("void f() { x = not 123; }", true, Settings::Native, "test.cpp")); } void simplifyRoundCurlyParentheses() { ASSERT_EQUALS("; x = 123 ;", tokenizeAndStringify(";x=({123;});")); ASSERT_EQUALS("; x = y ;", tokenizeAndStringify(";x=({y;});")); } void simplifyOperatorName1() { // make sure C code doesn't get changed const char code[] = "void operator () {}" "int main()" "{" " operator();" "}"; const char result [] = "void operator ( ) { } " "int main ( ) " "{ " "operator ( ) ; " "}"; ASSERT_EQUALS(result, tokenizeAndStringify(code, /*expand=*/true, /*platform=*/Settings::Native, "test.c")); } void simplifyOperatorName2() { const char code[] = "class Fred" "{" " Fred(const Fred & f) { operator = (f); }" " operator = ();" "}"; const char result [] = "class Fred " "{ " "Fred ( const Fred & f ) { operator= ( f ) ; } " "operator= ( ) ; " "}"; ASSERT_EQUALS(result, tokenizeAndStringify(code)); } void simplifyOperatorName3() { // #2615 const char code[] = "void f() {" "static_cast(xResult.operator->())->GetMatrix();" "}"; const char result[] = "void f ( ) { static_cast < ScToken * > ( xResult . operator. ( ) ) . GetMatrix ( ) ; }"; ASSERT_EQUALS(result, tokenizeAndStringify(code)); } void simplifyOperatorName4() { const char code[] = "void operator==() { }"; const char result[] = "void operator== ( ) { }"; ASSERT_EQUALS(result, tokenizeAndStringify(code)); } void simplifyOperatorName5() { const char code1[] = "std::istream & operator >> (std::istream & s, Fred &f);"; const char result1[] = "std :: istream & operator>> ( std :: istream & s , Fred & f ) ;"; ASSERT_EQUALS(result1, tokenizeAndStringify(code1)); const char code2[] = "std::ostream & operator << (std::ostream & s, const Fred &f);"; const char result2[] = "std :: ostream & operator<< ( std :: ostream & s , const Fred & f ) ;"; ASSERT_EQUALS(result2, tokenizeAndStringify(code2)); } void simplifyOperatorName6() { // ticket #3195 const char code1[] = "value_type * operator ++ (int);"; const char result1[] = "value_type * operator++ ( int ) ;"; ASSERT_EQUALS(result1, tokenizeAndStringify(code1)); const char code2[] = "value_type * operator -- (int);"; const char result2[] = "value_type * operator-- ( int ) ;"; ASSERT_EQUALS(result2, tokenizeAndStringify(code2)); } void simplifyOperatorName7() { // ticket #4619 const char code1[] = "value_type * operator += (int);"; const char result1[] = "value_type * operator+= ( int ) ;"; ASSERT_EQUALS(result1, tokenizeAndStringify(code1)); } void simplifyOperatorName8() { // ticket #5706 const char code1[] = "value_type * operator += (int) noexcept ;"; const char result1[] = "value_type * operator+= ( int ) noexcept ( true ) ;"; ASSERT_EQUALS(result1, tokenizeAndStringify(code1)); const char code2[] = "value_type * operator += (int) noexcept ( true ) ;"; const char result2[] = "value_type * operator+= ( int ) noexcept ( true ) ;"; ASSERT_EQUALS(result2, tokenizeAndStringify(code2)); const char code3[] = "value_type * operator += (int) throw ( ) ;"; const char result3[] = "value_type * operator+= ( int ) throw ( ) ;"; ASSERT_EQUALS(result3, tokenizeAndStringify(code3)); const char code4[] = "value_type * operator += (int) const noexcept ;"; const char result4[] = "value_type * operator+= ( int ) const noexcept ;"; ASSERT_EQUALS(result4, tokenizeAndStringify(code4)); const char code5[] = "value_type * operator += (int) const noexcept ( true ) ;"; const char result5[] = "value_type * operator+= ( int ) const noexcept ( true ) ;"; ASSERT_EQUALS(result5, tokenizeAndStringify(code5)); const char code6[] = "value_type * operator += (int) const throw ( ) ;"; const char result6[] = "value_type * operator+= ( int ) const throw ( ) ;"; ASSERT_EQUALS(result6, tokenizeAndStringify(code6)); const char code7[] = "value_type * operator += (int) const noexcept ( false ) ;"; const char result7[] = "value_type * operator+= ( int ) const noexcept ( false ) ;"; ASSERT_EQUALS(result7, tokenizeAndStringify(code7)); } void simplifyOperatorName9() { // Ticket #5709 const char code[] = "struct R { R operator, ( R b ) ; } ;"; ASSERT_EQUALS(code, tokenizeAndStringify(code)); } void simplifyOperatorName10() { // #8746 const char code1[] = "using a::operator=;"; ASSERT_EQUALS("using a :: operator= ;", tokenizeAndStringify(code1)); const char code2[] = "{ return &Fred::operator!=; }"; ASSERT_EQUALS("{ return & Fred :: operator!= ; }", tokenizeAndStringify(code2)); } void simplifyOperatorName11() { // #8889 const char code[] = "auto operator = (const Fred & other) -> Fred & ;"; ASSERT_EQUALS("auto operator= ( const Fred & other ) . Fred & ;", tokenizeAndStringify(code)); const char code1[] = "auto operator = (const Fred & other) -> Fred & { }"; ASSERT_EQUALS("auto operator= ( const Fred & other ) . Fred & { }", tokenizeAndStringify(code1)); const char code2[] = "template void g(S<&T::operator+ >) {}"; ASSERT_EQUALS("template < typename T > void g ( S < & T :: operator+ > ) { }", tokenizeAndStringify(code2)); const char code3[] = "template void g(S<&T::operator int>) {}"; ASSERT_EQUALS("template < typename T > void g ( S < & T :: operatorint > ) { }", tokenizeAndStringify(code3)); const char code4[] = "template void g(S<&T::template operator- >) {}"; ASSERT_EQUALS("template < typename T > void g ( S < & T :: operator- < double > > ) { }", tokenizeAndStringify(code4)); } void simplifyOperatorName12() { // #9110 const char code[] = "namespace a {" "template void operator+(b);" "}" "using a::operator+;"; ASSERT_EQUALS("namespace a { " "template < typename b > void operator+ ( b ) ; " "} " "using a :: operator+ ;", tokenizeAndStringify(code)); } void simplifyOperatorName13() { // user defined literal const char code[] = "unsigned long operator\"\"_numch(const char *ch, unsigned long size);"; ASSERT_EQUALS("unsigned long operator\"\"_numch ( const char * ch , unsigned long size ) ;", tokenizeAndStringify(code)); } void simplifyOperatorName14() { // std::complex operator "" if { const char code[] = "constexpr std::complex operator\"\"if(long double __num);"; ASSERT_EQUALS("const std :: complex < float > operator\"\"if ( long double __num ) ;", tokenizeAndStringify(code)); } { const char code[] = "constexpr std::complex operator\"\"if(long double __num) { }"; ASSERT_EQUALS("const std :: complex < float > operator\"\"if ( long double __num ) { }", tokenizeAndStringify(code)); } } void simplifyOperatorName15() { // ticket #9468 syntaxError const char code[] = "template struct a;" "template struct b {" " typedef char c;" " operator c();" "};" "template <> struct a : b { using b::operator char; };"; ASSERT_EQUALS("struct a ; template < typename > struct a ; " "struct b ; " "struct a : b { using b :: operatorchar ; } ; struct b { " "operatorchar ( ) ; " "} ;", tokenizeAndStringify(code)); } void simplifyOperatorName16() { // ticket #9472 { const char code[] = "class I : public A { iterator& operator++() override; };"; ASSERT_EQUALS("class I : public A { iterator & operator++ ( ) override ; } ;", tokenizeAndStringify(code)); } { const char code[] = "class I : public A { iterator& operator++() override { } };"; ASSERT_EQUALS("class I : public A { iterator & operator++ ( ) override { } } ;", tokenizeAndStringify(code)); } } void simplifyOperatorName17() { { const char code[] = "template void b(a c, a d) { c.operator>() == d; }"; ASSERT_EQUALS("template < class a > void b ( a c , a d ) { c . operator> ( ) == d ; }", tokenizeAndStringify(code)); } { const char code[] = "template void b(a c, a d) { c.operator>() == (d + 1); }"; ASSERT_EQUALS("template < class a > void b ( a c , a d ) { c . operator> ( ) == ( d + 1 ) ; }", tokenizeAndStringify(code)); } { const char code[] = "template void b(a c, a d) { c.operator<() == d; }"; ASSERT_EQUALS("template < class a > void b ( a c , a d ) { c . operator< ( ) == d ; }", tokenizeAndStringify(code)); } { const char code[] = "template void b(a c, a d) { c.operator>() == (d + 1); }"; ASSERT_EQUALS("template < class a > void b ( a c , a d ) { c . operator> ( ) == ( d + 1 ) ; }", tokenizeAndStringify(code)); } { const char code[] = "template void b(a c, a d) { c.operator++() == d; }"; ASSERT_EQUALS("template < class a > void b ( a c , a d ) { c . operator++ ( ) == d ; }", tokenizeAndStringify(code)); } { const char code[] = "template void b(a c, a d) { c.operator++() == (d + 1); }"; ASSERT_EQUALS("template < class a > void b ( a c , a d ) { c . operator++ ( ) == ( d + 1 ) ; }", tokenizeAndStringify(code)); } } void simplifyOperatorName18() { // global namespace { const char code[] = "struct Fred { operator std::string() const { return std::string(\"Fred\"); } };"; ASSERT_EQUALS("struct Fred { operatorstd::string ( ) const { return std :: string ( \"Fred\" ) ; } } ;", tokenizeAndStringify(code)); } { const char code[] = "struct Fred { operator ::std::string() const { return ::std::string(\"Fred\"); } };"; ASSERT_EQUALS("struct Fred { operator::std::string ( ) const { return :: std :: string ( \"Fred\" ) ; } } ;", tokenizeAndStringify(code)); } } void simplifyOperatorName19() { const char code[] = "struct v {};" "enum E { e };" "struct s {" " operator struct v() { return v(); };" " operator enum E() { return e; }" "};" "void f() {" " (void)&s::operator struct v;" " (void)&s::operator enum E;" "}"; ASSERT_EQUALS("struct v { } ; " "enum E { e } ; " "struct s { " "operatorstructv ( ) { return v ( ) ; } ; " "operatorenumE ( ) { return e ; } " "} ; " "void f ( ) { " "( void ) & s :: operatorstructv ; " "( void ) & s :: operatorenumE ; " "}", tokenizeAndStringify(code)); } void simplifyOperatorName20() { const char code[] = "void operator \"\" _a(const char *);" "namespace N {" " using ::operator \"\" _a;" " void operator \"\" _b(const char *);" "}"; ASSERT_EQUALS("void operator\"\"_a ( const char * ) ; " "namespace N { " "using :: operator\"\"_a ; " "void operator\"\"_b ( const char * ) ; " "}", tokenizeAndStringify(code)); } void simplifyOperatorName21() { const char code[] = "template void operator \"\" _h() {}" "template<> void operator \"\" _h<'a', 'b', 'c'>() {}" "template void operator \"\" _h<'a', 'b', 'c', 'd'>();"; ASSERT_EQUALS("void operator\"\"_h<'a','b','c'> ( ) ; " "void operator\"\"_h<'a','b','c','d'> ( ) ; " "void operator\"\"_h<'a','b','c'> ( ) { } " "void operator\"\"_h<'a','b','c','d'> ( ) { }", tokenizeAndStringify(code)); } void simplifyOperatorName22() { const char code[] = "static RSLRelOp convertOperator(const Software::ComparisonOperator& op) {" " if (op == &Software::operator==) return RSLEqual;" "return RSLNotEqual;" "}"; ASSERT_EQUALS("static RSLRelOp convertOperator ( const Software :: ComparisonOperator & op ) { " "if ( op == & Software :: operator== ) { return RSLEqual ; } " "return RSLNotEqual ; " "}", tokenizeAndStringify(code)); } void simplifyOperatorName23() { { const char code[] = "double *vtkMatrix3x3::operator[](const unsigned int i) {" " VTK_LEGACY_BODY(vtkMatrix3x3::operator[], \"VTK 7.0\");" " return &(this->Element[i][0]);" "}"; ASSERT_EQUALS("double * vtkMatrix3x3 :: operator[] ( const unsigned int i ) { " "VTK_LEGACY_BODY ( vtkMatrix3x3 :: operator[] , \"VTK 7.0\" ) ; " "return & ( this . Element [ i ] [ 0 ] ) ; " "}", tokenizeAndStringify(code)); } { const char code[] = "double *vtkMatrix3x3::operator,(const unsigned int i) {" " VTK_LEGACY_BODY(vtkMatrix3x3::operator,, \"VTK 7.0\");" " return &(this->Element[i][0]);" "}"; ASSERT_EQUALS("double * vtkMatrix3x3 :: operator, ( const unsigned int i ) { " "VTK_LEGACY_BODY ( vtkMatrix3x3 :: operator, , \"VTK 7.0\" ) ; " "return & ( this . Element [ i ] [ 0 ] ) ; " "}", tokenizeAndStringify(code)); } } void simplifyOperatorName24() { { const char code[] = "void foo() { int i = a.operator++() ? a.operator--() : 0; }"; ASSERT_EQUALS("void foo ( ) { int i ; i = a . operator++ ( ) ? a . operator-- ( ) : 0 ; }", tokenizeAndStringify(code)); } { const char code[] = "void foo() { int i = a.operator++(0) ? a.operator--(0) : 0; }"; ASSERT_EQUALS("void foo ( ) { int i ; i = a . operator++ ( 0 ) ? a . operator-- ( 0 ) : 0 ; }", tokenizeAndStringify(code)); } } void simplifyOperatorName25() { const char code[] = "bool negative(const Number &num) { return num.operator std::string()[0] == '-'; }"; ASSERT_EQUALS("bool negative ( const Number & num ) { return num . operatorstd::string ( ) [ 0 ] == '-' ; }", tokenizeAndStringify(code)); } void simplifyOperatorName26() { const char code[] = "void foo() {" " x = y.operator *().z[123];" "}"; ASSERT_EQUALS("void foo ( ) { x = y . operator* ( ) . z [ 123 ] ; }", tokenizeAndStringify(code)); } void simplifyOperatorName27() { const char code[] = "int operator \"\" i (const char *, int);\n" "x = \"abc\"i;"; ASSERT_EQUALS("int operator\"\"i ( const char * , int ) ;\n" "x = operator\"\"i ( \"abc\" , 3 ) ;", tokenizeAndStringify(code)); } void simplifyOperatorName28() { const char code[] = "template struct overloaded : Ts... { using Ts::operator()...; };\n" "int main() { }"; ASSERT_EQUALS("template < class ... Ts > struct overloaded : Ts ... { using Ts :: operator ( ) ... ; } ;\n" "int main ( ) { }", tokenizeAndStringify(code)); } void simplifyOperatorName29() { Settings settings; settings.standards.cpp = Standards::CPP20; ASSERT_EQUALS("auto operator<=> ( ) ;", tokenizeAndStringify("auto operator<=>();", settings)); } void simplifyOverloadedOperators1() { const char code[] = "struct S { void operator()(int); };\n" "\n" "void foo(S x) {\n" " x(123);\n" "}"; ASSERT_EQUALS("struct S { void operator() ( int ) ; } ;\n" "\n" "void foo ( S x ) {\n" "x . operator() ( 123 ) ;\n" "}", tokenizeAndStringify(code)); } void simplifyOverloadedOperators2() { // #9879 - (*this)(123); const char code[] = "struct S {\n" " void operator()(int);\n" " void foo() { (*this)(123); }\n" "};\n"; ASSERT_EQUALS("struct S {\n" "void operator() ( int ) ;\n" "void foo ( ) { ( * this ) . operator() ( 123 ) ; }\n" "} ;", tokenizeAndStringify(code)); } void simplifyOverloadedOperators3() { // #9881 const char code[] = "struct Func { double operator()(double x) const; };\n" "void foo(double, double);\n" "void test() {\n" " Func max;\n" " double y = 0;\n" " foo(0, max(y));\n" "}"; ASSERT_EQUALS("struct Func { double operator() ( double x ) const ; } ;\n" "void foo ( double , double ) ;\n" "void test ( ) {\n" "Func max ;\n" "double y ; y = 0 ;\n" "foo ( 0 , max . operator() ( y ) ) ;\n" "}", tokenizeAndStringify(code)); } void simplifyNullArray() { ASSERT_EQUALS("* ( foo . bar [ 5 ] ) = x ;", tokenizeAndStringify("0[foo.bar[5]] = x;")); } void removeMacrosInGlobalScope() { // remove some unhandled macros in the global scope. ASSERT_EQUALS("void f ( ) { }", tokenizeAndStringify("void f() NOTHROW { }")); ASSERT_EQUALS("struct Foo { } ;", tokenizeAndStringify("struct __declspec(dllexport) Foo {};")); ASSERT_EQUALS("namespace { int a ; }", tokenizeAndStringify("ABA() namespace { int a ; }")); // #3750 ASSERT_THROW(tokenizeAndStringify("; AB(foo*) foo::foo() { }"), InternalError); // #4834 - syntax error ASSERT_THROW(tokenizeAndStringify("A(B) foo() {}"), InternalError); // #3855 ASSERT_EQUALS("; class foo { }", tokenizeAndStringify("; AB class foo { }")); ASSERT_EQUALS("; CONST struct ABC abc ;", tokenizeAndStringify("; CONST struct ABC abc ;")); ASSERT_NO_THROW(tokenizeAndStringify("class A {\n" " UNKNOWN_MACRO(A)\n" // <- this macro is ignored "private:\n" " int x;\n" "};")); ASSERT_THROW(tokenizeAndStringify("MACRO(test) void test() { }"), InternalError); // #7931 ASSERT_THROW(tokenizeAndStringify("BEGIN_MESSAGE_MAP(CSetProgsAdvDlg, CResizableStandAloneDialog)\n" " ON_BN_CLICKED(IDC_ADDTOOL, OnBnClickedAddtool)\n" "END_MESSAGE_MAP()\n" "\n" "BOOL CSetProgsAdvDlg::OnInitDialog() {}"), InternalError); } void removeMacroInVarDecl() { // #4304 // only remove macros with parentheses (those hurt most) ASSERT_EQUALS("void f ( ) { PROGMEM int x ; }", tokenizeAndStringify("void f() { PROGMEM int x ; }")); ASSERT_EQUALS("void f ( ) { int x ; }", tokenizeAndStringify("void f() { SECTION(\".data.ro\") int x ; }")); // various variable declarations ASSERT_EQUALS("void f ( ) { CONST int x ; }", tokenizeAndStringify("void f() { SECTION(\".data.ro\") CONST int x ; }")); ASSERT_EQUALS("void f ( ) { char a [ 4 ] ; }", tokenizeAndStringify("void f() { SECTION(\".data.ro\") char a[4]; }")); ASSERT_EQUALS("void f ( ) { const char a [ 4 ] ; }", tokenizeAndStringify("void f() { SECTION(\".data.ro\") const char a[4]; }")); ASSERT_EQUALS("void f ( ) { struct ABC abc ; }", tokenizeAndStringify("void f() { SECTION(\".data.ro\") struct ABC abc; }")); ASSERT_EQUALS("void f ( ) { CONST struct ABC abc ; }", tokenizeAndStringify("void f() { SECTION(\".data.ro\") CONST struct ABC abc; }")); } void addSemicolonAfterUnknownMacro() { // #6975 ASSERT_EQUALS("void f ( ) { MACRO ( ) ; try { } }", tokenizeAndStringify("void f() { MACRO() try {} }")); // #9376 ASSERT_EQUALS("MACRO ( ) ; using namespace foo ;", tokenizeAndStringify("MACRO() using namespace foo;")); } void multipleAssignment() { ASSERT_EQUALS("a = b = 0 ;", tokenizeAndStringify("a=b=0;")); } void platformWin() { const char code[] = "BOOL f;" "BOOLEAN g;" "BYTE h;" "CHAR i;" "DWORD j;" "FLOAT k;" "INT l;" "INT32 m;" "INT64 n;" "LONG o;" "SHORT p;" "UCHAR q;" "UINT r;" "ULONG s;" "USHORT t;" "WORD u;" "VOID *v;" "LPBOOL w;" "PBOOL x;" "LPBYTE y;" "PBOOLEAN z;" "PBYTE A;" "LPCSTR B;" "PCSTR C;" "LPCVOID D;" "LPDWORD E;" "LPINT F;" "PINT G;" "LPLONG H;" "PLONG I;" "LPSTR J;" "PSTR K;" "PCHAR L;" "LPVOID M;" "PVOID N;" "BOOL _bool;" "HFILE hfile;" "LONG32 long32;" "LCID lcid;" "LCTYPE lctype;" "LGRPID lgrpid;" "LONG64 long64;" "PUCHAR puchar;" "LPCOLORREF lpcolorref;" "PDWORD pdword;" "PULONG pulong;" "SERVICE_STATUS_HANDLE service_status_hanlde;" "SC_LOCK sc_lock;" "SC_HANDLE sc_handle;" "HACCEL haccel;" "HCONV hconv;" "HCONVLIST hconvlist;" "HDDEDATA hddedata;" "HDESK hdesk;" "HDROP hdrop;" "HDWP hdwp;" "HENHMETAFILE henhmetafile;" "HHOOK hhook;" "HKL hkl;" "HMONITOR hmonitor;" "HSZ hsz;" "HWINSTA hwinsta;" "PWCHAR pwchar;" "PUSHORT pushort;" "LANGID langid;" "DWORD64 dword64;" "ULONG64 ulong64;" "LPWSTR lpcwstr;" "LPCWSTR lpcwstr;" "LPHANDLE lpHandle;" "PCWSTR pcwStr;" "PDWORDLONG pdWordLong;" "PDWORD_PTR pdWordPtr;" "PDWORD32 pdWord32;" "PDWORD64 pdWord64;" "LONGLONG ll;" "USN usn;" "PULONG64 puLong64;" "PULONG32 puLong32;" "PFLOAT ptrToFloat;"; const char expected[] = "int f ; " "unsigned char g ; " "unsigned char h ; " "char i ; " "unsigned long j ; " "float k ; " "int l ; " "int m ; " "long long n ; " "long o ; " "short p ; " "unsigned char q ; " "unsigned int r ; " "unsigned long s ; " "unsigned short t ; " "unsigned short u ; " "void * v ; " "int * w ; " "int * x ; " "unsigned char * y ; " "unsigned char * z ; " "unsigned char * A ; " "const char * B ; " "const char * C ; " "const void * D ; " "unsigned long * E ; " "int * F ; " "int * G ; " "long * H ; " "long * I ; " "char * J ; " "char * K ; " "char * L ; " "void * M ; " "void * N ; " "int _bool ; " "int hfile ; " "int long32 ; " "unsigned long lcid ; " "unsigned long lctype ; " "unsigned long lgrpid ; " "long long long64 ; " "unsigned char * puchar ; " "unsigned long * lpcolorref ; " "unsigned long * pdword ; " "unsigned long * pulong ; " "void * service_status_hanlde ; " "void * sc_lock ; " "void * sc_handle ; " "void * haccel ; " "void * hconv ; " "void * hconvlist ; " "void * hddedata ; " "void * hdesk ; " "void * hdrop ; " "void * hdwp ; " "void * henhmetafile ; " "void * hhook ; " "void * hkl ; " "void * hmonitor ; " "void * hsz ; " "void * hwinsta ; " "wchar_t * pwchar ; " "unsigned short * pushort ; " "unsigned short langid ; " "unsigned long long dword64 ; " "unsigned long long ulong64 ; " "wchar_t * lpcwstr ; " "const wchar_t * lpcwstr ; " "void * lpHandle ; " "const wchar_t * pcwStr ; " "long * pdWordLong ; " "long * pdWordPtr ; " "unsigned int * pdWord32 ; " "unsigned long * pdWord64 ; " "long long ll ; " "long long usn ; " "unsigned long long * puLong64 ; " "unsigned int * puLong32 ; " "float * ptrToFloat ;"; // These types should be defined the same on all Windows platforms const std::string win32A = tokenizeAndStringifyWindows(code, true, Settings::Win32A); ASSERT_EQUALS(expected, win32A); ASSERT_EQUALS(win32A, tokenizeAndStringifyWindows(code, true, Settings::Win32W)); ASSERT_EQUALS(win32A, tokenizeAndStringifyWindows(code, true, Settings::Win64)); } void platformWin32A() { const char code[] = "wchar_t wc;" "TCHAR c;" "PTSTR ptstr;" "LPTSTR lptstr;" "PCTSTR pctstr;" "LPCTSTR lpctstr;" "void foo() {" " TCHAR tc = _T(\'c\'); " " TCHAR src[10] = _T(\"123456789\");" " TCHAR dst[10];" " _tcscpy(dst, src);" " dst[0] = 0;" " _tcscat(dst, src);" " LPTSTR d = _tcsdup(str);" " _tprintf(_T(\"Hello world!\"));" " _stprintf(dst, _T(\"Hello!\"));" " _sntprintf(dst, sizeof(dst) / sizeof(TCHAR), _T(\"Hello world!\"));" " _tscanf(_T(\"%s\"), dst);" " _stscanf(dst, _T(\"%s\"), dst);" "}" "TBYTE tbyte;"; const char expected[] = "wchar_t wc ; " "char c ; " "char * ptstr ; " "char * lptstr ; " "const char * pctstr ; " "const char * lpctstr ; " "void foo ( ) { " "char tc ; tc = \'c\' ; " "char src [ 10 ] = \"123456789\" ; " "char dst [ 10 ] ; " "strcpy ( dst , src ) ; " "dst [ 0 ] = 0 ; " "strcat ( dst , src ) ; " "char * d ; d = strdup ( str ) ; " "printf ( \"Hello world!\" ) ; " "sprintf ( dst , \"Hello!\" ) ; " "_snprintf ( dst , sizeof ( dst ) / sizeof ( char ) , \"Hello world!\" ) ; " "scanf ( \"%s\" , dst ) ; " "sscanf ( dst , \"%s\" , dst ) ; " "} " "unsigned char tbyte ;"; ASSERT_EQUALS(expected, tokenizeAndStringifyWindows(code, true, Settings::Win32A)); } void platformWin32W() { const char code[] = "wchar_t wc;" "TCHAR c;" "PTSTR ptstr;" "LPTSTR lptstr;" "PCTSTR pctstr;" "LPCTSTR lpctstr;" "TBYTE tbyte;" "void foo() {" " TCHAR tc = _T(\'c\');" " TCHAR src[10] = _T(\"123456789\");" " TCHAR dst[10];" " _tcscpy(dst, src);" " dst[0] = 0;" " _tcscat(dst, src);" " LPTSTR d = _tcsdup(str);" " _tprintf(_T(\"Hello world!\"));" " _stprintf(dst, _T(\"Hello!\"));" " _sntprintf(dst, sizeof(dst) / sizeof(TCHAR), _T(\"Hello world!\"));" " _tscanf(_T(\"%s\"), dst);" " _stscanf(dst, _T(\"%s\"), dst);" "}"; const char expected[] = "wchar_t wc ; " "wchar_t c ; " "wchar_t * ptstr ; " "wchar_t * lptstr ; " "const wchar_t * pctstr ; " "const wchar_t * lpctstr ; " "unsigned wchar_t tbyte ; " "void foo ( ) { " "wchar_t tc ; tc = L\'c\' ; " "wchar_t src [ 10 ] = L\"123456789\" ; " "wchar_t dst [ 10 ] ; " "wcscpy ( dst , src ) ; " "dst [ 0 ] = 0 ; " "wcscat ( dst , src ) ; " "wchar_t * d ; d = wcsdup ( str ) ; " "wprintf ( L\"Hello world!\" ) ; " "swprintf ( dst , L\"Hello!\" ) ; " "_snwprintf ( dst , sizeof ( dst ) / sizeof ( wchar_t ) , L\"Hello world!\" ) ; " "wscanf ( L\"%s\" , dst ) ; " "swscanf ( dst , L\"%s\" , dst ) ; " "}"; ASSERT_EQUALS(expected, tokenizeAndStringifyWindows(code, true, Settings::Win32W)); } void platformWin32AStringCat() { //#5150 const char code[] = "TCHAR text[] = _T(\"123\") _T(\"456\") _T(\"789\");"; const char expected[] = "char text [ 10 ] = \"123456789\" ;"; ASSERT_EQUALS(expected, tokenizeAndStringifyWindows(code, true, Settings::Win32A)); } void platformWin32WStringCat() { //#5150 const char code[] = "TCHAR text[] = _T(\"123\") _T(\"456\") _T(\"789\");"; const char expected[] = "wchar_t text [ 10 ] = L\"123456789\" ;"; ASSERT_EQUALS(expected, tokenizeAndStringifyWindows(code, true, Settings::Win32W)); } void platformWinWithNamespace() { const char code1[] = "UINT32 a; ::UINT32 b; foo::UINT32 c;"; const char expected1[] = "unsigned int a ; unsigned int b ; foo :: UINT32 c ;"; ASSERT_EQUALS(expected1, tokenizeAndStringifyWindows(code1, true, Settings::Win32A)); const char code2[] = "LPCVOID a; ::LPCVOID b; foo::LPCVOID c;"; const char expected2[] = "const void * a ; const void * b ; foo :: LPCVOID c ;"; ASSERT_EQUALS(expected2, tokenizeAndStringifyWindows(code2, true, Settings::Win32A)); } void isZeroNumber() const { ASSERT_EQUALS(true, Tokenizer::isZeroNumber("0.0")); ASSERT_EQUALS(true, Tokenizer::isZeroNumber("+0.0")); ASSERT_EQUALS(true, Tokenizer::isZeroNumber("-0.0")); ASSERT_EQUALS(true, Tokenizer::isZeroNumber("+0L")); ASSERT_EQUALS(true, Tokenizer::isZeroNumber("+0")); ASSERT_EQUALS(true, Tokenizer::isZeroNumber("-0")); ASSERT_EQUALS(true, Tokenizer::isZeroNumber("-0E+0")); ASSERT_EQUALS(false, Tokenizer::isZeroNumber("1.0")); ASSERT_EQUALS(false, Tokenizer::isZeroNumber("+1.0")); ASSERT_EQUALS(false, Tokenizer::isZeroNumber("-1")); ASSERT_EQUALS(false, Tokenizer::isZeroNumber("")); ASSERT_EQUALS(false, Tokenizer::isZeroNumber("garbage")); ASSERT_EQUALS(false, Tokenizer::isZeroNumber("E2")); ASSERT_EQUALS(false, Tokenizer::isZeroNumber("2e")); } void isOneNumber() const { ASSERT_EQUALS(true, Tokenizer::isOneNumber("1.0")); ASSERT_EQUALS(true, Tokenizer::isOneNumber("+1.0")); ASSERT_EQUALS(true, Tokenizer::isOneNumber("1.0e+0")); ASSERT_EQUALS(true, Tokenizer::isOneNumber("+1L")); ASSERT_EQUALS(true, Tokenizer::isOneNumber("+1")); ASSERT_EQUALS(true, Tokenizer::isOneNumber("1")); ASSERT_EQUALS(true, Tokenizer::isOneNumber("+1E+0")); ASSERT_EQUALS(false, Tokenizer::isOneNumber("0.0")); ASSERT_EQUALS(false, Tokenizer::isOneNumber("+0.0")); ASSERT_EQUALS(false, Tokenizer::isOneNumber("-0")); ASSERT_EQUALS(false, Tokenizer::isOneNumber("")); ASSERT_EQUALS(false, Tokenizer::isOneNumber("garbage")); } void isTwoNumber() const { ASSERT_EQUALS(true, Tokenizer::isTwoNumber("2.0")); ASSERT_EQUALS(true, Tokenizer::isTwoNumber("+2.0")); ASSERT_EQUALS(true, Tokenizer::isTwoNumber("2.0e+0")); ASSERT_EQUALS(true, Tokenizer::isTwoNumber("+2L")); ASSERT_EQUALS(true, Tokenizer::isTwoNumber("+2")); ASSERT_EQUALS(true, Tokenizer::isTwoNumber("2")); ASSERT_EQUALS(true, Tokenizer::isTwoNumber("+2E+0")); ASSERT_EQUALS(false, Tokenizer::isTwoNumber("0.0")); ASSERT_EQUALS(false, Tokenizer::isTwoNumber("+0.0")); ASSERT_EQUALS(false, Tokenizer::isTwoNumber("-0")); ASSERT_EQUALS(false, Tokenizer::isTwoNumber("")); ASSERT_EQUALS(false, Tokenizer::isTwoNumber("garbage")); } void simplifyStaticConst() { const char code1[] = "class foo { public: bool const static c ; }"; const char expected1[] = "class foo { public: static const bool c ; }"; ASSERT_EQUALS(expected1, tokenizeAndStringify(code1)); const char code2[] = "int long long f()\n" "{\n" "static const long long signed int i1;\n" "static const long long int signed i2;\n" "static const signed long long int i3;\n" "static const signed int long long i4;\n" "static const int signed long long i5;\n" "static const int long long signed i6;\n" "long long static const signed int i7;\n" "long long static const int signed i8;\n" "signed static const long long int i9;\n" "signed static const int long long i10;\n" "int static const signed long long i11;\n" "int static const long long signed i12;\n" "long long signed int static const i13;\n" "long long int signed static const i14;\n" "signed long long int static const i15;\n" "signed int long long static const i16;\n" "int signed long long static const i17;\n" "int long long signed static const i18;\n" "return i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10 + i11 + i12\n" "+ i13 + i14 + i15 + i16 + i17 + i18;\n" "}"; const char expected2[] = "long long f ( )\n" "{\n" "static const signed long long i1 ;\n" "static const signed long long i2 ;\n" "static const signed long long i3 ;\n" "static const signed long long i4 ;\n" "static const signed long long i5 ;\n" "static const signed long long i6 ;\n" "static const signed long long i7 ;\n" "static const signed long long i8 ;\n" "static const signed long long i9 ;\n" "static const signed long long i10 ;\n" "static const signed long long i11 ;\n" "static const signed long long i12 ;\n" "static const signed long long i13 ;\n" "static const signed long long i14 ;\n" "static const signed long long i15 ;\n" "static const signed long long i16 ;\n" "static const signed long long i17 ;\n" "static const signed long long i18 ;\n" "return i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10 + i11 + i12\n" "+ i13 + i14 + i15 + i16 + i17 + i18 ;\n" "}"; ASSERT_EQUALS(expected2, tokenizeAndStringify(code2)); const char code3[] = "const unsigned long extern int i;"; const char expected3[] = "extern const unsigned long i ;"; ASSERT_EQUALS(expected3, tokenizeAndStringify(code3)); } void simplifyCPPAttribute() { ASSERT_EQUALS("int f ( ) ;", tokenizeAndStringify("[[deprecated]] int f();", true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("[ [ deprecated ] ] int f ( ) ;", tokenizeAndStringify("[[deprecated]] int f();", true, Settings::Native, "test.cpp", false)); ASSERT_EQUALS("[ [ deprecated ] ] int f ( ) ;", tokenizeAndStringify("[[deprecated]] int f();", true, Settings::Native, "test.c", true)); ASSERT_EQUALS("template < class T > int f ( ) { }", tokenizeAndStringify("template [[noreturn]] int f(){}", true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("int f ( int i ) ;", tokenizeAndStringify("[[maybe_unused]] int f([[maybe_unused]] int i);", true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("[ [ maybe_unused ] ] int f ( [ [ maybe_unused ] ] int i ) ;", tokenizeAndStringify("[[maybe_unused]] int f([[maybe_unused]] int i);", true, Settings::Native, "test.cpp", false)); ASSERT_EQUALS("struct a ;", tokenizeAndStringify("struct [[]] a;", true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("struct a ;", tokenizeAndStringify("struct [[,]] a;", true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("struct a ;", tokenizeAndStringify("struct [[deprecated,]] a;", true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("struct a ;", tokenizeAndStringify("struct [[,,]] a;", true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("struct a ;", tokenizeAndStringify("struct [[deprecated,,]] a;", true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("struct a ;", tokenizeAndStringify("struct [[deprecated,maybe_unused,]] a;", true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("struct a ;", tokenizeAndStringify("struct [[,,,]] a;", true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("struct a ;", tokenizeAndStringify("struct alignas(int) a;", true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("struct a ;", tokenizeAndStringify("struct alignas ( alignof ( float ) ) a;", true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("char a [ 256 ] ;", tokenizeAndStringify("alignas(256) char a[256];", true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("struct a ;", tokenizeAndStringify("struct alignas(float) [[deprecated(reason)]] a;", true, Settings::Native, "test.cpp", true)); ASSERT_EQUALS("struct a ;", tokenizeAndStringify("struct [[deprecated,maybe_unused]] alignas(double) [[trivial_abi]] a;", true, Settings::Native, "test.cpp", true)); } void simplifyCaseRange() { ASSERT_EQUALS("void f ( ) { switch ( x ) { case 1 : case 2 : case 3 : case 4 : ; } }", tokenizeAndStringify("void f() { switch(x) { case 1 ... 4: } }")); ASSERT_EQUALS("void f ( ) { switch ( x ) { case 4 ... 1 : ; } }", tokenizeAndStringify("void f() { switch(x) { case 4 ... 1: } }")); tokenizeAndStringify("void f() { switch(x) { case 1 ... 1000000: } }"); // Do not run out of memory ASSERT_EQUALS("void f ( ) { switch ( x ) { case 'a' : case 98 : case 'c' : ; } }", tokenizeAndStringify("void f() { switch(x) { case 'a' ... 'c': } }")); ASSERT_EQUALS("void f ( ) { switch ( x ) { case 'c' ... 'a' : ; } }", tokenizeAndStringify("void f() { switch(x) { case 'c' ... 'a': } }")); ASSERT_EQUALS("void f ( ) { switch ( x ) { case '[' : case 92 : case ']' : ; } }", tokenizeAndStringify("void f() { switch(x) { case '[' ... ']': } }")); ASSERT_EQUALS("void f ( ) { switch ( x ) { case '&' : case 39 : case '(' : ; } }", tokenizeAndStringify("void f() { switch(x) { case '&' ... '(': } }")); ASSERT_EQUALS("void f ( ) { switch ( x ) { case '\\x61' : case 98 : case '\\x63' : ; } }", tokenizeAndStringify("void f() { switch(x) { case '\\x61' ... '\\x63': } }")); } void simplifyEmptyNamespaces() { ASSERT_EQUALS(";", tokenizeAndStringify("namespace { }")); ASSERT_EQUALS(";", tokenizeAndStringify("namespace foo { }")); ASSERT_EQUALS(";", tokenizeAndStringify("namespace foo { namespace { } }")); ASSERT_EQUALS(";", tokenizeAndStringify("namespace { namespace { } }")); // Ticket #9512 ASSERT_EQUALS(";", tokenizeAndStringify("namespace foo { namespace bar { } }")); } void prepareTernaryOpForAST() { ASSERT_EQUALS("a ? b : c ;", tokenizeAndStringify("a ? b : c;")); ASSERT_EQUALS("a ? ( b , c ) : d ;", tokenizeAndStringify("a ? b , c : d;")); ASSERT_EQUALS("a ? ( b , c ) : d ;", tokenizeAndStringify("a ? (b , c) : d;")); ASSERT_EQUALS("a ? ( 1 ? ( a , b ) : 3 ) : d ;", tokenizeAndStringify("a ? 1 ? a, b : 3 : d;")); ASSERT_EQUALS("a ? ( std :: map < int , int > ( ) ) : 0 ;", tokenizeAndStringify("typedef std::map mymap; a ? mymap() : 0;")); ASSERT_EQUALS("a ? ( b < c ) : d > e", tokenizeAndStringify("a ? b < c : d > e")); } enum class AstStyle { Simple, Z3 }; std::string testAst(const char code[], AstStyle style = AstStyle::Simple) { // tokenize given code.. Tokenizer tokenList(&settings0, nullptr); std::istringstream istr(code); if (!tokenList.list.createTokens(istr,"test.cpp")) return "ERROR"; tokenList.combineStringAndCharLiterals(); tokenList.combineOperators(); tokenList.simplifySpaceshipOperator(); tokenList.createLinks(); tokenList.createLinks2(); tokenList.list.front()->assignIndexes(); // set varid.. for (Token *tok = tokenList.list.front(); tok; tok = tok->next()) { if (tok->str() == "var") tok->varId(1); } // Create AST.. tokenList.prepareTernaryOpForAST(); tokenList.list.createAst(); tokenList.list.validateAst(); // Basic AST validation for (const Token *tok = tokenList.list.front(); tok; tok = tok->next()) { if (tok->astOperand2() && !tok->astOperand1() && tok->str() != ";" && tok->str() != ":") return "Op2 but no Op1 for token: " + tok->str(); } // Return stringified AST if (style == AstStyle::Z3) return tokenList.list.front()->astTop()->astStringZ3(); std::string ret; std::set astTop; for (const Token *tok = tokenList.list.front(); tok; tok = tok->next()) { if (tok->astOperand1() && astTop.find(tok->astTop()) == astTop.end()) { astTop.insert(tok->astTop()); if (!ret.empty()) ret = ret + " "; ret += tok->astTop()->astString(); } } return ret; } void astexpr() { // simple expressions with arithmetical ops ASSERT_EQUALS("12+3+", testAst("1+2+3")); ASSERT_EQUALS("12*3+", testAst("1*2+3")); ASSERT_EQUALS("123*+", testAst("1+2*3")); ASSERT_EQUALS("12*34*+", testAst("1*2+3*4")); ASSERT_EQUALS("12*34*5*+", testAst("1*2+3*4*5")); ASSERT_EQUALS("0(r.&", testAst("(&((typeof(x))0).r);")); ASSERT_EQUALS("0(r.&", testAst("&((typeof(x))0).r;")); ASSERT_EQUALS("0f1(||", testAst("; 0 || f(1);")); // Various tests of precedence ASSERT_EQUALS("ab::c+", testAst("a::b+c")); ASSERT_EQUALS("abc+=", testAst("a=b+c")); ASSERT_EQUALS("abc=,", testAst("a,b=c")); ASSERT_EQUALS("a-1+", testAst("-a+1")); ASSERT_EQUALS("ab++-c-", testAst("a-b++-c")); ASSERT_EQUALS("ab<=>", testAst("a<=>b")); // sizeof ASSERT_EQUALS("ab.sizeof", testAst("sizeof a.b")); // assignment operators ASSERT_EQUALS("ab>>=", testAst("a>>=b;")); ASSERT_EQUALS("ab<<=", testAst("a<<=b;")); ASSERT_EQUALS("ab+=", testAst("a+=b;")); ASSERT_EQUALS("ab-=", testAst("a-=b;")); ASSERT_EQUALS("ab*=", testAst("a*=b;")); ASSERT_EQUALS("ab/=", testAst("a/=b;")); ASSERT_EQUALS("ab%=", testAst("a%=b;")); ASSERT_EQUALS("ab&=", testAst("a&=b;")); ASSERT_EQUALS("ab|=", testAst("a|=b;")); ASSERT_EQUALS("ab^=", testAst("a^=b;")); ASSERT_EQUALS("ab*c*.(+return", testAst("return a + ((*b).*c)();")); // assignments are executed from right to left ASSERT_EQUALS("abc==", testAst("a=b=c;")); // ternary operator ASSERT_EQUALS("ab0=c1=:?", testAst("a?b=0:c=1;")); ASSERT_EQUALS("fabc,d:?=e,", testAst("f = a ? b, c : d, e;")); ASSERT_EQUALS("fabc,de,:?=", testAst("f = (a ? (b, c) : (d, e));")); ASSERT_EQUALS("fabc,de,:?=", testAst("f = (a ? b, c : (d, e));")); ASSERT_EQUALS("ab35,4:?foo(:?return", testAst("return (a ? b ? (3,5) : 4 : foo());")); ASSERT_EQUALS("check(result_type00,{invalid:?return", testAst("return check() ? result_type {0, 0} : invalid;")); ASSERT_EQUALS("x01:?return", testAst("return x ? 0 : 1;")); ASSERT_EQUALS("x00throw:?return", testAst("return x ? 0 : throw 0;")); // #9768 ASSERT_EQUALS("val0<1throwval:?return", testAst("return val < 0 ? throw 1 : val;")); // #8526 ASSERT_EQUALS("ix0<00throw:?=", testAst("int i = x < 0 ? 0 : throw 0;")); ASSERT_EQUALS("a\"\"=", testAst("a=\"\"")); ASSERT_EQUALS("a\'\'=", testAst("a=\'\'")); ASSERT_EQUALS("'X''a'>", testAst("('X' > 'a')")); ASSERT_EQUALS("L'X'L'a'>", testAst("(L'X' > L'a')")); ASSERT_EQUALS("u'X'u'a'>", testAst("(u'X' > u'a')")); ASSERT_EQUALS("U'X'U'a'>", testAst("(U'X' > U'a')")); ASSERT_EQUALS("u8'X'u8'a'>", testAst("(u8'X' > u8'a')")); ASSERT_EQUALS("a0>bc/d:?", testAst("(a>0) ? (b/(c)) : d;")); ASSERT_EQUALS("abc/+d+", testAst("a + (b/(c)) + d;")); ASSERT_EQUALS("x1024x/0:?", testAst("void f() { x ? 1024 / x : 0; }")); ASSERT_EQUALS("absizeofd(ef.+(=", testAst("a = b(sizeof(c d) + e.f)")); ASSERT_EQUALS("a*b***", testAst("*a * **b;")); // Correctly distinguish between unary and binary operator* // strings ASSERT_EQUALS("f\"A\"1,(",testAst("f(\"A\" B, 1);")); ASSERT_EQUALS("fA1,(",testAst("f(A \"B\", 1);")); // C++ : type() ASSERT_EQUALS("fint(0,(", testAst("f(int(),0);")); ASSERT_EQUALS("f(0,(", testAst("f(int *(),0);")); // typedef int* X; f(X(),0); ASSERT_EQUALS("f((0,(", testAst("f((intp)int *(),0);")); ASSERT_EQUALS("zx1(&y2(&|=", testAst("z = (x & (unsigned)1) | (y & (unsigned)2);")); // not type() // for ASSERT_EQUALS("for;;(", testAst("for(;;)")); ASSERT_EQUALS("fora0=a8 var : d);")); ASSERT_EQUALS("forvare:(", testAst("for (a::b var : e);")); ASSERT_EQUALS("forx*0=yz;;(", testAst("for(*x=0;y;z)")); ASSERT_EQUALS("forx0=y(8next ) {}")); ASSERT_EQUALS("forx0=x;;(", testAst("for (int x=0; x;);")); // for with initializer (c++20) ASSERT_EQUALS("forab=ca:;(", testAst("for(a=b;int c:a)")); // problems with multiple expressions ASSERT_EQUALS("ax( whilex(", testAst("a(x) while (x)")); ASSERT_EQUALS("ifx( i0= whilei(", testAst("if (x) { ({ int i = 0; while(i); }) };")); ASSERT_EQUALS("ifx( BUG_ON{!( i0= whilei(", testAst("if (x) { BUG_ON(!({int i=0; while(i);})); }")); ASSERT_EQUALS("v0= while{0!=( v0= while{0!=( v0=", testAst("({ v = 0; }); while (({ v = 0; }) != 0); while (({ v = 0; }) != 0);")); ASSERT_EQUALS("abc.1:?1+bd.1:?+=", testAst("a =(b.c ? : 1) + 1 + (b.d ? : 1);")); ASSERT_EQUALS("catch...(", testAst("try {} catch (...) {}")); ASSERT_EQUALS("", testAst("void Foo(Bar&);")); ASSERT_EQUALS("", testAst("void Foo(Bar&&);")); ASSERT_EQUALS("Barb&", testAst("void Foo(Bar& b);")); ASSERT_EQUALS("Barb&&", testAst("void Foo(Bar&& b);")); ASSERT_EQUALS("DerivedDerived::(", testAst("Derived::~Derived() {}")); ASSERT_EQUALS("ifCA_FarReadfilenew(,sizeofobjtype(,(!(", testAst("if (!CA_FarRead(file, (void far *)new, sizeof(objtype)))")); // #5910 - don't hang if C code is parsed as C++ // C++17: if (expr1; expr2) ASSERT_EQUALS("ifx3=y;(", testAst("if (int x=3; y)")); } void astexpr2() { // limit for large expressions // #7724 - wrong AST causes hang // Ideally a proper AST is created for this code. const char code[] = "const char * a(int type) {\n" " return (\n" " (type == 1) ? \"\"\n" " : (type == 2) ? \"\"\n" " : (type == 3) ? \"\"\n" " : (type == 4) ? \"\"\n" " : (type == 5) ? \"\"\n" " : (type == 6) ? \"\"\n" " : (type == 7) ? \"\"\n" " : (type == 8) ? \"\"\n" " : (type == 9) ? \"\"\n" " : (type == 10) ? \"\"\n" " : (type == 11) ? \"\"\n" " : (type == 12) ? \"\"\n" " : (type == 13) ? \"\"\n" " : (type == 14) ? \"\"\n" " : (type == 15) ? \"\"\n" " : (type == 16) ? \"\"\n" " : (type == 17) ? \"\"\n" " : (type == 18) ? \"\"\n" " : (type == 19) ? \"\"\n" " : (type == 20) ? \"\"\n" " : (type == 21) ? \"\"\n" " : (type == 22) ? \"\"\n" " : (type == 23) ? \"\"\n" " : (type == 24) ? \"\"\n" " : (type == 25) ? \"\"\n" " : (type == 26) ? \"\"\n" " : (type == 27) ? \"\"\n" " : (type == 28) ? \"\"\n" " : (type == 29) ? \"\"\n" " : (type == 30) ? \"\"\n" " : (type == 31) ? \"\"\n" " : (type == 32) ? \"\"\n" " : (type == 33) ? \"\"\n" " : (type == 34) ? \"\"\n" " : (type == 35) ? \"\"\n" " : (type == 36) ? \"\"\n" " : (type == 37) ? \"\"\n" " : (type == 38) ? \"\"\n" " : (type == 39) ? \"\"\n" " : (type == 40) ? \"\"\n" " : (type == 41) ? \"\"\n" " : (type == 42) ? \"\"\n" " : (type == 43) ? \"\"\n" " : (type == 44) ? \"\"\n" " : (type == 45) ? \"\"\n" " : (type == 46) ? \"\"\n" " : (type == 47) ? \"\"\n" " : (type == 48) ? \"\"\n" " : (type == 49) ? \"\"\n" " : (type == 50) ? \"\"\n" " : (type == 51) ? \"\"\n" " : \"\");\n" "}\n"; // Ensure that the AST is validated for the simplified token list TODO_ASSERT_THROW(tokenizeAndStringify(code), InternalError); // this should not crash/hang } void astnewdelete() { ASSERT_EQUALS("aintnew=", testAst("a = new int;")); ASSERT_EQUALS("aint4[new=", testAst("a = new int[4];")); ASSERT_EQUALS("aFoobar(new=", testAst("a = new Foo(bar);")); ASSERT_EQUALS("aFoobar(new=", testAst("a = new Foo(bar);")); ASSERT_EQUALS("aFoo(new=", testAst("a = new Foo();")); ASSERT_EQUALS("aXnew(", testAst("a (new (X));")); ASSERT_EQUALS("aXnew5,(", testAst("a (new (X), 5);")); ASSERT_EQUALS("adelete", testAst("delete a;")); ASSERT_EQUALS("adelete", testAst("delete (a);")); ASSERT_EQUALS("adelete", testAst("delete[] a;")); ASSERT_EQUALS("ab.3c-(delete", testAst("delete[] a.b(3 - c);")); ASSERT_EQUALS("aA1(new(bB2(new(,", testAst("a(new A(1)), b(new B(2))")); ASSERT_EQUALS("Fred10[new", testAst(";new Fred[10];")); ASSERT_EQUALS("adelete", testAst("void f() { delete a; }")); // placement new ASSERT_EQUALS("X12,3,(new ab,c,", testAst("new (a,b,c) X(1,2,3);")); ASSERT_EQUALS("a::new=", testAst("a = new (b) ::X;")); ASSERT_EQUALS("cCnew= abc:?", testAst("c = new(a ? b : c) C;")); // invalid code (libreoffice), don't hang // #define SlideSorterViewShell // SfxViewFrame* pFrame; // new SlideSorterViewShell(pFrame,rViewShellBase,pParentWindow,pFrameViewArgument); ASSERT_EQUALS("fxnewy,z,(", testAst("f(new (x,y,z));")); // clang testsuite.. ASSERT_EQUALS("const0(new", testAst("new const auto (0);")); ASSERT_EQUALS("autonew", testAst("new (auto) (0.0);")); ASSERT_EQUALS("int3[4[5[new", testAst("new (int S::*[3][4][5]) ();")); ASSERT_EQUALS("pSnew=", testAst("p=new (x)(S)(1,2);")); ASSERT_EQUALS("inti[new(", testAst("(void)new (int[i]);")); ASSERT_EQUALS("intp* pnew malloc4(", testAst("int*p; new (p) (malloc(4));")); ASSERT_EQUALS("intnew", testAst("new (&w.x)(int*)(0);")); ASSERT_EQUALS("&new", testAst("new (&w.x)(0);")); // <- the "(int*)" has been simplified // gcc testsuite.. ASSERT_EQUALS("char10[new(", testAst("(void)new(char*)[10];")); } void astpar() { // parentheses ASSERT_EQUALS("12+3*", testAst("(1+2)*3")); ASSERT_EQUALS("123+*", testAst("1*(2+3)")); ASSERT_EQUALS("123+*4*", testAst("1*(2+3)*4")); ASSERT_EQUALS("ifab.c&d==(", testAst("if((a.b&c)==d){}")); ASSERT_EQUALS("pf.pf.12,(&&", testAst("((p.f) && (p.f)(1,2))")); ASSERT_EQUALS("forresdirGetFirst.file&_T(,(=;;(", testAst("for ((res = dir.GetFirst(&file, _T("")));;) {}")); // problems with: if (x[y]==z) ASSERT_EQUALS("ifa(0[1==(", testAst("if(a()[0]==1){}")); ASSERT_EQUALS("ifbuff0[&(*1==(", testAst("if (*((DWORD*)&buff[0])==1){}")); ASSERT_EQUALS("ifp*0[1==(", testAst("if((*p)[0]==1)")); ASSERT_EQUALS("ifab.cd.[e==(", testAst("if(a.b[c.d]==e){}")); ASSERT_EQUALS("iftpnote.i1-[note.0==tpnote.i1-[type.4>||(", testAst("if ((tp.note[i - 1].note == 0) || (tp.note[i - 1].type > 4)) {}")); ASSERT_EQUALS("ab.i[j1+[", testAst("a.b[i][j+1]")); // problems with: x=expr ASSERT_EQUALS("(= x (( (. ([ a i) f)))", testAst("x = ((a[i]).f)();", AstStyle::Z3)); ASSERT_EQUALS("abc.de.++[=", testAst("a = b.c[++(d.e)];")); ASSERT_EQUALS("abc(1+=", testAst("a = b(c**)+1;")); ASSERT_EQUALS("abc.=", testAst("a = (b).c;")); // casts ASSERT_EQUALS("a1(2(+=",testAst("a=(t)1+(t)2;")); ASSERT_EQUALS("a1(2+=",testAst("a=(t)1+2;")); ASSERT_EQUALS("a1(2+=",testAst("a=(t*)1+2;")); ASSERT_EQUALS("a1(2+=",testAst("a=(t&)1+2;")); ASSERT_EQUALS("a1(2+=",testAst("a=(t&&)1+2;")); ASSERT_EQUALS("ab::r&c(=", testAst("a::b& r = (a::b&)c;")); // #5261 ASSERT_EQUALS("ab10:?=", testAst("a=(b)?1:0;")); ASSERT_EQUALS("ac5[new(=", testAst("a = (b*)(new c[5]);")); // #8786 ASSERT_EQUALS("a(4+", testAst("(int)(a) + 4;")); // (cast){data}[index] ASSERT_EQUALS("a&{(0[1[5[0=", testAst("(int (**)[i]){&a}[0][1][5] = 0;")); ASSERT_EQUALS("ab12,{(0[,(", testAst("a(b, (int []){1,2}[0]);")); ASSERT_EQUALS("n0=", testAst("TrivialDefCtor{[2][2]}[1][1].n = 0;")); ASSERT_EQUALS("aT12,3,{1[=", testAst("a = T{1, 2, 3}[1];")); // Type{data}() ASSERT_EQUALS("ab{(=", testAst("a=b{}();")); ASSERT_EQUALS("abc{((=", testAst("a=b(c{}());")); ASSERT_EQUALS("xNULL!=0(x(:?", testAst("void f() { {} ((x != NULL) ? (void)0 : x()); }")); // ({..}) ASSERT_EQUALS("a{+d+ bc+", testAst("a+({b+c;})+d")); ASSERT_EQUALS("a{d*+ bc+", testAst("a+({b+c;})*d")); ASSERT_EQUALS("xa{((= bc( yd{((= ef(", testAst("x=(int)(a({b(c);}));" // don't hang "y=(int)(d({e(f);}));")); ASSERT_EQUALS("A{{,( x0= Bx1={x2={,(", // TODO: This is not perfect!! testAst("A({},{x=0;});" // don't hang "B({x=1},{x=2});")); ASSERT_EQUALS("xMACROtype.T=value.1=,{({=", testAst("x = { MACRO( { .type=T, .value=1 } ) }")); // don't hang: MACRO({..}) ASSERT_EQUALS("fori10=i{;;( i--", testAst("for (i=10;i;({i--;}) ) {}")); ASSERT_EQUALS("c{1{,{2.3f{,(", testAst("c({{}, {1}}, {2.3f});")); // function pointer TODO_ASSERT_EQUALS("todo", "va_argapvoid((,(*0=", testAst("*va_arg(ap, void(**) ()) = 0;")); // struct/array initialization ASSERT_EQUALS("name_bytes[bits~unusedBits>>unusedBits<<{=", testAst("const uint8_t name_bytes[] = { (~bits >> unusedBits) << unusedBits };")); ASSERT_EQUALS("abuf.0{={=", testAst("a = { .buf = { 0 } };")); ASSERT_EQUALS("ab2[a.0=b.0=,{a.0=b.0=,{,{=", testAst("struct AB ab[2] = { { .a=0, .b=0 }, { .a=0, .b=0 } };")); ASSERT_EQUALS("tset{=", testAst("struct cgroup_taskset tset = {};")); ASSERT_EQUALS("s1a&,{2b&,{,{=", testAst("s = { {1, &a}, {2, &b} };")); ASSERT_EQUALS("s0[L.2[x={=", testAst("s = { [0].L[2] = x};")); ASSERT_EQUALS("ac.0={(=", testAst("a = (b){.c=0,};")); // <- useless comma ASSERT_EQUALS("xB[1y.z.1={(&=,{={=", testAst("x = { [B] = {1, .y = &(struct s) { .z=1 } } };")); ASSERT_EQUALS("xab,c,{=", testAst("x={a,b,(c)};")); ASSERT_EQUALS("x0fSa.1=b.2=,c.\"\"=,{(||=", testAst("x = 0 || f(S{.a = 1, .b = 2, .c = \"\" });")); ASSERT_EQUALS("x0fSa.1{=b.2{,c.\"\"=,{(||=", testAst("x = 0 || f(S{.a = { 1 }, .b { 2 }, .c = \"\" });")); ASSERT_EQUALS("a0{,( \"\"abc12:?,", testAst("a(0, {{\"\", (abc) ? 1 : 2}});")); ASSERT_EQUALS("a0{,( \'\'abc12:?,", testAst("a(0, {{\'\', (abc) ? 1 : 2}});")); ASSERT_EQUALS("x12,{34,{,{56,{78,{,{,{=", testAst("x = { { {1,2}, {3,4} }, { {5,6}, {7,8} } };")); // struct initialization hang ASSERT_EQUALS("sbar.1{,{(={= forfieldfield++;;(", testAst("struct S s = {.bar = (struct foo) { 1, { } } };\n" "void f(struct cmd *) { for (; field; field++) {} }")); // template parentheses: <> ASSERT_EQUALS("ab::c(de::(<=return", testAst("return a::b(c) <= d::e();")); // #6195 // C++ initializer ASSERT_EQUALS("Class{", testAst("Class{};")); ASSERT_EQUALS("Class12,{", testAst("Class{1,2};")); ASSERT_EQUALS("Class12,{", testAst("Class{1,2};")); ASSERT_EQUALS("abc{d:?=", testAst("a=b?c{}:d;")); ASSERT_EQUALS("abc12,{d:?=", testAst("a=b?c{1,2}:d;")); ASSERT_EQUALS("abc{d:?=", testAst("a=b?c{}:d;")); ASSERT_EQUALS("abc12,{d:?=", testAst("a=b?c{1,2}:d;")); ASSERT_EQUALS("a::12,{", testAst("::a{1,2};")); // operator precedence ASSERT_EQUALS("Abc({newreturn", testAst("return new A {b(c)};")); ASSERT_EQUALS("a{{return", testAst("return{{a}};")); ASSERT_EQUALS("a{b{,{return", testAst("return{{a},{b}};")); ASSERT_EQUALS("stdvector::", testAst("std::vector>{{},{}}")); ASSERT_EQUALS("abR{{,P(,((", testAst("a(b(R{},{},P()));")); ASSERT_EQUALS("f1{2{,3{,{x,(", testAst("f({{1},{2},{3}},x);")); ASSERT_EQUALS("a1{ b2{", testAst("auto a{1}; auto b{2};")); ASSERT_EQUALS("var1ab::23,{,{4ab::56,{,{,{", testAst("auto var{{1,a::b{2,3}}, {4,a::b{5,6}}};")); ASSERT_EQUALS("var{{,{,{{", testAst("auto var{ {{},{}}, {} };")); // Initialization with decltype(expr) instead of a type ASSERT_EQUALS("decltypex((", testAst("decltype(x)();")); ASSERT_EQUALS("decltypex({", testAst("decltype(x){};")); ASSERT_EQUALS("decltypexy+(yx+(", testAst("decltype(x+y)(y+x);")); ASSERT_EQUALS("decltypexy+(yx+{", testAst("decltype(x+y){y+x};")); } void astbrackets() { // [] ASSERT_EQUALS("a23+[4+", testAst("a[2+3]+4")); ASSERT_EQUALS("a1[0[", testAst("a[1][0]")); ASSERT_EQUALS("ab0[=", testAst("a=(b)[0];")); ASSERT_EQUALS("abc.0[=", testAst("a=b.c[0];")); ASSERT_EQUALS("ab0[1[=", testAst("a=b[0][1];")); } void astvardecl() { // Variable declaration ASSERT_EQUALS("a1[\"\"=", testAst("char a[1]=\"\";")); ASSERT_EQUALS("charp*(3[char5[3[new=", testAst("char (*p)[3] = new char[5][3];")); ASSERT_EQUALS("varp=", testAst("const int *var = p;")); // #9127 const char code1[] = "using uno::Ref;\n" "Ref r;\n" "int var(0);"; ASSERT_EQUALS("unoRef:: var0(", testAst(code1)); ASSERT_EQUALS("vary=", testAst("std::string var = y;")); // create ast for decltype ASSERT_EQUALS("decltypex( var1=", testAst("decltype(x) var = 1;")); ASSERT_EQUALS("a1bdecltypet((>2,(", testAst("a(1 > b(decltype(t)), 2);")); // #10271 ASSERT_EQUALS("decltypex({01:?", testAst("decltype(x){} ? 0 : 1;")); } void astunaryop() { // unary operators ASSERT_EQUALS("1a--+", testAst("1 + --a")); ASSERT_EQUALS("1a--+", testAst("1 + a--")); ASSERT_EQUALS("ab+!", testAst("!(a+b)")); ASSERT_EQUALS("ab.++", testAst("++a.b;")); ASSERT_EQUALS("ab.++", testAst("a.b++;")); ASSERT_EQUALS("ab::++", testAst("a::b++;")); ASSERT_EQUALS("c5[--*", testAst("*c[5]--;")); ASSERT_EQUALS("xreturn", testAst("return x;")); ASSERT_EQUALS("x(throw", testAst(";throw x();")); ASSERT_EQUALS("a*bc:?return", testAst("return *a ? b : c;")); ASSERT_EQUALS("xy*--=", testAst("x = -- * y;")); ASSERT_EQUALS("x(throw", testAst(";throw (foo) x;")); // #9955 // Unary :: operator ASSERT_EQUALS("abcd::12,(e/:?=", testAst("a = b ? c : ::d(1,2) / e;")); // how is "--" handled here: ASSERT_EQUALS("ab4<,etc.. ASSERT_EQUALS("a(3==", testAst("a()==3")); ASSERT_EQUALS("ab(== f(", testAst("a == b(); f();")); ASSERT_EQUALS("static_casta(i[", testAst("; static_cast(a)[i];")); // #6203 ASSERT_EQUALS("reinterpret_castreinterpret_castptr(123&(", testAst(";reinterpret_cast(reinterpret_cast(ptr) & 123);")); // #7253 ASSERT_EQUALS("bcd.(=", testAst(";a && b = c->d();")); // This two unit tests were added to avoid a crash. The actual correct AST result for non-executable code has not been determined so far. ASSERT_NO_THROW(testAst("class C : public ::a::b { };")); ASSERT_EQUALS("AB: abc+=", testAst("struct A : public B { void f() { a=b+c; } };")); ASSERT_EQUALS("xfts(=", testAst("; auto x = f(ts...);")); } void astcast() { ASSERT_EQUALS("ac&(=", testAst("a = (long)&c;")); ASSERT_EQUALS("ac*(=", testAst("a = (Foo*)*c;")); ASSERT_EQUALS("ac-(=", testAst("a = (long)-c;")); ASSERT_EQUALS("ac~(=", testAst("a = (b)~c;")); ASSERT_EQUALS("ac(=", testAst("a = (some)c;")); ASSERT_EQUALS("afoveon_avgimage((foveon_avgimage((+=", testAst("a = foveon_avg(((short(*)[4]) image)) + foveon_avg(((short(*)[4]) image));")); ASSERT_EQUALS("c(40< ASSERT_EQUALS("{([(return 0return", testAst("return []() -> int { return 0; }();")); ASSERT_EQUALS("{(something[(return 0return", testAst("return [something]() -> int { return 0; }();")); ASSERT_EQUALS("{([cd,(return 0return", testAst("return [](int a, int b) -> int { return 0; }(c, d);")); ASSERT_EQUALS("{([return", testAst("return []() -> decltype(0) {};")); ASSERT_EQUALS("x{(&[=", testAst("x = [&]()->std::string const & {};")); ASSERT_EQUALS("f{([=", testAst("f = []() -> foo* {};")); ASSERT_EQUALS("f{([=", testAst("f = []() -> foo&& {};")); ASSERT_EQUALS("f{([=", testAst("f = [](void) mutable -> foo* {};")); ASSERT_EQUALS("f{([=", testAst("f = []() mutable {};")); ASSERT_EQUALS("x{([= 0return", testAst("x = [](){return 0; };")); ASSERT_EQUALS("ab{&[(= cd=", testAst("a = b([&]{c=d;});")); // 8628 ASSERT_EQUALS("f{([( switchx( 1case y++", testAst("f([](){switch(x){case 1:{++y;}}});")); ASSERT_EQUALS("{(=[{return ab=", testAst("return {\n" " [=]() {\n" " a = b;\n" " }\n" "};\n")); ASSERT_EQUALS("{=[{return ab=", testAst("return {\n" " [=] {\n" " a = b;\n" " }\n" "};\n")); ASSERT_EQUALS("{(=[{return ab=", testAst("return {\n" " [=]() -> int {\n" " a=b;\n" " }\n" "}")); ASSERT_EQUALS("{(=[{return ab=", testAst("return {\n" " [=]() mutable -> int {\n" " a=b;\n" " }\n" "}")); // daca@home hang ASSERT_EQUALS("a{(&[= 0return b{(=[= fori0=i10!=i++;;(", testAst("a = [&]() -> std::pair { return 0; };\n" "b = [=]() { for (i = 0; i != 10; ++i); };")); // #9662 ASSERT_EQUALS("b{[{ stdunique_ptr::0nullptrnullptr:?{", testAst("auto b{[] { std::unique_ptr{0 ? nullptr : nullptr}; }};")); ASSERT_EQUALS("b{[=", testAst("void a() { [b = [] { ; }] {}; }")); // Lambda capture expression (C++14) ASSERT_EQUALS("a{b1=[= c2=", testAst("a = [b=1]{c=2;};")); // #9729 ASSERT_NO_THROW(tokenizeAndStringify("void foo() { bar([]() noexcept { if (0) {} }); }")); // #10079 - createInnerAST bug.. ASSERT_EQUALS("x{([= yz= switchy(", testAst("x = []() -> std::vector {\n" " const auto y = z;\n" " switch (y) {}\n" "};")); } void astcase() { ASSERT_EQUALS("0case", testAst("case 0:")); ASSERT_EQUALS("12+case", testAst("case 1+2:")); ASSERT_EQUALS("xyz:?case", testAst("case (x?y:z):")); ASSERT_EQUALS("switchx( 1case y++ 2case", testAst("switch(x){case 1:{++y;break;case 2:break;}}")); } void astrefqualifier() { ASSERT_EQUALS("b(int.", testAst("class a { auto b() -> int&; };")); ASSERT_EQUALS("b(int.", testAst("class a { auto b() -> int&&; };")); ASSERT_EQUALS("b(", testAst("class a { void b() &&; };")); ASSERT_EQUALS("b(", testAst("class a { void b() &; };")); ASSERT_EQUALS("b(", testAst("class a { void b() && {} };")); ASSERT_EQUALS("b(", testAst("class a { void b() & {} };")); } //Verify that returning a newly constructed object generates the correct AST even when the class name is scoped //Addresses https://trac.cppcheck.net/ticket/9700 void astnewscoped() { ASSERT_EQUALS("(return (new A))", testAst("return new A;", AstStyle::Z3)); ASSERT_EQUALS("(return (new (( A)))", testAst("return new A();", AstStyle::Z3)); ASSERT_EQUALS("(return (new (( A true)))", testAst("return new A(true);", AstStyle::Z3)); ASSERT_EQUALS("(return (new (:: A B)))", testAst("return new A::B;", AstStyle::Z3)); ASSERT_EQUALS("(return (new (( (:: A B))))", testAst("return new A::B();", AstStyle::Z3)); ASSERT_EQUALS("(return (new (( (:: A B) true)))", testAst("return new A::B(true);", AstStyle::Z3)); ASSERT_EQUALS("(return (new (:: (:: A B) C)))", testAst("return new A::B::C;", AstStyle::Z3)); ASSERT_EQUALS("(return (new (( (:: (:: A B) C))))", testAst("return new A::B::C();", AstStyle::Z3)); ASSERT_EQUALS("(return (new (( (:: (:: A B) C) true)))", testAst("return new A::B::C(true);", AstStyle::Z3)); ASSERT_EQUALS("(return (new (:: (:: (:: A B) C) D)))", testAst("return new A::B::C::D;", AstStyle::Z3)); ASSERT_EQUALS("(return (new (( (:: (:: (:: A B) C) D))))", testAst("return new A::B::C::D();", AstStyle::Z3)); ASSERT_EQUALS("(return (new (( (:: (:: (:: A B) C) D) true)))", testAst("return new A::B::C::D(true);", AstStyle::Z3)); } void compileLimits() { const char raw_code[] = "#define PTR1 (* (* (* (* (* (* (* (* (* (*\n" "#define PTR2 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1\n" "#define PTR3 PTR2 PTR2 PTR2 PTR2 PTR2 PTR2 PTR2 PTR2 PTR2 PTR2\n" "#define PTR4 PTR3 PTR3 PTR3 PTR3 PTR3 PTR3 PTR3 PTR3 PTR3 PTR3\n" "#define PTR5 PTR4 PTR4 PTR4 PTR4 PTR4 PTR4 PTR4 PTR4 PTR4 PTR4\n" "#define PTR6 PTR5 PTR5 PTR5 PTR5 PTR5 PTR5 PTR5 PTR5 PTR5 PTR5\n" "\n" "#define RBR1 ) ) ) ) ) ) ) ) ) )\n" "#define RBR2 RBR1 RBR1 RBR1 RBR1 RBR1 RBR1 RBR1 RBR1 RBR1 RBR1\n" "#define RBR3 RBR2 RBR2 RBR2 RBR2 RBR2 RBR2 RBR2 RBR2 RBR2 RBR2\n" "#define RBR4 RBR3 RBR3 RBR3 RBR3 RBR3 RBR3 RBR3 RBR3 RBR3 RBR3\n" "#define RBR5 RBR4 RBR4 RBR4 RBR4 RBR4 RBR4 RBR4 RBR4 RBR4 RBR4\n" "#define RBR6 RBR5 RBR5 RBR5 RBR5 RBR5 RBR5 RBR5 RBR5 RBR5 RBR5\n" "\n" "int PTR4 q4_var RBR4 = 0;\n"; // Preprocess file.. Preprocessor preprocessor(settings0); std::list configurations; std::string filedata; std::istringstream fin(raw_code); preprocessor.preprocess(fin, filedata, configurations, emptyString, settings0.includePaths); const std::string code = preprocessor.getcode(filedata, emptyString, emptyString); tokenizeAndStringify(code.c_str()); // just survive... } bool isStartOfExecutableScope(int offset, const char code[]) { Tokenizer tokenizer(&settings0, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); return Tokenizer::startOfExecutableScope(tokenizer.tokens()->tokAt(offset)) != nullptr; } void startOfExecutableScope() { ASSERT(isStartOfExecutableScope(3, "void foo() { }")); ASSERT(isStartOfExecutableScope(3, "void foo() const { }")); ASSERT(isStartOfExecutableScope(3, "void foo() volatile { }")); ASSERT(isStartOfExecutableScope(3, "void foo() override { }")); ASSERT(isStartOfExecutableScope(3, "void foo() noexcept { }")); ASSERT(isStartOfExecutableScope(3, "void foo() NOEXCEPT { }")); ASSERT(isStartOfExecutableScope(3, "void foo() CONST NOEXCEPT { }")); ASSERT(isStartOfExecutableScope(3, "void foo() const noexcept { }")); ASSERT(isStartOfExecutableScope(3, "void foo() noexcept(true) { }")); ASSERT(isStartOfExecutableScope(3, "void foo() const noexcept(true) { }")); ASSERT(isStartOfExecutableScope(3, "void foo() throw() { }")); ASSERT(isStartOfExecutableScope(3, "void foo() THROW() { }")); ASSERT(isStartOfExecutableScope(3, "void foo() CONST THROW() { }")); ASSERT(isStartOfExecutableScope(3, "void foo() const throw() { }")); ASSERT(isStartOfExecutableScope(3, "void foo() throw(int) { }")); ASSERT(isStartOfExecutableScope(3, "void foo() const throw(int) { }")); ASSERT(isStartOfExecutableScope(2, "foo() : a(1) { }")); ASSERT(isStartOfExecutableScope(2, "foo() : a(1), b(2) { }")); ASSERT(isStartOfExecutableScope(2, "foo() : a{1} { }")); ASSERT(isStartOfExecutableScope(2, "foo() : a{1}, b{2} { }")); } void removeMacroInClassDef() { // #6058 ASSERT_EQUALS("class Fred { } ;", tokenizeAndStringify("class DLLEXPORT Fred { } ;")); ASSERT_EQUALS("class Fred : Base { } ;", tokenizeAndStringify("class Fred FINAL : Base { } ;")); // Regression for C code: ASSERT_EQUALS("struct Fred { } ;", tokenizeAndStringify("struct DLLEXPORT Fred { } ;", true, Settings::Native, "test.c")); } void sizeofAddParentheses() { ASSERT_EQUALS("sizeof ( sizeof ( 1 ) ) ;", tokenizeAndStringify("sizeof sizeof 1;")); ASSERT_EQUALS("sizeof ( a . b ) + 3 ;", tokenizeAndStringify("sizeof a.b+3;")); ASSERT_EQUALS("sizeof ( a [ 2 ] . b ) + 3 ;", tokenizeAndStringify("sizeof a[2].b+3;")); ASSERT_EQUALS("f ( 0 , sizeof ( ptr . bar ) ) ;", tokenizeAndStringify("f(0, sizeof ptr->bar );")); ASSERT_EQUALS("sizeof ( a ) > sizeof ( & main ) ;", tokenizeAndStringify("sizeof a > sizeof &main;")); } void reportUnknownMacros() { const char code1[] = "MY_UNKNOWN_IMP1(IInStream)\n" "STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) { if (ptr); }"; ASSERT_THROW(tokenizeAndStringify(code1), InternalError); const char code2[] = "void foo() { dostuff(x 0); }"; ASSERT_THROW(tokenizeAndStringify(code2), InternalError); const char code3[] = "f(\"1\" __stringify(48) \"1\");"; ASSERT_THROW(tokenizeAndStringify(code3), InternalError); const char code4[] = "struct Foo {\n" " virtual MACRO(int) f1() {}\n" " virtual MACRO(int) f2() {}\n" "};"; ASSERT_THROW(tokenizeAndStringify(code4), InternalError); const char code5[] = "void foo() {\n" " EVALUATE(123, int x=a; int y=b+c;);\n" "}"; ASSERT_THROW(tokenizeAndStringify(code5), InternalError); const char code6[] = "void foo() { dostuff(a, .x=0); }"; ASSERT_THROW(tokenizeAndStringify(code6), InternalError); const char code7[] = "void foo() { dostuff(ZEND_NUM_ARGS() TSRMLS_CC, x, y); }"; // #9476 ASSERT_THROW(tokenizeAndStringify(code7), InternalError); const char code8[] = "void foo() { a = [](int x, decltype(vec) y){}; }"; ASSERT_NO_THROW(tokenizeAndStringify(code8)); } void findGarbageCode() { // Test Tokenizer::findGarbageCode() // C++ try/catch in global scope ASSERT_THROW_EQUALS(tokenizeAndStringify("try { }"), InternalError, "syntax error: keyword 'try' is not allowed in global scope"); ASSERT_NO_THROW(tokenizeAndStringify("void f() try { } catch (int) { }")); // before if|for|while|switch ASSERT_NO_THROW(tokenizeAndStringify("void f() { do switch (a) {} while (1); }")); ASSERT_NO_THROW(tokenizeAndStringify("void f() { label: switch (a) {} }")); ASSERT_NO_THROW(tokenizeAndStringify("void f() { UNKNOWN_MACRO if (a) {} }")); ASSERT_NO_THROW(tokenizeAndStringify("void f() { []() -> int * {}; }")); ASSERT_NO_THROW(tokenizeAndStringify("void f() { const char* var = \"1\" \"2\"; }")); ASSERT_THROW(tokenizeAndStringify("void f() { MACRO(switch); }"), InternalError); ASSERT_THROW(tokenizeAndStringify("void f() { MACRO(x,switch); }"), InternalError); ASSERT_THROW(tokenizeAndStringify("void foo() { for_chain( if (!done) done = 1); }"), InternalError); ASSERT_THROW(tokenizeAndStringify("void foo() { for_chain( a, b, if (!done) done = 1); }"), InternalError); ASSERT_THROW_EQUALS(tokenizeAndStringify("void f() { if (retval==){} }"), InternalError, "syntax error: ==)"); // after (expr) ASSERT_NO_THROW(tokenizeAndStringify("void f() { switch (a) int b; }")); ASSERT_NO_THROW(tokenizeAndStringify("S s = { .x=2, .y[0]=3 };")); ASSERT_NO_THROW(tokenizeAndStringify("S s = { .ab.a=2, .ab.b=3 };")); ASSERT_NO_THROW(tokenizeAndStringify("extern \"C\" typedef void FUNC();")); // Ticket #9572 ASSERT_NO_THROW(tokenizeAndStringify("struct poc { " " struct { int d; } port[1]; " "}; " "struct poc p = { .port[0] = {.d = 3} };")); // op op ASSERT_THROW_EQUALS(tokenizeAndStringify("void f() { dostuff (x==>y); }"), InternalError, "syntax error: == >"); // Ticket #9664 ASSERT_NO_THROW(tokenizeAndStringify("S s = { .x { 2 }, .y[0] { 3 } };")); ASSERT_THROW_EQUALS(tokenizeAndStringify("void f() { assert(a==()); }"), InternalError, "syntax error: ==()"); ASSERT_THROW_EQUALS(tokenizeAndStringify("void f() { assert(a+()); }"), InternalError, "syntax error: +()"); // #9445 - typeof is not a keyword in C ASSERT_NO_THROW(tokenizeAndStringify("void foo() { char *typeof, *value; }", false, Settings::Native, "test.c")); } void checkEnableIf() { ASSERT_NO_THROW(tokenizeAndStringify( "template<\n" " typename U,\n" " typename std::enable_if<\n" " std::is_convertible{}>::type* = nullptr>\n" "void foo(U x);\n")); ASSERT_NO_THROW(tokenizeAndStringify( "template\n" "T f(const T a, const T b) {\n" " return a < b ? b : a;\n" "}\n")); ASSERT_NO_THROW(tokenizeAndStringify( "template\n" "struct A {\n" " T f(const T a, const T b) {\n" " return a < b ? b : a;\n" " }\n" "};\n")); ASSERT_NO_THROW(tokenizeAndStringify( "const int a = 1;\n" "const int b = 2;\n" "template\n" "struct A {\n" " int x = a < b ? b : a;" "};\n")); } void checkTemplates() { // #9109 ASSERT_NO_THROW(tokenizeAndStringify( "namespace {\n" "template struct a;\n" "template struct b {};\n" "}\n" "namespace {\n" "template struct c;\n" "template struct e {\n" " using f = a< b::g> >;\n" " bool h = f::h;\n" "};\n" "template using j = typename e::g;\n" "}\n")); ASSERT_NO_THROW(tokenizeAndStringify( "template struct a {\n" " void c();\n" "};\n" "void f() {\n" " a<> b;\n" " b.a<>::c();\n" "}\n")); // #9138 ASSERT_NO_THROW(tokenizeAndStringify( "template struct a;\n" "template using c = int;\n" "template c d;\n" "template <> struct a {\n" "template constexpr auto g() { d<0 || e::f>; return 0; }\n" "};\n")); // #9144 ASSERT_NO_THROW(tokenizeAndStringify( "namespace a {\n" "template struct c;\n" "}\n" "namespace boost {\n" "using a::c;\n" "}\n" "namespace d = boost;\n" "using d::c;\n" "template struct e {};\n" "static_assert(sizeof(e<>) == sizeof(e, c, int>), \"\");\n")); // #9146 ASSERT_NO_THROW(tokenizeAndStringify( "template struct a;\n" "template using c = typename a::e;\n" "template struct f;\n" "template using g = typename f>::e;\n")); // #9153 ASSERT_NO_THROW(tokenizeAndStringify( "namespace {\n" "template struct a;\n" "}\n" "namespace {\n" "namespace b {\n" "template struct B { using B::d; };\n" "}\n" "template using e = typename b::B;\n" "namespace b {\n" "template struct f;\n" "}\n" "template using g = b::f>;\n" "}\n")); // #9154 ASSERT_NO_THROW(tokenizeAndStringify( "template using a = int;\n" "template using aa = a;\n" "template struct A;\n" "template struct d;\n" "template using e = typename d::g;\n" "template struct h;\n" "template using i = typename h::g;\n" "template class j> using k = typename f::g;\n" "template using l = a, aa>::c>;\n" "template struct m;\n" "template using o = typename m::g;\n" "template struct p;\n" "template using q = typename p, n>>::g;\n" "template using c = e, b...>>;\n" "template struct s;\n" "template