Some refactorizations in Tokenizer:

- Refactorized simplifyTypedef
- Perform some template specific code only on non-C code
This commit is contained in:
PKEuS 2015-03-15 10:04:44 +01:00
parent 3d83b9e4a6
commit 713d993f71
2 changed files with 47 additions and 65 deletions

View File

@ -194,7 +194,7 @@ void Tokenizer::duplicateDeclarationError(const Token *tok1, const Token *tok2,
} }
// check if this statement is a duplicate definition // check if this statement is a duplicate definition
bool Tokenizer::duplicateTypedef(Token **tokPtr, const Token *name, const Token *typeDef, bool undefinedStruct) const bool Tokenizer::duplicateTypedef(Token **tokPtr, const Token *name, const Token *typeDef, const std::set<std::string>& structs) const
{ {
// check for an end of definition // check for an end of definition
const Token * tok = *tokPtr; const Token * tok = *tokPtr;
@ -287,7 +287,7 @@ bool Tokenizer::duplicateTypedef(Token **tokPtr, const Token *name, const Token
// declaration after forward declaration // declaration after forward declaration
return true; return true;
} else if (tok->next()->str() == "{") { } else if (tok->next()->str() == "{") {
if (!undefinedStruct) if (structs.find(name->strAt(-1)) == structs.end())
duplicateTypedefError(*tokPtr, name, "struct"); duplicateTypedefError(*tokPtr, name, "struct");
return true; return true;
} else if (Token::Match(tok->next(), ")|*")) { } else if (Token::Match(tok->next(), ")|*")) {
@ -533,6 +533,13 @@ static Token *processFunc(Token *tok2, bool inOperator)
void Tokenizer::simplifyTypedef() void Tokenizer::simplifyTypedef()
{ {
// Collect all structs for later detection of undefined structs
std::set<std::string> structs;
for (const Token* tok = list.front(); tok; tok = tok->next()) {
if (Token::Match(tok, "struct %type% {|:"))
structs.insert(tok->strAt(1));
}
std::vector<Space> spaceInfo; std::vector<Space> spaceInfo;
bool isNamespace = false; bool isNamespace = false;
std::string className; std::string className;
@ -583,8 +590,7 @@ void Tokenizer::simplifyTypedef()
// pull struct, union, enum or class definition out of typedef // pull struct, union, enum or class definition out of typedef
// use typedef name for unnamed struct, union, enum or class // use typedef name for unnamed struct, union, enum or class
if (Token::Match(tok->next(), "const| struct|enum|union|class %type% {") || if (Token::Match(tok->next(), "const| struct|enum|union|class %type%| {")) {
Token::Match(tok->next(), "const| struct|enum|union|class {")) {
Token *tok1 = splitDefinitionFromTypedef(tok); Token *tok1 = splitDefinitionFromTypedef(tok);
if (!tok1) if (!tok1)
continue; continue;
@ -602,22 +608,14 @@ void Tokenizer::simplifyTypedef()
} }
/** @todo add support for union */ /** @todo add support for union */
bool undefinedStruct = false; if (Token::Match(tok->next(), "enum %type% %type% ;") && tok->strAt(2) == tok->strAt(3)) {
if (Token::Match(tok, "typedef enum|struct %type% %type% ;") && tok->strAt(2) == tok->strAt(3)) { tok->deleteNext(3);
if (tok->next()->str() == "enum") { tok->deleteThis();
tok->deleteNext(3); if (tok->next())
tok->deleteThis(); tok->deleteThis();
if (tok->next()) //now the next token to process is 'tok', not 'tok->next()';
tok->deleteThis(); goback = true;
//now the next token to process is 'tok', not 'tok->next()'; continue;
goback = true;
continue;
} else {
const std::string pattern("struct " + tok->strAt(2) + " {|:");
const Token *tok2 = Token::findmatch(list.front(), pattern.c_str(), tok);
if (!tok2)
undefinedStruct = true;
}
} }
Token *typeName; Token *typeName;
@ -667,8 +665,9 @@ void Tokenizer::simplifyTypedef()
} else if (Token::Match(tokOffset, "%type% ::")) { } else if (Token::Match(tokOffset, "%type% ::")) {
typeStart = tokOffset; typeStart = tokOffset;
while (Token::Match(tokOffset, "%type% ::")) do {
tokOffset = tokOffset->tokAt(2); tokOffset = tokOffset->tokAt(2);
} while (Token::Match(tokOffset, "%type% ::"));
typeEnd = tokOffset; typeEnd = tokOffset;
@ -712,7 +711,7 @@ void Tokenizer::simplifyTypedef()
} }
// check for template // check for template
if (tokOffset->str() == "<") { if (!isC() && tokOffset->str() == "<") {
typeEnd = tokOffset->findClosingBracket(); typeEnd = tokOffset->findClosingBracket();
while (typeEnd && Token::Match(typeEnd->next(), ":: %type%")) while (typeEnd && Token::Match(typeEnd->next(), ":: %type%"))
@ -848,15 +847,15 @@ void Tokenizer::simplifyTypedef()
// function: typedef ... ( ... type )( ... ); // function: typedef ... ( ... type )( ... );
// typedef ... (( ... type )( ... )); // typedef ... (( ... type )( ... ));
// typedef ... ( * ( ... type )( ... )); // typedef ... ( * ( ... type )( ... ));
else if ((tokOffset->str() == "(" && else if (tokOffset->str() == "(" && (
Token::Match(tokOffset->link()->previous(), "%type% ) (") && (Token::Match(tokOffset->link()->previous(), "%type% ) (") &&
Token::Match(tokOffset->link()->next()->link(), ") const|volatile|;")) || Token::Match(tokOffset->link()->next()->link(), ") const|volatile|;")) ||
(Token::simpleMatch(tokOffset, "( (") && (Token::simpleMatch(tokOffset, "( (") &&
Token::Match(tokOffset->next()->link()->previous(), "%type% ) (") && Token::Match(tokOffset->next()->link()->previous(), "%type% ) (") &&
Token::Match(tokOffset->next()->link()->next()->link(), ") const|volatile| ) ;|,")) || Token::Match(tokOffset->next()->link()->next()->link(), ") const|volatile| ) ;|,")) ||
(Token::simpleMatch(tokOffset, "( * (") && (Token::simpleMatch(tokOffset, "( * (") &&
Token::Match(tokOffset->linkAt(2)->previous(), "%type% ) (") && Token::Match(tokOffset->linkAt(2)->previous(), "%type% ) (") &&
Token::Match(tokOffset->linkAt(2)->next()->link(), ") const|volatile| ) ;|,"))) { Token::Match(tokOffset->linkAt(2)->next()->link(), ") const|volatile| ) ;|,")))) {
if (tokOffset->next()->str() == "(") if (tokOffset->next()->str() == "(")
tokOffset = tokOffset->next(); tokOffset = tokOffset->next();
else if (Token::simpleMatch(tokOffset, "( * (")) { else if (Token::simpleMatch(tokOffset, "( * (")) {
@ -987,8 +986,6 @@ void Tokenizer::simplifyTypedef()
while (!done) { while (!done) {
std::string pattern = typeName->str(); std::string pattern = typeName->str();
int scope = 0; int scope = 0;
bool inScope = true;
bool exitThisScope = false;
int exitScope = 0; int exitScope = 0;
bool simplifyType = false; bool simplifyType = false;
bool inMemberFunc = false; bool inMemberFunc = false;
@ -1020,12 +1017,7 @@ void Tokenizer::simplifyTypedef()
} else { } else {
--scope; --scope;
if (scope < 0) if (scope < 0)
inScope = false; break;
if (exitThisScope) {
if (scope < exitScope)
exitThisScope = false;
}
} }
} }
@ -1096,15 +1088,9 @@ void Tokenizer::simplifyTypedef()
// check for typedef that can be substituted // check for typedef that can be substituted
else if (Token::Match(tok2, pattern.c_str()) || else if (Token::Match(tok2, pattern.c_str()) ||
(inMemberFunc && tok2->str() == typeName->str())) { (inMemberFunc && tok2->str() == typeName->str())) {
std::string pattern1;
// member function class variables don't need qualification // member function class variables don't need qualification
if (inMemberFunc && tok2->str() == typeName->str()) if (!(inMemberFunc && tok2->str() == typeName->str()) && pattern.find("::") != std::string::npos) { // has a "something ::"
pattern1 = tok2->str();
else
pattern1 = pattern;
if (pattern1.find("::") != std::string::npos) { // has a "something ::"
Token *start = tok2; Token *start = tok2;
size_t count = 0; size_t count = 0;
int back = int(classLevel) - 1; int back = int(classLevel) - 1;
@ -1143,7 +1129,7 @@ void Tokenizer::simplifyTypedef()
} }
simplifyType = true; simplifyType = true;
} }
} else if ((inScope && !exitThisScope) || inMemberFunc) { } else {
if (tok2->strAt(-1) == "::") { if (tok2->strAt(-1) == "::") {
// Don't replace this typename if it's preceded by "::" unless it's a namespace // Don't replace this typename if it's preceded by "::" unless it's a namespace
if (!spaceInfo.empty() && (tok2->strAt(-2) == spaceInfo[0].className) && spaceInfo[0].isNamespace) { if (!spaceInfo.empty() && (tok2->strAt(-2) == spaceInfo[0].className) && spaceInfo[0].isNamespace) {
@ -1152,7 +1138,7 @@ void Tokenizer::simplifyTypedef()
} }
} else if (Token::Match(tok2->previous(), "case %type% :")) { } else if (Token::Match(tok2->previous(), "case %type% :")) {
tok2 = tok2->next(); tok2 = tok2->next();
} else if (duplicateTypedef(&tok2, typeName, typeDef, undefinedStruct)) { } else if (duplicateTypedef(&tok2, typeName, typeDef, structs)) {
exitScope = scope; exitScope = scope;
// skip to end of scope if not already there // skip to end of scope if not already there
@ -1250,8 +1236,7 @@ void Tokenizer::simplifyTypedef()
tok2 = copyTokens(tok2, typeStart->next(), typeEnd); tok2 = copyTokens(tok2, typeStart->next(), typeEnd);
if (!pointers.empty()) { if (!pointers.empty()) {
std::list<std::string>::const_iterator iter; for (std::list<std::string>::const_iterator iter = pointers.begin(); iter != pointers.end(); ++iter) {
for (iter = pointers.begin(); iter != pointers.end(); ++iter) {
tok2->insertToken(*iter); tok2->insertToken(*iter);
tok2 = tok2->next(); tok2 = tok2->next();
} }
@ -1482,7 +1467,7 @@ void Tokenizer::simplifyTypedef()
else if (tok2->next()->str().at(0) == '\"') else if (tok2->next()->str().at(0) == '\"')
tok2 = tok2->tokAt(2); tok2 = tok2->tokAt(2);
} }
} while (Token::Match(tok2, ", %name% ;|'|=|,")); } while (Token::Match(tok2, ", %name% ;|=|,"));
} }
simplifyType = false; simplifyType = false;
@ -1509,17 +1494,16 @@ void Tokenizer::simplifyTypedef()
if (tokOffset && tokOffset->str() == "[") { if (tokOffset && tokOffset->str() == "[") {
arrayStart = tokOffset; arrayStart = tokOffset;
bool atEnd = false; for (;;) {
while (!atEnd) {
while (tokOffset->next() && !Token::Match(tokOffset->next(), ";|,")) while (tokOffset->next() && !Token::Match(tokOffset->next(), ";|,"))
tokOffset = tokOffset->next(); tokOffset = tokOffset->next();
if (!tokOffset->next()) if (!tokOffset->next())
return; // invalid input return; // invalid input
else if (tokOffset->next()->str() == ";") else if (tokOffset->next()->str() == ";")
atEnd = true; break;
else if (tokOffset->str() == "]") else if (tokOffset->str() == "]")
atEnd = true; break;
else else
tokOffset = tokOffset->next(); tokOffset = tokOffset->next();
} }
@ -1762,6 +1746,7 @@ bool Tokenizer::hasEnumsWithTypedef()
const Token *tok2 = Token::findsimplematch(tok, "typedef", tok->link()); const Token *tok2 = Token::findsimplematch(tok, "typedef", tok->link());
if (tok2) if (tok2)
syntaxError(tok2); syntaxError(tok2);
tok = tok->link();
} }
} }
@ -2365,8 +2350,8 @@ static bool setVarIdParseDeclaration(const Token **tok, const std::map<std::stri
++typeCount; ++typeCount;
++singleNameCount; ++singleNameCount;
} }
} else if ((TemplateSimplifier::templateParameters(tok2) > 0) || } else if (!c && ((TemplateSimplifier::templateParameters(tok2) > 0) ||
Token::simpleMatch(tok2, "< >") /* Ticket #4764 */) { Token::simpleMatch(tok2, "< >") /* Ticket #4764 */)) {
tok2 = tok2->findClosingBracket(); tok2 = tok2->findClosingBracket();
if (tok2->str() != ">") if (tok2->str() != ">")
break; break;
@ -3535,14 +3520,12 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
// unsigned long long int => long _isUnsigned=true,_isLong=true // unsigned long long int => long _isUnsigned=true,_isLong=true
simplifyStdType(); simplifyStdType();
// The simplifyTemplates have inner loops
if (_settings->terminated()) if (_settings->terminated())
return false; return false;
// simplify bit fields.. // simplify bit fields..
simplifyBitfields(); simplifyBitfields();
// The simplifyTemplates have inner loops
if (_settings->terminated()) if (_settings->terminated())
return false; return false;
@ -3551,7 +3534,6 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
// struct simplification "struct S {} s; => struct S { } ; S s ; // struct simplification "struct S {} s; => struct S { } ; S s ;
simplifyStructDecl(); simplifyStructDecl();
// The simplifyTemplates have inner loops
if (_settings->terminated()) if (_settings->terminated())
return false; return false;
@ -3564,7 +3546,6 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
// x = ({ 123; }); => { x = 123; } // x = ({ 123; }); => { x = 123; }
simplifyAssignmentBlock(); simplifyAssignmentBlock();
// The simplifyTemplates have inner loops
if (_settings->terminated()) if (_settings->terminated())
return false; return false;
@ -4923,7 +4904,7 @@ bool Tokenizer::simplifyConstTernaryOp()
const int offset = (tok->previous()->str() == ")") ? 2 : 1; const int offset = (tok->previous()->str() == ")") ? 2 : 1;
bool inTemplateParameter = false; bool inTemplateParameter = false;
if (tok->strAt(-2*offset) == "<") { if (!isC() && tok->strAt(-2*offset) == "<") {
if (!TemplateSimplifier::templateParameters(tok->tokAt(-2*offset))) if (!TemplateSimplifier::templateParameters(tok->tokAt(-2*offset)))
continue; continue;
inTemplateParameter = true; inTemplateParameter = true;
@ -5515,7 +5496,7 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, Token * tokEnd, bool only_k_r_
} }
//skip combinations of templates and namespaces //skip combinations of templates and namespaces
while (Token::Match(tok2, "%type% <") || Token::Match(tok2, "%type% ::")) { while (!isC() && (Token::Match(tok2, "%type% <") || Token::Match(tok2, "%type% ::"))) {
if (tok2->next()->str() == "<" && !TemplateSimplifier::templateParameters(tok2->next())) { if (tok2->next()->str() == "<" && !TemplateSimplifier::templateParameters(tok2->next())) {
tok2 = nullptr; tok2 = nullptr;
break; break;
@ -5594,7 +5575,7 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, Token * tokEnd, bool only_k_r_
while (tok2 && tok2->str() != "," && tok2->str() != ";") { while (tok2 && tok2->str() != "," && tok2->str() != ";") {
if (Token::Match(tok2, "{|(|[")) if (Token::Match(tok2, "{|(|["))
tok2 = tok2->link(); tok2 = tok2->link();
if (tok2->str() == "<" && TemplateSimplifier::templateParameters(tok2) > 0) if (!isC() && tok2->str() == "<" && TemplateSimplifier::templateParameters(tok2) > 0)
tok2 = tok2->findClosingBracket(); tok2 = tok2->findClosingBracket();
tok2 = tok2->next(); tok2 = tok2->next();
} }
@ -5666,7 +5647,7 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, Token * tokEnd, bool only_k_r_
if (Token::Match(tok2, "{|(")) if (Token::Match(tok2, "{|("))
tok2 = tok2->link(); tok2 = tok2->link();
else if (tok2->str() == "<" && tok2->previous()->isName() && !tok2->previous()->varId()) else if (!isC() && tok2->str() == "<" && tok2->previous()->isName() && !tok2->previous()->varId())
tok2 = tok2->findClosingBracket(); tok2 = tok2->findClosingBracket();
else if (std::strchr(";,", tok2->str()[0])) { else if (std::strchr(";,", tok2->str()[0])) {

View File

@ -27,6 +27,7 @@
#include <string> #include <string>
#include <map> #include <map>
#include <set>
#include <list> #include <list>
#include <ctime> #include <ctime>
@ -696,7 +697,7 @@ public:
*/ */
void duplicateEnumError(const Token *tok1, const Token *tok2, const std::string & type) const; void duplicateEnumError(const Token *tok1, const Token *tok2, const std::string & type) const;
bool duplicateTypedef(Token **tokPtr, const Token *name, const Token *typeDef, bool undefinedStruct) const; bool duplicateTypedef(Token **tokPtr, const Token *name, const Token *typeDef, const std::set<std::string>& structs) const;
void duplicateTypedefError(const Token *tok1, const Token *tok2, const std::string & type) const; void duplicateTypedefError(const Token *tok1, const Token *tok2, const std::string & type) const;
/** /**