Clang import: Better type handling

This commit is contained in:
Daniel Marjamäki 2020-11-03 21:37:28 +01:00
parent eece8ee66b
commit 198bbc8a5a
3 changed files with 34 additions and 10 deletions

View File

@ -267,7 +267,7 @@ namespace clangimport {
private:
Token *createTokens(TokenList *tokenList);
Token *addtoken(TokenList *tokenList, const std::string &str, bool valueType=true);
void addTypeTokens(TokenList *tokenList, const std::string &str);
const ::Type *addTypeTokens(TokenList *tokenList, const std::string &str, const Scope *scope = nullptr);
Scope *createScope(TokenList *tokenList, Scope::ScopeType scopeType, AstNodePtr astNode, const Token *def);
Scope *createScope(TokenList *tokenList, Scope::ScopeType scopeType, const std::vector<AstNodePtr> &children, const Token *def);
Token *createTokensCall(TokenList *tokenList);
@ -430,11 +430,10 @@ Token *clangimport::AstNode::addtoken(TokenList *tokenList, const std::string &s
return tokenList->back();
}
void clangimport::AstNode::addTypeTokens(TokenList *tokenList, const std::string &str)
const ::Type * clangimport::AstNode::addTypeTokens(TokenList *tokenList, const std::string &str, const Scope *scope)
{
if (str.find("\':\'") != std::string::npos) {
addTypeTokens(tokenList, str.substr(0, str.find("\':\'") + 1));
return;
return addTypeTokens(tokenList, str.substr(0, str.find("\':\'") + 1), scope);
}
std::string type;
@ -448,6 +447,23 @@ void clangimport::AstNode::addTypeTokens(TokenList *tokenList, const std::string
for (const std::string &s: splitString(type))
addtoken(tokenList, s, false);
// Set Type
if (!scope) {
scope = tokenList->back() ? tokenList->back()->scope() : nullptr;
if (!scope)
return nullptr;
}
for (const Token *typeToken = tokenList->back(); Token::Match(typeToken, "&|*|%name%"); typeToken = typeToken->previous()) {
if (!typeToken->isName())
continue;
const ::Type *recordType = scope->findType(typeToken->str());
if (recordType) {
const_cast<Token*>(typeToken)->type(recordType);
return recordType;
}
}
return nullptr;
}
const Scope *clangimport::AstNode::getNestedInScope(TokenList *tokenList)
@ -469,7 +485,7 @@ void clangimport::AstNode::setValueType(Token *tok)
continue;
TokenList decl(nullptr);
addTypeTokens(&decl, type);
addTypeTokens(&decl, type, tok->scope());
if (!decl.front())
break;
@ -965,8 +981,10 @@ Token *clangimport::AstNode::createTokens(TokenList *tokenList)
Scope *recordScope = createScope(tokenList, Scope::ScopeType::eStruct, children, classDef);
mData->mSymbolDatabase->typeList.push_back(Type(classDef, recordScope, classDef->scope()));
recordScope->definedType = &mData->mSymbolDatabase->typeList.back();
if (!recordName.empty())
if (!recordName.empty()) {
recordScope->className = recordName;
const_cast<Scope *>(classDef->scope())->definedTypesMap[recordName] = recordScope->definedType;
}
return nullptr;
}
@ -1145,14 +1163,14 @@ void clangimport::AstNode::createTokensFunctionDecl(TokenList *tokenList)
continue;
if (tokenList->back() != par1)
addtoken(tokenList, ",");
addTypeTokens(tokenList, child->mExtTokens.back());
const Type *recordType = addTypeTokens(tokenList, child->mExtTokens.back(), nestedIn);
const Token *typeEndToken = tokenList->back();
const std::string spelling = child->getSpelling();
Token *vartok = nullptr;
if (!spelling.empty())
vartok = child->addtoken(tokenList, spelling);
if (!prev) {
function->argumentList.push_back(Variable(vartok, child->getType(), nullptr, typeEndToken, i, AccessControl::Argument, nullptr, scope));
function->argumentList.push_back(Variable(vartok, child->getType(), nullptr, typeEndToken, i, AccessControl::Argument, recordType, scope));
if (vartok) {
const std::string addr = child->mExtTokens[0];
mData->varDecl(addr, vartok, &function->argumentList.back());
@ -1218,6 +1236,7 @@ void clangimport::AstNode::createTokensForCXXRecord(TokenList *tokenList)
scope->className = className;
mData->mSymbolDatabase->typeList.push_back(Type(classToken, scope, classToken->scope()));
scope->definedType = &mData->mSymbolDatabase->typeList.back();
const_cast<Scope *>(classToken->scope())->definedTypesMap[className] = scope->definedType;
}
addtoken(tokenList, ";");
const_cast<Token *>(tokenList->back())->scope(classToken->scope());
@ -1234,7 +1253,7 @@ Token * clangimport::AstNode::createTokensVarDecl(TokenList *tokenList)
typeIndex--;
const std::string type = mExtTokens[typeIndex];
const std::string name = mExtTokens[typeIndex - 1];
addTypeTokens(tokenList, type);
const ::Type *recordType = addTypeTokens(tokenList, type);
if (!startToken && tokenList->back()) {
startToken = tokenList->back();
while (Token::Match(startToken->previous(), "%type%|*|&|&&"))
@ -1242,7 +1261,7 @@ Token * clangimport::AstNode::createTokensVarDecl(TokenList *tokenList)
}
Token *vartok1 = addtoken(tokenList, name);
Scope *scope = const_cast<Scope *>(tokenList->back()->scope());
scope->varlist.push_back(Variable(vartok1, type, startToken, vartok1->previous(), 0, scope->defaultAccess(), nullptr, scope));
scope->varlist.push_back(Variable(vartok1, type, startToken, vartok1->previous(), 0, scope->defaultAccess(), recordType, scope));
mData->varDecl(addr, vartok1, &scope->varlist.back());
if (mExtTokens.back() == "cinit" && !children.empty()) {
Token *eq = addtoken(tokenList, "=");

View File

@ -1840,6 +1840,8 @@ Variable::Variable(const Token *name_, const std::string &clangType, const Token
mTypeStartToken = mTypeStartToken->previous();
if (mTypeStartToken->str() == "const")
mTypeStartToken = mTypeStartToken->next();
if (mTypeStartToken->str() == "struct")
mTypeStartToken = mTypeStartToken->next();
}
if (Token::simpleMatch(mTypeStartToken, "static"))
setFlag(fIsStatic, true);

View File

@ -99,6 +99,9 @@ def test_symbol_database_5():
def test_symbol_database_6():
check_symbol_database('inline static int foo(int x) { return x; }')
def test_symbol_database_7():
check_symbol_database('struct S {int x;}; void f(struct S *s) {}')
def test_symbol_database_operator():
check_symbol_database('struct Fred { void operator=(int x); };')