From 7c790ca0701cebeb819a6c0dc2128c3d95bb7818 Mon Sep 17 00:00:00 2001 From: Swasti Shrivastava <37058682+swasti16@users.noreply.github.com> Date: Sat, 10 Feb 2024 17:05:53 +0530 Subject: [PATCH] #12400: dump file: Add volatileness to ValueType (#5967) --- lib/symboldatabase.cpp | 81 +++++++++++++++++++++++++++++++++++-- lib/symboldatabase.h | 10 +++++ test/testsymboldatabase.cpp | 42 +++++++++++++++++++ 3 files changed, 129 insertions(+), 4 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index ae2bc481ed9..6e3eda8fb5f 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2437,6 +2437,7 @@ void Variable::setValueType(const ValueType &valueType) if ((mValueType->pointer > 0) && (!isArray() || Token::Match(mNameToken->previous(), "( * %name% )"))) setFlag(fIsPointer, true); setFlag(fIsConst, mValueType->constness & (1U << mValueType->pointer)); + setFlag(fIsVolatile, mValueType->volatileness & (1U << mValueType->pointer)); if (mValueType->smartPointerType) setFlag(fIsSmartPointer, true); } @@ -4354,6 +4355,10 @@ void SymbolDatabase::printXml(std::ostream &out) const outs += " constness=\""; outs += std::to_string(var->valueType()->constness); outs += '\"'; + + outs += " volatileness=\""; + outs += std::to_string(var->valueType()->volatileness); + outs += '\"'; } outs += " isArray=\""; outs += bool_to_string(var->isArray()); @@ -5608,7 +5613,8 @@ static bool hasMatchingConstructor(const Scope* classScope, const ValueType* arg vt->type == argType->type && (argType->sign == ValueType::Sign::UNKNOWN_SIGN || vt->sign == argType->sign) && vt->pointer == argType->pointer && - (vt->constness & 1) >= (argType->constness & 1); + (vt->constness & 1) >= (argType->constness & 1) && + (vt->volatileness & 1) >= (argType->volatileness & 1); }); } @@ -5717,6 +5723,8 @@ const Function* Scope::findFunction(const Token *tok, bool requireConst) const { if (typeToken->str() == "const") ret.constness |= (1 << ret.pointer); + else if (typeToken->str() == "volatile") + ret.volatileness |= (1 << ret.pointer); else if (typeToken->str() == "*") ret.pointer++; else if (typeToken->str() == "<") { @@ -6454,6 +6462,8 @@ void SymbolDatabase::setValueType(Token* tok, const Variable& var, SourceLocatio const ValueType * const vt = tok->astOperand1()->valueType(); if (vt && (vt->constness & 1) != 0) valuetype.constness |= 1; + if (vt && (vt->volatileness & 1) != 0) + valuetype.volatileness |= 1; } setValueType(tok, valuetype); } @@ -6549,6 +6559,8 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source if (parsedecl(vt1->containerTypeToken, &item, mDefaultSignedness, mSettings, mIsCpp)) { if (item.constness == 0) item.constness = vt1->constness; + if (item.volatileness == 0) + item.volatileness = vt1->volatileness; if (isContainerYieldPointer(vt1->container->getYield(parent->next()->str()))) item.pointer += 1; else @@ -6583,10 +6595,14 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source ValueType vt(*vt2); if (vt.constness & (1 << vt.pointer)) vt.constness &= ~(1 << vt.pointer); + if (vt.volatileness & (1 << vt.pointer)) + vt.volatileness &= ~(1 << vt.pointer); if (autoTok->strAt(1) == "*" && vt.pointer) vt.pointer--; if (Token::Match(autoTok->tokAt(-1), "const|constexpr")) vt.constness |= (1 << vt.pointer); + if (Token::simpleMatch(autoTok->tokAt(-1), "volatile")) + vt.volatileness |= (1 << vt.pointer); setValueType(autoTok, vt); setAutoTokenProperties(autoTok); if (vt2->pointer > vt.pointer) @@ -6601,10 +6617,16 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source vt2_.pointer = 1; if ((vt.constness & (1 << vt2->pointer)) != 0) vt2_.constness |= (1 << vt2->pointer); - if (!Token::Match(autoTok->tokAt(1), "*|&")) + if ((vt.volatileness & (1 << vt2->pointer)) != 0) + vt2_.volatileness |= (1 << vt2->pointer); + if (!Token::Match(autoTok->tokAt(1), "*|&")) { vt2_.constness = vt.constness; + vt2_.volatileness = vt.volatileness; + } if (Token::simpleMatch(autoTok->tokAt(1), "* const")) vt2_.constness |= (1 << vt2->pointer); + if (Token::simpleMatch(autoTok->tokAt(1), "* volatile")) + vt2_.volatileness |= (1 << vt2->pointer); var->setValueType(vt2_); if (vt2->typeScope && vt2->typeScope->definedType) { var->type(vt2->typeScope->definedType); @@ -6655,6 +6677,8 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source if (parsedecl(valuetype.containerTypeToken, &vt, mDefaultSignedness, mSettings, mIsCpp)) { if (vt.constness == 0) vt.constness = valuetype.constness; + if (vt.volatileness == 0) + vt.volatileness = valuetype.volatileness; vt.reference = Reference::LValue; setValueType(parent, vt); return; @@ -6667,6 +6691,8 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source if (parsedecl(valuetype.smartPointerTypeToken, &vt, mDefaultSignedness, mSettings, mIsCpp)) { if (vt.constness == 0) vt.constness = valuetype.constness; + if (vt.volatileness == 0) + vt.volatileness = valuetype.volatileness; setValueType(parent, vt); return; } @@ -6729,11 +6755,13 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source !parent->previous()->valueType() && Token::simpleMatch(parent->astParent()->astOperand1(), "for")) { const bool isconst = Token::simpleMatch(parent->astParent()->next(), "const"); + const bool isvolatile = Token::simpleMatch(parent->astParent()->next(), "volatile"); Token * const autoToken = parent->astParent()->tokAt(isconst ? 2 : 1); if (vt2->pointer) { ValueType autovt(*vt2); autovt.pointer--; autovt.constness = 0; + autovt.volatileness = 0; setValueType(autoToken, autovt); setAutoTokenProperties(autoToken); ValueType varvt(*vt2); @@ -6746,6 +6774,12 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source else varvt.constness |= 1; } + if (isvolatile) { + if (varvt.pointer && varvt.reference != Reference::None) + varvt.volatileness |= (1 << varvt.pointer); + else + varvt.volatileness |= 1; + } setValueType(parent->previous(), varvt); auto *var = const_cast(parent->previous()->variable()); if (var) { @@ -6800,6 +6834,12 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source else autovt.constness |= 1; } + if (autoToken->previous()->str() == "volatile") { + if (autovt.pointer && autovt.reference != Reference::None) + autovt.volatileness |= 2; + else + autovt.volatileness |= 1; + } } } @@ -6812,6 +6852,8 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source autovt.pointer--; if (isconst) varvt.constness |= (1 << autovt.pointer); + if (isvolatile) + varvt.volatileness |= (1 << autovt.pointer); setValueType(parent->previous(), varvt); auto * var = const_cast(parent->previous()->variable()); if (var) { @@ -7071,6 +7113,8 @@ static const Token* parsedecl(const Token* type, parsedecl(type->type()->typeStart, valuetype, defaultSignedness, settings, isCpp); else if (Token::Match(type, "const|constexpr")) valuetype->constness |= (1 << (valuetype->pointer - pointer0)); + else if (Token::simpleMatch(type, "volatile")) + valuetype->volatileness |= (1 << (valuetype->pointer - pointer0)); else if (settings.clang && type->str().size() > 2 && type->str().find("::") < type->str().find('<')) { TokenList typeTokens(&settings); std::string::size_type pos1 = 0; @@ -7161,13 +7205,17 @@ static const Token* parsedecl(const Token* type, if (vt->sign != ValueType::Sign::UNKNOWN_SIGN) valuetype->sign = vt->sign; valuetype->constness = vt->constness; + valuetype->volatileness = vt->volatileness; valuetype->originalTypeName = vt->originalTypeName; const bool hasConst = Token::simpleMatch(type->previous(), "const"); + const bool hasVolatile = Token::simpleMatch(type->previous(), "volatile"); while (Token::Match(type, "%name%|*|&|&&|::") && !type->variable()) { if (type->str() == "*") { valuetype->pointer = 1; if (hasConst) valuetype->constness = 1; + if (hasVolatile) + valuetype->volatileness = 1; } else if (type->str() == "&") { valuetype->reference = Reference::LValue; } else if (type->str() == "&&") { @@ -7175,6 +7223,8 @@ static const Token* parsedecl(const Token* type, } if (type->str() == "const") valuetype->constness |= (1 << valuetype->pointer); + if (type->str() == "volatile") + valuetype->volatileness |= (1 << valuetype->pointer); type = type->next(); } break; @@ -7336,7 +7386,8 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to } else if (tok->tokType() == Token::eChar || tok->tokType() == Token::eString) { nonneg int const pointer = tok->tokType() == Token::eChar ? 0U : 1U; nonneg int const constness = tok->tokType() == Token::eChar ? 0U : 1U; - ValueType valuetype(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::CHAR, pointer, constness); + nonneg int const volatileness = 0U; + ValueType valuetype(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::CHAR, pointer, constness, volatileness); if (mIsCpp && mSettings.standards.cpp >= Standards::CPP20 && tok->isUtf8()) { valuetype.originalTypeName = "char8_t"; @@ -7671,6 +7722,8 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to vt.typeScope = defScope; if (fscope->function->isConst()) vt.constness = 1; + if (fscope->function->isVolatile()) + vt.volatileness = 1; setValueType(tok, vt); } } @@ -7898,6 +7951,12 @@ std::string ValueType::dump() const ret += '\"'; } + if (volatileness > 0) { + ret += " valueType-volatileness=\""; + ret += std::to_string(volatileness); + ret += '\"'; + } + if (reference == Reference::None) ret += " valueType-reference=\"None\""; else if (reference == Reference::LValue) @@ -7927,6 +7986,12 @@ bool ValueType::isConst(nonneg int indirect) const return constness & (1 << (pointer - indirect)); } +bool ValueType::isVolatile(nonneg int indirect) const +{ + if (indirect > pointer) + return false; + return volatileness & (1 << (pointer - indirect)); +} MathLib::bigint ValueType::typeSize(const Platform &platform, bool p) const { if (p && pointer) @@ -7979,6 +8044,8 @@ std::string ValueType::str() const std::string ret; if (constness & 1) ret = " const"; + if (volatileness & 1) + ret = " volatile"; if (type == VOID) ret += " void"; else if (isIntegral()) { @@ -8028,6 +8095,8 @@ std::string ValueType::str() const ret += " *"; if (constness & (2 << p)) ret += " const"; + if (volatileness & (2 << p)) + ret += " volatile"; } if (reference == Reference::LValue) ret += " &"; @@ -8064,8 +8133,12 @@ ValueType::MatchResult ValueType::matchParameter(const ValueType *call, const Va if (call->pointer > 0) { if ((call->constness | func->constness) != func->constness) return ValueType::MatchResult::NOMATCH; + if ((call->volatileness | func->volatileness) != func->volatileness) + return ValueType::MatchResult::NOMATCH; if (call->constness == 0 && func->constness != 0 && func->reference != Reference::None) return ValueType::MatchResult::NOMATCH; + if (call->volatileness == 0 && func->volatileness != 0 && func->reference != Reference::None) + return ValueType::MatchResult::NOMATCH; } if (call->type != func->type || (call->isEnum() && !func->isEnum())) { if (call->type == ValueType::Type::VOID || func->type == ValueType::Type::VOID) @@ -8104,7 +8177,7 @@ ValueType::MatchResult ValueType::matchParameter(const ValueType *call, const Va if (call->isIntegral() && func->isIntegral() && call->sign != ValueType::Sign::UNKNOWN_SIGN && func->sign != ValueType::Sign::UNKNOWN_SIGN && call->sign != func->sign) return ValueType::MatchResult::FALLBACK1; - if (func->reference != Reference::None && func->constness > call->constness) + if (func->reference != Reference::None && (func->constness > call->constness || func->volatileness > call->volatileness)) return ValueType::MatchResult::FALLBACK1; return ValueType::MatchResult::SAME; diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 5d9234bd237..2b9580a4cea 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -1232,6 +1232,7 @@ class CPPCHECKLIB ValueType { nonneg int bits{}; ///< bitfield bitcount nonneg int pointer{}; ///< 0=>not pointer, 1=>*, 2=>**, 3=>***, etc nonneg int constness{}; ///< bit 0=data, bit 1=*, bit 2=** + nonneg int volatileness{}; ///< bit 0=data, bit 1=*, bit 2=** Reference reference = Reference::None; ///< Is the outermost indirection of this type a reference or rvalue ///< reference or not? pointer=2, Reference=LValue would be a T**& const Scope* typeScope{}; ///< if the type definition is seen this point out the type scope @@ -1258,6 +1259,13 @@ class CPPCHECKLIB ValueType { pointer(p), constness(c) {} + ValueType(Sign s, Type t, nonneg int p, nonneg int c, nonneg int v) + : sign(s), + type(t), + pointer(p), + constness(c), + volatileness(v) + {} ValueType(Sign s, Type t, nonneg int p, nonneg int c, std::string otn) : sign(s), type(t), @@ -1294,6 +1302,8 @@ class CPPCHECKLIB ValueType { bool isConst(nonneg int indirect = 0) const; + bool isVolatile(nonneg int indirect = 0) const; + MathLib::bigint typeSize(const Platform &platform, bool p=false) const; /// Check if type is the same ignoring const and references diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 1cfaf407602..670ca8f6a22 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -1263,6 +1263,17 @@ class TestSymbolDatabase : public TestFixture { ASSERT(p->valueType()); ASSERT(p->valueType()->pointer == 0); ASSERT(p->valueType()->constness == 0); + ASSERT(p->valueType()->volatileness == 0); + ASSERT(p->valueType()->reference == Reference::None); + } + + { + GET_SYMBOL_DB("void foo(volatile int x) {}\n"); + const Variable* const p = db->getVariableFromVarId(1); + ASSERT(p->valueType()); + ASSERT(p->valueType()->pointer == 0); + ASSERT(p->valueType()->constness == 0); + ASSERT(p->valueType()->volatileness == 1); ASSERT(p->valueType()->reference == Reference::None); } { @@ -1271,6 +1282,7 @@ class TestSymbolDatabase : public TestFixture { ASSERT(p->valueType()); ASSERT(p->valueType()->pointer == 1); ASSERT(p->valueType()->constness == 0); + ASSERT(p->valueType()->volatileness == 0); ASSERT(p->valueType()->reference == Reference::None); } { @@ -1279,6 +1291,7 @@ class TestSymbolDatabase : public TestFixture { ASSERT(p->valueType()); ASSERT(p->valueType()->pointer == 0); ASSERT(p->valueType()->constness == 0); + ASSERT(p->valueType()->volatileness == 0); ASSERT(p->valueType()->reference == Reference::LValue); } { @@ -1287,6 +1300,7 @@ class TestSymbolDatabase : public TestFixture { ASSERT(p->valueType()); ASSERT(p->valueType()->pointer == 0); ASSERT(p->valueType()->constness == 0); + ASSERT(p->valueType()->volatileness == 0); ASSERT(p->valueType()->reference == Reference::RValue); } { @@ -1295,6 +1309,7 @@ class TestSymbolDatabase : public TestFixture { ASSERT(p->valueType()); ASSERT(p->valueType()->pointer == 1); ASSERT(p->valueType()->constness == 0); + ASSERT(p->valueType()->volatileness == 0); ASSERT(p->valueType()->reference == Reference::LValue); } { @@ -1303,6 +1318,7 @@ class TestSymbolDatabase : public TestFixture { ASSERT(p->valueType()); ASSERT(p->valueType()->pointer == 1); ASSERT(p->valueType()->constness == 0); + ASSERT(p->valueType()->volatileness == 0); ASSERT(p->valueType()->reference == Reference::RValue); } { @@ -1311,6 +1327,7 @@ class TestSymbolDatabase : public TestFixture { ASSERT(p->valueType()); ASSERT(p->valueType()->pointer == 2); ASSERT(p->valueType()->constness == 0); + ASSERT(p->valueType()->volatileness == 0); ASSERT(p->valueType()->reference == Reference::LValue); } { @@ -1319,6 +1336,7 @@ class TestSymbolDatabase : public TestFixture { ASSERT(p->valueType()); ASSERT(p->valueType()->pointer == 2); ASSERT(p->valueType()->constness == 0); + ASSERT(p->valueType()->volatileness == 0); ASSERT(p->valueType()->reference == Reference::RValue); } { @@ -1327,6 +1345,7 @@ class TestSymbolDatabase : public TestFixture { ASSERT(p->valueType()); ASSERT(p->valueType()->pointer == 0); ASSERT(p->valueType()->constness == 1); + ASSERT(p->valueType()->volatileness == 0); ASSERT(p->valueType()->reference == Reference::LValue); } { @@ -1335,6 +1354,7 @@ class TestSymbolDatabase : public TestFixture { ASSERT(p->valueType()); ASSERT(p->valueType()->pointer == 0); ASSERT(p->valueType()->constness == 1); + ASSERT(p->valueType()->volatileness == 0); ASSERT(p->valueType()->reference == Reference::RValue); } { @@ -1343,6 +1363,7 @@ class TestSymbolDatabase : public TestFixture { ASSERT(p->valueType()); ASSERT(p->valueType()->pointer == 1); ASSERT(p->valueType()->constness == 1); + ASSERT(p->valueType()->volatileness == 0); ASSERT(p->valueType()->reference == Reference::LValue); } { @@ -1351,6 +1372,7 @@ class TestSymbolDatabase : public TestFixture { ASSERT(p->valueType()); ASSERT(p->valueType()->pointer == 1); ASSERT(p->valueType()->constness == 1); + ASSERT(p->valueType()->volatileness == 0); ASSERT(p->valueType()->reference == Reference::RValue); } { @@ -1359,6 +1381,7 @@ class TestSymbolDatabase : public TestFixture { ASSERT(p->valueType()); ASSERT(p->valueType()->pointer == 1); ASSERT(p->valueType()->constness == 2); + ASSERT(p->valueType()->volatileness == 0); ASSERT(p->valueType()->reference == Reference::LValue); } { @@ -1367,8 +1390,27 @@ class TestSymbolDatabase : public TestFixture { ASSERT(p->valueType()); ASSERT(p->valueType()->pointer == 1); ASSERT(p->valueType()->constness == 2); + ASSERT(p->valueType()->volatileness == 0); ASSERT(p->valueType()->reference == Reference::RValue); } + { + GET_SYMBOL_DB("extern const volatile int* test[];\n"); + const Variable* const p = db->getVariableFromVarId(1); + ASSERT(p->valueType()); + ASSERT(p->valueType()->pointer == 1); + ASSERT(p->valueType()->constness == 1); + ASSERT(p->valueType()->volatileness == 1); + ASSERT(p->valueType()->reference == Reference::None); + } + { + GET_SYMBOL_DB("extern const int* volatile test[];\n"); + const Variable* const p = db->getVariableFromVarId(1); + ASSERT(p->valueType()); + ASSERT(p->valueType()->pointer == 1); + ASSERT(p->valueType()->constness == 1); + ASSERT(p->valueType()->volatileness == 2); + ASSERT(p->valueType()->reference == Reference::None); + } } void VariableValueTypeTemplate() {