ValueFlow: string can be constructed from init list (#3459)

This commit is contained in:
chrchr-github 2021-10-02 23:09:49 +02:00 committed by GitHub
parent 5be950a4ff
commit 609e20d9d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 15 additions and 1 deletions

View File

@ -203,6 +203,11 @@ bool astIsUnknownSignChar(const Token *tok)
return astIsCharWithSign(tok, ValueType::Sign::UNKNOWN_SIGN); return astIsCharWithSign(tok, ValueType::Sign::UNKNOWN_SIGN);
} }
bool astIsGenericChar(const Token* tok)
{
return tok && tok->valueType() && (tok->valueType()->type == ValueType::Type::CHAR || tok->valueType()->type == ValueType::Type::WCHAR_T);
}
bool astIsIntegral(const Token *tok, bool unknown) bool astIsIntegral(const Token *tok, bool unknown)
{ {
const ValueType *vt = tok ? tok->valueType() : nullptr; const ValueType *vt = tok ? tok->valueType() : nullptr;

View File

@ -67,6 +67,8 @@ bool astHasVar(const Token * tok, nonneg int varid);
bool astIsSignedChar(const Token *tok); bool astIsSignedChar(const Token *tok);
/** Is expression a 'char' if no promotion is used? */ /** Is expression a 'char' if no promotion is used? */
bool astIsUnknownSignChar(const Token *tok); bool astIsUnknownSignChar(const Token *tok);
/** Is expression a char according to valueType? */
bool astIsGenericChar(const Token* tok);
/** Is expression of integral type? */ /** Is expression of integral type? */
bool astIsIntegral(const Token *tok, bool unknown); bool astIsIntegral(const Token *tok, bool unknown);
bool astIsUnsigned(const Token* tok); bool astIsUnsigned(const Token* tok);

View File

@ -7045,8 +7045,9 @@ static std::vector<ValueFlow::Value> getInitListSize(const Token* tok,
bool known = true) bool known = true)
{ {
std::vector<const Token*> args = getArguments(tok); std::vector<const Token*> args = getArguments(tok);
// Strings don't use an init list
if (!args.empty() && container->stdStringLike) { if (!args.empty() && container->stdStringLike) {
if (astIsGenericChar(args[0])) // init list of chars
return { makeContainerSizeValue(args.size(), known) };
if (astIsIntegral(args[0], false)) { if (astIsIntegral(args[0], false)) {
if (args.size() > 1) if (args.size() > 1)
return {makeContainerSizeValue(args[0], known)}; return {makeContainerSizeValue(args[0], known)};

View File

@ -5126,6 +5126,12 @@ private:
"}"; "}";
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "s . size"), 3)); ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "s . size"), 3));
code = "void f() {\n"
" std::string s = { 'a', 'b', 'c' };\n" // size of s is 3
" s.size();\n"
"}";
ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "s . size"), 3));
code = "void f() {\n" code = "void f() {\n"
" std::string s=\"abc\";\n" // size of s is 3 " std::string s=\"abc\";\n" // size of s is 3
" s += unknown;\n" " s += unknown;\n"