From d26bcfe8d5bab7826b0b290b41fcb7ab79b9e4c7 Mon Sep 17 00:00:00 2001 From: Reijo Tomperi Date: Mon, 2 Jan 2012 22:37:32 +0200 Subject: [PATCH] Refactoring: Move code into templatesimplifier --- lib/templatesimplifier.cpp | 105 +++++++++++++++++++++++++++++++++++++ lib/templatesimplifier.h | 6 +++ lib/tokenize.cpp | 99 ++-------------------------------- 3 files changed, 115 insertions(+), 95 deletions(-) diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 245e6f2fa..d505ae177 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -18,6 +18,8 @@ #include "templatesimplifier.h" #include "token.h" +#include +#include //--------------------------------------------------------------------------- #ifdef _MSC_VER @@ -65,3 +67,106 @@ void TemplateSimplifier::cleanupAfterSimplify(Token *tokens) } } } + + +const Token* TemplateSimplifier::hasComplicatedSyntaxErrorsInTemplates(Token *tokens) +{ + // check for more complicated syntax errors when using templates.. + for (const Token *tok = tokens; tok; tok = tok->next()) { + // skip executing scopes.. + if (Token::Match(tok, ") const| {") || Token::Match(tok, "[,=] {")) { + while (tok->str() != "{") + tok = tok->next(); + tok = tok->link(); + } + + // skip executing scopes (ticket #1984).. + if (Token::simpleMatch(tok, "; {")) + tok = tok->next()->link(); + + // skip executing scopes (ticket #3183).. + if (Token::simpleMatch(tok, "( {")) + tok = tok->next()->link(); + + // skip executing scopes (ticket #1985).. + if (Token::simpleMatch(tok, "try {")) { + tok = tok->next()->link(); + while (Token::simpleMatch(tok, "} catch (")) { + tok = tok->linkAt(2); + if (Token::simpleMatch(tok, ") {")) + tok = tok->next()->link(); + } + } + + // not start of statement? + if (tok->previous() && !Token::Match(tok, "[;{}]")) + continue; + + // skip starting tokens.. ;;; typedef typename foo::bar::.. + while (Token::Match(tok, "[;{}]")) + tok = tok->next(); + while (Token::Match(tok, "typedef|typename")) + tok = tok->next(); + while (Token::Match(tok, "%type% ::")) + tok = tok->tokAt(2); + if (!tok) + break; + + // template variable or type.. + if (Token::Match(tok, "%type% <")) { + // these are used types.. + std::set usedtypes; + + // parse this statement and see if the '<' and '>' are matching + unsigned int level = 0; + for (const Token *tok2 = tok; tok2 && !Token::Match(tok2, "[;{}]"); tok2 = tok2->next()) { + if (tok2->str() == "(") + tok2 = tok2->link(); + else if (tok2->str() == "<") { + bool inclevel = false; + if (Token::simpleMatch(tok2->previous(), "operator <")) + ; + else if (level == 0) + inclevel = true; + else if (tok2->next() && tok2->next()->isStandardType()) + inclevel = true; + else if (Token::simpleMatch(tok2, "< typename")) + inclevel = true; + else if (Token::Match(tok2->tokAt(-2), "<|, %type% <") && usedtypes.find(tok2->previous()->str()) != usedtypes.end()) + inclevel = true; + else if (Token::Match(tok2, "< %type%") && usedtypes.find(tok2->next()->str()) != usedtypes.end()) + inclevel = true; + else if (Token::Match(tok2, "< %type%")) { + // is the next token a type and not a variable/constant? + // assume it's a type if there comes another "<" + const Token *tok3 = tok2->next(); + while (Token::Match(tok3, "%type% ::")) + tok3 = tok3->tokAt(2); + if (Token::Match(tok3, "%type% <")) + inclevel = true; + } + + if (inclevel) { + ++level; + if (Token::Match(tok2->tokAt(-2), "<|, %type% <")) + usedtypes.insert(tok2->previous()->str()); + } + } else if (tok2->str() == ">") { + if (level > 0) + --level; + } else if (tok2->str() == ">>") { + if (level > 0) + --level; + if (level > 0) + --level; + } + } + if (level > 0) { +// syntaxError(tok); + return tok; + } + } + } + + return 0; +} diff --git a/lib/templatesimplifier.h b/lib/templatesimplifier.h index c93207bc3..63a35cb10 100644 --- a/lib/templatesimplifier.h +++ b/lib/templatesimplifier.h @@ -42,6 +42,12 @@ public: * there are function calls etc with "wrong" syntax. */ static void cleanupAfterSimplify(Token *tokens); + + /** + * @return 0 if there are no syntax errors or return token which identifies + * the location of syntax error. + */ + static const Token* hasComplicatedSyntaxErrorsInTemplates(Token *tokens); }; /// @} diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 8760145d5..80812bc7c 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -2384,101 +2384,10 @@ bool Tokenizer::tokenize(std::istream &code, bool Tokenizer::hasComplicatedSyntaxErrorsInTemplates() { - // check for more complicated syntax errors when using templates.. - for (const Token *tok = _tokens; tok; tok = tok->next()) { - // skip executing scopes.. - if (Token::Match(tok, ") const| {") || Token::Match(tok, "[,=] {")) { - while (tok->str() != "{") - tok = tok->next(); - tok = tok->link(); - } - - // skip executing scopes (ticket #1984).. - if (Token::simpleMatch(tok, "; {")) - tok = tok->next()->link(); - - // skip executing scopes (ticket #3183).. - if (Token::simpleMatch(tok, "( {")) - tok = tok->next()->link(); - - // skip executing scopes (ticket #1985).. - if (Token::simpleMatch(tok, "try {")) { - tok = tok->next()->link(); - while (Token::simpleMatch(tok, "} catch (")) { - tok = tok->linkAt(2); - if (Token::simpleMatch(tok, ") {")) - tok = tok->next()->link(); - } - } - - // not start of statement? - if (tok->previous() && !Token::Match(tok, "[;{}]")) - continue; - - // skip starting tokens.. ;;; typedef typename foo::bar::.. - while (Token::Match(tok, "[;{}]")) - tok = tok->next(); - while (Token::Match(tok, "typedef|typename")) - tok = tok->next(); - while (Token::Match(tok, "%type% ::")) - tok = tok->tokAt(2); - if (!tok) - break; - - // template variable or type.. - if (Token::Match(tok, "%type% <")) { - // these are used types.. - std::set usedtypes; - - // parse this statement and see if the '<' and '>' are matching - unsigned int level = 0; - for (const Token *tok2 = tok; tok2 && !Token::Match(tok2, "[;{}]"); tok2 = tok2->next()) { - if (tok2->str() == "(") - tok2 = tok2->link(); - else if (tok2->str() == "<") { - bool inclevel = false; - if (Token::simpleMatch(tok2->previous(), "operator <")) - ; - else if (level == 0) - inclevel = true; - else if (tok2->next() && tok2->next()->isStandardType()) - inclevel = true; - else if (Token::simpleMatch(tok2, "< typename")) - inclevel = true; - else if (Token::Match(tok2->tokAt(-2), "<|, %type% <") && usedtypes.find(tok2->previous()->str()) != usedtypes.end()) - inclevel = true; - else if (Token::Match(tok2, "< %type%") && usedtypes.find(tok2->next()->str()) != usedtypes.end()) - inclevel = true; - else if (Token::Match(tok2, "< %type%")) { - // is the next token a type and not a variable/constant? - // assume it's a type if there comes another "<" - const Token *tok3 = tok2->next(); - while (Token::Match(tok3, "%type% ::")) - tok3 = tok3->tokAt(2); - if (Token::Match(tok3, "%type% <")) - inclevel = true; - } - - if (inclevel) { - ++level; - if (Token::Match(tok2->tokAt(-2), "<|, %type% <")) - usedtypes.insert(tok2->previous()->str()); - } - } else if (tok2->str() == ">") { - if (level > 0) - --level; - } else if (tok2->str() == ">>") { - if (level > 0) - --level; - if (level > 0) - --level; - } - } - if (level > 0) { - syntaxError(tok); - return true; - } - } + const Token *tok = TemplateSimplifier::hasComplicatedSyntaxErrorsInTemplates(_tokens); + if (tok) { + syntaxError(tok); + return true; } return false;