This commit is contained in:
Sébastien Debrard 2011-03-03 21:35:32 +01:00
commit a69fbffa76
9 changed files with 319 additions and 162 deletions

View File

@ -266,7 +266,6 @@ void CheckAutoVariables::returnPointerToLocalArray()
tok2 = tok2->next()->link(); tok2 = tok2->next()->link();
unsigned int indentlevel = 0; unsigned int indentlevel = 0;
std::set<unsigned int> arrayVar;
for (; tok2; tok2 = tok2->next()) for (; tok2; tok2 = tok2->next())
{ {
// indentlevel.. // indentlevel..
@ -279,21 +278,13 @@ void CheckAutoVariables::returnPointerToLocalArray()
--indentlevel; --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.. // Return pointer to local array variable..
if (Token::Match(tok2, "return %var% ;")) if (Token::Match(tok2, "return %var% ;"))
{ {
const unsigned int varid = tok2->next()->varId(); 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); errorReturnPointerToLocalArray(tok2);
} }
@ -361,7 +352,6 @@ void CheckAutoVariables::returnReference()
tok2 = tok2->link(); tok2 = tok2->link();
unsigned int indentlevel = 0; unsigned int indentlevel = 0;
std::set<unsigned int> localvar; // local variables in function
for (; tok2; tok2 = tok2->next()) for (; tok2; tok2 = tok2->next())
{ {
// indentlevel.. // indentlevel..
@ -374,33 +364,14 @@ void CheckAutoVariables::returnReference()
--indentlevel; --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.. // return..
else if (Token::Match(tok2, "return %var% ;")) if (Token::Match(tok2, "return %var% ;"))
{ {
// is the returned variable a local variable? // is the returned variable a local variable?
if ((tok2->next()->varId() > 0) && const unsigned int varid = tok2->next()->varId();
(localvar.find(tok2->next()->varId()) != localvar.end())) const Variable *var = symbolDatabase->getVariableFromVarId(varid);
if (var && var->isLocal() && !var->isStatic())
{ {
// report error.. // report error..
errorReturnReference(tok2); errorReturnReference(tok2);
@ -462,7 +433,6 @@ void CheckAutoVariables::returncstr()
tok2 = tok2->next()->link(); tok2 = tok2->next()->link();
unsigned int indentlevel = 0; unsigned int indentlevel = 0;
std::set<unsigned int> localvar; // local variables in function
for (; tok2; tok2 = tok2->next()) for (; tok2; tok2 = tok2->next())
{ {
// indentlevel.. // indentlevel..
@ -475,31 +445,14 @@ void CheckAutoVariables::returncstr()
--indentlevel; --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.. // 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? // is the returned variable a local variable?
if ((tok2->next()->varId() > 0) && const unsigned int varid = tok2->next()->varId();
(localvar.find(tok2->next()->varId()) != localvar.end())) const Variable *var = symbolDatabase->getVariableFromVarId(varid);
if (var && var->isLocal() && !var->isStatic())
{ {
// report error.. // report error..
errorReturnAutocstr(tok2); errorReturnAutocstr(tok2);

View File

@ -178,10 +178,6 @@ std::string Preprocessor::read(std::istream &istr, const std::string &filename,
// Remove all comments.. // Remove all comments..
result = removeComments(result, filename, settings); 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 // 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 // Clean up preprocessor #if statements with Parantheses
result = removeParantheses(result); result = removeParantheses(result);
// Remove '#if 0' blocks
if (result.find("#if 0\n") != std::string::npos)
result = removeIf0(result);
return result; return result;
} }
@ -563,19 +563,33 @@ std::string Preprocessor::removeIf0(const std::string &code)
else else
{ {
// replace '#if 0' with empty line // replace '#if 0' with empty line
ret << "\n"; ret << line << "\n";
// goto the end of the '#if 0' block // goto the end of the '#if 0' block
unsigned int level = 1; unsigned int level = 1;
bool in = false;
while (level > 0 && std::getline(istr,line)) while (level > 0 && std::getline(istr,line))
{ {
if (line.compare(0,3,"#if") == 0) if (line.compare(0,3,"#if") == 0)
++level; ++level;
else if (line == "#endif") else if (line == "#endif")
--level; --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 // replace code within '#if 0' block with empty lines
ret << "\n"; ret << "\n";
continue;
}
ret << line << "\n";
} }
} }
} }

View File

@ -623,22 +623,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
scope = *it; scope = *it;
if (scope->isClassOrStruct() && scope->needInitialization == Scope::Unknown) if (scope->isClassOrStruct() && scope->needInitialization == Scope::Unknown)
{ debugMessage(scope->classDef, "SymbolDatabase::SymbolDatabase couldn't resolve all user defined types.");
std::list<ErrorLogger::ErrorMessage::FileLocation> 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);
}
} }
} }
@ -1078,6 +1063,27 @@ const Token *SymbolDatabase::initBaseInfo(Scope *scope, const Token *tok)
return tok2; return tok2;
} }
void SymbolDatabase::debugMessage(const Token *tok, const std::string &msg) const
{
if (tok && _settings->debugwarnings)
{
std::list<ErrorLogger::ErrorMessage::FileLocation> 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 unsigned int Function::argCount() const
@ -1124,6 +1130,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
const Token *endTok; const Token *endTok;
const Token *nameTok; const Token *nameTok;
bool isConstVar; bool isConstVar;
bool isArrayVar;
const Token *tok = arg->next(); const Token *tok = arg->next();
for (;;) for (;;)
{ {
@ -1131,6 +1138,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
endTok = NULL; endTok = NULL;
nameTok = NULL; nameTok = NULL;
isConstVar = bool(tok->str() == "const"); isConstVar = bool(tok->str() == "const");
isArrayVar = false;
while (tok->str() != "," && tok->str() != ")") while (tok->str() != "," && tok->str() != ")")
{ {
@ -1139,12 +1147,28 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
nameTok = tok; nameTok = tok;
endTok = tok->previous(); endTok = tok->previous();
} }
else if (tok->str() == "[")
isArrayVar = true;
tok = tok->next(); tok = tok->next();
} }
// check for argument with no name // check for argument with no name or missing varid
if (!endTok) if (!endTok)
{
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(); endTok = tok->previous();
}
const Token *typeTok = startTok; const Token *typeTok = startTok;
if (isConstVar) if (isConstVar)
@ -1156,7 +1180,7 @@ void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *s
bool isClassVar = startTok == endTok && !startTok->isStandardType(); 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() == ")") if (tok->str() == ")")
break; 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 the vartok was set in the if-blocks above, create a entry for this variable..
if (vartok && vartok->str() != "operator") if (vartok && vartok->str() != "operator")
{ {
if (vartok->varId() == 0 && !vartok->isBoolean() && check->_settings->debugwarnings) if (vartok->varId() == 0 && !vartok->isBoolean())
{ check->debugMessage(vartok, "Scope::getVariableList found variable \'" + vartok->str() + "\' with varid 0.");
std::list<ErrorLogger::ErrorMessage::FileLocation> 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);
}
const Scope *scope = NULL; const Scope *scope = NULL;

View File

@ -500,6 +500,11 @@ public:
return _variableList[varId]; return _variableList[varId];
} }
/**
* @brief output a debug message
*/
void debugMessage(const Token *tok, const std::string &msg) const;
private: private:
// Needed by Borland C++: // Needed by Borland C++:

