Clang import; Better sizeof/type handling
This commit is contained in:
parent
f7a30fc99f
commit
b905547c76
|
@ -741,6 +741,8 @@ Token *clangimport::AstNode::createTokens(TokenList *tokenList)
|
||||||
Scope *recordScope = createScope(tokenList, Scope::ScopeType::eStruct, children);
|
Scope *recordScope = createScope(tokenList, Scope::ScopeType::eStruct, children);
|
||||||
mData->mSymbolDatabase->typeList.push_back(Type(classDef, recordScope, classDef->scope()));
|
mData->mSymbolDatabase->typeList.push_back(Type(classDef, recordScope, classDef->scope()));
|
||||||
recordScope->definedType = &mData->mSymbolDatabase->typeList.back();
|
recordScope->definedType = &mData->mSymbolDatabase->typeList.back();
|
||||||
|
if (!recordName.empty())
|
||||||
|
const_cast<Scope *>(classDef->scope())->definedTypesMap[recordName] = recordScope->definedType;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -939,6 +941,55 @@ Token * clangimport::AstNode::createTokensVarDecl(TokenList *tokenList)
|
||||||
return vartok1;
|
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)
|
void clangimport::parseClangAstDump(Tokenizer *tokenizer, std::istream &f)
|
||||||
{
|
{
|
||||||
TokenList *tokenList = &tokenizer->list;
|
TokenList *tokenList = &tokenizer->list;
|
||||||
|
@ -993,5 +1044,7 @@ void clangimport::parseClangAstDump(Tokenizer *tokenizer, std::istream &f)
|
||||||
|
|
||||||
symbolDatabase->clangSetVariables(data.getVariableList());
|
symbolDatabase->clangSetVariables(data.getVariableList());
|
||||||
tokenList->clangSetOrigFiles();
|
tokenList->clangSetOrigFiles();
|
||||||
|
setTypes(tokenList);
|
||||||
|
setValues(tokenizer, symbolDatabase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,7 @@ public:
|
||||||
|
|
||||||
const Token * typeStart;
|
const Token * typeStart;
|
||||||
const Token * typeEnd;
|
const Token * typeEnd;
|
||||||
|
MathLib::bigint sizeOf;
|
||||||
|
|
||||||
Type(const Token* classDef_ = nullptr, const Scope* classScope_ = nullptr, const Scope* enclosingScope_ = nullptr) :
|
Type(const Token* classDef_ = nullptr, const Scope* classScope_ = nullptr, const Scope* enclosingScope_ = nullptr) :
|
||||||
classDef(classDef_),
|
classDef(classDef_),
|
||||||
|
@ -108,7 +109,8 @@ public:
|
||||||
enclosingScope(enclosingScope_),
|
enclosingScope(enclosingScope_),
|
||||||
needInitialization(NeedInitialization::Unknown),
|
needInitialization(NeedInitialization::Unknown),
|
||||||
typeStart(nullptr),
|
typeStart(nullptr),
|
||||||
typeEnd(nullptr) {
|
typeEnd(nullptr),
|
||||||
|
sizeOf(0) {
|
||||||
if (classDef_ && classDef_->str() == "enum")
|
if (classDef_ && classDef_->str() == "enum")
|
||||||
needInitialization = NeedInitialization::True;
|
needInitialization = NeedInitialization::True;
|
||||||
else if (classDef_ && classDef_->str() == "using") {
|
else if (classDef_ && classDef_->str() == "using") {
|
||||||
|
|
|
@ -78,6 +78,8 @@ private:
|
||||||
TEST_CASE(symbolDatabaseFunction1);
|
TEST_CASE(symbolDatabaseFunction1);
|
||||||
TEST_CASE(symbolDatabaseFunction2);
|
TEST_CASE(symbolDatabaseFunction2);
|
||||||
TEST_CASE(symbolDatabaseNodeType1);
|
TEST_CASE(symbolDatabaseNodeType1);
|
||||||
|
|
||||||
|
TEST_CASE(valueFlow1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string parse(const char clang[]) {
|
std::string parse(const char clang[]) {
|
||||||
|
@ -586,6 +588,7 @@ private:
|
||||||
|
|
||||||
#define GET_SYMBOL_DB(clang) \
|
#define GET_SYMBOL_DB(clang) \
|
||||||
Settings settings; \
|
Settings settings; \
|
||||||
|
settings.platform(cppcheck::Platform::PlatformType::Unix64); \
|
||||||
Tokenizer tokenizer(&settings, this); \
|
Tokenizer tokenizer(&settings, this); \
|
||||||
std::istringstream istr(clang); \
|
std::istringstream istr(clang); \
|
||||||
clangimport::parseClangAstDump(&tokenizer, istr); \
|
clangimport::parseClangAstDump(&tokenizer, istr); \
|
||||||
|
@ -644,6 +647,22 @@ private:
|
||||||
ASSERT(!!tok->valueType());
|
ASSERT(!!tok->valueType());
|
||||||
ASSERT_EQUALS("signed long", tok->valueType()->str());
|
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)
|
REGISTER_TEST(TestClangImport)
|
||||||
|
|
Loading…
Reference in New Issue