diff --git a/Makefile b/Makefile
index 0023b4b16..b008aa403 100644
--- a/Makefile
+++ b/Makefile
@@ -184,6 +184,7 @@ LIBOBJ = $(libcppdir)/analyzerinfo.o \
$(libcppdir)/checkunusedfunctions.o \
$(libcppdir)/checkunusedvar.o \
$(libcppdir)/checkvaarg.o \
+ $(libcppdir)/clangastdump.o \
$(libcppdir)/cppcheck.o \
$(libcppdir)/ctu.o \
$(libcppdir)/errorlogger.o \
@@ -479,7 +480,10 @@ $(libcppdir)/checkunusedvar.o: lib/checkunusedvar.cpp lib/astutils.h lib/check.h
$(libcppdir)/checkvaarg.o: lib/checkvaarg.cpp lib/astutils.h lib/check.h lib/checkvaarg.h lib/config.h lib/errorlogger.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkvaarg.o $(libcppdir)/checkvaarg.cpp
-$(libcppdir)/cppcheck.o: lib/cppcheck.cpp externals/picojson.h externals/simplecpp/simplecpp.h externals/tinyxml/tinyxml2.h lib/analyzerinfo.h lib/check.h lib/checkunusedfunctions.h lib/config.h lib/cppcheck.h lib/ctu.h lib/errorlogger.h lib/exprengine.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/version.h
+$(libcppdir)/clangastdump.o: lib/clangastdump.cpp lib/clangastdump.h lib/config.h lib/errorlogger.h lib/library.h lib/mathlib.h lib/platform.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
+ $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/clangastdump.o $(libcppdir)/clangastdump.cpp
+
+$(libcppdir)/cppcheck.o: lib/cppcheck.cpp externals/picojson.h externals/simplecpp/simplecpp.h externals/tinyxml/tinyxml2.h lib/analyzerinfo.h lib/check.h lib/checkunusedfunctions.h lib/clangastdump.h lib/config.h lib/cppcheck.h lib/ctu.h lib/errorlogger.h lib/exprengine.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/version.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/cppcheck.o $(libcppdir)/cppcheck.cpp
$(libcppdir)/ctu.o: lib/ctu.cpp externals/tinyxml/tinyxml2.h lib/astutils.h lib/check.h lib/config.h lib/ctu.h lib/errorlogger.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
@@ -488,7 +492,7 @@ $(libcppdir)/ctu.o: lib/ctu.cpp externals/tinyxml/tinyxml2.h lib/astutils.h lib/
$(libcppdir)/errorlogger.o: lib/errorlogger.cpp externals/tinyxml/tinyxml2.h lib/analyzerinfo.h lib/check.h lib/config.h lib/cppcheck.h lib/errorlogger.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/errorlogger.o $(libcppdir)/errorlogger.cpp
-$(libcppdir)/exprengine.o: lib/exprengine.cpp lib/astutils.h lib/config.h lib/errorlogger.h lib/exprengine.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
+$(libcppdir)/exprengine.o: lib/exprengine.cpp lib/astutils.h lib/config.h lib/errorlogger.h lib/exprengine.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/exprengine.o $(libcppdir)/exprengine.cpp
$(libcppdir)/importproject.o: lib/importproject.cpp externals/picojson.h externals/tinyxml/tinyxml2.h lib/config.h lib/errorlogger.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp
index d52ab1629..3fbc7f6c6 100644
--- a/cli/cmdlineparser.cpp
+++ b/cli/cmdlineparser.cpp
@@ -133,6 +133,9 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
else if (std::strncmp(argv[i], "--addon=", 8) == 0)
mSettings->addons.emplace_back(argv[i]+8);
+ else if (std::strcmp(argv[i], "--clang") == 0)
+ mSettings->clang = true;
+
else if (std::strncmp(argv[i], "--cppcheck-build-dir=", 21) == 0) {
mSettings->buildDir = Path::fromNativeSeparators(argv[i] + 21);
if (endsWith(mSettings->buildDir, '/'))
diff --git a/lib/clangastdump.cpp b/lib/clangastdump.cpp
new file mode 100644
index 000000000..212756190
--- /dev/null
+++ b/lib/clangastdump.cpp
@@ -0,0 +1,306 @@
+/*
+ * Cppcheck - A tool for static C/C++ code analysis
+ * Copyright (C) 2007-2019 Cppcheck team.
+ *
+ * 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 .
+ */
+
+#include "clangastdump.h"
+#include "symboldatabase.h"
+#include "tokenize.h"
+
+#include
+#include
+#include
+
+static const std::string BinaryOperator = "BinaryOperator";
+static const std::string CallExpr = "CallExpr";
+static const std::string CompoundStmt = "CompoundStmt";
+static const std::string DeclRefExpr = "DeclRefExpr";
+static const std::string FunctionDecl = "FunctionDecl";
+static const std::string ImplicitCastExpr = "ImplicitCastExpr";
+static const std::string IntegerLiteral = "IntegerLiteral";
+static const std::string ParmVarDecl = "ParmVarDecl";
+static const std::string ReturnStmt = "ReturnStmt";
+static const std::string UnaryOperator = "UnaryOperator";
+
+static std::string unquote(const std::string &s)
+{
+ return (s[0] == '\'') ? s.substr(1, s.size() - 2) : s;
+}
+
+static std::vector splitString(const std::string &line)
+{
+ std::vector ret;
+ std::string::size_type pos1 = line.find_first_not_of(" ");
+ while (pos1 != std::string::npos) {
+ std::string::size_type pos2;
+ if (line[pos1] == '<')
+ pos2 = line.find(">", pos1);
+ else if (line[pos1] == '\'')
+ pos2 = line.find("\'", pos1+1);
+ else
+ pos2 = line.find(" ", pos1) - 1;
+ ret.push_back(line.substr(pos1, pos2+1-pos1));
+ if (pos2 == std::string::npos)
+ break;
+ pos1 = line.find_first_not_of(" ", pos2 + 1);
+ }
+ return ret;
+}
+
+namespace clangastdump {
+ struct Data {
+ std::map varId;
+ std::map variableMap;
+ };
+
+ class AstNode {
+ public:
+ AstNode(const std::string &nodeType, const std::string &ext, Data *data, SymbolDatabase *symbolDatabase)
+ : nodeType(nodeType), mExtTokens(splitString(ext)), mData(data), mSymbolDatabase(symbolDatabase)
+ {}
+ std::string nodeType;
+ std::vector> children;
+
+ void setLocations(TokenList *tokenList, int file, int line, int col);
+
+ void dumpAst(int num = 0, int indent = 0) const;
+ Token *createTokens(TokenList *tokenList);
+ private:
+ Token *addtoken(TokenList *tokenList, const std::string &str);
+ Token *addTypeTokens(TokenList *tokenList, const std::string &str);
+ std::string getSpelling() const;
+ std::string getType() const;
+
+ int mFile = 0;
+ int mLine = 1;
+ int mCol = 1;
+ int mVarId = 0;
+ std::vector mExtTokens;
+ Data *mData;
+ SymbolDatabase *mSymbolDatabase;
+ };
+
+ typedef std::shared_ptr AstNodePtr;
+}
+
+std::string clangastdump::AstNode::getSpelling() const
+{
+ if (nodeType == ParmVarDecl)
+ return mExtTokens[mExtTokens.size() - 2];
+ return "";
+}
+
+std::string clangastdump::AstNode::getType() const
+{
+ if (nodeType == DeclRefExpr)
+ return unquote(mExtTokens.back());
+ if (nodeType == BinaryOperator)
+ return unquote(mExtTokens[mExtTokens.size() - 2]);
+ if (nodeType == IntegerLiteral)
+ return unquote(mExtTokens[mExtTokens.size() - 2]);
+ return "";
+}
+
+void clangastdump::AstNode::dumpAst(int num, int indent) const
+{
+ (void)num;
+ std::cout << std::string(indent, ' ') << nodeType;
+ for (auto tok: mExtTokens)
+ std::cout << " " << tok;
+ std::cout << std::endl;
+ for (int c = 0; c < children.size(); ++c)
+ children[c]->dumpAst(c, indent + 2);
+}
+
+void clangastdump::AstNode::setLocations(TokenList *tokenList, int file, int line, int col)
+{
+ for (const std::string &ext: mExtTokens) {
+ if (ext.compare(0,5,"appendFileIfNew(ext.substr(1,ext.find(":") - 1));
+ }
+ mFile = file;
+ mLine = line;
+ mCol = col;
+ for (auto child: children)
+ child->setLocations(tokenList, file, line, col);
+}
+
+Token *clangastdump::AstNode::addtoken(TokenList *tokenList, const std::string &str)
+{
+ tokenList->addtoken(str, mLine, mFile);
+ if (getType() == "int")
+ tokenList->back()->setValueType(new ValueType(ValueType::Sign::SIGNED, ValueType::Type::INT, 0));
+ return tokenList->back();
+}
+
+Token *clangastdump::AstNode::addTypeTokens(TokenList *tokenList, const std::string &str)
+{
+ if (str.find(" (") == std::string::npos)
+ return addtoken(tokenList, unquote(str));
+ return addtoken(tokenList, str.substr(1,str.find(" (")-1));
+}
+
+Token *clangastdump::AstNode::createTokens(TokenList *tokenList)
+{
+ 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;
+ }
+ if (nodeType == CallExpr) {
+ Token *op1 = children[0]->createTokens(tokenList);
+ Token *call = addtoken(tokenList, "(");
+ call->astOperand1(op1);
+ for (int c = 1; c < children.size(); ++c)
+ call->astOperand2(children[c]->createTokens(tokenList));
+ call->link(addtoken(tokenList, ")"));
+ return call;
+ }
+ if (nodeType == CompoundStmt) {
+ Token *start = addtoken(tokenList, "{");
+ for (AstNodePtr child: children) {
+ child->createTokens(tokenList);
+ child->addtoken(tokenList, ";");
+ }
+ Token *end = addtoken(tokenList, "}");
+ start->link(end);
+ return start;
+ }
+ if (nodeType == DeclRefExpr) {
+ Token *vartok = addtoken(tokenList, unquote(mExtTokens[mExtTokens.size() - 2]));
+ std::string addr = mExtTokens[mExtTokens.size() - 3];
+ vartok->varId(mData->varId[addr]);
+ vartok->variable(mData->variableMap[addr]);
+ return vartok;
+ }
+ if (nodeType == FunctionDecl) {
+ addTypeTokens(tokenList, mExtTokens.back());
+ Token *nameToken = addtoken(tokenList, mExtTokens[mExtTokens.size() - 2]);
+ Scope &globalScope = mSymbolDatabase->scopeList.front();
+ mSymbolDatabase->scopeList.push_back(Scope(nullptr, nullptr, &globalScope));
+ Scope &scope = mSymbolDatabase->scopeList.back();
+ mSymbolDatabase->functionScopes.push_back(&scope);
+ globalScope.functionList.push_back(Function(nameToken));
+ scope.function = &globalScope.functionList.back();
+ Token *par1 = addtoken(tokenList, "(");
+ for (AstNodePtr child: children) {
+ if (child->nodeType != ParmVarDecl)
+ continue;
+ if (tokenList->back() != par1)
+ addtoken(tokenList, ",");
+ addTypeTokens(tokenList, child->mExtTokens.back());
+ const std::string spelling = child->getSpelling();
+ if (!spelling.empty()) {
+ Token *vartok = addtoken(tokenList, spelling);
+ std::string addr = child->mExtTokens[0];
+ int varId = mData->varId.size() + 1;
+ 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, ")");
+ par1->link(par2);
+ children.back()->createTokens(tokenList);
+ if (Token::simpleMatch(par2, ") {")) {
+ Token *bodyStart = par2->next();
+ scope.bodyStart = bodyStart;
+ scope.bodyEnd = bodyStart->link();
+ }
+ return nullptr;
+ }
+ if (nodeType == ImplicitCastExpr)
+ return children[0]->createTokens(tokenList);
+ if (nodeType == IntegerLiteral)
+ return addtoken(tokenList, mExtTokens.back());
+ if (nodeType == ReturnStmt) {
+ Token *tok1 = addtoken(tokenList, "return");
+ if (!children.empty())
+ tok1->astOperand1(children[0]->createTokens(tokenList));
+ return tok1;
+ }
+ if (nodeType == UnaryOperator) {
+ Token *unop = addtoken(tokenList, unquote(mExtTokens.back()));
+ unop->astOperand1(children[0]->createTokens(tokenList));
+ return unop;
+ }
+ return addtoken(tokenList, "?" + nodeType + "?");
+}
+
+void clangastdump::parseClangAstDump(Tokenizer *tokenizer, std::istream &f)
+{
+ TokenList *tokenList = &tokenizer->list;
+ clangastdump::Data data;
+
+ tokenizer->createSymbolDatabase();
+ SymbolDatabase *symbolDatabase = const_cast(tokenizer->getSymbolDatabase());
+ symbolDatabase->scopeList.push_back(Scope(nullptr, nullptr, nullptr));
+ symbolDatabase->scopeList.back().type = Scope::ScopeType::eGlobal;
+
+ std::string line;
+ std::vector tree;
+ while (std::getline(f,line)) {
+ const std::string::size_type pos1 = line.find("-");
+ if (pos1 == std::string::npos)
+ continue;
+ 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);
+
+ if (nodeType == FunctionDecl) {
+ if (!tree.empty()) {
+ tree[0]->setLocations(tokenList, 0, 1, 1);
+ tree[0]->createTokens(tokenList);
+ }
+ tree.clear();
+ tree.push_back(std::make_shared(nodeType, ext, &data, symbolDatabase));
+ continue;
+ }
+
+ const int level = (pos1 - 1) / 2;
+ if (level == 0 || tree.empty())
+ continue;
+
+ AstNodePtr newNode = std::make_shared(nodeType, ext, &data, symbolDatabase);
+ tree[level - 1]->children.push_back(newNode);
+ if (level >= tree.size())
+ tree.push_back(newNode);
+ else
+ tree[level] = newNode;
+ }
+
+ if (!tree.empty()) {
+ tree[0]->setLocations(tokenList, 0, 1, 1);
+ tree[0]->createTokens(tokenList);
+ }
+
+ symbolDatabase->clangSetVariables(data.variableMap);
+ tokenList->clangSetOrigFiles();
+}
+
diff --git a/lib/clangastdump.h b/lib/clangastdump.h
new file mode 100644
index 000000000..0d712d824
--- /dev/null
+++ b/lib/clangastdump.h
@@ -0,0 +1,37 @@
+/*
+ * Cppcheck - A tool for static C/C++ code analysis
+ * Copyright (C) 2007-2020 Cppcheck team.
+ *
+ * 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 .
+ */
+
+
+//---------------------------------------------------------------------------
+#ifndef clangastdumpH
+#define clangastdumpH
+//---------------------------------------------------------------------------
+
+#include
+#include
+
+class SymbolDatabase;
+class Tokenizer;
+
+namespace clangastdump {
+
+ void parseClangAstDump(Tokenizer *tokenizer, std::istream &f);
+
+}
+
+#endif
diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp
index f4f275a3c..0e3f6e92e 100644
--- a/lib/cppcheck.cpp
+++ b/lib/cppcheck.cpp
@@ -19,6 +19,7 @@
#include "check.h"
#include "checkunusedfunctions.h"
+#include "clangastdump.h"
#include "ctu.h"
#include "library.h"
#include "mathlib.h"
@@ -196,6 +197,24 @@ static std::vector split(const std::string &str, const std::string
return ret;
}
+static std::pair executeCommand(const std::string &cmd)
+{
+#ifdef _WIN32
+ std::unique_ptr pipe(_popen(cmd.c_str(), "r"), _pclose);
+#else
+ std::unique_ptr pipe(popen(cmd.c_str(), "r"), pclose);
+#endif
+
+ if (!pipe)
+ return std::pair(false, "");
+
+ char buffer[1024];
+ std::string result;
+ while (fgets(buffer, sizeof(buffer), pipe.get()) != nullptr)
+ result += buffer;
+ return std::pair(true, result);
+}
+
CppCheck::CppCheck(ErrorLogger &errorLogger, bool useGlobalSuppressions)
: mErrorLogger(errorLogger), mExitCode(0), mSuppressInternalErrorFound(false), mUseGlobalSuppressions(useGlobalSuppressions), mTooManyConfigs(false), mSimplify(true)
{
@@ -222,6 +241,24 @@ const char * CppCheck::extraVersion()
unsigned int CppCheck::check(const std::string &path)
{
+ if (mSettings.clang) {
+ /* Experimental: import clang ast dump */
+ const std::string cmd = "clang -cc1 -ast-dump " + path;
+ std::pair res = executeCommand(cmd);
+ if (!res.first) {
+ std::cerr << "Failed to execute '" + cmd + "'" << std::endl;
+ return 0;
+ }
+ //std::cout << "Checking Clang ast dump:\n" << res.second << std::endl;
+ std::istringstream ast(res.second);
+ Tokenizer tokenizer(&mSettings, this);
+ clangastdump::parseClangAstDump(&tokenizer, ast);
+ //tokenizer.tokens()->printOut("");
+ //tokenizer.tokens()->printAst(true, false, std::cout);
+ ExprEngine::runChecks(this, &tokenizer, &mSettings);
+ return 0;
+ }
+
std::ifstream fin(path);
return checkFile(Path::simplifyPath(path), emptyString, fin);
}
diff --git a/lib/errorlogger.cpp b/lib/errorlogger.cpp
index 8dc654b32..b03c5d388 100644
--- a/lib/errorlogger.cpp
+++ b/lib/errorlogger.cpp
@@ -112,12 +112,12 @@ ErrorLogger::ErrorMessage::ErrorMessage(const std::list& callstack
: id(id), severity(severity), cwe(cwe.id), inconclusive(inconclusive)
{
// Format callstack
- for (std::list::const_iterator it = callstack.begin(); it != callstack.end(); ++it) {
+ for (const Token *tok: callstack) {
// --errorlist can provide null values here
- if (!(*it))
+ if (!tok)
continue;
- callStack.emplace_back(*it, list);
+ callStack.emplace_back(tok, list);
}
if (list && !list->getFiles().empty())
diff --git a/lib/lib.pri b/lib/lib.pri
index f689e5289..83b357b38 100644
--- a/lib/lib.pri
+++ b/lib/lib.pri
@@ -31,6 +31,7 @@ HEADERS += $${PWD}/analyzerinfo.h \
$${PWD}/checkunusedfunctions.h \
$${PWD}/checkunusedvar.h \
$${PWD}/checkvaarg.h \
+ $${PWD}/clangastdump.h \
$${PWD}/cppcheck.h \
$${PWD}/ctu.h \
$${PWD}/errorlogger.h \
@@ -82,6 +83,7 @@ SOURCES += $${PWD}/analyzerinfo.cpp \
$${PWD}/checkunusedfunctions.cpp \
$${PWD}/checkunusedvar.cpp \
$${PWD}/checkvaarg.cpp \
+ $${PWD}/clangastdump.cpp \
$${PWD}/cppcheck.cpp \
$${PWD}/ctu.cpp \
$${PWD}/errorlogger.cpp \
diff --git a/lib/settings.cpp b/lib/settings.cpp
index f329bc552..b74566e3c 100644
--- a/lib/settings.cpp
+++ b/lib/settings.cpp
@@ -34,6 +34,7 @@ Settings::Settings()
checkLibrary(false),
checkHeaders(true),
checkUnusedTemplates(false),
+ clang(false),
debugSimplified(false),
debugnormal(false),
debugwarnings(false),
diff --git a/lib/settings.h b/lib/settings.h
index 2caacfaf1..d72444c55 100644
--- a/lib/settings.h
+++ b/lib/settings.h
@@ -93,6 +93,9 @@ public:
/** Check unused templates */
bool checkUnusedTemplates;
+ /** Use Clang */
+ bool clang;
+
/** @brief include paths excluded from checking the configuration */
std::set configExcludePaths;
diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp
index df3aff0a5..7bfea025c 100644
--- a/lib/symboldatabase.cpp
+++ b/lib/symboldatabase.cpp
@@ -39,6 +39,9 @@
SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
: mTokenizer(tokenizer), mSettings(settings), mErrorLogger(errorLogger)
{
+ if (!tokenizer || !tokenizer->tokens())
+ return;
+
mIsCpp = isCPP();
if (mSettings->defaultSign == 's' || mSettings->defaultSign == 'S')
@@ -1715,6 +1718,13 @@ void SymbolDatabase::validate() const
//validateVariables();
}
+void SymbolDatabase::clangSetVariables(const std::map &variableMap)
+{
+ mVariableList.resize(variableMap.size() + 1);
+ for (std::map::const_iterator it = variableMap.begin(); it != variableMap.end(); ++it)
+ mVariableList[it->second->declarationId()] = it->second;
+}
+
Variable::~Variable()
{
delete mValueType;
@@ -1738,6 +1748,9 @@ const Token * Variable::declEndToken() const
void Variable::evaluate(const Settings* settings)
{
+ if (!settings)
+ return;
+
const Library * const lib = settings ? &settings->library : nullptr;
if (mNameToken)
@@ -2020,6 +2033,26 @@ Function::Function(const Tokenizer *mTokenizer,
}
}
+Function::Function(const Token *tokenDef)
+ : tokenDef(tokenDef),
+ argDef(nullptr),
+ token(nullptr),
+ arg(nullptr),
+ retDef(nullptr),
+ retType(nullptr),
+ functionScope(nullptr),
+ nestedIn(nullptr),
+ initArgCount(0),
+ type(eFunction),
+ access(AccessControl::Public),
+ noexceptArg(nullptr),
+ throwArg(nullptr),
+ templateDef(nullptr),
+ mFlags(0)
+{
+}
+
+
static std::string qualifiedName(const Scope *scope)
{
std::string name = scope->className;
diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h
index 30592243e..4338ee49b 100644
--- a/lib/symboldatabase.h
+++ b/lib/symboldatabase.h
@@ -716,6 +716,7 @@ public:
enum Type { eConstructor, eCopyConstructor, eMoveConstructor, eOperatorEqual, eDestructor, eFunction, eLambda };
Function(const Tokenizer *mTokenizer, const Token *tok, const Scope *scope, const Token *tokDef, const Token *tokArgDef);
+ Function(const Token *tokenDef);
const std::string &name() const {
return tokenDef->str();
@@ -1304,6 +1305,8 @@ public:
/** Set array dimensions when valueflow analysis is completed */
void setArrayDimensionsUsingValueFlow();
+ void clangSetVariables(const std::map &variableMap);
+
private:
friend class Scope;
friend class Function;
diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp
index ad7b22bc3..9c02b35be 100644
--- a/lib/tokenlist.cpp
+++ b/lib/tokenlist.cpp
@@ -94,6 +94,11 @@ int TokenList::appendFileIfNew(const std::string &fileName)
return mFiles.size() - 1;
}
+void TokenList::clangSetOrigFiles()
+{
+ mOrigFiles = mFiles;
+}
+
void TokenList::deleteTokens(Token *tok)
{
while (tok) {
diff --git a/lib/tokenlist.h b/lib/tokenlist.h
index 58c1fbcd6..3257ec671 100644
--- a/lib/tokenlist.h
+++ b/lib/tokenlist.h
@@ -186,6 +186,8 @@ public:
*/
void simplifyStdType();
+ void clangSetOrigFiles();
+
private:
/** Disable copy constructor, no implementation */