View File

@ -1790,6 +1790,7 @@ void Tokenizer::simplifyTypedef()
{ {
if (!inCast && !inSizeof) if (!inCast && !inSizeof)
tok2 = tok2->next(); tok2 = tok2->next();
tok2 = copyTokens(tok2, arrayStart, arrayEnd); tok2 = copyTokens(tok2, arrayStart, arrayEnd);
tok2 = tok2->next(); tok2 = tok2->next();
@ -4600,9 +4601,6 @@ void Tokenizer::simplifyIfAddBraces()
continue; continue;
} }
if (tok->previous() && !Token::Match(tok->previous(), ";|{|}|else|)|:"))
continue;
if (Token::Match(tok, "if|for|while (")) if (Token::Match(tok, "if|for|while ("))
{ {
// don't add "{}" around ";" in "do {} while();" (#609) // 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, ("!|==|!=|<|<=|>|>= " + structname + " %varid% ==|!=|<|<=|>|>=|)|;").c_str(), varid) ||
Token::Match(tok3->previous(), "strlen|free ( %varid% )", 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()) if (!structname.empty())
{ {
tok3->deleteNext(); 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, ("<<|>> " + structname + " %varid% [+-*/%^|;])]").c_str(), varid) ||
Token::Match(tok3->previous(), ("[=+-*/%^|[] ( " + structname + " %varid%").c_str(), varid)) Token::Match(tok3->previous(), ("[=+-*/%^|[] ( " + structname + " %varid%").c_str(), varid))
{ {
if (value[0] == '\"')
break;
if (!structname.empty()) if (!structname.empty())
{ {
tok3->deleteNext(); tok3->deleteNext();
@ -6853,13 +6859,14 @@ bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsign
// return variable.. // return variable..
if (Token::Match(tok3, "return %varid% %any%", varid) && if (Token::Match(tok3, "return %varid% %any%", varid) &&
isOp(tok3->tokAt(2))) isOp(tok3->tokAt(2)) &&
value[0] != '\"')
{ {
tok3->next()->str(value); tok3->next()->str(value);
tok3->next()->varId(valueVarId); 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->deleteNext();
tok3->next()->str(value); tok3->next()->str(value);
@ -9124,7 +9131,8 @@ void Tokenizer::simplifyBitfields()
{ {
Token *last = 0; 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; int offset = 0;
if (tok->next()->str() == "const") if (tok->next()->str() == "const")
@ -9133,7 +9141,8 @@ void Tokenizer::simplifyBitfields()
last = tok->tokAt(5 + offset); last = tok->tokAt(5 + offset);
Token::eraseTokens(tok->tokAt(2 + offset), 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; int offset = 0;
if (tok->next()->str() == "const") if (tok->next()->str() == "const")
@ -9349,26 +9358,56 @@ const SymbolDatabase *Tokenizer::getSymbolDatabase() const
void Tokenizer::simplifyOperatorName() 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(); // operator op
Token *tok2 = tok1; std::string op;
Token *par = tok->next();
bool done = false;
while (!done && par)
{
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;
tok1 = tok1->previous(); while (par->str() != ")")
while (tok1 && !Token::Match(tok1, "operator|{|}|;|public:|private|protected:"))
{ {
tok1 = tok1->previous(); 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) tok->str("operator" + op);
{ Token::eraseTokens(tok,par);
tok1->str(tok1->str() + tok1->next()->str());
tok1->deleteNext();
}
} }
} }
} }

View File

@ -216,7 +216,7 @@ private:
" EventPtr event = *eventP;\n" " EventPtr event = *eventP;\n"
" *actionsP = &event->actions;\n" " *actionsP = &event->actions;\n"
"}\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() void returnLocalVariable1()

View File

@ -92,6 +92,11 @@ private:
TEST_CASE(error3); 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 // Don't handle include in a #if 0 block
TEST_CASE(if0_include_1); TEST_CASE(if0_include_1);
TEST_CASE(if0_include_2); TEST_CASE(if0_include_2);
@ -641,6 +646,74 @@ private:
ASSERT_EQUALS("[test.c:1]: (error) #error hello world!\n", errout.str()); 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() void if0_include_1()
{ {
Settings settings; Settings settings;
@ -650,7 +723,7 @@ private:
"#include \"a.h\"\n" "#include \"a.h\"\n"
"#endif\n" "#endif\n"
"AB\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() void if0_include_2()
@ -665,7 +738,7 @@ private:
"#endif\n" "#endif\n"
"#endif\n" "#endif\n"
"AB\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() void includeguard1()

View File

@ -80,6 +80,7 @@ private:
TEST_CASE(ifAddBraces12); TEST_CASE(ifAddBraces12);
TEST_CASE(ifAddBraces13); TEST_CASE(ifAddBraces13);
TEST_CASE(ifAddBraces14); // #2610 - segfault: if()<{} TEST_CASE(ifAddBraces14); // #2610 - segfault: if()<{}
TEST_CASE(ifAddBraces15); // #2616 - unknown macro before if
TEST_CASE(whileAddBraces); TEST_CASE(whileAddBraces);
TEST_CASE(doWhileAddBraces); TEST_CASE(doWhileAddBraces);
@ -305,7 +306,10 @@ private:
// Tokenize JAVA // Tokenize JAVA
TEST_CASE(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 // Some simple cleanups of unhandled macros in the global scope
TEST_CASE(removeMacrosInGlobalScope); TEST_CASE(removeMacrosInGlobalScope);
@ -858,6 +862,12 @@ private:
tokenizeAndStringify("if()<{}", false); 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() void whileAddBraces()
{ {
@ -2042,6 +2052,7 @@ private:
} }
void simplifyKnownVariables42() void simplifyKnownVariables42()
{
{ {
const char code[] = "void f() {\n" const char code[] = "void f() {\n"
" char str1[10], str2[10];\n" " char str1[10], str2[10];\n"
@ -2056,6 +2067,33 @@ private:
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); 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() void simplifyKnownVariablesBailOutAssign()
{ {
const char code[] = "int foo() {\n" const char code[] = "int foo() {\n"
@ -5118,6 +5156,12 @@ private:
const char code3[] = "struct A { bool : true; };"; const char code3[] = "struct A { bool : true; };";
ASSERT_EQUALS("struct A { } ;", tokenizeAndStringify(code3,false)); 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() void microsoftMFC()
@ -5312,36 +5356,56 @@ private:
ASSERT_EQUALS("void f ( ) { }", javatest("void f() throws Exception { }")); ASSERT_EQUALS("void f ( ) { }", javatest("void f() throws Exception { }"));
} }
void simplifyOperatorName() void simplifyOperatorName1()
{ {
// make sure C code doesn't get changed // make sure C code doesn't get changed
const char code1[] = "void operator () {}" const char code[] = "void operator () {}"
"int main()" "int main()"
"{" "{"
" operator();" " operator();"
"}"; "}";
const char result1 [] = "void operator ( ) { } " const char result [] = "void operator ( ) { } "
"int main ( ) " "int main ( ) "
"{ " "{ "
"operator ( ) ; " "operator ( ) ; "
"}"; "}";
ASSERT_EQUALS(result1, tokenizeAndStringify(code1,false)); ASSERT_EQUALS(result, tokenizeAndStringify(code,false));
}
const char code2[] = "class Fred" void simplifyOperatorName2()
{
const char code[] = "class Fred"
"{" "{"
" Fred(const Fred & f) { operator = (f); }" " Fred(const Fred & f) { operator = (f); }"
" operator = ();" " operator = ();"
"}"; "}";
const char result2 [] = "class Fred " const char result [] = "class Fred "
"{ " "{ "
"Fred ( const Fred & f ) { operator= ( f ) ; } " "Fred ( const Fred & f ) { operator= ( f ) ; } "
"operator= ( ) ; " "operator= ( ) ; "
"}"; "}";
ASSERT_EQUALS(result2, tokenizeAndStringify(code2,false)); ASSERT_EQUALS(result, tokenizeAndStringify(code,false));
}
void simplifyOperatorName3()
{
// #2615
const char code[] = "void f() {"
"static_cast<ScToken*>(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() void removeMacrosInGlobalScope()