diff --git a/lib/clangimport.cpp b/lib/clangimport.cpp index f8145d1fc..de90db68b 100644 --- a/lib/clangimport.cpp +++ b/lib/clangimport.cpp @@ -741,6 +741,8 @@ Token *clangimport::AstNode::createTokens(TokenList *tokenList) Scope *recordScope = createScope(tokenList, Scope::ScopeType::eStruct, children); mData->mSymbolDatabase->typeList.push_back(Type(classDef, recordScope, classDef->scope())); recordScope->definedType = &mData->mSymbolDatabase->typeList.back(); + if (!recordName.empty()) + const_cast(classDef->scope())->definedTypesMap[recordName] = recordScope->definedType; } return nullptr; } @@ -939,6 +941,55 @@ Token * clangimport::AstNode::createTokensVarDecl(TokenList *tokenList) return vartok1; } +static void setTypes(TokenList *tokenList) +{ + for (Token *tok = tokenList->front(); tok; tok = tok->next()) { + if (Token::simpleMatch(tok, "sizeof (")) { + for (Token *typeToken = tok->tokAt(2); typeToken->str() != ")"; typeToken = typeToken->next()) { + if (typeToken->type()) + continue; + typeToken->type(typeToken->scope()->findType(typeToken->str())); + } + } + } +} + +static void setValues(Tokenizer *tokenizer, SymbolDatabase *symbolDatabase) +{ + const Settings * const settings = tokenizer->getSettings(); + + for (Scope &scope: symbolDatabase->scopeList) { + if (!scope.definedType) + continue; + + int typeSize = 0; + for (const Variable &var: scope.varlist) { + int mul = 1; + for (const auto &dim: var.dimensions()) { + mul *= dim.num; + } + if (var.valueType()) + typeSize += mul * var.valueType()->typeSize(*settings); + } + scope.definedType->sizeOf = typeSize; + } + + for (Token *tok = const_cast(tokenizer->tokens()); tok; tok = tok->next()) { + if (Token::simpleMatch(tok, "sizeof (")) { + int sz = 0; + for (Token *typeToken = tok->tokAt(2); typeToken->str() != ")"; typeToken = typeToken->next()) { + if (typeToken->type()) + sz = typeToken->type()->sizeOf; + } + if (sz <= 0) + continue; + ValueFlow::Value v(sz); + v.setKnown(); + tok->next()->addValue(v); + } + } +} + void clangimport::parseClangAstDump(Tokenizer *tokenizer, std::istream &f) { TokenList *tokenList = &tokenizer->list; @@ -993,5 +1044,7 @@ void clangimport::parseClangAstDump(Tokenizer *tokenizer, std::istream &f) symbolDatabase->clangSetVariables(data.getVariableList()); tokenList->clangSetOrigFiles(); + setTypes(tokenList); + setValues(tokenizer, symbolDatabase); } diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index dbc39eb55..98296541a 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -101,6 +101,7 @@ public: const Token * typeStart; const Token * typeEnd; + MathLib::bigint sizeOf; Type(const Token* classDef_ = nullptr, const Scope* classScope_ = nullptr, const Scope* enclosingScope_ = nullptr) : classDef(classDef_), @@ -108,7 +109,8 @@ public: enclosingScope(enclosingScope_), needInitialization(NeedInitialization::Unknown), typeStart(nullptr), - typeEnd(nullptr) { + typeEnd(nullptr), + sizeOf(0) { if (classDef_ && classDef_->str() == "enum") needInitialization = NeedInitialization::True; else if (classDef_ && classDef_->str() == "using") { diff --git a/test/testclangimport.cpp b/test/testclangimport.cpp index 00d804f0a..b4d5b88c1 100644 --- a/test/testclangimport.cpp +++ b/test/testclangimport.cpp @@ -78,6 +78,8 @@ private: TEST_CASE(symbolDatabaseFunction1); TEST_CASE(symbolDatabaseFunction2); TEST_CASE(symbolDatabaseNodeType1); + + TEST_CASE(valueFlow1); } std::string parse(const char clang[]) { @@ -586,6 +588,7 @@ private: #define GET_SYMBOL_DB(clang) \ Settings settings; \ + settings.platform(cppcheck::Platform::PlatformType::Unix64); \ Tokenizer tokenizer(&settings, this); \ std::istringstream istr(clang); \ clangimport::parseClangAstDump(&tokenizer, istr); \ @@ -644,6 +647,22 @@ private: ASSERT(!!tok->valueType()); ASSERT_EQUALS("signed long", tok->valueType()->str()); } + + void valueFlow1() { + const char clang[] = "|-RecordDecl 0x2fc5a88 <1.c:1:1, line:4:1> line:1:8 struct S definition\n" + "| |-FieldDecl 0x2fc5b48 col:7 x 'int'\n" + "| `-FieldDecl 0x2fc5c10 col:7 buf 'int [10]'\n" + "`-VarDecl 0x2fc5c70 col:5 sz 'int' cinit\n" + " `-ImplicitCastExpr 0x2fc5d88 'int' \n" + " `-UnaryExprOrTypeTraitExpr 0x2fc5d68 'unsigned long' sizeof 'struct S':'struct S'"; + GET_SYMBOL_DB(clang); + + const Token *tok = Token::findsimplematch(tokenizer.tokens(), "sizeof ("); + ASSERT(!!tok); + tok = tok->next(); + ASSERT(tok->hasKnownIntValue()); + ASSERT_EQUALS(44, tok->getKnownIntValue()); + } }; REGISTER_TEST(TestClangImport)