diff --git a/lib/token.cpp b/lib/token.cpp index 0ed2ff1ab51..685e8fe95fe 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -107,6 +107,8 @@ static const std::unordered_set controlFlowKeywords = { void Token::update_property_info() { + assert(mImpl); + setFlag(fIsControlFlowKeyword, false); // TODO: clear fIsLong isStandardType(false); @@ -134,8 +136,7 @@ void Token::update_property_info() else if (mStr == "asm") { // TODO: not a keyword tokType(eKeyword); } - // TODO: remove condition? appears to be (no longer necessary) protection for reset of varids in Tokenizer::setVarId() - else if (mTokType != eVariable && mTokType != eFunction && mTokType != eType && mTokType != eKeyword) { + else { tokType(eName); // some types are not being treated as keywords update_property_isStandardType(); @@ -183,8 +184,7 @@ void Token::update_property_info() } else { tokType(eNone); } - // TODO: make sure varid is only set for eVariable - //assert(!mImpl->mVarId || mTokType == eVariable); + assert(!mImpl->mVarId || mTokType == eVariable); // TODO: validate type for linked token? } diff --git a/lib/token.h b/lib/token.h index 826a66d2448..ef5cc39a325 100644 --- a/lib/token.h +++ b/lib/token.h @@ -956,15 +956,7 @@ class CPPCHECKLIB Token { return; mImpl->mVarId = id; - // TODO: remove special handling? - if (id != 0) { - tokType(eVariable); - isStandardType(false); - // TODO: clear fIsLong - // TODO: clear fIsControlFlowKeyword - } else { - update_property_info(); - } + update_property_info(); } nonneg int exprId() const { @@ -1104,6 +1096,9 @@ class CPPCHECKLIB Token { * to. */ void link(Token *linkToToken) { + if (mLink == linkToToken) + return; + mLink = linkToToken; if (mStr == "<" || mStr == ">") update_property_info(); diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index bcd53feec1e..691ee21f102 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -3543,6 +3543,7 @@ void Tokenizer::combineOperators() } if (simplify) { tok->str(tok->str() + ":"); + tok->tokType(Token::Type::eKeyword); // we need to preserve the keyword type after setting a non-keyword string tok->deleteNext(); } } else if (tok->str() == "->") { @@ -10278,6 +10279,8 @@ void Tokenizer::simplifyOperatorName() for (Token *tok = list.front(); tok; tok = tok->next()) { if (Token::Match(tok, "using|:: operator %op%|%name% ;")) { tok->next()->str("operator" + tok->strAt(2)); + tok->next()->tokType(Token::Type::eKeyword); // we need to preserve the keyword type after setting a non-keyword string + // TODO: tok->next()->isOperatorKeyword(true); tok->next()->deleteNext(); continue; } @@ -10287,6 +10290,8 @@ void Tokenizer::simplifyOperatorName() // operator op if (Token::Match(tok, "operator %op% (") && !operatorEnd(tok->linkAt(2))) { tok->str(tok->str() + tok->strAt(1)); + tok->tokType(Token::Type::eKeyword); // we need to preserve the keyword type after setting a non-keyword string + // TODO: tok->isOperatorKeyword(true); tok->deleteNext(); continue; } @@ -10359,11 +10364,15 @@ void Tokenizer::simplifyOperatorName() const bool returnsRef = Token::simpleMatch(par, "( & (") && tok->next()->isName(); if (par && !op.empty()) { if (returnsRef) { - par->next()->insertToken("operator" + op)->isOperatorKeyword(true); + Token* tok_op = par->next()->insertToken("operator" + op); + // TODO: tok_op->tokType(Token::Type::eKeyword); // the given token is not a keyword but should be treated as such + tok_op->isOperatorKeyword(true); tok->deleteThis(); } else { tok->str("operator" + op); + tok->tokType(Token::Type::eKeyword); // we need to preserve the keyword type after setting a non-keyword string + // TODO: tok->isOperatorKeyword(true); Token::eraseTokens(tok, par); } } diff --git a/test/test64bit.cpp b/test/test64bit.cpp index 44046fce1a9..506450e19e4 100644 --- a/test/test64bit.cpp +++ b/test/test64bit.cpp @@ -43,10 +43,10 @@ class Test64BitPortability : public TestFixture { #define check(...) check_(__FILE__, __LINE__, __VA_ARGS__) template - void check_(const char* file, int line, const char (&code)[size]) { + void check_(const char* file, int line, const char (&code)[size], bool cpp = true) { // Tokenize.. SimpleTokenizer tokenizer(settings, *this); - ASSERT_LOC(tokenizer.tokenize(code), file, line); + ASSERT_LOC(tokenizer.tokenize(code, cpp), file, line); // Check char variable usage.. Check64BitPortability check64BitPortability(&tokenizer, &settings, this); @@ -156,6 +156,12 @@ class Test64BitPortability : public TestFixture { " return p ? p : 0;\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check("int f(int* p) {\n" + " int n = (int)(size_t)*p;\n" + " return n;\n" + "}\n", false); + ASSERT_EQUALS("", errout_str()); } void structmember() { diff --git a/test/testtoken.cpp b/test/testtoken.cpp index 6e17fa0857b..96381a1a222 100644 --- a/test/testtoken.cpp +++ b/test/testtoken.cpp @@ -123,6 +123,8 @@ class TestToken : public TestFixture { TEST_CASE(update_property_info_ecomparisonop_link); TEST_CASE(update_property_info_etype_c); TEST_CASE(update_property_info_etype_cpp); + TEST_CASE(update_property_info_replace); // #13743 + TEST_CASE(varid_reset); } @@ -1341,13 +1343,6 @@ class TestToken : public TestFixture { tok.varId(17); assert_tok(&tok, Token::Type::eVariable); } - { - TokensFrontBack tokensFrontBack(list); - Token tok(tokensFrontBack); - tok.varId(17); - tok.str("var1"); - assert_tok(&tok, Token::Type::eVariable); - } } void update_property_info_ekeyword_c() const @@ -1496,6 +1491,16 @@ class TestToken : public TestFixture { } } + void update_property_info_replace() const // #13743 + { + TokensFrontBack tokensFrontBack(list); + Token tok(tokensFrontBack); + tok.str("size_t"); + assert_tok(&tok, Token::Type::eType, false, true); + tok.str("long"); + assert_tok(&tok, Token::Type::eType, false, true); + } + void varid_reset() const { TokenList list_c{&settingsDefault}; diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 6af2b140989..b183cc206f2 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -475,6 +475,8 @@ class TestTokenizer : public TestFixture { TEST_CASE(atomicCast); // #12605 TEST_CASE(constFunctionPtrTypedef); // #12135 + + TEST_CASE(simplifyPlatformTypes); } #define tokenizeAndStringify(...) tokenizeAndStringify_(__FILE__, __LINE__, __VA_ARGS__) @@ -8495,6 +8497,24 @@ class TestTokenizer : public TestFixture { ASSERT_NO_THROW(tokenizeAndStringify(code)); ASSERT_EQUALS("void ( * const f ) ( ) ;", tokenizeAndStringify("typedef void (*fp_t)(); fp_t const f;")); } + + void simplifyPlatformTypes() { + { + const char code[] = "size_t f();"; + ASSERT_EQUALS("unsigned long f ( ) ;", tokenizeAndStringify(code, true, Platform::Type::Unix32)); + ASSERT_EQUALS("unsigned long f ( ) ;", tokenizeAndStringify(code, true, Platform::Type::Unix64)); + } + { + const char code[] = "ssize_t f();"; + ASSERT_EQUALS("long f ( ) ;", tokenizeAndStringify(code, true, Platform::Type::Unix32)); + ASSERT_EQUALS("long f ( ) ;", tokenizeAndStringify(code, true, Platform::Type::Unix64)); + } + { + const char code[] = "std::ptrdiff_t f();"; + ASSERT_EQUALS("long f ( ) ;", tokenizeAndStringify(code, true, Platform::Type::Unix32)); + ASSERT_EQUALS("long f ( ) ;", tokenizeAndStringify(code, true, Platform::Type::Unix64)); + } + } }; REGISTER_TEST(TestTokenizer)