Clang import; Better sizeof/type handling

This commit is contained in:
Daniel Marjamäki 2020-01-18 11:07:36 +01:00
parent f7a30fc99f
commit b905547c76
3 changed files with 75 additions and 1 deletions

View File

@ -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<Scope *>(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<Token*>(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);
}

View File

@ -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") {

View File

@ -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 <line:2:3, col:7> col:7 x 'int'\n"
"| `-FieldDecl 0x2fc5c10 <line:3:3, col:13> col:7 buf 'int [10]'\n"
"`-VarDecl 0x2fc5c70 <line:6:1, col:25> col:5 sz 'int' cinit\n"
" `-ImplicitCastExpr 0x2fc5d88 <col:10, col:25> 'int' <IntegralCast>\n"
" `-UnaryExprOrTypeTraitExpr 0x2fc5d68 <col:10, col:25> '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)