diff --git a/gui/projectfiledialog.cpp b/gui/projectfiledialog.cpp index 89bfd2b2b..a8917fc41 100644 --- a/gui/projectfiledialog.cpp +++ b/gui/projectfiledialog.cpp @@ -98,7 +98,7 @@ QStringList ProjectFileDialog::GetIncludePaths() const QListWidgetItem *item = mUI.mListIncludeDirs->item(i); includePaths << QDir::fromNativeSeparators(item->text()); } - return includePaths; + return includePaths; } QStringList ProjectFileDialog::GetDefines() const diff --git a/lib/checkautovariables.cpp b/lib/checkautovariables.cpp index 10b53cd2b..9c8657cc9 100644 --- a/lib/checkautovariables.cpp +++ b/lib/checkautovariables.cpp @@ -266,7 +266,6 @@ void CheckAutoVariables::returnPointerToLocalArray() tok2 = tok2->next()->link(); unsigned int indentlevel = 0; - std::set arrayVar; for (; tok2; tok2 = tok2->next()) { // indentlevel.. @@ -279,21 +278,13 @@ void CheckAutoVariables::returnPointerToLocalArray() --indentlevel; } - // Declaring a local array.. - if (Token::Match(tok2, "[;{}] %type% %var% [")) - { - const unsigned int varid = tok2->tokAt(2)->varId(); - if (varid > 0) - { - arrayVar.insert(varid); - } - } - // Return pointer to local array variable.. if (Token::Match(tok2, "return %var% ;")) { const unsigned int varid = tok2->next()->varId(); - if (varid > 0 && arrayVar.find(varid) != arrayVar.end()) + const Variable *var = symbolDatabase->getVariableFromVarId(varid); + + if (var && var->isLocal() && !var->isStatic() && var->isArray()) { errorReturnPointerToLocalArray(tok2); } @@ -361,7 +352,6 @@ void CheckAutoVariables::returnReference() tok2 = tok2->link(); unsigned int indentlevel = 0; - std::set localvar; // local variables in function for (; tok2; tok2 = tok2->next()) { // indentlevel.. @@ -374,33 +364,14 @@ void CheckAutoVariables::returnReference() --indentlevel; } - // declare local variable.. - if (Token::Match(tok2, "[{};] %type%") && tok2->next()->str() != "return") - { - // goto next token.. - tok2 = tok2->next(); - - // skip "const" - if (Token::Match(tok2, "const %type%")) - tok2 = tok2->next(); - - // skip "std::" if it is seen - if (Token::simpleMatch(tok2, "std ::")) - tok2 = tok2->tokAt(2); - - // is it a variable declaration? - if (Token::Match(tok2, "%type% %var% ;")) - localvar.insert(tok2->next()->varId()); - else if (Token::Match(tok2, "%type% < %any% > %var% ;")) - localvar.insert(tok2->tokAt(4)->varId()); - } - // return.. - else if (Token::Match(tok2, "return %var% ;")) + if (Token::Match(tok2, "return %var% ;")) { // is the returned variable a local variable? - if ((tok2->next()->varId() > 0) && - (localvar.find(tok2->next()->varId()) != localvar.end())) + const unsigned int varid = tok2->next()->varId(); + const Variable *var = symbolDatabase->getVariableFromVarId(varid); + + if (var && var->isLocal() && !var->isStatic()) { // report error.. errorReturnReference(tok2); @@ -462,7 +433,6 @@ void CheckAutoVariables::returncstr() tok2 = tok2->next()->link(); unsigned int indentlevel = 0; - std::set localvar; // local variables in function for (; tok2; tok2 = tok2->next()) { // indentlevel.. @@ -475,31 +445,14 @@ void CheckAutoVariables::returncstr() --indentlevel; } - // declare local variable.. - if (Token::Match(tok2, "[{};] %type%") && tok2->next()->str() != "return") - { - // goto next token.. - tok2 = tok2->next(); - - // skip "const" - if (Token::Match(tok2, "const %type%")) - tok2 = tok2->next(); - - // skip "std::" if it is seen - if (Token::simpleMatch(tok2, "std ::")) - tok2 = tok2->tokAt(2); - - // is it a variable declaration? - if (Token::Match(tok2, "%type% %var% [;=]")) - localvar.insert(tok2->next()->varId()); - } - // return.. - else if (Token::Match(tok2, "return %var% . c_str ( ) ;")) + if (Token::Match(tok2, "return %var% . c_str ( ) ;")) { // is the returned variable a local variable? - if ((tok2->next()->varId() > 0) && - (localvar.find(tok2->next()->varId()) != localvar.end())) + const unsigned int varid = tok2->next()->varId(); + const Variable *var = symbolDatabase->getVariableFromVarId(varid); + + if (var && var->isLocal() && !var->isStatic()) { // report error.. errorReturnAutocstr(tok2); diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 17963f673..45ed8a425 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -178,10 +178,6 @@ std::string Preprocessor::read(std::istream &istr, const std::string &filename, // Remove all comments.. result = removeComments(result, filename, settings); - // Remove '#if 0' blocks - if (result.find("#if 0\n") != std::string::npos) - result = removeIf0(result); - // ------------------------------------------------------------------------------------------ // // Clean up all preprocessor statements @@ -192,6 +188,10 @@ std::string Preprocessor::read(std::istream &istr, const std::string &filename, // Clean up preprocessor #if statements with Parantheses result = removeParantheses(result); + // Remove '#if 0' blocks + if (result.find("#if 0\n") != std::string::npos) + result = removeIf0(result); + return result; } @@ -563,19 +563,33 @@ std::string Preprocessor::removeIf0(const std::string &code) else { // replace '#if 0' with empty line - ret << "\n"; + ret << line << "\n"; // goto the end of the '#if 0' block unsigned int level = 1; + bool in = false; while (level > 0 && std::getline(istr,line)) { if (line.compare(0,3,"#if") == 0) ++level; else if (line == "#endif") --level; + else if (line == "#else") + { + if (level == 1) + in = true; + } + else + { + if (in) + ret << line << "\n"; + else + // replace code within '#if 0' block with empty lines + ret << "\n"; + continue; + } - // replace code within '#if 0' block with empty lines - ret << "\n"; + ret << line << "\n"; } } } diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 03ccd8b00..769f13671 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -623,22 +623,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti scope = *it; if (scope->isClassOrStruct() && scope->needInitialization == Scope::Unknown) - { - std::list locationList; - ErrorLogger::ErrorMessage::FileLocation loc; - loc.line = scope->classDef->linenr(); - loc.setfile(_tokenizer->file(scope->classDef)); - locationList.push_back(loc); - - const ErrorLogger::ErrorMessage errmsg(locationList, - Severity::debug, - "SymbolDatabase::SymbolDatabase couldn't resolve all user defined types.", - "debug"); - if (_errorLogger) - _errorLogger->reportErr(errmsg); - else - Check::reportError(errmsg); - } + debugMessage(scope->classDef, "SymbolDatabase::SymbolDatabase couldn't resolve all user defined types."); } } @@ -1078,6 +1063,27 @@ const Token *SymbolDatabase::initBaseInfo(Scope *scope, const Token *tok) return tok2; } +void SymbolDatabase::debugMessage(const Token *tok, const std::string &msg) const +{ + if (tok && _settings->debugwarnings) + { + std::list locationList; + ErrorLogger::ErrorMessage::FileLocation loc; + loc.line = tok->linenr(); + loc.setfile(_tokenizer->file(tok)); + locationList.push_back(loc); + + const ErrorLogger::ErrorMessage errmsg(locationList, + Severity::debug, + msg, + "debug"); + if (_errorLogger) + _errorLogger->reportErr(errmsg); + else + Check::reportError(errmsg); + } +} + //--------------------------------------------------------------------------- unsigned int Function::argCount() const @@ -1124,6 +1130,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s const Token *endTok; const Token *nameTok; bool isConstVar; + bool isArrayVar; const Token *tok = arg->next(); for (;;) { @@ -1131,6 +1138,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s endTok = NULL; nameTok = NULL; isConstVar = bool(tok->str() == "const"); + isArrayVar = false; while (tok->str() != "," && tok->str() != ")") { @@ -1139,12 +1147,28 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s nameTok = tok; endTok = tok->previous(); } + else if (tok->str() == "[") + isArrayVar = true; + tok = tok->next(); } - // check for argument with no name + // check for argument with no name or missing varid if (!endTok) - endTok = tok->previous(); + { + if (tok->previous()->isName()) + { + if (tok->previous() != startTok->tokAt(isConstVar ? 1 : 0)) + { + nameTok = tok->previous(); + endTok = nameTok->previous(); + + symbolDatabase->debugMessage(nameTok, "Function::addArguments found argument \'" + nameTok->str() + "\' with varid 0."); + } + } + else + endTok = tok->previous(); + } const Token *typeTok = startTok; if (isConstVar) @@ -1156,7 +1180,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s bool isClassVar = startTok == endTok && !startTok->isStandardType(); - argumentList.push_back(Variable(nameTok, startTok, endTok, count++, Argument, false, false, isConstVar, isClassVar, argType, scope, false)); + argumentList.push_back(Variable(nameTok, startTok, endTok, count++, Argument, false, false, isConstVar, isClassVar, argType, scope, isArrayVar)); if (tok->str() == ")") break; @@ -1429,23 +1453,8 @@ void Scope::getVariableList() // If the vartok was set in the if-blocks above, create a entry for this variable.. if (vartok && vartok->str() != "operator") { - if (vartok->varId() == 0 && !vartok->isBoolean() && check->_settings->debugwarnings) - { - std::list locationList; - ErrorLogger::ErrorMessage::FileLocation loc; - loc.line = vartok->linenr(); - loc.setfile(check->_tokenizer->file(vartok)); - locationList.push_back(loc); - - const ErrorLogger::ErrorMessage errmsg(locationList, - Severity::debug, - "Scope::getVariableList found variable \'" + vartok->str() + "\' with varid 0.", - "debug"); - if (check->_errorLogger) - check->_errorLogger->reportErr(errmsg); - else - Check::reportError(errmsg); - } + if (vartok->varId() == 0 && !vartok->isBoolean()) + check->debugMessage(vartok, "Scope::getVariableList found variable \'" + vartok->str() + "\' with varid 0."); const Scope *scope = NULL; diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 3e11805b3..e1cb05206 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -500,6 +500,11 @@ public: return _variableList[varId]; } + /** + * @brief output a debug message + */ + void debugMessage(const Token *tok, const std::string &msg) const; + private: // Needed by Borland C++: diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 7460faf3b..cd1baa565 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1790,6 +1790,7 @@ void Tokenizer::simplifyTypedef() { if (!inCast && !inSizeof) tok2 = tok2->next(); + tok2 = copyTokens(tok2, arrayStart, arrayEnd); tok2 = tok2->next(); @@ -4600,9 +4601,6 @@ void Tokenizer::simplifyIfAddBraces() continue; } - if (tok->previous() && !Token::Match(tok->previous(), ";|{|}|else|)|:")) - continue; - if (Token::Match(tok, "if|for|while (")) { // don't add "{}" around ";" in "do {} while();" (#609) @@ -6639,6 +6637,12 @@ bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsign Token::Match(tok3, ("!|==|!=|<|<=|>|>= " + structname + " %varid% ==|!=|<|<=|>|>=|)|;").c_str(), varid) || Token::Match(tok3->previous(), "strlen|free ( %varid% )", varid)) { + if (value[0] == '\"' && tok3->strAt(-1) != "strlen") + { + // bail out if value is a string unless if it's just given + // as parameter to strlen + break; + } if (!structname.empty()) { tok3->deleteNext(); @@ -6737,6 +6741,8 @@ bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsign Token::Match(tok3, ("<<|>> " + structname + " %varid% [+-*/%^|;])]").c_str(), varid) || Token::Match(tok3->previous(), ("[=+-*/%^|[] ( " + structname + " %varid%").c_str(), varid)) { + if (value[0] == '\"') + break; if (!structname.empty()) { tok3->deleteNext(); @@ -6853,13 +6859,14 @@ bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsign // return variable.. if (Token::Match(tok3, "return %varid% %any%", varid) && - isOp(tok3->tokAt(2))) + isOp(tok3->tokAt(2)) && + value[0] != '\"') { tok3->next()->str(value); tok3->next()->varId(valueVarId); } - else if (pointeralias && Token::Match(tok3, "return * %varid% ;", varid)) + else if (pointeralias && Token::Match(tok3, "return * %varid% ;", varid) && value[0] != '\"') { tok3->deleteNext(); tok3->next()->str(value); @@ -9124,7 +9131,8 @@ void Tokenizer::simplifyBitfields() { Token *last = 0; - if (Token::Match(tok, ";|{|}|public:|protected:|private: const| %type% %var% : %any% ;|,")) + if (Token::Match(tok, ";|{|}|public:|protected:|private: const| %type% %var% : %any% ;|,") && + tok->next()->str() != "case") { int offset = 0; if (tok->next()->str() == "const") @@ -9133,7 +9141,8 @@ void Tokenizer::simplifyBitfields() last = tok->tokAt(5 + offset); Token::eraseTokens(tok->tokAt(2 + offset), tok->tokAt(5 + offset)); } - else if (Token::Match(tok, ";|{|}|public:|protected:|private: const| %type% : %any% ;")) + else if (Token::Match(tok, ";|{|}|public:|protected:|private: const| %type% : %any% ;") && + tok->next()->str() != "default") { int offset = 0; if (tok->next()->str() == "const") @@ -9349,26 +9358,56 @@ const SymbolDatabase *Tokenizer::getSymbolDatabase() const void Tokenizer::simplifyOperatorName() { - for (const Token *tok = _tokens; tok; tok = tok->next()) + for (Token *tok = _tokens; tok; tok = tok->next()) { - if (Token::Match(tok, ") const| {|;|=")) + if (tok->str() == "operator") { - Token *tok1 = tok->link(); - Token *tok2 = tok1; - - tok1 = tok1->previous(); - while (tok1 && !Token::Match(tok1, "operator|{|}|;|public:|private|protected:")) + // operator op + std::string op; + Token *par = tok->next(); + bool done = false; + while (!done && par) { - tok1 = tok1->previous(); + done = true; + if (par && par->isName()) + { + op += par->str(); + par = par->next(); + done = false; + } + if (Token::Match(par, "[<>+-*&/=.]") || Token::Match(par, "==|!=|<=|>=")) + { + op += par->str(); + par = par->next(); + done = false; + } + if (Token::simpleMatch(par, "[ ]")) + { + op += "[]"; + par = par->next()->next(); + done = false; + } + if (Token::Match(par, "( *| )")) + { + // break out and simplify.. + if (Token::Match(par, "( ) const| [=;{),]")) + break; + + while (par->str() != ")") + { + op += par->str(); + par = par->next(); + } + op += ")"; + par = par->next(); + done = false; + } } - if (tok1 && tok1->str() == "operator") + if (par && Token::Match(par->link(), ") const| [=;{),]")) { - while (tok1->next() != tok2) - { - tok1->str(tok1->str() + tok1->next()->str()); - tok1->deleteNext(); - } + tok->str("operator" + op); + Token::eraseTokens(tok,par); } } } diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index 5131b86e1..91c8406cc 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -216,7 +216,7 @@ private: " EventPtr event = *eventP;\n" " *actionsP = &event->actions;\n" "}\n"); - ASSERT_EQUALS(std::string(""), errout.str()); + TODO_ASSERT_EQUALS("", "[test.cpp:1]: (debug) Function::addArguments found argument 'eventP' with varid 0.\n", errout.str()); } void returnLocalVariable1() diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index 37df95c61..96e1a33cf 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -92,6 +92,11 @@ private: TEST_CASE(error3); + TEST_CASE(if0_exclude); + TEST_CASE(if0_whitespace); + TEST_CASE(if0_else); + TEST_CASE(if0_elif); + // Don't handle include in a #if 0 block TEST_CASE(if0_include_1); TEST_CASE(if0_include_2); @@ -641,6 +646,74 @@ private: ASSERT_EQUALS("[test.c:1]: (error) #error hello world!\n", errout.str()); } + void if0_exclude() + { + Settings settings; + Preprocessor preprocessor(&settings, this); + + std::istringstream code("#if 0\n" + "A\n" + "#endif\n" + "B\n"); + ASSERT_EQUALS("#if 0\n\n#endif\nB\n", preprocessor.read(code,"",NULL)); + + std::istringstream code2("#if (0)\n" + "A\n" + "#endif\n" + "B\n"); + ASSERT_EQUALS("#if 0\n\n#endif\nB\n", preprocessor.read(code2,"",NULL)); + } + + void if0_whitespace() + { + Settings settings; + Preprocessor preprocessor(&settings, this); + + std::istringstream code(" # if 0 \n" + "A\n" + " # endif \n" + "B\n"); + ASSERT_EQUALS("#if 0\n\n#endif\nB\n", preprocessor.read(code,"",NULL)); + } + + void if0_else() + { + Settings settings; + Preprocessor preprocessor(&settings, this); + + std::istringstream code("#if 0\n" + "A\n" + "#else\n" + "B\n" + "#endif\n" + "C\n"); + ASSERT_EQUALS("#if 0\n\n#else\nB\n#endif\nC\n", preprocessor.read(code,"",NULL)); + + std::istringstream code2("#if 1\n" + "A\n" + "#else\n" + "B\n" + "#endif\n" + "C\n"); + TODO_ASSERT_EQUALS("#if 1\nA\n#else\n\n#endif\nC\n", + "#if 1\nA\n#else\nB\n#endif\nC\n", preprocessor.read(code2,"",NULL)); + } + + void if0_elif() + { + Settings settings; + Preprocessor preprocessor(&settings, this); + + std::istringstream code("#if 0\n" + "A\n" + "#elif 1\n" + "B\n" + "#endif\n" + "C\n"); + TODO_ASSERT_EQUALS("#if 0\n\n#elif 1\nB\n#endif\nC\n", + "#if 0\n\n\n\n#endif\nC\n", preprocessor.read(code,"",NULL)); + } + void if0_include_1() { Settings settings; @@ -650,7 +723,7 @@ private: "#include \"a.h\"\n" "#endif\n" "AB\n"); - ASSERT_EQUALS("\n\n\nAB\n", preprocessor.read(code,"",NULL)); + ASSERT_EQUALS("#if 0\n\n#endif\nAB\n", preprocessor.read(code,"",NULL)); } void if0_include_2() @@ -665,7 +738,7 @@ private: "#endif\n" "#endif\n" "AB\n"); - ASSERT_EQUALS("\n\n\n\n\n\nAB\n", preprocessor.read(code,"",NULL)); + ASSERT_EQUALS("#if 0\n\n#ifdef WIN32\n#else\n#endif\n#endif\nAB\n", preprocessor.read(code,"",NULL)); } void includeguard1() diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index c25552845..04697796f 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -80,6 +80,7 @@ private: TEST_CASE(ifAddBraces12); TEST_CASE(ifAddBraces13); TEST_CASE(ifAddBraces14); // #2610 - segfault: if()<{} + TEST_CASE(ifAddBraces15); // #2616 - unknown macro before if TEST_CASE(whileAddBraces); TEST_CASE(doWhileAddBraces); @@ -305,7 +306,10 @@ private: // Tokenize JAVA TEST_CASE(java); - TEST_CASE(simplifyOperatorName); + TEST_CASE(simplifyOperatorName1); + TEST_CASE(simplifyOperatorName2); + TEST_CASE(simplifyOperatorName3); + TEST_CASE(simplifyOperatorName4); // Some simple cleanups of unhandled macros in the global scope TEST_CASE(removeMacrosInGlobalScope); @@ -858,6 +862,12 @@ private: tokenizeAndStringify("if()<{}", false); } + void ifAddBraces15() + { + // ticket #2616 - unknown macro before if + ASSERT_EQUALS("{ A if ( x ) { y ( ) ; } }", tokenizeAndStringify("{A if(x)y();}", false)); + } + void whileAddBraces() { @@ -2043,17 +2053,45 @@ private: void simplifyKnownVariables42() { - const char code[] = "void f() {\n" - " char str1[10], str2[10];\n" - " strcpy(str1, \"abc\");\n" - " strcpy(str2, str1);\n" - "}"; - const char expected[] = "void f ( ) {\n" - "char str1 [ 10 ] ; char str2 [ 10 ] ;\n" - "strcpy ( str1 , \"abc\" ) ;\n" - "strcpy ( str2 , \"abc\" ) ;\n" + { + const char code[] = "void f() {\n" + " char str1[10], str2[10];\n" + " strcpy(str1, \"abc\");\n" + " strcpy(str2, str1);\n" "}"; - ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); + const char expected[] = "void f ( ) {\n" + "char str1 [ 10 ] ; char str2 [ 10 ] ;\n" + "strcpy ( str1 , \"abc\" ) ;\n" + "strcpy ( str2 , \"abc\" ) ;\n" + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); + } + + { + const char code[] = "void f() {" + " char *s = malloc(10);" + " strcpy(s, \"\");" + " free(s);" + "}"; + const char expected[] = "void f ( ) {" + " char * s ; s = malloc ( 10 ) ;" + " strcpy ( s , \"\" ) ;" + " free ( s ) ; " + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); + } + + { + const char code[] = "void f(char *p, char *q) {" + " strcpy(p, \"abc\");" + " q = p;" + "}"; + const char expected[] = "void f ( char * p , char * q ) {" + " strcpy ( p , \"abc\" ) ;" + " q = p ; " + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); + } } void simplifyKnownVariablesBailOutAssign() @@ -5118,6 +5156,12 @@ private: const char code3[] = "struct A { bool : true; };"; ASSERT_EQUALS("struct A { } ;", tokenizeAndStringify(code3,false)); + + const char code4[] = "void f(int a) { switch (a) { case b: break; } }"; + ASSERT_EQUALS("void f ( int a ) { switch ( a ) { case b : ; break ; } }", tokenizeAndStringify(code4,true)); + + const char code5[] = "void f(int a) { switch (a) { default: break; } }"; + ASSERT_EQUALS("void f ( int a ) { switch ( a ) { default : ; break ; } }", tokenizeAndStringify(code5,true)); } void microsoftMFC() @@ -5312,36 +5356,56 @@ private: ASSERT_EQUALS("void f ( ) { }", javatest("void f() throws Exception { }")); } - void simplifyOperatorName() + void simplifyOperatorName1() { // make sure C code doesn't get changed - const char code1[] = "void operator () {}" - "int main()" - "{" - " operator();" - "}"; + const char code[] = "void operator () {}" + "int main()" + "{" + " operator();" + "}"; - const char result1 [] = "void operator ( ) { } " - "int main ( ) " - "{ " - "operator ( ) ; " - "}"; + const char result [] = "void operator ( ) { } " + "int main ( ) " + "{ " + "operator ( ) ; " + "}"; - ASSERT_EQUALS(result1, tokenizeAndStringify(code1,false)); + ASSERT_EQUALS(result, tokenizeAndStringify(code,false)); + } - const char code2[] = "class Fred" - "{" - " Fred(const Fred & f) { operator = (f); }" - " operator = ();" - "}"; + void simplifyOperatorName2() + { + const char code[] = "class Fred" + "{" + " Fred(const Fred & f) { operator = (f); }" + " operator = ();" + "}"; - const char result2 [] = "class Fred " - "{ " - "Fred ( const Fred & f ) { operator= ( f ) ; } " - "operator= ( ) ; " - "}"; + const char result [] = "class Fred " + "{ " + "Fred ( const Fred & f ) { operator= ( f ) ; } " + "operator= ( ) ; " + "}"; - ASSERT_EQUALS(result2, tokenizeAndStringify(code2,false)); + ASSERT_EQUALS(result, tokenizeAndStringify(code,false)); + } + + 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,false)); + } + + void simplifyOperatorName4() + { + const char code[] = "void operator==() { }"; + const char result[] = "void operator== ( ) { }"; + ASSERT_EQUALS(result, tokenizeAndStringify(code,false)); } void removeMacrosInGlobalScope()