cppcheck/lib/clangimport.cpp

1515 lines
58 KiB
C++
Raw Normal View History

2020-01-05 15:12:53 +01:00
/*
* Cppcheck - A tool for static C/C++ code analysis
2020-05-10 11:16:32 +02:00
* Copyright (C) 2007-2020 Cppcheck team.
2020-01-05 15:12:53 +01:00
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
2020-01-10 16:29:06 +01:00
#include "clangimport.h"
2020-01-08 09:51:35 +01:00
#include "settings.h"
2020-01-05 15:12:53 +01:00
#include "symboldatabase.h"
#include "tokenize.h"
2020-01-07 18:33:24 +01:00
#include "utils.h"
2020-01-05 15:12:53 +01:00
#include <algorithm>
2020-01-05 15:12:53 +01:00
#include <memory>
#include <vector>
#include <iostream>
2020-11-08 17:02:19 +01:00
static const std::string AccessSpecDecl = "AccessSpecDecl";
2020-01-07 12:19:06 +01:00
static const std::string ArraySubscriptExpr = "ArraySubscriptExpr";
2020-01-05 15:12:53 +01:00
static const std::string BinaryOperator = "BinaryOperator";
2020-01-08 12:29:54 +01:00
static const std::string BreakStmt = "BreakStmt";
2020-01-05 15:12:53 +01:00
static const std::string CallExpr = "CallExpr";
2020-01-20 17:38:33 +01:00
static const std::string CaseStmt = "CaseStmt";
2020-01-09 16:54:45 +01:00
static const std::string CharacterLiteral = "CharacterLiteral";
2020-01-08 21:31:06 +01:00
static const std::string ClassTemplateDecl = "ClassTemplateDecl";
static const std::string ClassTemplateSpecializationDecl = "ClassTemplateSpecializationDecl";
2020-01-21 07:00:03 +01:00
static const std::string ConditionalOperator = "ConditionalOperator";
2020-01-25 17:22:22 +01:00
static const std::string ConstantExpr = "ConstantExpr";
2020-01-12 18:41:46 +01:00
static const std::string CompoundAssignOperator = "CompoundAssignOperator";
2020-01-05 15:12:53 +01:00
static const std::string CompoundStmt = "CompoundStmt";
2020-01-08 12:29:54 +01:00
static const std::string ContinueStmt = "ContinueStmt";
2020-01-10 16:19:01 +01:00
static const std::string CStyleCastExpr = "CStyleCastExpr";
static const std::string CXXBindTemporaryExpr = "CXXBindTemporaryExpr";
2020-01-09 16:19:23 +01:00
static const std::string CXXBoolLiteralExpr = "CXXBoolLiteralExpr";
static const std::string CXXConstructorDecl = "CXXConstructorDecl";
2020-01-10 18:54:28 +01:00
static const std::string CXXConstructExpr = "CXXConstructExpr";
2020-01-21 06:52:45 +01:00
static const std::string CXXDefaultArgExpr = "CXXDefaultArgExpr";
2020-01-21 17:14:01 +01:00
static const std::string CXXDeleteExpr = "CXXDeleteExpr";
2020-04-12 17:27:32 +02:00
static const std::string CXXDestructorDecl = "CXXDestructorDecl";
2020-01-18 19:23:37 +01:00
static const std::string CXXForRangeStmt = "CXXForRangeStmt";
static const std::string CXXFunctionalCastExpr = "CXXFunctionalCastExpr";
2020-01-08 21:49:23 +01:00
static const std::string CXXMemberCallExpr = "CXXMemberCallExpr";
static const std::string CXXMethodDecl = "CXXMethodDecl";
2020-01-21 12:16:39 +01:00
static const std::string CXXNewExpr = "CXXNewExpr";
2020-01-10 19:01:33 +01:00
static const std::string CXXNullPtrLiteralExpr = "CXXNullPtrLiteralExpr";
2020-01-09 15:59:09 +01:00
static const std::string CXXOperatorCallExpr = "CXXOperatorCallExpr";
static const std::string CXXRecordDecl = "CXXRecordDecl";
2020-01-09 20:53:06 +01:00
static const std::string CXXStaticCastExpr = "CXXStaticCastExpr";
static const std::string CXXStdInitializerListExpr = "CXXStdInitializerListExpr";
static const std::string CXXTemporaryObjectExpr = "CXXTemporaryObjectExpr";
static const std::string CXXThisExpr = "CXXThisExpr";
2020-01-21 11:16:22 +01:00
static const std::string CXXThrowExpr = "CXXThrowExpr";
2020-01-05 15:12:53 +01:00
static const std::string DeclRefExpr = "DeclRefExpr";
2020-01-08 10:35:44 +01:00
static const std::string DeclStmt = "DeclStmt";
2020-10-29 09:48:35 +01:00
static const std::string DefaultStmt = "DefaultStmt";
2020-01-20 20:46:33 +01:00
static const std::string DoStmt = "DoStmt";
2020-01-23 16:06:25 +01:00
static const std::string EnumConstantDecl = "EnumConstantDecl";
static const std::string EnumDecl = "EnumDecl";
static const std::string ExprWithCleanups = "ExprWithCleanups";
2020-01-07 18:33:24 +01:00
static const std::string FieldDecl = "FieldDecl";
2020-01-20 14:09:21 +01:00
static const std::string FloatingLiteral = "FloatingLiteral";
2020-01-08 10:35:44 +01:00
static const std::string ForStmt = "ForStmt";
2020-01-05 15:12:53 +01:00
static const std::string FunctionDecl = "FunctionDecl";
2020-01-08 20:47:52 +01:00
static const std::string FunctionTemplateDecl = "FunctionTemplateDecl";
2020-01-20 19:07:10 +01:00
static const std::string GotoStmt = "GotoStmt";
2020-01-05 19:18:32 +01:00
static const std::string IfStmt = "IfStmt";
2020-01-05 15:12:53 +01:00
static const std::string ImplicitCastExpr = "ImplicitCastExpr";
2020-01-13 12:44:11 +01:00
static const std::string InitListExpr = "InitListExpr";
2020-01-05 15:12:53 +01:00
static const std::string IntegerLiteral = "IntegerLiteral";
2020-01-20 19:07:10 +01:00
static const std::string LabelStmt = "LabelStmt";
2020-11-24 19:34:37 +01:00
static const std::string LinkageSpecDecl = "LinkageSpecDecl";
2020-01-20 21:27:49 +01:00
static const std::string MaterializeTemporaryExpr = "MaterializeTemporaryExpr";
2020-01-08 09:51:35 +01:00
static const std::string MemberExpr = "MemberExpr";
static const std::string NamespaceDecl = "NamespaceDecl";
2020-01-08 12:19:48 +01:00
static const std::string NullStmt = "NullStmt";
2020-01-09 10:49:47 +01:00
static const std::string ParenExpr = "ParenExpr";
2020-01-05 15:12:53 +01:00
static const std::string ParmVarDecl = "ParmVarDecl";
2020-01-07 18:33:24 +01:00
static const std::string RecordDecl = "RecordDecl";
2020-01-05 15:12:53 +01:00
static const std::string ReturnStmt = "ReturnStmt";
static const std::string StringLiteral = "StringLiteral";
2020-01-20 14:23:43 +01:00
static const std::string SwitchStmt = "SwitchStmt";
2020-01-08 20:47:52 +01:00
static const std::string TemplateArgument = "TemplateArgument";
2020-01-08 14:25:09 +01:00
static const std::string TypedefDecl = "TypedefDecl";
2020-01-05 15:12:53 +01:00
static const std::string UnaryOperator = "UnaryOperator";
2020-01-09 17:31:46 +01:00
static const std::string UnaryExprOrTypeTraitExpr = "UnaryExprOrTypeTraitExpr";
2020-01-06 13:47:19 +01:00
static const std::string VarDecl = "VarDecl";
2020-01-08 12:19:48 +01:00
static const std::string WhileStmt = "WhileStmt";
2020-01-05 15:12:53 +01:00
static std::string unquote(const std::string &s)
{
return (s[0] == '\'') ? s.substr(1, s.size() - 2) : s;
}
2020-01-05 15:12:53 +01:00
static std::vector<std::string> splitString(const std::string &line)
{
std::vector<std::string> ret;
std::string::size_type pos1 = line.find_first_not_of(" ");
while (pos1 < line.size()) {
2020-01-05 15:12:53 +01:00
std::string::size_type pos2;
if (line[pos1] == '*') {
ret.push_back("*");
pos1 = line.find_first_not_of(" ", pos1 + 1);
continue;
}
2020-01-05 15:12:53 +01:00
if (line[pos1] == '<')
pos2 = line.find(">", pos1);
else if (line[pos1] == '\"')
pos2 = line.find("\"", pos1+1);
2020-01-08 09:51:35 +01:00
else if (line[pos1] == '\'') {
2020-01-05 15:12:53 +01:00
pos2 = line.find("\'", pos1+1);
2020-01-09 14:13:39 +01:00
if (pos2 < (int)line.size() - 3 && line.compare(pos2, 3, "\':\'", 0, 3) == 0)
2020-01-08 09:51:35 +01:00
pos2 = line.find("\'", pos2 + 3);
2020-01-10 11:04:37 +01:00
} else {
pos2 = pos1;
while (pos2 < line.size() && (line[pos2] == '_' || line[pos2] == ':' || std::isalnum((unsigned char)line[pos2])))
++pos2;
if (pos2 > pos1 && pos2 < line.size() && line[pos2] == '<' && std::isalpha(line[pos1])) {
int tlevel = 1;
while (++pos2 < line.size() && tlevel > 0) {
if (line[pos2] == '<')
++tlevel;
else if (line[pos2] == '>')
--tlevel;
}
if (tlevel == 0 && pos2 < line.size() && line[pos2] == ' ') {
ret.push_back(line.substr(pos1, pos2-pos1));
pos1 = pos2 + 1;
continue;
}
}
2020-01-05 15:12:53 +01:00
pos2 = line.find(" ", pos1) - 1;
if ((std::isalpha(line[pos1]) || line[pos1] == '_') &&
line.find("::", pos1) < pos2 &&
line.find("::", pos1) < line.find("<", pos1)) {
pos2 = line.find("::", pos1);
ret.push_back(line.substr(pos1, pos2-pos1));
ret.push_back("::");
pos1 = pos2 + 2;
continue;
}
if ((std::isalpha(line[pos1]) || line[pos1] == '_') &&
2020-01-10 11:40:28 +01:00
line.find("<", pos1) < pos2 &&
line.find("<<",pos1) != line.find("<",pos1) &&
line.find(">", pos1) != std::string::npos &&
line.find(">", pos1) > pos2) {
2020-01-10 11:04:37 +01:00
int level = 0;
for (pos2 = pos1; pos2 < line.size(); ++pos2) {
if (line[pos2] == '<')
++level;
else if (line[pos2] == '>') {
if (level <= 1)
break;
--level;
}
}
if (level > 1 && pos2 + 1 >= line.size())
2020-01-10 11:04:37 +01:00
return std::vector<std::string> {};
pos2 = line.find(" ", pos2);
if (pos2 != std::string::npos)
--pos2;
}
}
if (pos2 == std::string::npos) {
ret.push_back(line.substr(pos1));
2020-01-05 15:12:53 +01:00
break;
}
ret.push_back(line.substr(pos1, pos2+1-pos1));
2020-01-05 15:12:53 +01:00
pos1 = line.find_first_not_of(" ", pos2 + 1);
}
return ret;
}
2020-11-08 17:02:19 +01:00
static bool contains(const std::vector<std::string> &haystack, const std::string &needle)
{
return std::find(haystack.begin(), haystack.end(), needle) != haystack.end();
}
2020-01-10 16:29:06 +01:00
namespace clangimport {
2020-01-05 15:12:53 +01:00
struct Data {
2020-01-06 13:47:19 +01:00
struct Decl {
2020-11-08 10:57:48 +01:00
explicit Decl(Scope *scope) : def(nullptr), enumerator(nullptr), function(nullptr), scope(scope), var(nullptr) {}
2020-11-08 10:31:48 +01:00
Decl(Token *def, Variable *var) : def(def), enumerator(nullptr), function(nullptr), scope(nullptr), var(var) {}
Decl(Token *def, Function *function) : def(def), enumerator(nullptr), function(function), scope(nullptr), var(nullptr) {}
Decl(Token *def, Enumerator *enumerator) : def(def), enumerator(enumerator), function(nullptr), scope(nullptr), var(nullptr) {}
2020-01-06 15:26:21 +01:00
void ref(Token *tok) {
2020-01-26 07:32:14 +01:00
if (enumerator)
tok->enumerator(enumerator);
if (function)
tok->function(function);
2020-01-26 07:32:14 +01:00
if (var) {
tok->variable(var);
2020-01-26 07:32:14 +01:00
tok->varId(var->declarationId());
}
2020-01-06 15:26:21 +01:00
}
2020-01-06 13:47:19 +01:00
Token *def;
2020-01-26 07:32:14 +01:00
Enumerator *enumerator;
2020-01-06 15:26:21 +01:00
Function *function;
2020-11-08 10:31:48 +01:00
Scope *scope;
2020-01-06 13:47:19 +01:00
Variable *var;
};
const Settings *mSettings = nullptr;
2020-01-06 13:47:19 +01:00
SymbolDatabase *mSymbolDatabase = nullptr;
2020-01-26 07:32:14 +01:00
int enumValue = 0;
void enumDecl(const std::string &addr, Token *nameToken, Enumerator *enumerator) {
Decl decl(nameToken, enumerator);
2020-01-06 13:47:19 +01:00
mDeclMap.insert(std::pair<std::string, Decl>(addr, decl));
2020-01-26 07:32:14 +01:00
nameToken->enumerator(enumerator);
notFound(addr);
2020-01-06 13:47:19 +01:00
}
2020-01-06 15:26:21 +01:00
void funcDecl(const std::string &addr, Token *nameToken, Function *function) {
Decl decl(nameToken, function);
mDeclMap.insert(std::pair<std::string, Decl>(addr, decl));
nameToken->function(function);
notFound(addr);
2020-01-06 15:26:21 +01:00
}
2020-11-08 10:31:48 +01:00
void scopeDecl(const std::string &addr, Scope *scope) {
Decl decl(scope);
mDeclMap.insert(std::pair<std::string, Decl>(addr, decl));
}
2020-01-26 07:32:14 +01:00
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);
if (def->valueType())
var->setValueType(*def->valueType());
notFound(addr);
}
2020-01-06 13:47:19 +01:00
void ref(const std::string &addr, Token *tok) {
auto it = mDeclMap.find(addr);
2020-01-06 15:26:21 +01:00
if (it != mDeclMap.end())
it->second.ref(tok);
else
mNotFound[addr].push_back(tok);
2020-01-06 13:47:19 +01:00
}
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;
}
bool hasDecl(const std::string &addr) const {
return mDeclMap.find(addr) != mDeclMap.end();
}
2020-11-08 10:31:48 +01:00
const Scope *getScope(const std::string &addr) {
auto it = mDeclMap.find(addr);
return (it == mDeclMap.end() ? nullptr : it->second.scope);
}
// "}" tokens that are not end-of-scope
std::set<Token *> mNotScope;
2020-11-08 17:02:19 +01:00
std::map<const Scope *, AccessControl> scopeAccessControl;
2020-01-06 13:47:19 +01:00
private:
void notFound(const std::string &addr) {
auto it = mNotFound.find(addr);
if (it != mNotFound.end()) {
for (Token *reftok: it->second)
ref(addr, reftok);
mNotFound.erase(it);
}
}
2020-01-06 13:47:19 +01:00
std::map<std::string, Decl> mDeclMap;
std::map<std::string, std::vector<Token *>> mNotFound;
2020-01-06 13:47:19 +01:00
int mVarId = 0;
2020-01-05 15:12:53 +01:00
};
2020-01-07 19:47:06 +01:00
class AstNode;
typedef std::shared_ptr<AstNode> AstNodePtr;
2020-01-05 15:12:53 +01:00
class AstNode {
public:
2020-01-06 13:47:19 +01:00
AstNode(const std::string &nodeType, const std::string &ext, Data *data)
: nodeType(nodeType), mExtTokens(splitString(ext)), mData(data)
2020-01-05 15:12:53 +01:00
{}
std::string nodeType;
2020-01-07 19:47:06 +01:00
std::vector<AstNodePtr> children;
2020-01-05 15:12:53 +01:00
void setLocations(TokenList *tokenList, int file, int line, int col);
void dumpAst(int num = 0, int indent = 0) const;
2020-01-08 10:35:44 +01:00
void createTokens1(TokenList *tokenList) {
//dumpAst();
if (!tokenList->back())
setLocations(tokenList, 0, 1, 1);
else
setLocations(tokenList, tokenList->back()->fileIndex(), tokenList->back()->linenr(), 1);
2020-01-08 10:35:44 +01:00
createTokens(tokenList);
2020-01-08 14:25:09 +01:00
if (nodeType == VarDecl || nodeType == RecordDecl || nodeType == TypedefDecl)
2020-01-08 10:35:44 +01:00
addtoken(tokenList, ";");
mData->mNotScope.clear();
2020-01-08 10:35:44 +01:00
}
2020-01-05 15:12:53 +01:00
private:
2020-01-08 10:35:44 +01:00
Token *createTokens(TokenList *tokenList);
2020-01-10 12:13:50 +01:00
Token *addtoken(TokenList *tokenList, const std::string &str, bool valueType=true);
2020-11-03 21:37:28 +01:00
const ::Type *addTypeTokens(TokenList *tokenList, const std::string &str, const Scope *scope = nullptr);
2020-11-08 10:31:48 +01:00
void addFullScopeNameTokens(TokenList *tokenList, const Scope *recordScope);
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);
2020-01-08 21:49:23 +01:00
Token *createTokensCall(TokenList *tokenList);
void createTokensFunctionDecl(TokenList *tokenList);
2020-01-08 21:31:06 +01:00
void createTokensForCXXRecord(TokenList *tokenList);
2020-01-08 10:35:44 +01:00
Token *createTokensVarDecl(TokenList *tokenList);
2020-01-05 15:12:53 +01:00
std::string getSpelling() const;
2020-01-13 17:56:30 +01:00
std::string getType(int index = 0) const;
std::string getFullType(int index = 0) const;
bool isDefinition() const;
2020-01-08 21:31:06 +01:00
std::string getTemplateParameters() const;
2020-01-07 18:33:24 +01:00
const Scope *getNestedInScope(TokenList *tokenList);
2020-01-09 17:31:46 +01:00
void setValueType(Token *tok);
2020-01-05 15:12:53 +01:00
int mFile = 0;
int mLine = 1;
int mCol = 1;
std::vector<std::string> mExtTokens;
Data *mData;
};
}
2020-01-10 16:29:06 +01:00
std::string clangimport::AstNode::getSpelling() const
2020-01-05 15:12:53 +01:00
{
2020-01-12 18:41:46 +01:00
if (nodeType == CompoundAssignOperator) {
int typeIndex = 1;
while (typeIndex < mExtTokens.size() && mExtTokens[typeIndex][0] != '\'')
typeIndex++;
// name is next quoted token
2020-01-12 18:41:46 +01:00
int nameIndex = typeIndex + 1;
while (nameIndex < mExtTokens.size() && mExtTokens[nameIndex][0] != '\'')
nameIndex++;
return (nameIndex < mExtTokens.size()) ? unquote(mExtTokens[nameIndex]) : "";
}
if (nodeType == UnaryExprOrTypeTraitExpr) {
int typeIndex = 1;
while (typeIndex < mExtTokens.size() && mExtTokens[typeIndex][0] != '\'')
typeIndex++;
int nameIndex = typeIndex + 1;
return (nameIndex < mExtTokens.size()) ? unquote(mExtTokens[nameIndex]) : "";
}
2020-01-12 18:41:46 +01:00
int typeIndex = mExtTokens.size() - 1;
if (nodeType == FunctionDecl || nodeType == CXXConstructorDecl || nodeType == CXXMethodDecl) {
2020-01-19 09:45:47 +01:00
while (typeIndex >= 0 && mExtTokens[typeIndex][0] != '\'')
2020-01-12 18:41:46 +01:00
typeIndex--;
2020-01-19 09:45:47 +01:00
if (typeIndex <= 0)
return "";
}
2020-01-12 18:41:46 +01:00
const std::string &str = mExtTokens[typeIndex - 1];
if (str.compare(0,4,"col:") == 0)
return "";
if (str.compare(0,8,"<invalid") == 0)
2020-01-08 16:42:21 +01:00
return "";
return str;
2020-01-05 15:12:53 +01:00
}
2020-01-13 17:56:30 +01:00
std::string clangimport::AstNode::getType(int index) const
2020-01-05 15:12:53 +01:00
{
std::string type = getFullType(index);
if (type.find(" (") != std::string::npos) {
std::string::size_type pos = type.find(" (");
type[pos] = '\'';
type.erase(pos+1);
}
2020-01-11 16:49:30 +01:00
if (type.find(" *(") != std::string::npos) {
std::string::size_type pos = type.find(" *(") + 2;
type[pos] = '\'';
type.erase(pos+1);
}
if (type.find(" &(") != std::string::npos) {
std::string::size_type pos = type.find(" &(") + 2;
type[pos] = '\'';
type.erase(pos+1);
}
return unquote(type);
2020-01-05 15:12:53 +01:00
}
std::string clangimport::AstNode::getFullType(int index) const
{
int typeIndex = 1;
while (typeIndex < mExtTokens.size() && mExtTokens[typeIndex][0] != '\'')
typeIndex++;
if (typeIndex >= mExtTokens.size())
return "";
std::string type = mExtTokens[typeIndex];
if (type.find("\':\'") != std::string::npos) {
if (index == 0)
type.erase(type.find("\':\'") + 1);
else
type.erase(0, type.find("\':\'") + 2);
}
return type;
}
bool clangimport::AstNode::isDefinition() const
{
2020-11-08 17:02:19 +01:00
return contains(mExtTokens, "definition");
}
2020-01-10 16:29:06 +01:00
std::string clangimport::AstNode::getTemplateParameters() const
2020-01-08 21:31:06 +01:00
{
if (children.empty() || children[0]->nodeType != TemplateArgument)
return "";
std::string templateParameters;
for (AstNodePtr child: children) {
if (child->nodeType == TemplateArgument) {
if (templateParameters.empty())
templateParameters = "<";
else
templateParameters += ",";
templateParameters += unquote(child->mExtTokens.back());
}
}
return templateParameters + ">";
}
2020-01-10 16:29:06 +01:00
void clangimport::AstNode::dumpAst(int num, int indent) const
2020-01-05 15:12:53 +01:00
{
(void)num;
std::cout << std::string(indent, ' ') << nodeType;
for (auto tok: mExtTokens)
std::cout << " " << tok;
std::cout << std::endl;
2020-01-09 10:49:47 +01:00
for (int c = 0; c < children.size(); ++c) {
if (children[c])
children[c]->dumpAst(c, indent + 2);
else
std::cout << std::string(indent + 2, ' ') << "<<<<NULL>>>>>" << std::endl;
2020-01-09 10:49:47 +01:00
}
2020-01-05 15:12:53 +01:00
}
2020-01-10 16:29:06 +01:00
void clangimport::AstNode::setLocations(TokenList *tokenList, int file, int line, int col)
2020-01-05 15:12:53 +01:00
{
for (const std::string &ext: mExtTokens) {
if (ext.compare(0,5,"<col:") == 0)
col = std::atoi(ext.substr(5).c_str());
2020-01-06 09:05:39 +01:00
else if (ext.compare(0,6,"<line:") == 0) {
2020-01-05 15:12:53 +01:00
line = std::atoi(ext.substr(6).c_str());
2020-01-06 09:05:39 +01:00
if (ext.find(", col:") != std::string::npos)
col = std::atoi(ext.c_str() + ext.find(", col:") + 6);
2020-01-12 18:05:45 +01:00
} else if (ext[0] == '<' && ext.find(":") != std::string::npos) {
std::string::size_type sep1 = ext.find(":");
std::string::size_type sep2 = ext.find(":", sep1+1);
file = tokenList->appendFileIfNew(ext.substr(1, sep1 - 1));
line = MathLib::toLongNumber(ext.substr(sep1+1, sep2-sep1));
}
2020-01-05 15:12:53 +01:00
}
mFile = file;
mLine = line;
mCol = col;
2020-01-05 19:18:32 +01:00
for (auto child: children) {
if (child)
child->setLocations(tokenList, file, line, col);
}
2020-01-05 15:12:53 +01:00
}
2020-01-10 16:29:06 +01:00
Token *clangimport::AstNode::addtoken(TokenList *tokenList, const std::string &str, bool valueType)
2020-01-05 15:12:53 +01:00
{
2020-01-07 18:33:24 +01:00
const Scope *scope = getNestedInScope(tokenList);
2020-01-05 15:12:53 +01:00
tokenList->addtoken(str, mLine, mFile);
2020-01-06 09:05:39 +01:00
tokenList->back()->column(mCol);
2020-01-05 19:18:32 +01:00
tokenList->back()->scope(scope);
2020-01-10 12:13:50 +01:00
if (valueType)
setValueType(tokenList->back());
2020-01-05 15:12:53 +01:00
return tokenList->back();
}
2020-11-03 21:37:28 +01:00
const ::Type * clangimport::AstNode::addTypeTokens(TokenList *tokenList, const std::string &str, const Scope *scope)
2020-01-05 15:12:53 +01:00
{
if (str.find("\':\'") != std::string::npos) {
2020-11-03 21:37:28 +01:00
return addTypeTokens(tokenList, str.substr(0, str.find("\':\'") + 1), scope);
}
2020-01-08 09:51:35 +01:00
std::string type;
if (str.find(" (") != std::string::npos) {
if (str.find("<") != std::string::npos)
type = str.substr(1, str.find("<")) + "...>";
else
type = str.substr(1,str.find(" (")-1);
} else
2020-01-08 09:51:35 +01:00
type = unquote(str);
2020-01-08 09:51:35 +01:00
for (const std::string &s: splitString(type))
2020-01-10 12:13:50 +01:00
addtoken(tokenList, s, false);
2020-11-03 21:37:28 +01:00
// 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->check->findVariableType(scope, typeToken);
2020-11-03 21:37:28 +01:00
if (recordType) {
const_cast<Token*>(typeToken)->type(recordType);
return recordType;
}
}
return nullptr;
2020-01-05 15:12:53 +01:00
}
2020-11-08 10:31:48 +01:00
void clangimport::AstNode::addFullScopeNameTokens(TokenList *tokenList, const Scope *recordScope)
{
if (!recordScope)
return;
std::list<const Scope *> scopes;
while (recordScope && recordScope != tokenList->back()->scope() && !recordScope->isExecutable()) {
scopes.push_front(recordScope);
recordScope = recordScope->nestedIn;
}
for (const Scope *s: scopes) {
if (!s->className.empty()) {
addtoken(tokenList, s->className);
addtoken(tokenList, "::");
}
}
}
2020-01-10 16:29:06 +01:00
const Scope *clangimport::AstNode::getNestedInScope(TokenList *tokenList)
2020-01-07 18:33:24 +01:00
{
if (!tokenList->back())
return &mData->mSymbolDatabase->scopeList.front();
if (tokenList->back()->str() == "}" && mData->mNotScope.find(tokenList->back()) == mData->mNotScope.end())
2020-01-07 18:33:24 +01:00
return tokenList->back()->scope()->nestedIn;
return tokenList->back()->scope();
}
2020-01-10 16:29:06 +01:00
void clangimport::AstNode::setValueType(Token *tok)
2020-01-09 17:31:46 +01:00
{
2020-01-13 17:56:30 +01:00
for (int i = 0; i < 2; i++) {
const std::string &type = getType(i);
2020-01-10 12:13:50 +01:00
2020-01-13 17:56:30 +01:00
if (type.find("<") != std::string::npos)
// TODO
continue;
2020-01-09 17:31:46 +01:00
2020-01-13 17:56:30 +01:00
TokenList decl(nullptr);
2020-11-03 21:37:28 +01:00
addTypeTokens(&decl, type, tok->scope());
2020-01-13 17:56:30 +01:00
if (!decl.front())
break;
2020-01-09 17:31:46 +01:00
2020-01-13 17:56:30 +01:00
ValueType valueType = ValueType::parseDecl(decl.front(), mData->mSettings);
if (valueType.type != ValueType::Type::UNKNOWN_TYPE) {
tok->setValueType(new ValueType(valueType));
break;
}
}
2020-01-09 17:31:46 +01:00
}
Scope *clangimport::AstNode::createScope(TokenList *tokenList, Scope::ScopeType scopeType, AstNodePtr astNode, const Token *def)
2020-01-07 19:47:06 +01:00
{
std::vector<AstNodePtr> children2{astNode};
return createScope(tokenList, scopeType, children2, def);
2020-01-07 19:47:06 +01:00
}
Scope *clangimport::AstNode::createScope(TokenList *tokenList, Scope::ScopeType scopeType, const std::vector<AstNodePtr> & children2, const Token *def)
2020-01-05 19:18:32 +01:00
{
2020-01-06 13:47:19 +01:00
SymbolDatabase *symbolDatabase = mData->mSymbolDatabase;
2020-01-25 09:31:47 +01:00
Scope *nestedIn = const_cast<Scope *>(getNestedInScope(tokenList));
2020-01-07 18:33:24 +01:00
2020-01-06 13:47:19 +01:00
symbolDatabase->scopeList.push_back(Scope(nullptr, nullptr, nestedIn));
Scope *scope = &symbolDatabase->scopeList.back();
2020-01-26 07:32:14 +01:00
if (scopeType == Scope::ScopeType::eEnum)
scope->enumeratorList.reserve(children2.size());
2020-01-25 09:31:47 +01:00
nestedIn->nestedList.push_back(scope);
2020-01-05 19:18:32 +01:00
scope->type = scopeType;
scope->classDef = def;
2020-01-25 11:58:40 +01:00
scope->check = nestedIn->check;
scope->bodyStart = addtoken(tokenList, "{");
2020-11-09 19:30:05 +01:00
mData->scopeAccessControl[scope] = scope->defaultAccess();
if (!children2.empty()) {
tokenList->back()->scope(scope);
for (AstNodePtr astNode: children2) {
2020-11-07 22:27:11 +01:00
if (astNode->nodeType == "VisibilityAttr")
continue;
2020-11-08 17:02:19 +01:00
if (astNode->nodeType == AccessSpecDecl) {
if (contains(astNode->mExtTokens, "private"))
mData->scopeAccessControl[scope] = AccessControl::Private;
else if (contains(astNode->mExtTokens, "protected"))
mData->scopeAccessControl[scope] = AccessControl::Protected;
else if (contains(astNode->mExtTokens, "public"))
mData->scopeAccessControl[scope] = AccessControl::Public;
continue;
}
astNode->createTokens(tokenList);
if (scopeType == Scope::ScopeType::eEnum)
astNode->addtoken(tokenList, ",");
else if (!Token::Match(tokenList->back(), "[;{}]"))
astNode->addtoken(tokenList, ";");
}
}
scope->bodyEnd = addtoken(tokenList, "}");
Token::createMutualLinks(const_cast<Token*>(scope->bodyStart), const_cast<Token*>(scope->bodyEnd));
2020-11-08 17:02:19 +01:00
mData->scopeAccessControl.erase(scope);
2020-01-05 19:18:32 +01:00
return scope;
}
2020-01-10 16:29:06 +01:00
Token *clangimport::AstNode::createTokens(TokenList *tokenList)
2020-01-05 15:12:53 +01:00
{
2020-01-07 12:19:06 +01:00
if (nodeType == ArraySubscriptExpr) {
Token *array = children[0]->createTokens(tokenList);
Token *bracket1 = addtoken(tokenList, "[");
Token *index = children[1]->createTokens(tokenList);
Token *bracket2 = addtoken(tokenList, "]");
bracket1->astOperand1(array);
bracket1->astOperand2(index);
bracket1->link(bracket2);
2020-01-09 12:42:29 +01:00
bracket2->link(bracket1);
2020-01-07 12:19:06 +01:00
return bracket1;
}
2020-01-05 15:12:53 +01:00
if (nodeType == BinaryOperator) {
Token *tok1 = children[0]->createTokens(tokenList);
Token *binop = addtoken(tokenList, unquote(mExtTokens.back()));
Token *tok2 = children[1]->createTokens(tokenList);
binop->astOperand1(tok1);
binop->astOperand2(tok2);
return binop;
}
2020-01-08 12:29:54 +01:00
if (nodeType == BreakStmt)
return addtoken(tokenList, "break");
2020-01-09 16:54:45 +01:00
if (nodeType == CharacterLiteral) {
int c = MathLib::toLongNumber(mExtTokens.back());
if (c == 0)
return addtoken(tokenList, "\'\\0\'");
if (c == '\r')
return addtoken(tokenList, "\'\\r\'");
if (c == '\n')
return addtoken(tokenList, "\'\\n\'");
if (c == '\t')
return addtoken(tokenList, "\'\\t\'");
2020-01-10 17:37:36 +01:00
if (c == '\\')
return addtoken(tokenList, "\'\\\\\'");
2020-01-09 16:54:45 +01:00
if (c < ' ' || c >= 0x80) {
std::ostringstream hex;
hex << std::hex << ((c>>4) & 0xf) << (c&0xf);
return addtoken(tokenList, "\'\\x" + hex.str() + "\'");
}
return addtoken(tokenList, std::string("\'") + char(c) + std::string("\'"));
}
2020-01-08 21:49:23 +01:00
if (nodeType == CallExpr)
return createTokensCall(tokenList);
2020-01-20 17:38:33 +01:00
if (nodeType == CaseStmt) {
Token *caseToken = addtoken(tokenList, "case");
Token *exprToken = children[0]->createTokens(tokenList);
caseToken->astOperand1(exprToken);
2020-01-20 17:38:33 +01:00
addtoken(tokenList, ":");
2020-01-25 17:22:22 +01:00
children.back()->createTokens(tokenList);
2020-01-20 17:38:33 +01:00
return nullptr;
}
2020-01-08 21:31:06 +01:00
if (nodeType == ClassTemplateDecl) {
for (AstNodePtr child: children) {
if (child->nodeType == ClassTemplateSpecializationDecl)
child->createTokens(tokenList);
}
return nullptr;
}
if (nodeType == ClassTemplateSpecializationDecl) {
createTokensForCXXRecord(tokenList);
return nullptr;
}
2020-01-21 07:00:03 +01:00
if (nodeType == ConditionalOperator) {
Token *expr1 = children[0]->createTokens(tokenList);
Token *tok1 = addtoken(tokenList, "?");
Token *expr2 = children[1]->createTokens(tokenList);
Token *tok2 = addtoken(tokenList, ":");
Token *expr3 = children[2]->createTokens(tokenList);
tok2->astOperand1(expr2);
2020-01-21 11:07:23 +01:00
tok2->astOperand2(expr3);
2020-01-21 07:00:03 +01:00
tok1->astOperand1(expr1);
tok1->astOperand2(tok2);
return tok1;
}
2020-01-12 18:41:46 +01:00
if (nodeType == CompoundAssignOperator) {
Token *lhs = children[0]->createTokens(tokenList);
Token *assign = addtoken(tokenList, getSpelling());
Token *rhs = children[1]->createTokens(tokenList);
assign->astOperand1(lhs);
assign->astOperand2(rhs);
return assign;
}
2020-01-05 15:12:53 +01:00
if (nodeType == CompoundStmt) {
for (AstNodePtr child: children) {
child->createTokens(tokenList);
2020-01-09 10:49:47 +01:00
if (!Token::Match(tokenList->back(), "[;{}]"))
child->addtoken(tokenList, ";");
2020-01-05 15:12:53 +01:00
}
2020-01-05 19:18:32 +01:00
return nullptr;
2020-01-05 15:12:53 +01:00
}
2020-01-25 17:22:22 +01:00
if (nodeType == ConstantExpr)
return children.back()->createTokens(tokenList);
2020-01-08 12:29:54 +01:00
if (nodeType == ContinueStmt)
return addtoken(tokenList, "continue");
2020-01-10 16:19:01 +01:00
if (nodeType == CStyleCastExpr) {
Token *par1 = addtoken(tokenList, "(");
addTypeTokens(tokenList, '\'' + getType() + '\'');
Token *par2 = addtoken(tokenList, ")");
par1->link(par2);
par2->link(par1);
par1->astOperand1(children[0]->createTokens(tokenList));
return par1;
}
if (nodeType == CXXBindTemporaryExpr)
return children[0]->createTokens(tokenList);
2020-01-09 16:19:23 +01:00
if (nodeType == CXXBoolLiteralExpr) {
addtoken(tokenList, mExtTokens.back());
tokenList->back()->setValueType(new ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::BOOL, 0));
return tokenList->back();
}
if (nodeType == CXXConstructExpr) {
if (!children.empty())
return children[0]->createTokens(tokenList);
addTypeTokens(tokenList, '\'' + getType() + '\'');
Token *type = tokenList->back();
Token *par1 = addtoken(tokenList, "(");
Token *par2 = addtoken(tokenList, ")");
par1->link(par2);
par2->link(par1);
par1->astOperand1(type);
return par1;
}
if (nodeType == CXXConstructorDecl) {
createTokensFunctionDecl(tokenList);
return nullptr;
}
2020-01-21 17:14:01 +01:00
if (nodeType == CXXDeleteExpr) {
addtoken(tokenList, "delete");
children[0]->createTokens(tokenList);
return nullptr;
}
2020-04-12 17:27:32 +02:00
if (nodeType == CXXDestructorDecl) {
createTokensFunctionDecl(tokenList);
return nullptr;
}
2020-01-18 19:23:37 +01:00
if (nodeType == CXXForRangeStmt) {
Token *forToken = addtoken(tokenList, "for");
Token *par1 = addtoken(tokenList, "(");
AstNodePtr varDecl;
if (children[6]->nodeType == DeclStmt)
varDecl = children[6]->children[0];
else
varDecl = children[5]->children[0];
varDecl->mExtTokens.pop_back();
varDecl->children.clear();
Token *expr1 = varDecl->createTokens(tokenList);
2020-01-18 19:23:37 +01:00
Token *colon = addtoken(tokenList, ":");
AstNodePtr range;
for (int i = 0; i < 2; i++) {
if (children[i] && children[i]->nodeType == DeclStmt && children[i]->children[0]->nodeType == VarDecl) {
range = children[i]->children[0]->children[0];
break;
}
}
Token *expr2 = range->createTokens(tokenList);
2020-01-18 19:23:37 +01:00
Token *par2 = addtoken(tokenList, ")");
par1->link(par2);
par2->link(par1);
colon->astOperand1(expr1);
colon->astOperand2(expr2);
par1->astOperand1(forToken);
par1->astOperand2(colon);
createScope(tokenList, Scope::ScopeType::eFor, children.back(), forToken);
2020-01-18 19:23:37 +01:00
return nullptr;
}
if (nodeType == CXXMethodDecl) {
for (int i = 0; i+1 < mExtTokens.size(); ++i) {
if (mExtTokens[i] == "prev" && !mData->hasDecl(mExtTokens[i+1]))
return nullptr;
}
createTokensFunctionDecl(tokenList);
return nullptr;
}
2020-01-08 21:49:23 +01:00
if (nodeType == CXXMemberCallExpr)
return createTokensCall(tokenList);
2020-01-21 12:16:39 +01:00
if (nodeType == CXXNewExpr) {
Token *newtok = addtoken(tokenList, "new");
2020-10-29 20:51:33 +01:00
if (children.size() == 1 && children[0]->nodeType == CXXConstructExpr) {
newtok->astOperand1(children[0]->createTokens(tokenList));
return newtok;
}
2020-01-21 12:16:39 +01:00
std::string type = getType();
if (type.find("*") != std::string::npos)
type = type.erase(type.rfind("*"));
addTypeTokens(tokenList, type);
if (!children.empty()) {
Token *bracket1 = addtoken(tokenList, "[");
children[0]->createTokens(tokenList);
Token *bracket2 = addtoken(tokenList, "]");
bracket1->link(bracket2);
bracket2->link(bracket1);
}
return newtok;
}
2020-01-10 19:01:33 +01:00
if (nodeType == CXXNullPtrLiteralExpr)
return addtoken(tokenList, "nullptr");
2020-01-09 15:59:09 +01:00
if (nodeType == CXXOperatorCallExpr)
return createTokensCall(tokenList);
if (nodeType == CXXRecordDecl) {
createTokensForCXXRecord(tokenList);
return nullptr;
}
if (nodeType == CXXStaticCastExpr || nodeType == CXXFunctionalCastExpr) {
2020-01-09 20:53:06 +01:00
Token *cast = addtoken(tokenList, getSpelling());
Token *par1 = addtoken(tokenList, "(");
Token *expr = children[0]->createTokens(tokenList);
Token *par2 = addtoken(tokenList, ")");
par1->link(par2);
par2->link(par1);
par1->astOperand1(cast);
par1->astOperand2(expr);
setValueType(par1);
return par1;
}
if (nodeType == CXXStdInitializerListExpr)
return children[0]->createTokens(tokenList);
if (nodeType == CXXTemporaryObjectExpr && !children.empty())
return children[0]->createTokens(tokenList);
if (nodeType == CXXThisExpr)
return addtoken(tokenList, "this");
2020-01-21 11:16:22 +01:00
if (nodeType == CXXThrowExpr) {
Token *t = addtoken(tokenList, "throw");
t->astOperand1(children[0]->createTokens(tokenList));
return t;
}
2020-01-05 15:12:53 +01:00
if (nodeType == DeclRefExpr) {
2020-01-06 13:47:19 +01:00
const std::string addr = mExtTokens[mExtTokens.size() - 3];
2020-01-10 11:04:37 +01:00
std::string name = unquote(getSpelling());
Token *reftok = addtoken(tokenList, name.empty() ? "<NoName>" : name);
2020-01-06 13:47:19 +01:00
mData->ref(addr, reftok);
return reftok;
2020-01-05 15:12:53 +01:00
}
if (nodeType == DeclStmt)
return children[0]->createTokens(tokenList);
2020-10-29 09:48:35 +01:00
if (nodeType == DefaultStmt) {
addtoken(tokenList, "default");
addtoken(tokenList, ":");
children.back()->createTokens(tokenList);
return nullptr;
}
2020-01-20 20:46:33 +01:00
if (nodeType == DoStmt) {
addtoken(tokenList, "do");
createScope(tokenList, Scope::ScopeType::eDo, children[0], tokenList->back());
2020-01-20 20:46:33 +01:00
Token *tok1 = addtoken(tokenList, "while");
Token *par1 = addtoken(tokenList, "(");
Token *expr = children[1]->createTokens(tokenList);
Token *par2 = addtoken(tokenList, ")");
par1->link(par2);
par2->link(par1);
par1->astOperand1(tok1);
par1->astOperand2(expr);
return nullptr;
}
2020-01-26 07:32:14 +01:00
if (nodeType == EnumConstantDecl) {
Token *nameToken = addtoken(tokenList, getSpelling());
Scope *scope = const_cast<Scope *>(nameToken->scope());
scope->enumeratorList.push_back(Enumerator(nameToken->scope()));
Enumerator *e = &scope->enumeratorList.back();
e->name = nameToken;
e->value = mData->enumValue++;
e->value_known = true;
mData->enumDecl(mExtTokens.front(), nameToken, e);
return nameToken;
}
2020-01-23 16:06:25 +01:00
if (nodeType == EnumDecl) {
2020-01-26 07:32:14 +01:00
mData->enumValue = 0;
2020-01-23 16:06:25 +01:00
Token *enumtok = addtoken(tokenList, "enum");
2020-01-24 21:34:29 +01:00
Token *nametok = nullptr;
2020-01-23 16:06:25 +01:00
if (mExtTokens[mExtTokens.size() - 3].compare(0,4,"col:") == 0)
2020-01-24 21:34:29 +01:00
nametok = addtoken(tokenList, mExtTokens.back());
Scope *enumscope = createScope(tokenList, Scope::ScopeType::eEnum, children, enumtok);
if (nametok)
enumscope->className = nametok->str();
if (enumscope->bodyEnd && Token::simpleMatch(enumscope->bodyEnd->previous(), ", }"))
const_cast<Token *>(enumscope->bodyEnd)->deletePrevious();
2020-01-24 21:34:29 +01:00
// Create enum type
mData->mSymbolDatabase->typeList.push_back(Type(enumtok, enumscope, enumtok->scope()));
enumscope->definedType = &mData->mSymbolDatabase->typeList.back();
if (nametok)
const_cast<Scope *>(enumtok->scope())->definedTypesMap[nametok->str()] = enumscope->definedType;
2020-01-23 16:06:25 +01:00
return nullptr;
}
if (nodeType == ExprWithCleanups)
return children[0]->createTokens(tokenList);
2020-01-08 10:35:44 +01:00
if (nodeType == FieldDecl)
return createTokensVarDecl(tokenList);
2020-01-20 14:09:21 +01:00
if (nodeType == FloatingLiteral)
return addtoken(tokenList, mExtTokens.back());
2020-01-08 10:35:44 +01:00
if (nodeType == ForStmt) {
Token *forToken = addtoken(tokenList, "for");
Token *par1 = addtoken(tokenList, "(");
2020-01-09 10:49:47 +01:00
Token *expr1 = children[0] ? children[0]->createTokens(tokenList) : nullptr;
2020-01-08 10:35:44 +01:00
Token *sep1 = addtoken(tokenList, ";");
2020-01-09 10:49:47 +01:00
Token *expr2 = children[2] ? children[2]->createTokens(tokenList) : nullptr;
2020-01-08 10:35:44 +01:00
Token *sep2 = addtoken(tokenList, ";");
2020-01-09 10:49:47 +01:00
Token *expr3 = children[3] ? children[3]->createTokens(tokenList) : nullptr;
2020-01-08 10:35:44 +01:00
Token *par2 = addtoken(tokenList, ")");
par1->link(par2);
2020-01-09 12:42:29 +01:00
par2->link(par1);
2020-01-08 10:35:44 +01:00
par1->astOperand1(forToken);
par1->astOperand2(sep1);
sep1->astOperand1(expr1);
sep1->astOperand2(sep2);
sep2->astOperand1(expr2);
sep2->astOperand2(expr3);
createScope(tokenList, Scope::ScopeType::eFor, children[4], forToken);
2020-01-07 18:33:24 +01:00
return nullptr;
}
2020-01-05 15:12:53 +01:00
if (nodeType == FunctionDecl) {
createTokensFunctionDecl(tokenList);
2020-01-05 19:18:32 +01:00
return nullptr;
}
2020-01-08 20:47:52 +01:00
if (nodeType == FunctionTemplateDecl) {
bool first = true;
for (AstNodePtr child: children) {
if (child->nodeType == FunctionDecl) {
if (!first)
child->createTokens(tokenList);
first = false;
}
}
return nullptr;
}
2020-01-20 19:07:10 +01:00
if (nodeType == GotoStmt) {
addtoken(tokenList, "goto");
addtoken(tokenList, unquote(mExtTokens[mExtTokens.size() - 2]));
addtoken(tokenList, ";");
return nullptr;
}
2020-01-05 19:18:32 +01:00
if (nodeType == IfStmt) {
2020-01-23 16:18:39 +01:00
AstNodePtr cond;
AstNodePtr thenCode;
AstNodePtr elseCode;
if (children.size() == 2) {
cond = children[children.size() - 2];
thenCode = children[children.size() - 1];
} else {
cond = children[children.size() - 3];
thenCode = children[children.size() - 2];
elseCode = children[children.size() - 1];
}
2020-01-05 19:18:32 +01:00
Token *iftok = addtoken(tokenList, "if");
Token *par1 = addtoken(tokenList, "(");
par1->astOperand1(iftok);
par1->astOperand2(cond->createTokens(tokenList));
Token *par2 = addtoken(tokenList, ")");
par1->link(par2);
2020-01-09 12:42:29 +01:00
par2->link(par1);
2020-01-23 16:18:39 +01:00
createScope(tokenList, Scope::ScopeType::eIf, thenCode, iftok);
if (elseCode) {
elseCode->addtoken(tokenList, "else");
createScope(tokenList, Scope::ScopeType::eElse, elseCode, tokenList->back());
2020-01-07 12:38:37 +01:00
}
2020-01-05 15:12:53 +01:00
return nullptr;
}
2020-01-12 18:05:45 +01:00
if (nodeType == ImplicitCastExpr) {
Token *expr = children[0]->createTokens(tokenList);
if (!expr->valueType() || contains(mExtTokens, "<ArrayToPointerDecay>"))
setValueType(expr);
2020-01-12 18:05:45 +01:00
return expr;
}
2020-01-13 12:44:11 +01:00
if (nodeType == InitListExpr) {
const Scope *scope = tokenList->back()->scope();
Token *start = addtoken(tokenList, "{");
start->scope(scope);
for (AstNodePtr child: children) {
if (tokenList->back()->str() != "{")
addtoken(tokenList, ",");
child->createTokens(tokenList);
}
Token *end = addtoken(tokenList, "}");
end->scope(scope);
start->link(end);
end->link(start);
mData->mNotScope.insert(end);
2020-01-13 12:44:11 +01:00
return start;
}
2020-01-05 15:12:53 +01:00
if (nodeType == IntegerLiteral)
return addtoken(tokenList, mExtTokens.back());
2020-01-20 19:07:10 +01:00
if (nodeType == LabelStmt) {
addtoken(tokenList, unquote(mExtTokens.back()));
addtoken(tokenList, ":");
for (auto child: children)
child->createTokens(tokenList);
return nullptr;
}
2020-11-24 19:34:37 +01:00
if (nodeType == LinkageSpecDecl)
return nullptr;
2020-01-20 21:27:49 +01:00
if (nodeType == MaterializeTemporaryExpr)
return children[0]->createTokens(tokenList);
2020-01-08 09:51:35 +01:00
if (nodeType == MemberExpr) {
Token *s = children[0]->createTokens(tokenList);
Token *dot = addtoken(tokenList, ".");
std::string memberName = getSpelling();
2020-01-09 13:40:38 +01:00
if (memberName.compare(0, 2, "->") == 0) {
dot->originalName("->");
memberName = memberName.substr(2);
2020-01-09 13:40:38 +01:00
} else if (memberName.compare(0, 1, ".") == 0) {
memberName = memberName.substr(1);
}
2020-01-09 13:40:38 +01:00
if (memberName.empty())
memberName = "<unknown>";
Token *member = addtoken(tokenList, memberName);
2020-01-08 09:51:35 +01:00
mData->ref(mExtTokens.back(), member);
dot->astOperand1(s);
dot->astOperand2(member);
return dot;
}
2020-01-20 21:27:49 +01:00
if (nodeType == NamespaceDecl) {
if (children.empty())
return nullptr;
Token *defToken = addtoken(tokenList, "namespace");
2020-01-24 21:34:29 +01:00
const std::string &s = mExtTokens[mExtTokens.size() - 2];
Token *nameToken = (s.compare(0,4,"col:")==0 || s.compare(0,5,"line:")==0) ?
2020-01-20 21:27:49 +01:00
addtoken(tokenList, mExtTokens.back()) : nullptr;
Scope *scope = createScope(tokenList, Scope::ScopeType::eNamespace, children, defToken);
2020-01-20 21:27:49 +01:00
if (nameToken)
scope->className = nameToken->str();
return nullptr;
}
if (nodeType == NullStmt)
return addtoken(tokenList, ";");
2020-01-09 10:49:47 +01:00
if (nodeType == ParenExpr) {
Token *par1 = addtoken(tokenList, "(");
Token *expr = children[0]->createTokens(tokenList);
Token *par2 = addtoken(tokenList, ")");
par1->link(par2);
2020-01-09 12:42:29 +01:00
par2->link(par1);
2020-01-09 10:49:47 +01:00
return expr;
}
2020-01-07 18:33:24 +01:00
if (nodeType == RecordDecl) {
const Token *classDef = addtoken(tokenList, "struct");
2020-01-07 19:47:06 +01:00
const std::string &recordName = getSpelling();
if (!recordName.empty())
addtoken(tokenList, getSpelling());
if (!isDefinition()) {
addtoken(tokenList, ";");
return nullptr;
}
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();
2020-11-03 21:37:28 +01:00
if (!recordName.empty()) {
recordScope->className = recordName;
const_cast<Scope *>(classDef->scope())->definedTypesMap[recordName] = recordScope->definedType;
2020-11-03 21:37:28 +01:00
}
2020-01-07 18:33:24 +01:00
return nullptr;
}
2020-01-05 15:12:53 +01:00
if (nodeType == ReturnStmt) {
Token *tok1 = addtoken(tokenList, "return");
2020-10-04 20:02:19 +02:00
if (!children.empty()) {
children[0]->setValueType(tok1);
2020-01-05 15:12:53 +01:00
tok1->astOperand1(children[0]->createTokens(tokenList));
2020-10-04 20:02:19 +02:00
}
2020-01-05 15:12:53 +01:00
return tok1;
}
if (nodeType == StringLiteral)
return addtoken(tokenList, mExtTokens.back());
2020-01-20 14:23:43 +01:00
if (nodeType == SwitchStmt) {
Token *tok1 = addtoken(tokenList, "switch");
Token *par1 = addtoken(tokenList, "(");
Token *expr = children[children.size() - 2]->createTokens(tokenList);
Token *par2 = addtoken(tokenList, ")");
par1->link(par2);
par2->link(par1);
par1->astOperand1(tok1);
par1->astOperand2(expr);
createScope(tokenList, Scope::ScopeType::eSwitch, children.back(), tok1);
2020-01-20 14:23:43 +01:00
return nullptr;
}
2020-01-08 14:25:09 +01:00
if (nodeType == TypedefDecl) {
addtoken(tokenList, "typedef");
addTypeTokens(tokenList, getType());
return addtoken(tokenList, getSpelling());
}
2020-01-05 15:12:53 +01:00
if (nodeType == UnaryOperator) {
2020-01-09 19:07:14 +01:00
int index = (int)mExtTokens.size() - 1;
while (index > 0 && mExtTokens[index][0] != '\'')
--index;
Token *unop = addtoken(tokenList, unquote(mExtTokens[index]));
2020-01-05 15:12:53 +01:00
unop->astOperand1(children[0]->createTokens(tokenList));
return unop;
}
2020-01-09 17:31:46 +01:00
if (nodeType == UnaryExprOrTypeTraitExpr) {
Token *tok1 = addtoken(tokenList, getSpelling());
Token *par1 = addtoken(tokenList, "(");
if (children.empty())
addTypeTokens(tokenList, mExtTokens.back());
else
addTypeTokens(tokenList, children[0]->getType());
2020-01-09 17:31:46 +01:00
Token *par2 = addtoken(tokenList, ")");
par1->link(par2);
par2->link(par1);
par1->astOperand1(tok1);
par1->astOperand2(par1->next());
setValueType(par1);
return par1;
}
2020-01-08 10:35:44 +01:00
if (nodeType == VarDecl)
return createTokensVarDecl(tokenList);
2020-01-08 12:19:48 +01:00
if (nodeType == WhileStmt) {
AstNodePtr cond = children[children.size() - 2];
AstNodePtr body = children.back();
2020-01-08 12:19:48 +01:00
Token *whiletok = addtoken(tokenList, "while");
Token *par1 = addtoken(tokenList, "(");
par1->astOperand1(whiletok);
par1->astOperand2(cond->createTokens(tokenList));
Token *par2 = addtoken(tokenList, ")");
par1->link(par2);
2020-01-09 12:42:29 +01:00
par2->link(par1);
createScope(tokenList, Scope::ScopeType::eWhile, body, whiletok);
2020-01-08 12:19:48 +01:00
return nullptr;
}
2020-01-05 15:12:53 +01:00
return addtoken(tokenList, "?" + nodeType + "?");
}
2020-01-10 16:29:06 +01:00
Token * clangimport::AstNode::createTokensCall(TokenList *tokenList)
2020-01-08 21:49:23 +01:00
{
2020-01-09 15:59:09 +01:00
int firstParam;
Token *f;
if (nodeType == CXXOperatorCallExpr) {
firstParam = 2;
Token *obj = children[1]->createTokens(tokenList);
Token *dot = addtoken(tokenList, ".");
Token *op = children[0]->createTokens(tokenList);
dot->astOperand1(obj);
dot->astOperand2(op);
f = dot;
} else {
firstParam = 1;
f = children[0]->createTokens(tokenList);
}
f->setValueType(nullptr);
2020-01-08 21:49:23 +01:00
Token *par1 = addtoken(tokenList, "(");
par1->astOperand1(f);
2020-01-21 06:52:45 +01:00
int args = 0;
while (args < children.size() && children[args]->nodeType != CXXDefaultArgExpr)
args++;
Token *child = nullptr;
2020-01-21 06:52:45 +01:00
for (int c = firstParam; c < args; ++c) {
if (child) {
2020-01-08 21:49:23 +01:00
Token *comma = addtoken(tokenList, ",");
comma->setValueType(nullptr);
2020-01-08 21:49:23 +01:00
comma->astOperand1(child);
comma->astOperand2(children[c]->createTokens(tokenList));
child = comma;
2020-01-08 21:49:23 +01:00
} else {
child = children[c]->createTokens(tokenList);
2020-01-08 21:49:23 +01:00
}
}
par1->astOperand2(child);
2020-01-09 12:42:29 +01:00
Token *par2 = addtoken(tokenList, ")");
par1->link(par2);
par2->link(par1);
2020-01-08 21:49:23 +01:00
return par1;
}
2020-01-10 16:29:06 +01:00
void clangimport::AstNode::createTokensFunctionDecl(TokenList *tokenList)
{
2020-11-08 17:02:19 +01:00
const bool prev = contains(mExtTokens, "prev");
const bool hasBody = !children.empty() && children.back()->nodeType == CompoundStmt;
2020-11-08 17:02:19 +01:00
const bool isStatic = contains(mExtTokens, "static");
const bool isInline = contains(mExtTokens, "inline");
const Token *startToken = nullptr;
SymbolDatabase *symbolDatabase = mData->mSymbolDatabase;
if (nodeType != CXXConstructorDecl && nodeType != CXXDestructorDecl) {
if (isStatic)
addtoken(tokenList, "static");
if (isInline)
addtoken(tokenList, "inline");
const Token * const before = tokenList->back();
addTypeTokens(tokenList, '\'' + getType() + '\'');
startToken = before ? before->next() : tokenList->front();
}
2020-11-08 10:31:48 +01:00
if (mExtTokens.size() > 4 && mExtTokens[1] == "parent")
addFullScopeNameTokens(tokenList, mData->getScope(mExtTokens[2]));
Token *nameToken = addtoken(tokenList, getSpelling() + getTemplateParameters());
Scope *nestedIn = const_cast<Scope *>(nameToken->scope());
if (prev) {
const std::string addr = *(std::find(mExtTokens.begin(), mExtTokens.end(), "prev") + 1);
mData->ref(addr, nameToken);
}
if (!nameToken->function()) {
nestedIn->functionList.push_back(Function(nameToken, unquote(getFullType())));
mData->funcDecl(mExtTokens.front(), nameToken, &nestedIn->functionList.back());
if (nodeType == CXXConstructorDecl)
nestedIn->functionList.back().type = Function::Type::eConstructor;
2020-04-12 17:27:32 +02:00
else if (nodeType == CXXDestructorDecl)
nestedIn->functionList.back().type = Function::Type::eDestructor;
else
nestedIn->functionList.back().retDef = startToken;
}
Function * const function = const_cast<Function*>(nameToken->function());
2020-11-08 17:02:19 +01:00
if (!prev) {
auto accessControl = mData->scopeAccessControl.find(tokenList->back()->scope());
if (accessControl != mData->scopeAccessControl.end())
function->access = accessControl->second;
}
Scope *scope = nullptr;
if (hasBody) {
symbolDatabase->scopeList.push_back(Scope(nullptr, nullptr, nestedIn));
scope = &symbolDatabase->scopeList.back();
scope->check = symbolDatabase;
scope->function = function;
scope->classDef = nameToken;
scope->type = Scope::ScopeType::eFunction;
scope->className = nameToken->str();
nestedIn->nestedList.push_back(scope);
function->hasBody(true);
function->functionScope = scope;
}
Token *par1 = addtoken(tokenList, "(");
if (!function->arg)
function->arg = par1;
function->token = nameToken;
if (!function->nestedIn)
function->nestedIn = nestedIn;
function->argDef = par1;
// Function arguments
for (int i = 0; i < children.size(); ++i) {
AstNodePtr child = children[i];
if (child->nodeType != ParmVarDecl)
continue;
if (tokenList->back() != par1)
addtoken(tokenList, ",");
2020-11-03 21:37:28 +01:00
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);
2020-04-12 22:41:35 +02:00
if (!prev) {
2020-11-03 21:37:28 +01:00
function->argumentList.push_back(Variable(vartok, child->getType(), nullptr, typeEndToken, i, AccessControl::Argument, recordType, scope));
2020-04-12 22:41:35 +02:00
if (vartok) {
const std::string addr = child->mExtTokens[0];
mData->varDecl(addr, vartok, &function->argumentList.back());
}
} else if (vartok) {
const std::string addr = child->mExtTokens[0];
2020-04-12 22:41:35 +02:00
mData->ref(addr, vartok);
}
}
Token *par2 = addtoken(tokenList, ")");
par1->link(par2);
2020-01-09 12:42:29 +01:00
par2->link(par1);
if (function->isConst())
addtoken(tokenList, "const");
// Function body
if (hasBody) {
symbolDatabase->functionScopes.push_back(scope);
Token *bodyStart = addtoken(tokenList, "{");
bodyStart->scope(scope);
children.back()->createTokens(tokenList);
Token *bodyEnd = addtoken(tokenList, "}");
scope->bodyStart = bodyStart;
scope->bodyEnd = bodyEnd;
bodyStart->link(bodyEnd);
2020-01-09 12:42:29 +01:00
bodyEnd->link(bodyStart);
} else {
2020-11-08 17:02:19 +01:00
if (nodeType == CXXConstructorDecl && contains(mExtTokens, "default")) {
addtoken(tokenList, "=");
addtoken(tokenList, "default");
}
addtoken(tokenList, ";");
}
}
2020-01-10 16:29:06 +01:00
void clangimport::AstNode::createTokensForCXXRecord(TokenList *tokenList)
2020-01-08 21:31:06 +01:00
{
2020-11-08 17:02:19 +01:00
bool isStruct = contains(mExtTokens, "struct");
Token * const classToken = addtoken(tokenList, isStruct ? "struct" : "class");
std::string className;
if (mExtTokens[mExtTokens.size() - 2] == (isStruct?"struct":"class"))
className = mExtTokens.back();
else
className = mExtTokens[mExtTokens.size() - 2];
className += getTemplateParameters();
2020-01-08 21:31:06 +01:00
/*Token *nameToken =*/ addtoken(tokenList, className);
// base classes
bool firstBase = true;
for (AstNodePtr child: children) {
if (child->nodeType == "public" || child->nodeType == "protected" || child->nodeType == "private") {
addtoken(tokenList, firstBase ? ":" : ",");
addtoken(tokenList, child->nodeType);
addtoken(tokenList, unquote(child->mExtTokens.back()));
firstBase = false;
}
}
// definition
2020-11-01 11:33:01 +01:00
if (isDefinition()) {
std::vector<AstNodePtr> children2;
for (AstNodePtr child: children) {
if (child->nodeType == CXXConstructorDecl ||
child->nodeType == CXXDestructorDecl ||
child->nodeType == CXXMethodDecl ||
child->nodeType == FieldDecl ||
2020-11-08 17:02:19 +01:00
child->nodeType == VarDecl ||
child->nodeType == AccessSpecDecl ||
child->nodeType == TypedefDecl)
2020-11-01 11:33:01 +01:00
children2.push_back(child);
}
Scope *scope = createScope(tokenList, isStruct ? Scope::ScopeType::eStruct : Scope::ScopeType::eClass, children2, classToken);
2020-11-08 10:31:48 +01:00
const std::string addr = mExtTokens[0];
mData->scopeDecl(addr, scope);
2020-11-01 11:33:01 +01:00
scope->className = className;
mData->mSymbolDatabase->typeList.push_back(Type(classToken, scope, classToken->scope()));
scope->definedType = &mData->mSymbolDatabase->typeList.back();
2020-11-03 21:37:28 +01:00
const_cast<Scope *>(classToken->scope())->definedTypesMap[className] = scope->definedType;
}
2020-11-01 11:33:01 +01:00
addtoken(tokenList, ";");
const_cast<Token *>(tokenList->back())->scope(classToken->scope());
2020-01-08 21:31:06 +01:00
}
2020-01-10 16:29:06 +01:00
Token * clangimport::AstNode::createTokensVarDecl(TokenList *tokenList)
2020-01-07 19:51:44 +01:00
{
const std::string addr = mExtTokens.front();
const Token *startToken = nullptr;
2020-11-08 17:02:19 +01:00
if (contains(mExtTokens, "static"))
startToken = addtoken(tokenList, "static");
int typeIndex = mExtTokens.size() - 1;
while (typeIndex > 1 && std::isalpha(mExtTokens[typeIndex][0]))
typeIndex--;
const std::string type = mExtTokens[typeIndex];
const std::string name = mExtTokens[typeIndex - 1];
2020-11-03 21:37:28 +01:00
const ::Type *recordType = addTypeTokens(tokenList, type);
if (!startToken && tokenList->back()) {
startToken = tokenList->back();
while (Token::Match(startToken->previous(), "%type%|*|&|&&"))
startToken = startToken->previous();
}
2020-01-07 19:51:44 +01:00
Token *vartok1 = addtoken(tokenList, name);
Scope *scope = const_cast<Scope *>(tokenList->back()->scope());
scope->varlist.push_back(Variable(vartok1, unquote(type), startToken, vartok1->previous(), 0, scope->defaultAccess(), recordType, scope));
2020-01-07 19:51:44 +01:00
mData->varDecl(addr, vartok1, &scope->varlist.back());
2020-02-02 12:13:19 +01:00
if (mExtTokens.back() == "cinit" && !children.empty()) {
2020-01-07 19:51:44 +01:00
Token *eq = addtoken(tokenList, "=");
2020-01-08 10:35:44 +01:00
eq->astOperand1(vartok1);
2020-01-07 19:51:44 +01:00
eq->astOperand2(children.back()->createTokens(tokenList));
2020-01-08 10:35:44 +01:00
return eq;
} else if (mExtTokens.back() == "callinit") {
Token *par1 = addtoken(tokenList, "(");
par1->astOperand1(vartok1);
par1->astOperand2(children[0]->createTokens(tokenList));
Token *par2 = addtoken(tokenList, ")");
par1->link(par2);
par2->link(par1);
return par1;
} else if (mExtTokens.back() == "listinit") {
return children[0]->createTokens(tokenList);
2020-01-07 19:51:44 +01:00
}
2020-01-08 10:35:44 +01:00
return vartok1;
2020-01-07 19:51:44 +01:00
}
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, true);
}
scope.definedType->sizeOf = typeSize;
}
for (Token *tok = const_cast<Token*>(tokenizer->tokens()); tok; tok = tok->next()) {
if (Token::simpleMatch(tok, "sizeof (")) {
ValueType vt = ValueType::parseDecl(tok->tokAt(2), settings);
int sz = vt.typeSize(*settings, true);
if (sz <= 0)
continue;
long long mul = 1;
for (Token *arrtok = tok->linkAt(1)->previous(); arrtok; arrtok = arrtok->previous()) {
const std::string &a = arrtok->str();
if (a.size() > 2 && a[0] == '[' && a.back() == ']')
mul *= std::atoi(a.substr(1).c_str());
else
break;
}
ValueFlow::Value v(mul * sz);
v.setKnown();
tok->next()->addValue(v);
}
}
}
2020-01-10 16:29:06 +01:00
void clangimport::parseClangAstDump(Tokenizer *tokenizer, std::istream &f)
2020-01-05 15:12:53 +01:00
{
TokenList *tokenList = &tokenizer->list;
tokenizer->createSymbolDatabase();
SymbolDatabase *symbolDatabase = const_cast<SymbolDatabase *>(tokenizer->getSymbolDatabase());
symbolDatabase->scopeList.push_back(Scope(nullptr, nullptr, nullptr));
symbolDatabase->scopeList.back().type = Scope::ScopeType::eGlobal;
2020-01-25 11:58:40 +01:00
symbolDatabase->scopeList.back().check = symbolDatabase;
2020-01-05 15:12:53 +01:00
2020-01-10 16:29:06 +01:00
clangimport::Data data;
data.mSettings = tokenizer->getSettings();
2020-01-06 13:47:19 +01:00
data.mSymbolDatabase = symbolDatabase;
2020-01-05 15:12:53 +01:00
std::string line;
std::vector<AstNodePtr> tree;
while (std::getline(f,line)) {
const std::string::size_type pos1 = line.find("-");
if (pos1 == std::string::npos)
continue;
2020-01-05 19:18:32 +01:00
if (!tree.empty() && line.substr(pos1) == "-<<<NULL>>>") {
const int level = (pos1 - 1) / 2;
tree[level - 1]->children.push_back(nullptr);
continue;
}
2020-01-05 15:12:53 +01:00
const std::string::size_type pos2 = line.find(" ", pos1);
if (pos2 < pos1 + 4 || pos2 == std::string::npos)
continue;
const std::string nodeType = line.substr(pos1+1, pos2 - pos1 - 1);
const std::string ext = line.substr(pos2);
2020-01-08 14:25:09 +01:00
if (pos1 == 1 && endsWith(nodeType, "Decl", 4)) {
2020-01-08 10:35:44 +01:00
if (!tree.empty())
tree[0]->createTokens1(tokenList);
2020-01-05 15:12:53 +01:00
tree.clear();
2020-01-06 13:47:19 +01:00
tree.push_back(std::make_shared<AstNode>(nodeType, ext, &data));
2020-01-05 15:12:53 +01:00
continue;
}
const int level = (pos1 - 1) / 2;
if (level == 0 || tree.empty())
continue;
2020-01-06 13:47:19 +01:00
AstNodePtr newNode = std::make_shared<AstNode>(nodeType, ext, &data);
2020-01-05 15:12:53 +01:00
tree[level - 1]->children.push_back(newNode);
if (level >= tree.size())
tree.push_back(newNode);
else
tree[level] = newNode;
}
2020-01-08 10:35:44 +01:00
if (!tree.empty())
tree[0]->createTokens1(tokenList);
2020-01-05 15:12:53 +01:00
2020-01-06 13:47:19 +01:00
symbolDatabase->clangSetVariables(data.getVariableList());
2020-01-05 15:12:53 +01:00
tokenList->clangSetOrigFiles();
setTypes(tokenList);
setValues(tokenizer, symbolDatabase);
2020-01-05 15:12:53 +01:00
}