Clang Import; VarDecl
This commit is contained in:
parent
00c05ce626
commit
8ea22edb4e
|
@ -35,6 +35,7 @@ static const std::string IntegerLiteral = "IntegerLiteral";
|
||||||
static const std::string ParmVarDecl = "ParmVarDecl";
|
static const std::string ParmVarDecl = "ParmVarDecl";
|
||||||
static const std::string ReturnStmt = "ReturnStmt";
|
static const std::string ReturnStmt = "ReturnStmt";
|
||||||
static const std::string UnaryOperator = "UnaryOperator";
|
static const std::string UnaryOperator = "UnaryOperator";
|
||||||
|
static const std::string VarDecl = "VarDecl";
|
||||||
|
|
||||||
static std::string unquote(const std::string &s)
|
static std::string unquote(const std::string &s)
|
||||||
{
|
{
|
||||||
|
@ -63,14 +64,49 @@ static std::vector<std::string> splitString(const std::string &line)
|
||||||
|
|
||||||
namespace clangastdump {
|
namespace clangastdump {
|
||||||
struct Data {
|
struct Data {
|
||||||
std::map<std::string, int> varId;
|
struct Decl {
|
||||||
std::map<std::string, Variable *> variableMap;
|
Decl(Token *def, Variable *var) : def(def), var(var) {}
|
||||||
|
Token *def;
|
||||||
|
Variable *var;
|
||||||
|
};
|
||||||
|
|
||||||
|
SymbolDatabase *mSymbolDatabase = nullptr;
|
||||||
|
|
||||||
|
void varDecl(const std::string &addr, Token *def, Variable *var) {
|
||||||
|
Decl decl(def, var);
|
||||||
|
mDeclMap.insert(std::pair<std::string, Decl>(addr, decl));
|
||||||
|
def->varId(++mVarId);
|
||||||
|
def->variable(var);
|
||||||
|
var->setValueType(ValueType(ValueType::Sign::SIGNED, ValueType::Type::INT, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ref(const std::string &addr, Token *tok) {
|
||||||
|
auto it = mDeclMap.find(addr);
|
||||||
|
if (it != mDeclMap.end()) {
|
||||||
|
tok->varId(it->second.var->declarationId());
|
||||||
|
tok->variable(it->second.var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<const Variable *> getVariableList() const {
|
||||||
|
std::vector<const Variable *> ret;
|
||||||
|
ret.resize(mVarId + 1, nullptr);
|
||||||
|
for (auto it: mDeclMap) {
|
||||||
|
if (it.second.var)
|
||||||
|
ret[it.second.var->declarationId()] = it.second.var;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<std::string, Decl> mDeclMap;
|
||||||
|
int mVarId = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AstNode {
|
class AstNode {
|
||||||
public:
|
public:
|
||||||
AstNode(const std::string &nodeType, const std::string &ext, Data *data, SymbolDatabase *symbolDatabase)
|
AstNode(const std::string &nodeType, const std::string &ext, Data *data)
|
||||||
: nodeType(nodeType), mExtTokens(splitString(ext)), mData(data), mSymbolDatabase(symbolDatabase)
|
: nodeType(nodeType), mExtTokens(splitString(ext)), mData(data)
|
||||||
{}
|
{}
|
||||||
std::string nodeType;
|
std::string nodeType;
|
||||||
std::vector<std::shared_ptr<AstNode>> children;
|
std::vector<std::shared_ptr<AstNode>> children;
|
||||||
|
@ -92,7 +128,6 @@ namespace clangastdump {
|
||||||
int mVarId = 0;
|
int mVarId = 0;
|
||||||
std::vector<std::string> mExtTokens;
|
std::vector<std::string> mExtTokens;
|
||||||
Data *mData;
|
Data *mData;
|
||||||
SymbolDatabase *mSymbolDatabase;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<AstNode> AstNodePtr;
|
typedef std::shared_ptr<AstNode> AstNodePtr;
|
||||||
|
@ -152,7 +187,9 @@ Token *clangastdump::AstNode::addtoken(TokenList *tokenList, const std::string &
|
||||||
{
|
{
|
||||||
const Scope *scope;
|
const Scope *scope;
|
||||||
if (!tokenList->back())
|
if (!tokenList->back())
|
||||||
scope = &mSymbolDatabase->scopeList.front();
|
scope = &mData->mSymbolDatabase->scopeList.front();
|
||||||
|
else if (tokenList->back()->str() == "}")
|
||||||
|
scope = tokenList->back()->scope()->nestedIn;
|
||||||
else
|
else
|
||||||
scope = tokenList->back()->scope();
|
scope = tokenList->back()->scope();
|
||||||
tokenList->addtoken(str, mLine, mFile);
|
tokenList->addtoken(str, mLine, mFile);
|
||||||
|
@ -172,15 +209,17 @@ Token *clangastdump::AstNode::addTypeTokens(TokenList *tokenList, const std::str
|
||||||
|
|
||||||
Scope *clangastdump::AstNode::createScope(TokenList *tokenList, Scope::ScopeType scopeType, AstNode *astNode)
|
Scope *clangastdump::AstNode::createScope(TokenList *tokenList, Scope::ScopeType scopeType, AstNode *astNode)
|
||||||
{
|
{
|
||||||
|
SymbolDatabase *symbolDatabase = mData->mSymbolDatabase;
|
||||||
|
|
||||||
const Scope *nestedIn;
|
const Scope *nestedIn;
|
||||||
if (!tokenList->back())
|
if (!tokenList->back())
|
||||||
nestedIn = &mSymbolDatabase->scopeList.front();
|
nestedIn = &symbolDatabase->scopeList.front();
|
||||||
else if (tokenList->back()->str() == "}")
|
else if (tokenList->back()->str() == "}")
|
||||||
nestedIn = tokenList->back()->link()->previous()->scope();
|
nestedIn = tokenList->back()->link()->previous()->scope();
|
||||||
else
|
else
|
||||||
nestedIn = tokenList->back()->scope();
|
nestedIn = tokenList->back()->scope();
|
||||||
mSymbolDatabase->scopeList.push_back(Scope(nullptr, nullptr, nestedIn));
|
symbolDatabase->scopeList.push_back(Scope(nullptr, nullptr, nestedIn));
|
||||||
Scope *scope = &mSymbolDatabase->scopeList.back();
|
Scope *scope = &symbolDatabase->scopeList.back();
|
||||||
scope->type = scopeType;
|
scope->type = scopeType;
|
||||||
Token *bodyStart = addtoken(tokenList, "{");
|
Token *bodyStart = addtoken(tokenList, "{");
|
||||||
tokenList->back()->scope(scope);
|
tokenList->back()->scope(scope);
|
||||||
|
@ -231,21 +270,19 @@ Token *clangastdump::AstNode::createTokens(TokenList *tokenList)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (nodeType == DeclRefExpr) {
|
if (nodeType == DeclRefExpr) {
|
||||||
Token *vartok = addtoken(tokenList, unquote(mExtTokens[mExtTokens.size() - 2]));
|
const std::string addr = mExtTokens[mExtTokens.size() - 3];
|
||||||
std::string addr = mExtTokens[mExtTokens.size() - 3];
|
Token *reftok = addtoken(tokenList, unquote(mExtTokens[mExtTokens.size() - 2]));
|
||||||
if (mData->varId.find(addr) != mData->varId.end()) {
|
mData->ref(addr, reftok);
|
||||||
vartok->varId(mData->varId[addr]);
|
return reftok;
|
||||||
vartok->variable(mData->variableMap[addr]);
|
|
||||||
}
|
|
||||||
return vartok;
|
|
||||||
}
|
}
|
||||||
if (nodeType == FunctionDecl) {
|
if (nodeType == FunctionDecl) {
|
||||||
|
SymbolDatabase *symbolDatabase = mData->mSymbolDatabase;
|
||||||
addTypeTokens(tokenList, mExtTokens.back());
|
addTypeTokens(tokenList, mExtTokens.back());
|
||||||
Token *nameToken = addtoken(tokenList, mExtTokens[mExtTokens.size() - 2]);
|
Token *nameToken = addtoken(tokenList, mExtTokens[mExtTokens.size() - 2]);
|
||||||
Scope &globalScope = mSymbolDatabase->scopeList.front();
|
Scope &globalScope = symbolDatabase->scopeList.front();
|
||||||
mSymbolDatabase->scopeList.push_back(Scope(nullptr, nullptr, &globalScope));
|
symbolDatabase->scopeList.push_back(Scope(nullptr, nullptr, &globalScope));
|
||||||
Scope &scope = mSymbolDatabase->scopeList.back();
|
Scope &scope = symbolDatabase->scopeList.back();
|
||||||
mSymbolDatabase->functionScopes.push_back(&scope);
|
symbolDatabase->functionScopes.push_back(&scope);
|
||||||
globalScope.functionList.push_back(Function(nameToken));
|
globalScope.functionList.push_back(Function(nameToken));
|
||||||
scope.function = &globalScope.functionList.back();
|
scope.function = &globalScope.functionList.back();
|
||||||
scope.type = Scope::ScopeType::eFunction;
|
scope.type = Scope::ScopeType::eFunction;
|
||||||
|
@ -260,16 +297,10 @@ Token *clangastdump::AstNode::createTokens(TokenList *tokenList)
|
||||||
addTypeTokens(tokenList, child->mExtTokens.back());
|
addTypeTokens(tokenList, child->mExtTokens.back());
|
||||||
const std::string spelling = child->getSpelling();
|
const std::string spelling = child->getSpelling();
|
||||||
if (!spelling.empty()) {
|
if (!spelling.empty()) {
|
||||||
|
const std::string addr = child->mExtTokens[0];
|
||||||
Token *vartok = addtoken(tokenList, spelling);
|
Token *vartok = addtoken(tokenList, spelling);
|
||||||
std::string addr = child->mExtTokens[0];
|
scope.function->argumentList.push_back(Variable(vartok, nullptr, nullptr, 0, AccessControl::Argument, nullptr, &scope, nullptr));
|
||||||
int varId = mData->varId.size() + 1;
|
mData->varDecl(addr, vartok, &scope.function->argumentList.back());
|
||||||
mData->varId[addr] = varId;
|
|
||||||
vartok->varId(varId);
|
|
||||||
scope.function->argumentList.push_back(Variable(vartok, nullptr, nullptr, varId, AccessControl::Argument, nullptr, nullptr, nullptr));
|
|
||||||
Variable *var = &scope.function->argumentList.back();
|
|
||||||
mData->variableMap[addr] = var;
|
|
||||||
vartok->variable(var);
|
|
||||||
var->setValueType(ValueType(ValueType::Sign::SIGNED, ValueType::Type::INT, 0));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Token *par2 = addtoken(tokenList, ")");
|
Token *par2 = addtoken(tokenList, ")");
|
||||||
|
@ -315,19 +346,41 @@ Token *clangastdump::AstNode::createTokens(TokenList *tokenList)
|
||||||
unop->astOperand1(children[0]->createTokens(tokenList));
|
unop->astOperand1(children[0]->createTokens(tokenList));
|
||||||
return unop;
|
return unop;
|
||||||
}
|
}
|
||||||
|
if (nodeType == VarDecl) {
|
||||||
|
bool isInit = mExtTokens.back() == "cinit";
|
||||||
|
const std::string addr = mExtTokens.front();
|
||||||
|
const std::string type = isInit ? mExtTokens[mExtTokens.size() - 2] : mExtTokens.back();
|
||||||
|
const std::string name = isInit ? mExtTokens[mExtTokens.size() - 3] : mExtTokens[mExtTokens.size() - 2];
|
||||||
|
addTypeTokens(tokenList, type);
|
||||||
|
Token *vartok1 = addtoken(tokenList, name);
|
||||||
|
Scope *scope = const_cast<Scope *>(tokenList->back()->scope());
|
||||||
|
const AccessControl accessControl = (scope->type == Scope::ScopeType::eGlobal) ? (AccessControl::Global) : (AccessControl::Local);
|
||||||
|
scope->varlist.push_back(Variable(vartok1, nullptr, nullptr, 0, accessControl, nullptr, scope, nullptr));
|
||||||
|
mData->varDecl(addr, vartok1, &scope->varlist.back());
|
||||||
|
addtoken(tokenList, ";");
|
||||||
|
if (isInit) {
|
||||||
|
Token *vartok2 = addtoken(tokenList, name);
|
||||||
|
mData->ref(addr, vartok2);
|
||||||
|
Token *eq = addtoken(tokenList, "=");
|
||||||
|
eq->astOperand1(vartok2);
|
||||||
|
eq->astOperand2(children.back()->createTokens(tokenList));
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
return addtoken(tokenList, "?" + nodeType + "?");
|
return addtoken(tokenList, "?" + nodeType + "?");
|
||||||
}
|
}
|
||||||
|
|
||||||
void clangastdump::parseClangAstDump(Tokenizer *tokenizer, std::istream &f)
|
void clangastdump::parseClangAstDump(Tokenizer *tokenizer, std::istream &f)
|
||||||
{
|
{
|
||||||
TokenList *tokenList = &tokenizer->list;
|
TokenList *tokenList = &tokenizer->list;
|
||||||
clangastdump::Data data;
|
|
||||||
|
|
||||||
tokenizer->createSymbolDatabase();
|
tokenizer->createSymbolDatabase();
|
||||||
SymbolDatabase *symbolDatabase = const_cast<SymbolDatabase *>(tokenizer->getSymbolDatabase());
|
SymbolDatabase *symbolDatabase = const_cast<SymbolDatabase *>(tokenizer->getSymbolDatabase());
|
||||||
symbolDatabase->scopeList.push_back(Scope(nullptr, nullptr, nullptr));
|
symbolDatabase->scopeList.push_back(Scope(nullptr, nullptr, nullptr));
|
||||||
symbolDatabase->scopeList.back().type = Scope::ScopeType::eGlobal;
|
symbolDatabase->scopeList.back().type = Scope::ScopeType::eGlobal;
|
||||||
|
|
||||||
|
clangastdump::Data data;
|
||||||
|
data.mSymbolDatabase = symbolDatabase;
|
||||||
std::string line;
|
std::string line;
|
||||||
std::vector<AstNodePtr> tree;
|
std::vector<AstNodePtr> tree;
|
||||||
while (std::getline(f,line)) {
|
while (std::getline(f,line)) {
|
||||||
|
@ -345,13 +398,13 @@ void clangastdump::parseClangAstDump(Tokenizer *tokenizer, std::istream &f)
|
||||||
const std::string nodeType = line.substr(pos1+1, pos2 - pos1 - 1);
|
const std::string nodeType = line.substr(pos1+1, pos2 - pos1 - 1);
|
||||||
const std::string ext = line.substr(pos2);
|
const std::string ext = line.substr(pos2);
|
||||||
|
|
||||||
if (nodeType == FunctionDecl) {
|
if (pos1 == 1 && (nodeType == FunctionDecl || nodeType == VarDecl)) {
|
||||||
if (!tree.empty()) {
|
if (!tree.empty()) {
|
||||||
tree[0]->setLocations(tokenList, 0, 1, 1);
|
tree[0]->setLocations(tokenList, 0, 1, 1);
|
||||||
tree[0]->createTokens(tokenList);
|
tree[0]->createTokens(tokenList);
|
||||||
}
|
}
|
||||||
tree.clear();
|
tree.clear();
|
||||||
tree.push_back(std::make_shared<AstNode>(nodeType, ext, &data, symbolDatabase));
|
tree.push_back(std::make_shared<AstNode>(nodeType, ext, &data));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,7 +412,7 @@ void clangastdump::parseClangAstDump(Tokenizer *tokenizer, std::istream &f)
|
||||||
if (level == 0 || tree.empty())
|
if (level == 0 || tree.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
AstNodePtr newNode = std::make_shared<AstNode>(nodeType, ext, &data, symbolDatabase);
|
AstNodePtr newNode = std::make_shared<AstNode>(nodeType, ext, &data);
|
||||||
tree[level - 1]->children.push_back(newNode);
|
tree[level - 1]->children.push_back(newNode);
|
||||||
if (level >= tree.size())
|
if (level >= tree.size())
|
||||||
tree.push_back(newNode);
|
tree.push_back(newNode);
|
||||||
|
@ -372,7 +425,7 @@ void clangastdump::parseClangAstDump(Tokenizer *tokenizer, std::istream &f)
|
||||||
tree[0]->createTokens(tokenList);
|
tree[0]->createTokens(tokenList);
|
||||||
}
|
}
|
||||||
|
|
||||||
symbolDatabase->clangSetVariables(data.variableMap);
|
symbolDatabase->clangSetVariables(data.getVariableList());
|
||||||
tokenList->clangSetOrigFiles();
|
tokenList->clangSetOrigFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1718,11 +1718,9 @@ void SymbolDatabase::validate() const
|
||||||
//validateVariables();
|
//validateVariables();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolDatabase::clangSetVariables(const std::map<std::string, Variable *> &variableMap)
|
void SymbolDatabase::clangSetVariables(const std::vector<const Variable *> &variableList)
|
||||||
{
|
{
|
||||||
mVariableList.resize(variableMap.size() + 1);
|
mVariableList = variableList;
|
||||||
for (std::map<std::string, Variable *>::const_iterator it = variableMap.begin(); it != variableMap.end(); ++it)
|
|
||||||
mVariableList[it->second->declarationId()] = it->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable::~Variable()
|
Variable::~Variable()
|
||||||
|
|
|
@ -1305,7 +1305,7 @@ public:
|
||||||
/** Set array dimensions when valueflow analysis is completed */
|
/** Set array dimensions when valueflow analysis is completed */
|
||||||
void setArrayDimensionsUsingValueFlow();
|
void setArrayDimensionsUsingValueFlow();
|
||||||
|
|
||||||
void clangSetVariables(const std::map<std::string, Variable *> &variableMap);
|
void clangSetVariables(const std::vector<const Variable *> &variableMap);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class Scope;
|
friend class Scope;
|
||||||
|
|
Loading…
Reference in New Issue