diff --git a/cfg/std.cfg b/cfg/std.cfg index 97f5ce0152e..52ce5899ab7 100644 --- a/cfg/std.cfg +++ b/cfg/std.cfg @@ -6884,6 +6884,18 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun + + + + + false + + + + + + + diff --git a/lib/astutils.cpp b/lib/astutils.cpp index bc85cfab931..78252680e11 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -738,7 +738,7 @@ std::vector getParentValueTypes(const Token* tok, const Settings* set const ValueType* vtCont = contTok->valueType(); if (!vtCont->containerTypeToken) return {}; - ValueType vtParent = ValueType::parseDecl(vtCont->containerTypeToken, *settings, true); // TODO: set isCpp + ValueType vtParent = ValueType::parseDecl(vtCont->containerTypeToken, *settings); return {std::move(vtParent)}; } if (Token::Match(tok->astParent(), "return|(|{|%assign%") && parent) { diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 497babe1d60..29a94f024bd 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -3228,7 +3228,7 @@ void CheckClass::checkThisUseAfterFree() for (const Variable &var : classScope->varlist) { // Find possible "self pointer".. pointer/smartpointer member variable of "self" type. if (var.valueType() && var.valueType()->smartPointerType != classScope->definedType && var.valueType()->typeScope != classScope) { - const ValueType valueType = ValueType::parseDecl(var.typeStartToken(), *mSettings, true); // this is only called for C++ + const ValueType valueType = ValueType::parseDecl(var.typeStartToken(), *mSettings); if (valueType.smartPointerType != classScope->definedType) continue; } diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 6b94c3484b0..deaadbf7ca0 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -3647,17 +3647,23 @@ void CheckOther::checkKnownArgument() const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope *functionScope : symbolDatabase->functionScopes) { for (const Token *tok = functionScope->bodyStart; tok != functionScope->bodyEnd; tok = tok->next()) { - if (!Token::simpleMatch(tok->astParent(), "(")) + if (!tok->hasKnownIntValue()) continue; - if (!Token::Match(tok->astParent()->previous(), "%name%")) + if (Token::Match(tok, "++|--|%assign%")) continue; - if (Token::Match(tok->astParent()->previous(), "if|while|switch|sizeof")) + if (!Token::Match(tok->astParent(), "(|{|,")) continue; - if (tok == tok->astParent()->previous()) + if (tok->astParent()->isCast()) continue; - if (!tok->hasKnownIntValue()) + int argn = -1; + const Token* ftok = getTokenArgumentFunction(tok, argn); + if (!ftok) continue; - if (tok->tokType() == Token::eIncDecOp) + if (ftok->isCast()) + continue; + if (Token::Match(ftok, "if|while|switch|sizeof")) + continue; + if (tok == tok->astParent()->previous()) continue; if (isConstVarExpression(tok)) continue; @@ -3668,6 +3674,10 @@ void CheckOther::checkKnownArgument() tok2 = tok2->astOperand2(); if (isVariableExpression(tok2)) continue; + if (tok->isComparisonOp() && + isSameExpression( + mTokenizer->isCPP(), true, tok->astOperand1(), tok->astOperand2(), mSettings->library, true, true)) + continue; // ensure that there is a integer variable in expression with unknown value std::string varexpr; bool isVariableExprHidden = false; // Is variable expression explicitly hidden @@ -3706,7 +3716,7 @@ void CheckOther::checkKnownArgument() strTolower(funcname); if (funcname.find("assert") != std::string::npos) continue; - knownArgumentError(tok, tok->astParent()->previous(), &tok->values().front(), varexpr, isVariableExprHidden); + knownArgumentError(tok, ftok, &tok->values().front(), varexpr, isVariableExprHidden); } } } diff --git a/lib/checkstring.cpp b/lib/checkstring.cpp index 481438815d5..c9965b53e51 100644 --- a/lib/checkstring.cpp +++ b/lib/checkstring.cpp @@ -288,13 +288,7 @@ void CheckString::checkIncorrectStringCompare() incorrectStringCompareError(tok->next(), "substr", end->strAt(1)); } } - } else if (Token::Match(tok, "&&|%oror%|( %str%|%char% &&|%oror%|)") && !Token::Match(tok, "( %str%|%char% )")) { - incorrectStringBooleanError(tok->next(), tok->strAt(1)); - } else if (Token::Match(tok, "if|while ( %str%|%char% )") && !tok->tokAt(2)->getValue(0)) { - incorrectStringBooleanError(tok->tokAt(2), tok->strAt(2)); - } else if (tok->str() == "?" && Token::Match(tok->astOperand1(), "%str%|%char%")) { - incorrectStringBooleanError(tok->astOperand1(), tok->astOperand1()->str()); - } else if (Token::Match(tok, "%str%") && isUsedAsBool(tok)) + } else if (Token::Match(tok, "%str%|%char%") && isUsedAsBool(tok)) incorrectStringBooleanError(tok, tok->str()); } } diff --git a/lib/checktype.cpp b/lib/checktype.cpp index 3384bf69b5e..a15064122c1 100644 --- a/lib/checktype.cpp +++ b/lib/checktype.cpp @@ -437,7 +437,7 @@ void CheckType::checkFloatToIntegerOverflow() while (scope && scope->type != Scope::ScopeType::eLambda && scope->type != Scope::ScopeType::eFunction) scope = scope->nestedIn; if (scope && scope->type == Scope::ScopeType::eFunction && scope->function && scope->function->retDef) { - const ValueType &valueType = ValueType::parseDecl(scope->function->retDef, *mSettings, mTokenizer->isCPP()); + const ValueType &valueType = ValueType::parseDecl(scope->function->retDef, *mSettings); vtfloat = tok->astOperand1()->valueType(); checkFloatToIntegerOverflow(tok, &valueType, vtfloat, tok->astOperand1()->values()); } diff --git a/lib/clangimport.cpp b/lib/clangimport.cpp index 7b91d6c4b07..2e68aaa26bd 100644 --- a/lib/clangimport.cpp +++ b/lib/clangimport.cpp @@ -630,7 +630,7 @@ void clangimport::AstNode::setValueType(Token *tok) if (!decl.front()) break; - const ValueType valueType = ValueType::parseDecl(decl.front(), *mData->mSettings, true); // TODO: set isCpp + const ValueType valueType = ValueType::parseDecl(decl.front(), *mData->mSettings); if (valueType.type != ValueType::Type::UNKNOWN_TYPE) { tok->setValueType(new ValueType(valueType)); break; @@ -1545,7 +1545,7 @@ static void setValues(const Tokenizer *tokenizer, const SymbolDatabase *symbolDa for (Token *tok = const_cast(tokenizer->tokens()); tok; tok = tok->next()) { if (Token::simpleMatch(tok, "sizeof (")) { - ValueType vt = ValueType::parseDecl(tok->tokAt(2), *settings, tokenizer->isCPP()); + ValueType vt = ValueType::parseDecl(tok->tokAt(2), *settings); const int sz = vt.typeSize(settings->platform, true); if (sz <= 0) continue; diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index bfc04ae73be..f64caa82e27 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2214,12 +2214,13 @@ void Variable::evaluate(const Settings* settings) const Library * const lib = &settings->library; + // TODO: ValueType::parseDecl() is also performing a container lookup bool isContainer = false; if (mNameToken) setFlag(fIsArray, arrayDimensions(settings, isContainer)); if (mTypeStartToken) - setValueType(ValueType::parseDecl(mTypeStartToken,*settings, true)); // TODO: set isCpp + setValueType(ValueType::parseDecl(mTypeStartToken,*settings)); const Token* tok = mTypeStartToken; while (tok && tok->previous() && tok->previous()->isName()) @@ -2275,7 +2276,7 @@ void Variable::evaluate(const Settings* settings) setFlag(fIsClass, !lib->podtype(strtype) && !mTypeStartToken->isStandardType() && !isEnumType() && !isPointer() && !isReference() && strtype != "..."); setFlag(fIsStlType, Token::simpleMatch(mTypeStartToken, "std ::")); setFlag(fIsStlString, ::isStlStringType(mTypeStartToken)); - setFlag(fIsSmartPointer, lib->isSmartPointer(mTypeStartToken)); + setFlag(fIsSmartPointer, mTypeStartToken->isCpp() && lib->isSmartPointer(mTypeStartToken)); } if (mAccess == AccessControl::Argument) { tok = mNameToken; @@ -3558,7 +3559,7 @@ bool Type::isDerivedFrom(const std::string & ancestor) const bool Variable::arrayDimensions(const Settings* settings, bool& isContainer) { isContainer = false; - const Library::Container* container = settings->library.detectContainer(mTypeStartToken); + const Library::Container* container = (mTypeStartToken && mTypeStartToken->isCpp()) ? settings->library.detectContainer(mTypeStartToken) : nullptr; if (container && container->arrayLike_indexOp && container->size_templateArgNo > 0) { const Token* tok = Token::findsimplematch(mTypeStartToken, "<"); if (tok) { @@ -5653,7 +5654,7 @@ const Function* SymbolDatabase::findFunction(const Token* const tok) const return tok1->valueType()->typeScope->findFunction(tok, tok1->valueType()->constness == 1); if (tok1 && Token::Match(tok1->previous(), "%name% (") && tok1->previous()->function() && tok1->previous()->function()->retDef) { - ValueType vt = ValueType::parseDecl(tok1->previous()->function()->retDef, mSettings, mIsCpp); + ValueType vt = ValueType::parseDecl(tok1->previous()->function()->retDef, mSettings); if (vt.typeScope) return vt.typeScope->findFunction(tok, vt.constness == 1); } else if (Token::Match(tok1, "%var% .")) { @@ -5667,7 +5668,7 @@ const Function* SymbolDatabase::findFunction(const Token* const tok) const } else if (Token::simpleMatch(tok->previous()->astOperand1(), "(")) { const Token *castTok = tok->previous()->astOperand1(); if (castTok->isCast()) { - ValueType vt = ValueType::parseDecl(castTok->next(),mSettings, mIsCpp); + ValueType vt = ValueType::parseDecl(castTok->next(),mSettings); if (vt.typeScope) return vt.typeScope->findFunction(tok, vt.constness == 1); } @@ -5697,7 +5698,7 @@ const Function* SymbolDatabase::findFunction(const Token* const tok) const } // Check for constructor if (Token::Match(tok, "%name% (|{")) { - ValueType vt = ValueType::parseDecl(tok, mSettings, mIsCpp); + ValueType vt = ValueType::parseDecl(tok, mSettings); if (vt.typeScope) return vt.typeScope->findFunction(tok, false); } @@ -6991,7 +6992,7 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to } // Construct smart pointer - else if (mSettings.library.isSmartPointer(start)) { + else if (mIsCpp && mSettings.library.isSmartPointer(start)) { ValueType valuetype; if (parsedecl(start, &valuetype, mDefaultSignedness, mSettings, mIsCpp)) { setValueType(tok, valuetype); @@ -7066,7 +7067,7 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to } } } - if (tok->astParent() && Token::Match(tok->astOperand1(), "%name%|::")) { + if (mIsCpp && tok->astParent() && Token::Match(tok->astOperand1(), "%name%|::")) { const Token *typeStartToken = tok->astOperand1(); while (typeStartToken && typeStartToken->str() == "::") typeStartToken = typeStartToken->astOperand1(); @@ -7216,7 +7217,7 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to functionScope = functionScope->nestedIn; if (functionScope && functionScope->type == Scope::eFunction && functionScope->function && functionScope->function->retDef) { - ValueType vt = ValueType::parseDecl(functionScope->function->retDef, mSettings, mIsCpp); + ValueType vt = ValueType::parseDecl(functionScope->function->retDef, mSettings); setValueType(tok, vt); if (Token::simpleMatch(tok, "return {")) setValueType(tok->next(), vt); @@ -7314,10 +7315,10 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to createSymbolDatabaseSetVariablePointers(); } -ValueType ValueType::parseDecl(const Token *type, const Settings &settings, bool isCpp) +ValueType ValueType::parseDecl(const Token *type, const Settings &settings) { ValueType vt; - parsedecl(type, &vt, settings.platform.defaultSign == 'u' ? Sign::UNSIGNED : Sign::SIGNED, settings, isCpp); + parsedecl(type, &vt, settings.platform.defaultSign == 'u' ? Sign::UNSIGNED : Sign::SIGNED, settings, type->isCpp()); return vt; } diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index d7c50ee7a2a..8b988e54a02 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -1268,7 +1268,7 @@ class CPPCHECKLIB ValueType { originalTypeName(std::move(otn)) {} - static ValueType parseDecl(const Token *type, const Settings &settings, bool isCpp); + static ValueType parseDecl(const Token *type, const Settings &settings); static Type typeFromString(const std::string &typestr, bool longType); diff --git a/lib/token.cpp b/lib/token.cpp index 618979613d1..6c832f3a741 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -424,7 +424,13 @@ const std::string &Token::strAt(int index) const return tok ? tok->mStr : emptyString; } -static int multiComparePercent(const Token *tok, const char*& haystack, nonneg int varid) +static +#if defined(__GNUC__) +// GCC does not inline this by itself +// need to use the old syntax since the C++11 [[xxx:always_inline]] cannot be used here +inline __attribute__((always_inline)) +#endif +int multiComparePercent(const Token *tok, const char*& haystack, nonneg int varid) { ++haystack; // Compare only the first character of the string for optimization reasons @@ -556,7 +562,12 @@ static int multiComparePercent(const Token *tok, const char*& haystack, nonneg i return 0xFFFF; } -int Token::multiCompare(const Token *tok, const char *haystack, nonneg int varid) +static +#if defined(__GNUC__) +// need to use the old syntax since the C++11 [[xxx:always_inline]] cannot be used here +inline __attribute__((always_inline)) +#endif +int multiCompareImpl(const Token *tok, const char *haystack, nonneg int varid) { const char *needle = tok->str().c_str(); const char *needlePointer = needle; @@ -609,6 +620,12 @@ int Token::multiCompare(const Token *tok, const char *haystack, nonneg int varid return -1; } +// cppcheck-suppress unusedFunction - used in tests only +int Token::multiCompare(const Token *tok, const char *haystack, nonneg int varid) +{ + return multiCompareImpl(tok, haystack, varid); +} + bool Token::simpleMatch(const Token *tok, const char pattern[], size_t pattern_len) { if (!tok) @@ -730,7 +747,7 @@ bool Token::Match(const Token *tok, const char pattern[], nonneg int varid) // Parse multi options, such as void|int|char (accept token which is one of these 3) else { - const int res = multiCompare(tok, p, varid); + const int res = multiCompareImpl(tok, p, varid); if (res == 0) { // Empty alternative matches, use the same token on next round while (*p && *p != ' ') @@ -2569,3 +2586,11 @@ Token* findLambdaEndScope(Token* tok) const Token* findLambdaEndScope(const Token* tok) { return findLambdaEndScope(const_cast(tok)); } + +bool Token::isCpp() const +{ + if (mTokensFrontBack && mTokensFrontBack->list) { + return mTokensFrontBack->list->isCPP(); + } + return true; // assume C++ by default +} diff --git a/lib/token.h b/lib/token.h index e0ca0ed9d5e..b8232638152 100644 --- a/lib/token.h +++ b/lib/token.h @@ -154,6 +154,8 @@ struct TokenImpl { * The Token class also has other functions for management of token list, matching tokens, etc. */ class CPPCHECKLIB Token { + friend class TestToken; + private: TokensFrontBack* mTokensFrontBack{}; @@ -788,6 +790,7 @@ class CPPCHECKLIB Token { return const_cast(findmatch(const_cast(startTok), pattern, end, varId)); } +private: /** * Needle is build from multiple alternatives. If one of * them is equal to haystack, return value is 1. If there @@ -804,6 +807,7 @@ class CPPCHECKLIB Token { */ static int multiCompare(const Token *tok, const char *haystack, nonneg int varid); +public: nonneg int fileIndex() const { return mImpl->mFileIndex; } @@ -1480,6 +1484,9 @@ class CPPCHECKLIB Token { void setTokenDebug(TokenDebug td) { mImpl->mDebug = td; } + + /** defaults to C++ if it cannot be determined */ + bool isCpp() const; }; Token* findTypeEnd(Token* tok); diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 8ed4f29cc6c..ffd9c209517 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -760,7 +760,7 @@ static void setTokenValue(Token* tok, if (contains({ValueFlow::Value::ValueType::INT, ValueFlow::Value::ValueType::SYMBOLIC}, value.valueType) && Token::simpleMatch(parent->astOperand1(), "dynamic_cast")) return; - const ValueType &valueType = ValueType::parseDecl(castType, *settings, true); // TODO: set isCpp + const ValueType &valueType = ValueType::parseDecl(castType, *settings); if (value.isImpossible() && value.isIntValue() && value.intvalue < 0 && astIsUnsigned(tok) && valueType.sign == ValueType::SIGNED && tok->valueType() && ValueFlow::getSizeOf(*tok->valueType(), settings) >= ValueFlow::getSizeOf(valueType, settings)) @@ -1095,7 +1095,7 @@ static void setTokenValueCast(Token *parent, const ValueType &valueType, const V static nonneg int getSizeOfType(const Token *typeTok, const Settings *settings) { - const ValueType &valueType = ValueType::parseDecl(typeTok, *settings, true); // TODO: set isCpp + const ValueType &valueType = ValueType::parseDecl(typeTok, *settings); return ValueFlow::getSizeOf(valueType, settings); } @@ -1298,7 +1298,7 @@ static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, b setTokenValue(tok->next(), std::move(value), settings); } } else if (!tok2->type()) { - const ValueType& vt = ValueType::parseDecl(tok2, *settings, true); // TODO: set isCpp + const ValueType& vt = ValueType::parseDecl(tok2, *settings); size_t sz = ValueFlow::getSizeOf(vt, settings); const Token* brac = tok2->astParent(); while (Token::simpleMatch(brac, "[")) { @@ -4259,10 +4259,9 @@ struct LifetimeStore { static bool hasBorrowingVariables(const std::list& vars, const std::vector& args, int depth = 10) { if (depth < 0) - return false; + return true; return std::any_of(vars.cbegin(), vars.cend(), [&](const Variable& var) { - const ValueType* vt = var.valueType(); - if (vt) { + if (const ValueType* vt = var.valueType()) { if (vt->pointer > 0 && std::none_of(args.begin(), args.end(), [vt](const Token* arg) { return arg->valueType() && arg->valueType()->type == vt->type; @@ -4766,7 +4765,7 @@ static bool isContainerOfPointers(const Token* tok, const Settings* settings) return true; } - ValueType vt = ValueType::parseDecl(tok, *settings, true); // TODO: set isCpp + ValueType vt = ValueType::parseDecl(tok, *settings); return vt.pointer > 0; } @@ -8629,7 +8628,7 @@ static bool valueFlowIsSameContainerType(const ValueType& contType, const Token* if (!tok || !tok->valueType() || !tok->valueType()->containerTypeToken) return false; - const ValueType tokType = ValueType::parseDecl(tok->valueType()->containerTypeToken, *settings, true); + const ValueType tokType = ValueType::parseDecl(tok->valueType()->containerTypeToken, *settings); return contType.isTypeEqual(&tokType); } @@ -8649,7 +8648,7 @@ static std::vector getInitListSize(const Token* tok, if (valueType->container->stdStringLike) { initList = astIsGenericChar(args[0]) && !astIsPointer(args[0]); } else if (containerTypeToken && settings) { - ValueType vt = ValueType::parseDecl(containerTypeToken, *settings, true); // TODO: set isCpp + ValueType vt = ValueType::parseDecl(containerTypeToken, *settings); if (vt.pointer > 0 && astIsPointer(args[0])) initList = true; else if (vt.type == ValueType::ITERATOR && astIsIterator(args[0])) @@ -9109,7 +9108,7 @@ static bool getMinMaxValues(const std::string &typestr, const Settings *settings return false; typeTokens.simplifyPlatformTypes(); typeTokens.simplifyStdType(); - const ValueType &vt = ValueType::parseDecl(typeTokens.front(), *settings, true); // TODO: set isCpp + const ValueType &vt = ValueType::parseDecl(typeTokens.front(), *settings); return getMinMaxValues(&vt, settings->platform, minvalue, maxvalue); } diff --git a/test/cfg/std.cpp b/test/cfg/std.cpp index c6a04412543..4952c79d85e 100644 --- a/test/cfg/std.cpp +++ b/test/cfg/std.cpp @@ -4503,6 +4503,11 @@ void stdstring() // valid s.assign("a"); + +#ifdef __cpp_lib_starts_ends_with + // cppcheck-suppress ignoredReturnValue + s.starts_with("abc"); +#endif } void stdvector() diff --git a/test/testother.cpp b/test/testother.cpp index fe87e9d28e2..d789c3bb18c 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -10905,6 +10905,14 @@ class TestOther : public TestFixture { "}"); ASSERT_EQUALS("[test.cpp:3]: (style) Argument '(int)((x&0x01)>>7)' to function g is always 0. It does not matter what value 'x' has.\n", errout.str()); + check("void g(int, int);\n" + "void f(int x) {\n" + " g(x, (x & 0x01) >> 7);\n" + "}"); + ASSERT_EQUALS( + "[test.cpp:3]: (style) Argument '(x&0x01)>>7' to function g is always 0. It does not matter what value 'x' has.\n", + errout.str()); + check("void g(int);\n" "void f(int x) {\n" " g(0);\n" diff --git a/test/teststring.cpp b/test/teststring.cpp index c0330ee3e19..9ea166688d9 100644 --- a/test/teststring.cpp +++ b/test/teststring.cpp @@ -735,7 +735,9 @@ class TestString : public TestFixture { " if('\\0'){}\n" " if(L'\\0'){}\n" "}"); - ASSERT_EQUALS("", errout.str()); + ASSERT_EQUALS("[test.cpp:2]: (warning) Conversion of char literal '\\0' to bool always evaluates to false.\n" + "[test.cpp:3]: (warning) Conversion of char literal L'\\0' to bool always evaluates to false.\n", + errout.str()); check("void f() {\n" " if('\\0' || cond){}\n" @@ -757,6 +759,22 @@ class TestString : public TestFixture { " g(m[\"abc\"][0] ? true : false);\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + check("void g(bool);\n" + " void f(std::map>&m) {\n" + " if (m.count(\"abc\"))\n" + " g(m[\"abc\"][0] ? true : false);\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + check("void g(bool b);\n" + "void f() {\n" + " g('\\0');\n" + " g('a');\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3]: (warning) Conversion of char literal '\\0' to bool always evaluates to false.\n" + "[test.cpp:4]: (warning) Conversion of char literal 'a' to bool always evaluates to true.\n", + errout.str()); } void deadStrcmp() { diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 50a58464abf..f24942164fa 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -7359,6 +7359,17 @@ class TestValueFlow : public TestFixture { " if (llabs(0x80000000ffffffffL) == 0x7fffffff00000001L) {}\n" "}\n"; valueOfTok(code, "f"); + + code = "struct T {\n" + " T();\n" + " static T a[6][64];\n" + " static T b[2][64];\n" + " static T c[64][64];\n" + " static T d[2][64];\n" + " static T e[64];\n" + " static T f[64];\n" + "};\n"; + valueOfTok(code, "("); } void valueFlowCrashConstructorInitialization() { // #9577