From 8b9daadd2519b91aa088acd5d0f3e51a44619957 Mon Sep 17 00:00:00 2001 From: PKEuS Date: Wed, 4 Jun 2014 22:33:08 +0200 Subject: [PATCH] Replaced static variable isCPP in Token (was not threadsafe): - Encapsulate parameters passed through AST compiler functions in a struct -> Reduces maintenance overhead when changing them -> Contains parameter indicating if the file is C or C++ - Added eKeyword Token type (at the moment, only true for C++ keyword "delete", but should be set for other keywords as well) --- lib/token.cpp | 5 +- lib/token.h | 21 ++-- lib/tokenize.cpp | 1 - lib/tokenlist.cpp | 254 ++++++++++++++++++++++++--------------------- test/testtoken.cpp | 7 +- test/testutils.h | 6 +- 6 files changed, 157 insertions(+), 137 deletions(-) diff --git a/lib/token.cpp b/lib/token.cpp index 47399c22c..49dadb1a4 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -31,7 +31,6 @@ #include #include -bool Token::_isCPP = true; Token::Token(Token **t) : tokensBack(t), @@ -66,7 +65,7 @@ void Token::update_property_info() else if (_str[0] == '_' || std::isalpha((unsigned char)_str[0])) { // Name if (_varId) _type = eVariable; - else if (_type != eVariable && _type != eFunction && _type != eType) + else if (_type != eVariable && _type != eFunction && _type != eType && _type != eKeyword) _type = eName; } else if (std::isdigit((unsigned char)_str[0]) || (_str.length() > 1 && _str[0] == '-' && std::isdigit((unsigned char)_str[1]))) _type = eNumber; @@ -565,7 +564,7 @@ bool Token::Match(const Token *tok, const char pattern[], unsigned int varid) // Type (%type%) { p += 5; - multicompare(p, tok->isName() && tok->varId() == 0 && (tok->str() != "delete" || !Token::isCPP()), ismulticomp); + multicompare(p, tok->isName() && tok->varId() == 0 && !tok->isKeyword(), ismulticomp); } break; case 'a': diff --git a/lib/token.h b/lib/token.h index 003066edb..45666725a 100644 --- a/lib/token.h +++ b/lib/token.h @@ -58,7 +58,7 @@ private: public: enum Type { - eVariable, eType, eFunction, eName, // Names: Variable (varId), Type (typeId, later), Function (FuncId, later), Name (unknown identifier) + eVariable, eType, eFunction, eKeyword, eName, // Names: Variable (varId), Type (typeId, later), Function (FuncId, later), Language keyword, Name (unknown identifier) eNumber, eString, eChar, eBoolean, eLiteral, // Literals: Number, String, Character, User defined literal (C++11) eArithmeticalOp, eComparisonOp, eAssignmentOp, eLogicalOp, eBitOp, eIncDecOp, eExtendedOp, // Operators: Arithmetical, Comparison, Assignment, Logical, Bitwise, ++/--, Extended eBracket, // {, }, <, >: < and > only if link() is set. Otherwise they are comparison operators. @@ -213,8 +213,17 @@ public: void type(Type t) { _type = t; } + void isKeyword(bool kwd) { + if (kwd) + _type = eKeyword; + else if (_type == eKeyword) + _type = eName; + } + bool isKeyword() const { + return _type == eKeyword; + } bool isName() const { - return _type == eName || _type == eType || _type == eVariable || _type == eFunction || + return _type == eName || _type == eType || _type == eVariable || _type == eFunction || _type == eKeyword || _type == eBoolean; // TODO: "true"/"false" aren't really a name... } bool isUpperCaseName() const; @@ -754,8 +763,6 @@ private: // original name like size_t std::string _originalName; - static bool _isCPP; - public: void astOperand1(Token *tok); void astOperand2(Token *tok); @@ -805,12 +812,6 @@ public: void printAst(bool verbose) const; void printValueFlow() const; - static void isCPP(bool isCPP) { - _isCPP = isCPP; - } - static bool isCPP() { - return _isCPP; - } }; /// @} diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 046db6479..24cfeba6d 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1597,7 +1597,6 @@ bool Tokenizer::tokenize(std::istream &code, return false; } - Token::isCPP(isCPP()); if (simplifyTokenList1(FileName)) { if (!noSymbolDB_AST) { createSymbolDatabase(); diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index a17ab2e33..759cffd03 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -62,11 +62,15 @@ const std::string& TokenList::getSourceFilePath() const bool TokenList::isC() const { + if (!_settings) + return Path::isC(getSourceFilePath()); return _settings->enforcedLang == Settings::C || (_settings->enforcedLang == Settings::None && Path::isC(getSourceFilePath())); } bool TokenList::isCPP() const { + if (!_settings) + return Path::isCPP(getSourceFilePath()); return _settings->enforcedLang == Settings::CPP || (_settings->enforcedLang == Settings::None && Path::isCPP(getSourceFilePath())); } @@ -146,6 +150,8 @@ void TokenList::addtoken(const std::string & str, const unsigned int lineno, con _back->str(str2); } + if (isCPP() && str == "delete") + _back->isKeyword(true); _back->linenr(lineno); _back->fileIndex(fileno); } @@ -394,6 +400,13 @@ bool TokenList::createTokens(std::istream &code, const std::string& file0) //--------------------------------------------------------------------------- +struct AST_state { + std::stack op; + unsigned int depth; + bool cpp; + AST_state(bool cpp_) : depth(0), cpp(cpp_) {} +}; + static bool iscast(const Token *tok) { if (!Token::Match(tok, "( %var%")) @@ -424,74 +437,79 @@ static bool iscast(const Token *tok) return false; } -static void compileUnaryOp(Token *&tok, void (*f)(Token *&, std::stack &, unsigned int depth), std::stack &op, unsigned int depth) +static void compileUnaryOp(Token *&tok, AST_state& state, void(*f)(Token *&tok, AST_state& state)) { Token *unaryop = tok; if (f) { tok = tok->next(); - f(tok, op, depth); + state.depth++; + if (tok && state.depth <= AST_MAX_DEPTH) + f(tok, state); + state.depth--; } - if (!op.empty()) { - unaryop->astOperand1(op.top()); - op.pop(); + if (!state.op.empty()) { + unaryop->astOperand1(state.op.top()); + state.op.pop(); } - op.push(unaryop); + state.op.push(unaryop); } -static void compileBinOp(Token *&tok, void (*f)(Token *&, std::stack &, unsigned int depth), std::stack &op, unsigned int depth) +static void compileBinOp(Token *&tok, AST_state& state, void(*f)(Token *&tok, AST_state& state)) { Token *binop = tok; if (f) { tok = tok->next(); - if (tok) - f(tok, op, depth); + state.depth++; + if (tok && state.depth <= AST_MAX_DEPTH) + f(tok, state); + state.depth--; } // TODO: Should we check if op is empty. // * Is it better to add assertion that it isn't? // * Write debug warning if it's empty? - if (!op.empty()) { - binop->astOperand2(op.top()); - op.pop(); + if (!state.op.empty()) { + binop->astOperand2(state.op.top()); + state.op.pop(); } - if (!op.empty()) { - binop->astOperand1(op.top()); - op.pop(); + if (!state.op.empty()) { + binop->astOperand1(state.op.top()); + state.op.pop(); } - op.push(binop); + state.op.push(binop); } -static void compileExpression(Token *&tok, std::stack &op, unsigned int depth); +static void compileExpression(Token *&tok, AST_state& state); -static void compileTerm(Token *& tok, std::stack &op, unsigned int depth) +static void compileTerm(Token *&tok, AST_state& state) { if (!tok) return; if (Token::Match(tok, "L %str%|%char%")) tok = tok->next(); if (tok->isLiteral()) { - op.push(tok); + state.op.push(tok); tok = tok->next(); } else if (tok->str() == "return") { - compileUnaryOp(tok, compileExpression, op, depth); - op.pop(); - } else if (tok->isName() && (!Token::isCPP() || !Token::Match(tok, "new|delete")) && tok->str() != "case") { + compileUnaryOp(tok, state, compileExpression); + state.op.pop(); + } else if (tok->isName() && (!state.cpp || !Token::Match(tok, "new|delete")) && tok->str() != "case") { while (tok->next() && tok->next()->isName()) tok = tok->next(); - op.push(tok); + state.op.push(tok); if (tok->next() && tok->linkAt(1) && Token::Match(tok, "%var% <")) tok = tok->linkAt(1); tok = tok->next(); } else if (tok->str() == "{") { - op.push(tok); + state.op.push(tok); tok = tok->link()->next(); } } -static void compileScope(Token *&tok, std::stack &op, unsigned int depth) +static void compileScope(Token *&tok, AST_state& state) { - compileTerm(tok,op, depth); + compileTerm(tok, state); while (tok) { if (tok->str() == "::") { Token *binop = tok; @@ -499,41 +517,41 @@ static void compileScope(Token *&tok, std::stack &op, unsigned int depth if (tok && tok->str() == "~") // Jump over ~ of destructor definition tok = tok->next(); if (tok) - compileTerm(tok, op, depth); + compileTerm(tok, state); if (binop->previous() && binop->previous()->isName()) - compileBinOp(binop, nullptr, op, depth); + compileBinOp(binop, state, nullptr); else - compileUnaryOp(binop, nullptr, op, depth); + compileUnaryOp(binop, state, nullptr); } else break; } } -static bool isPrefixUnary(const Token* tok) +static bool isPrefixUnary(const Token* tok, bool cpp) { if (!tok->previous() - || ((Token::Match(tok->previous(), "(|[|{|%op%|;|}|?|:|,|.|return|::") || (Token::isCPP() && tok->strAt(-1) == "throw")) + || ((Token::Match(tok->previous(), "(|[|{|%op%|;|}|?|:|,|.|return|::") || (cpp && tok->strAt(-1) == "throw")) && (tok->previous()->type() != Token::eIncDecOp || tok->type() == Token::eIncDecOp))) return true; return tok->strAt(-1) == ")" && iscast(tok->linkAt(-1)); } -static void compilePrecedence2(Token *&tok, std::stack &op, unsigned int depth) +static void compilePrecedence2(Token *&tok, AST_state& state) { - compileScope(tok, op, depth); + compileScope(tok, state); while (tok) { - if (tok->type() == Token::eIncDecOp && !isPrefixUnary(tok)) { - compileUnaryOp(tok, compileScope, op, depth); + if (tok->type() == Token::eIncDecOp && !isPrefixUnary(tok, state.cpp)) { + compileUnaryOp(tok, state, compileScope); } else if (tok->str() == "." && tok->strAt(1) != "*") { if (tok->strAt(1) == ".") { - op.push(tok); + state.op.push(tok); tok = tok->tokAt(3); break; } else - compileBinOp(tok, compileScope, op, depth); + compileBinOp(tok, state, compileScope); } else if (tok->str() == "[") { - if (isPrefixUnary(tok) && tok->link()->strAt(1) == "(") { // Lambda + if (isPrefixUnary(tok, state.cpp) && tok->link()->strAt(1) == "(") { // Lambda // What we do here: // - Nest the round bracket under the square bracket. // - Nest what follows the lambda (if anything) with the lambda opening [ @@ -542,47 +560,47 @@ static void compilePrecedence2(Token *&tok, std::stack &op, unsigned int Token* roundBracket = squareBracket->link()->next(); Token* curlyBracket = Token::findsimplematch(roundBracket->link()->next(), "{"); tok = curlyBracket->next(); - compileExpression(tok, op, depth); - op.push(roundBracket); - compileUnaryOp(squareBracket, 0, op, depth); + compileExpression(tok, state); + state.op.push(roundBracket); + compileUnaryOp(squareBracket, state, nullptr); tok = curlyBracket->link()->next(); } else { Token* tok2 = tok; if (tok->strAt(1) != "]") - compileBinOp(tok, compileExpression, op, depth); + compileBinOp(tok, state, compileExpression); else - compileUnaryOp(tok, compileExpression, op, depth); + compileUnaryOp(tok, state, compileExpression); tok = tok2->link()->next(); } } else if (tok->str() == "(" && (!iscast(tok) || Token::Match(tok->previous(), "if|while|for|switch|catch"))) { Token* tok2 = tok; tok = tok->next(); - bool opPrevTopSquare = !op.empty() && op.top() && op.top()->str() == "["; - std::size_t oldOpSize = op.size(); - compileExpression(tok, op, depth); - bool operandInside = oldOpSize < op.size(); + bool opPrevTopSquare = !state.op.empty() && state.op.top() && state.op.top()->str() == "["; + std::size_t oldOpSize = state.op.size(); + compileExpression(tok, state); + bool operandInside = oldOpSize < state.op.size(); tok = tok2; - if ((tok->previous() && tok->previous()->isName() && (tok->strAt(-1) != "return" && (!Token::isCPP() || !Token::Match(tok->previous(), "throw|delete")))) - || (tok->strAt(-1) == "]" && (!Token::isCPP() || !Token::Match(tok->linkAt(-1)->previous(), "new|delete"))) + if ((tok->previous() && tok->previous()->isName() && (tok->strAt(-1) != "return" && (!state.cpp || !Token::Match(tok->previous(), "throw|delete")))) + || (tok->strAt(-1) == "]" && (!state.cpp || !Token::Match(tok->linkAt(-1)->previous(), "new|delete"))) || (tok->strAt(-1) == ">" && tok->linkAt(-1)) || (tok->strAt(-1) == ")" && !iscast(tok->linkAt(-1))) // Don't treat brackets to clarify precedence as function calls || (tok->strAt(-1) == "}" && opPrevTopSquare)) { if (operandInside) - compileBinOp(tok, 0, op, depth); + compileBinOp(tok, state, nullptr); else - compileUnaryOp(tok, 0, op, depth); + compileUnaryOp(tok, state, nullptr); } tok = tok->link()->next(); } else break; } } -static void compilePrecedence3(Token *&tok, std::stack &op, unsigned int depth) +static void compilePrecedence3(Token *&tok, AST_state& state) { - compilePrecedence2(tok, op, depth); + compilePrecedence2(tok, state); while (tok) { if ((Token::Match(tok, "[+-!~*&]") || tok->type() == Token::eIncDecOp) && - isPrefixUnary(tok)) { + isPrefixUnary(tok, state.cpp)) { if (Token::Match(tok, "* [*,)]")) { Token* tok2 = tok; while (tok2->next() && tok2->str() == "*") @@ -592,48 +610,48 @@ static void compilePrecedence3(Token *&tok, std::stack &op, unsigned int continue; } } - compileUnaryOp(tok, compilePrecedence3, op, depth); + compileUnaryOp(tok, state, compilePrecedence3); } else if (tok->str() == "(" && iscast(tok)) { Token* tok2 = tok; tok = tok->link()->next(); - compilePrecedence3(tok, op, depth); - compileUnaryOp(tok2, 0, op, depth); - } else if (Token::isCPP() && tok->str() == "new") { + compilePrecedence3(tok, state); + compileUnaryOp(tok2, state, nullptr); + } else if (state.cpp && tok->str() == "new") { Token* tok2 = tok; tok = tok->next(); - op.push(tok); + state.op.push(tok); while (Token::Match(tok, "%var%|*|&|<|[")) { if (tok->link()) tok = tok->link(); tok = tok->next(); } - compileUnaryOp(tok2, 0, op, depth); - } else if (Token::isCPP() && tok->str() == "delete") { + compileUnaryOp(tok2, state, nullptr); + } else if (state.cpp && tok->str() == "delete") { Token* tok2 = tok; tok = tok->next(); if (tok->str() == "[") tok = tok->link()->next(); - compilePrecedence3(tok, op, depth); - compileUnaryOp(tok2, 0, op, depth); + compilePrecedence3(tok, state); + compileUnaryOp(tok2, state, nullptr); } // TODO: Handle sizeof else break; } } -static void compilePointerToElem(Token *&tok, std::stack &op, unsigned int depth) +static void compilePointerToElem(Token *&tok, AST_state& state) { - compilePrecedence3(tok, op, depth); + compilePrecedence3(tok, state); while (tok) { if (Token::simpleMatch(tok, ". *")) { - compileBinOp(tok, compilePrecedence3, op, depth); + compileBinOp(tok, state, compilePrecedence3); } else break; } } -static void compileMulDiv(Token *&tok, std::stack &op, unsigned int depth) +static void compileMulDiv(Token *&tok, AST_state& state) { - compilePointerToElem(tok, op, depth); + compilePointerToElem(tok, state); while (tok) { if (Token::Match(tok, "[/%]") || (tok->str() == "*" && !tok->astOperand1())) { if (Token::Match(tok, "* [*,)]")) { @@ -645,142 +663,142 @@ static void compileMulDiv(Token *&tok, std::stack &op, unsigned int dept break; } } - compileBinOp(tok, compilePointerToElem, op, depth); + compileBinOp(tok, state, compilePointerToElem); } else break; } } -static void compileAddSub(Token *&tok, std::stack &op, unsigned int depth) +static void compileAddSub(Token *&tok, AST_state& state) { - compileMulDiv(tok, op, depth); + compileMulDiv(tok, state); while (tok) { if (Token::Match(tok, "+|-") && !tok->astOperand1()) { - compileBinOp(tok, compileMulDiv, op, depth); + compileBinOp(tok, state, compileMulDiv); } else break; } } -static void compileShift(Token *&tok, std::stack &op, unsigned int depth) +static void compileShift(Token *&tok, AST_state& state) { - compileAddSub(tok, op, depth); + compileAddSub(tok, state); while (tok) { if (Token::Match(tok, "<<|>>")) { - compileBinOp(tok, compileAddSub, op, depth); + compileBinOp(tok, state, compileAddSub); } else break; } } -static void compileRelComp(Token *&tok, std::stack &op, unsigned int depth) +static void compileRelComp(Token *&tok, AST_state& state) { - compileShift(tok, op, depth); + compileShift(tok, state); while (tok) { if (Token::Match(tok, "<|<=|>=|>") && !tok->link()) { - compileBinOp(tok, compileShift, op, depth); + compileBinOp(tok, state, compileShift); } else break; } } -static void compileEqComp(Token *&tok, std::stack &op, unsigned int depth) +static void compileEqComp(Token *&tok, AST_state& state) { - compileRelComp(tok, op, depth); + compileRelComp(tok, state); while (tok) { if (Token::Match(tok, "==|!=")) { - compileBinOp(tok, compileRelComp, op, depth); + compileBinOp(tok, state, compileRelComp); } else break; } } -static void compileAnd(Token *&tok, std::stack &op, unsigned int depth) +static void compileAnd(Token *&tok, AST_state& state) { - compileEqComp(tok, op, depth); + compileEqComp(tok, state); while (tok) { if (tok->str() == "&" && !tok->astOperand1()) { Token* tok2 = tok->next(); if (tok2->str() == "&") tok2 = tok2->next(); - if (Token::isCPP() && (tok2->str() == "," || tok2->str() == ")")) { + if (state.cpp && (tok2->str() == "," || tok2->str() == ")")) { tok = tok2; break; // rValue reference } - compileBinOp(tok, compileEqComp, op, depth); + compileBinOp(tok, state, compileEqComp); } else break; } } -static void compileXor(Token *&tok, std::stack &op, unsigned int depth) +static void compileXor(Token *&tok, AST_state& state) { - compileAnd(tok, op, depth); + compileAnd(tok, state); while (tok) { if (tok->str() == "^") { - compileBinOp(tok, compileAnd, op, depth); + compileBinOp(tok, state, compileAnd); } else break; } } -static void compileOr(Token *&tok, std::stack &op, unsigned int depth) +static void compileOr(Token *&tok, AST_state& state) { - compileXor(tok, op, depth); + compileXor(tok, state); while (tok) { if (tok->str() == "|") { - compileBinOp(tok, compileXor, op, depth); + compileBinOp(tok, state, compileXor); } else break; } } -static void compileLogicAnd(Token *&tok, std::stack &op, unsigned int depth) +static void compileLogicAnd(Token *&tok, AST_state& state) { - compileOr(tok, op, depth); + compileOr(tok, state); while (tok) { if (tok->str() == "&&") { - compileBinOp(tok, compileOr, op, depth); + compileBinOp(tok, state, compileOr); } else break; } } -static void compileLogicOr(Token *&tok, std::stack &op, unsigned int depth) +static void compileLogicOr(Token *&tok, AST_state& state) { - compileLogicAnd(tok, op, depth); + compileLogicAnd(tok, state); while (tok) { if (tok->str() == "||") { - compileBinOp(tok, compileLogicAnd, op, depth); + compileBinOp(tok, state, compileLogicAnd); } else break; } } -static void compileAssignTernary(Token *&tok, std::stack &op, unsigned int depth) +static void compileAssignTernary(Token *&tok, AST_state& state) { - compileLogicOr(tok, op, depth); + compileLogicOr(tok, state); while (tok) { // TODO: http://en.cppreference.com/w/cpp/language/operator_precedence says: // "The expression in the middle of the conditional operator (between ? and :) is parsed as if parenthesized: its precedence relative to ?: is ignored." if (tok->isAssignmentOp() || Token::Match(tok, "[?:]")) { if (tok->str() == "?" && tok->strAt(1) == ":") { - op.push(0); + state.op.push(0); } - compileBinOp(tok, compileAssignTernary, op, depth); + compileBinOp(tok, state, compileAssignTernary); } else break; } } -static void compileComma(Token *&tok, std::stack &op, unsigned int depth) +static void compileComma(Token *&tok, AST_state& state) { - compileAssignTernary(tok, op, depth); + compileAssignTernary(tok, state); while (tok) { if (tok->str() == ",") { - compileBinOp(tok, compileAssignTernary, op, depth); + compileBinOp(tok, state, compileAssignTernary); } else break; } } -static void compileExpression(Token *&tok, std::stack &op, unsigned int depth) +static void compileExpression(Token *&tok, AST_state& state) { - if (depth > AST_MAX_DEPTH) + if (state.depth > AST_MAX_DEPTH) return; // ticket #5592 if (tok) - compileComma(tok,op, depth+1U); + compileComma(tok, state); } -static Token * createAstAtToken(Token *tok) +static Token * createAstAtToken(Token *tok, bool cpp) { if (Token::simpleMatch(tok,"for (")) { Token *tok2 = tok->tokAt(2); @@ -793,8 +811,8 @@ static Token * createAstAtToken(Token *tok) break; } else if (Token::Match(tok2, "%var% %op%|(|[|.|:|::") || Token::Match(tok2->previous(), "[(;{}] %cop%|(")) { init1 = tok2; - std::stack operands; - compileExpression(tok2, operands, 0U); + AST_state state1(cpp); + compileExpression(tok2, state1); if (tok2->str() == ";" || tok2->str() == ")") break; init1 = 0; @@ -813,13 +831,13 @@ static Token * createAstAtToken(Token *tok) Token * const semicolon1 = tok2; tok2 = tok2->next(); - std::stack operands2; - compileExpression(tok2, operands2, 0U); + AST_state state2(cpp); + compileExpression(tok2, state2); Token * const semicolon2 = tok2; tok2 = tok2->next(); - std::stack operands3; - compileExpression(tok2, operands3, 0U); + AST_state state3(cpp); + compileExpression(tok2, state3); if (init != semicolon1) semicolon1->astOperand1(const_cast(init->astTop())); @@ -848,9 +866,9 @@ static Token * createAstAtToken(Token *tok) return tok->linkAt(1); if (tok->str() == "return" || !tok->previous() || Token::Match(tok, "%var% %op%|(|[|.|::") || Token::Match(tok->previous(), "[;{}] %cop%|( !!{")) { - std::stack operands; Token * const tok1 = tok; - compileExpression(tok, operands, 0U); + AST_state state(cpp); + compileExpression(tok, state); Token * const endToken = tok; if (endToken == tok1) return tok1; @@ -863,7 +881,7 @@ static Token * createAstAtToken(Token *tok) break; const Token * const endToken2 = tok->linkAt(1); for (; tok && tok != endToken && tok != endToken2; tok = tok ? tok->next() : NULL) - tok = createAstAtToken(tok); + tok = createAstAtToken(tok, cpp); } return endToken ? endToken->previous() : NULL; @@ -875,7 +893,7 @@ static Token * createAstAtToken(Token *tok) void TokenList::createAst() { for (Token *tok = _front; tok; tok = tok ? tok->next() : NULL) { - tok = createAstAtToken(tok); + tok = createAstAtToken(tok, isCPP()); } } diff --git a/test/testtoken.cpp b/test/testtoken.cpp index c3c9fc9ce..d6eb44f05 100644 --- a/test/testtoken.cpp +++ b/test/testtoken.cpp @@ -345,8 +345,11 @@ private: ASSERT_EQUALS(true, Token::Match(isVar.tokens(), "%type% %var%")); ASSERT_EQUALS(false, Token::Match(isVar.tokens(), "%type% %type%")); - givenACodeSampleToTokenize noType("delete", true); - ASSERT_EQUALS(false, Token::Match(noType.tokens(), "%type%")); + givenACodeSampleToTokenize noType1_cpp("delete", true, true); + ASSERT_EQUALS(false, Token::Match(noType1_cpp.tokens(), "%type%")); + + givenACodeSampleToTokenize noType1_c("delete", true, false); + ASSERT_EQUALS(true, Token::Match(noType1_c.tokens(), "%type%")); givenACodeSampleToTokenize noType2("void delete", true); ASSERT_EQUALS(false, Token::Match(noType2.tokens(), "!!foo %type%")); diff --git a/test/testutils.h b/test/testutils.h index 7f768df25..07f7031a0 100644 --- a/test/testutils.h +++ b/test/testutils.h @@ -30,13 +30,13 @@ private: Tokenizer _tokenizer; public: - givenACodeSampleToTokenize(const char sample[], bool createOnly = false) + givenACodeSampleToTokenize(const char sample[], bool createOnly = false, bool cpp = true) : _tokenizer(&_settings, 0) { std::istringstream iss(sample); if (createOnly) - _tokenizer.list.createTokens(iss); + _tokenizer.list.createTokens(iss, cpp ? "test.cpp" : "test.c"); else - _tokenizer.tokenize(iss, "test.cpp"); + _tokenizer.tokenize(iss, cpp ? "test.cpp" : "test.c"); } const Token* tokens() const {