diff --git a/.github/workflows/CI-windows.yml b/.github/workflows/CI-windows.yml index 67816efc6..5b9c7e17b 100644 --- a/.github/workflows/CI-windows.yml +++ b/.github/workflows/CI-windows.yml @@ -121,7 +121,6 @@ jobs: copy .\bin\cppcheck.exe .\cppcheck.exe || exit /b !errorlevel! copy .\bin\cppcheck-core.dll .\cppcheck-core.dll || exit /b !errorlevel! cd test/cli || exit /b !errorlevel! - python -m pytest --suppress-no-test-exit-code test-clang-import.py || exit /b !errorlevel! python -m pytest test-helloworld.py || exit /b !errorlevel! python -m pytest test-inline-suppress.py || exit /b !errorlevel! python -m pytest test-more-projects.py || exit /b !errorlevel! diff --git a/Makefile b/Makefile index aecab7833..a30c8765f 100644 --- a/Makefile +++ b/Makefile @@ -185,7 +185,6 @@ LIBOBJ = $(libcppdir)/analyzerinfo.o \ $(libcppdir)/checkunusedfunctions.o \ $(libcppdir)/checkunusedvar.o \ $(libcppdir)/checkvaarg.o \ - $(libcppdir)/clangimport.o \ $(libcppdir)/cppcheck.o \ $(libcppdir)/ctu.o \ $(libcppdir)/errorlogger.o \ @@ -233,7 +232,6 @@ TESTOBJ = test/options.o \ test/testbufferoverrun.o \ test/testbughuntingchecks.o \ test/testcharvar.o \ - test/testclangimport.o \ test/testclass.o \ test/testcmdlineparser.o \ test/testcondition.o \ @@ -493,10 +491,7 @@ $(libcppdir)/checkunusedvar.o: lib/checkunusedvar.cpp externals/simplecpp/simple $(libcppdir)/checkvaarg.o: lib/checkvaarg.cpp lib/astutils.h lib/check.h lib/checkvaarg.h lib/config.h lib/errortypes.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)/clangimport.o: lib/clangimport.cpp lib/astutils.h lib/clangimport.h lib/config.h lib/errortypes.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)/clangimport.o $(libcppdir)/clangimport.cpp - -$(libcppdir)/cppcheck.o: lib/cppcheck.cpp externals/picojson/picojson.h externals/simplecpp/simplecpp.h externals/tinyxml2/tinyxml2.h lib/analyzerinfo.h lib/astutils.h lib/check.h lib/checkunusedfunctions.h lib/clangimport.h lib/config.h lib/cppcheck.h lib/ctu.h lib/errorlogger.h lib/errortypes.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)/cppcheck.o: lib/cppcheck.cpp externals/picojson/picojson.h externals/simplecpp/simplecpp.h externals/tinyxml2/tinyxml2.h lib/analyzerinfo.h lib/astutils.h lib/check.h lib/checkunusedfunctions.h lib/config.h lib/cppcheck.h lib/ctu.h lib/errorlogger.h lib/errortypes.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/tinyxml2/tinyxml2.h lib/astutils.h lib/check.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.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 @@ -622,9 +617,6 @@ test/testbughuntingchecks.o: test/testbughuntingchecks.cpp lib/astutils.h lib/co test/testcharvar.o: test/testcharvar.cpp lib/astutils.h lib/check.h lib/checkother.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.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 test/testsuite.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testcharvar.o test/testcharvar.cpp -test/testclangimport.o: test/testclangimport.cpp lib/astutils.h lib/clangimport.h lib/config.h lib/errorlogger.h lib/errortypes.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 test/testsuite.h - $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testclangimport.o test/testclangimport.cpp - test/testclass.o: test/testclass.cpp externals/tinyxml2/tinyxml2.h lib/astutils.h lib/check.h lib/checkclass.h lib/config.h lib/errorlogger.h lib/errortypes.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 test/testsuite.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testclass.o test/testclass.cpp diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index c2e56db32..0c8807fea 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -235,10 +235,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) } else if (std::strncmp(argv[i], "--clang", 7) == 0) { - mSettings->clang = true; - if (std::strncmp(argv[i], "--clang=", 8) == 0) { - mSettings->clangExecutable = argv[i] + 8; - } + printMessage("Cppcheck: Clang import has been removed"); } else if (std::strncmp(argv[i], "--config-exclude=",17) ==0) { @@ -992,18 +989,11 @@ void CmdLineParser::printHelp() " * faster analysis; Cppcheck will reuse the results if\n" " the hash for a file is unchanged.\n" " * some useful debug information, i.e. commands used to\n" - " execute clang/clang-tidy/addons.\n" + " execute clang-tidy/addons.\n" " --check-config Check cppcheck configuration. The normal code\n" " analysis is disabled by this flag.\n" " --check-library Show information messages when library files have\n" " incomplete info.\n" - " --clang= Experimental: Use Clang parser instead of the builtin Cppcheck\n" - " parser. Takes the executable as optional parameter and\n" - " defaults to `clang`. Cppcheck will run the given Clang\n" - " executable, import the Clang AST and convert it into\n" - " Cppcheck data. After that the normal Cppcheck analysis is\n" - " used. You must have the executable in PATH if no path is\n" - " given.\n" " --config-exclude=\n" " Path (prefix) to be excluded from configuration\n" " checking. Preprocessor configurations defined in\n" diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 1e00d132d..129fe7549 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -873,7 +873,6 @@ Settings MainWindow::getCppcheckSettings() result.userDefines += define.toStdString(); } - result.clang = mProjectFile->clangParser; result.bugHunting = mProjectFile->bugHunting; result.bugHuntingReport = " "; diff --git a/gui/projectfile.cpp b/gui/projectfile.cpp index 53ccb92fc..9984a5039 100644 --- a/gui/projectfile.cpp +++ b/gui/projectfile.cpp @@ -45,7 +45,6 @@ ProjectFile::ProjectFile(const QString &filename, QObject *parent) : void ProjectFile::clear() { const Settings settings; - clangParser = false; bugHunting = false; mRootPath.clear(); mBuildDir.clear(); @@ -62,7 +61,7 @@ void ProjectFile::clear() mPlatform.clear(); mSuppressions.clear(); mAddons.clear(); - mClangAnalyzer = mClangTidy = false; + mClangTidy = false; mAnalyzeAllVsConfigs = false; mCheckHeaders = true; mCheckUnusedTemplates = true; @@ -118,9 +117,6 @@ bool ProjectFile::read(const QString &filename) if (xmlReader.name() == CppcheckXml::AnalyzeAllVsConfigsElementName) mAnalyzeAllVsConfigs = readBool(xmlReader); - if (xmlReader.name() == CppcheckXml::Parser) - clangParser = true; - if (xmlReader.name() == CppcheckXml::BugHunting) bugHunting = true; @@ -186,7 +182,6 @@ bool ProjectFile::read(const QString &filename) if (xmlReader.name() == CppcheckXml::ToolsElementName) { QStringList tools; readStringList(tools, xmlReader, CppcheckXml::ToolElementName); - mClangAnalyzer = tools.contains(CLANG_ANALYZER); mClangTidy = tools.contains(CLANG_TIDY); } @@ -875,12 +870,6 @@ bool ProjectFile::write(const QString &filename) xmlWriter.writeCharacters(mAnalyzeAllVsConfigs ? "true" : "false"); xmlWriter.writeEndElement(); - if (clangParser) { - xmlWriter.writeStartElement(CppcheckXml::Parser); - xmlWriter.writeCharacters("clang"); - xmlWriter.writeEndElement(); - } - if (bugHunting) { xmlWriter.writeStartElement(CppcheckXml::BugHunting); xmlWriter.writeEndElement(); @@ -1016,8 +1005,6 @@ bool ProjectFile::write(const QString &filename) CppcheckXml::AddonElementName); QStringList tools; - if (mClangAnalyzer) - tools << CLANG_ANALYZER; if (mClangTidy) tools << CLANG_TIDY; writeStringList(xmlWriter, @@ -1077,8 +1064,6 @@ QStringList ProjectFile::fromNativeSeparators(const QStringList &paths) QStringList ProjectFile::getAddonsAndTools() const { QStringList ret(mAddons); - if (mClangAnalyzer) - ret << CLANG_ANALYZER; if (mClangTidy) ret << CLANG_TIDY; return ret; diff --git a/gui/projectfile.h b/gui/projectfile.h index cd56f9557..647e61037 100644 --- a/gui/projectfile.h +++ b/gui/projectfile.h @@ -192,14 +192,6 @@ public: */ QStringList getAddonsAndTools() const; - bool getClangAnalyzer() const { - return false; //mClangAnalyzer; - } - - void setClangAnalyzer(bool c) { - mClangAnalyzer = c; - } - bool getClangTidy() const { return mClangTidy; } @@ -388,9 +380,6 @@ public: mCheckUnknownFunctionReturn = s; } - /** Use Clang parser */ - bool clangParser; - /** Bug hunting */ bool bugHunting; protected: @@ -583,9 +572,6 @@ private: */ QStringList mAddons; - /** @brief Execute clang analyzer? */ - bool mClangAnalyzer; - /** @brief Execute clang-tidy? */ bool mClangTidy; diff --git a/gui/projectfiledialog.cpp b/gui/projectfiledialog.cpp index 6c5e138ac..4a2e0c8db 100644 --- a/gui/projectfiledialog.cpp +++ b/gui/projectfiledialog.cpp @@ -270,10 +270,6 @@ void ProjectFileDialog::loadFromProjectFile(const ProjectFile *projectFile) mUI.mCheckUnusedTemplates->setChecked(projectFile->getCheckUnusedTemplates()); mUI.mMaxCtuDepth->setValue(projectFile->getMaxCtuDepth()); mUI.mMaxTemplateRecursion->setValue(projectFile->getMaxTemplateRecursion()); - if (projectFile->clangParser) - mUI.mBtnClangParser->setChecked(true); - else - mUI.mBtnCppcheckParser->setChecked(true); mUI.mBtnSafeClasses->setChecked(projectFile->safeChecks.classes); mUI.mBtnBugHunting->setChecked(projectFile->bugHunting); setExcludedPaths(projectFile->getExcludedPaths()); @@ -341,7 +337,6 @@ void ProjectFileDialog::loadFromProjectFile(const ProjectFile *projectFile) mUI.mAddonMisra->setText(mUI.mAddonMisra->text() + ' ' + tr("(no rule texts file)")); } - mUI.mToolClangAnalyzer->setChecked(projectFile->getClangAnalyzer()); mUI.mToolClangTidy->setChecked(projectFile->getClangTidy()); if (CheckThread::clangTidyCmd().isEmpty()) { mUI.mToolClangTidy->setText(tr("Clang-tidy (not found)")); @@ -368,7 +363,6 @@ void ProjectFileDialog::saveToProjectFile(ProjectFile *projectFile) const projectFile->setCheckPaths(getCheckPaths()); projectFile->setExcludedPaths(getExcludedPaths()); projectFile->setLibraries(getLibraries()); - projectFile->clangParser = mUI.mBtnClangParser->isChecked(); projectFile->safeChecks.classes = mUI.mBtnSafeClasses->isChecked(); projectFile->bugHunting = mUI.mBtnBugHunting->isChecked(); if (mUI.mComboBoxPlatform->currentText().endsWith(".xml")) @@ -408,7 +402,6 @@ void ProjectFileDialog::saveToProjectFile(ProjectFile *projectFile) const if (mUI.mAddonMisra->isChecked()) list << "misra"; projectFile->setAddons(list); - projectFile->setClangAnalyzer(mUI.mToolClangAnalyzer->isChecked()); projectFile->setClangTidy(mUI.mToolClangTidy->isChecked()); projectFile->setTags(mUI.mEditTags->text().split(";", QString::SkipEmptyParts)); } diff --git a/gui/projectfiledialog.ui b/gui/projectfiledialog.ui index e8db9338e..af9c14e30 100644 --- a/gui/projectfiledialog.ui +++ b/gui/projectfiledialog.ui @@ -426,32 +426,6 @@ - - - - Parser - - - - - - Cppcheck (built in) - - - true - - - - - - - Clang (experimental) - - - - - - diff --git a/gui/statsdialog.cpp b/gui/statsdialog.cpp index 7b01b6e85..32dfadd78 100644 --- a/gui/statsdialog.cpp +++ b/gui/statsdialog.cpp @@ -69,10 +69,6 @@ void StatsDialog::setProject(const ProjectFile* projectFile) QChartView *chartView; chartView = createChart(statsFile, "cppcheck"); mUI.mTabHistory->layout()->addWidget(chartView); - if (projectFile->getClangAnalyzer()) { - chartView = createChart(statsFile, CLANG_ANALYZER); - mUI.mTabHistory->layout()->addWidget(chartView); - } if (projectFile->getClangTidy()) { chartView = createChart(statsFile, CLANG_TIDY); mUI.mTabHistory->layout()->addWidget(chartView); diff --git a/lib/bughuntingchecks.cpp b/lib/bughuntingchecks.cpp index cc29463e6..c85041413 100644 --- a/lib/bughuntingchecks.cpp +++ b/lib/bughuntingchecks.cpp @@ -211,7 +211,7 @@ static void divByZero(const Token *tok, const ExprEngine::Value &value, ExprEngi if (tok->astParent()->astOperand2() == tok && value.isEqual(dataBase, 0)) { const char * const id = (tok->valueType() && tok->valueType()->isFloat()) ? "bughuntingDivByZeroFloat" : "bughuntingDivByZero"; const bool bailout = (value.type == ExprEngine::ValueType::BailoutValue); - dataBase->reportError(dataBase->settings->clang ? tok : tok->astParent(), + dataBase->reportError(tok->astParent(), Severity::SeverityType::error, id, "There is division, cannot determine that there can't be a division by zero.", diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 6562772b5..7ab27ef07 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -188,9 +188,6 @@ void CheckLeakAutoVar::doubleFreeError(const Token *tok, const Token *prevFreeTo void CheckLeakAutoVar::check() { - if (mSettings->clang) - return; - const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); // Local variables that are known to be non-zero. diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 0943c9c9d..b32ea164c 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -758,9 +758,6 @@ void CheckMemoryLeakInClass::publicAllocationError(const Token *tok, const std:: void CheckMemoryLeakStructMember::check() { - if (mSettings->clang) - return; - const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Variable* var : symbolDatabase->variableList()) { if (!var || !var->isLocal() || var->isStatic() || var->isReference()) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index dc40d73a4..4cd72cc4e 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -884,9 +884,6 @@ void CheckOther::unreachableCodeError(const Token *tok, bool inconclusive) //--------------------------------------------------------------------------- void CheckOther::checkVariableScope() { - if (mSettings->clang) - return; - if (!mSettings->severity.isEnabled(Severity::style)) return; diff --git a/lib/checkuninitvar.h b/lib/checkuninitvar.h index 2125b33fb..c852be046 100644 --- a/lib/checkuninitvar.h +++ b/lib/checkuninitvar.h @@ -65,9 +65,6 @@ public: /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE { - if (settings->clang) - return; - CheckUninitVar checkUninitVar(tokenizer, settings, errorLogger); checkUninitVar.check(); checkUninitVar.valueFlowUninit(); diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index fe37e477f..57d26d58c 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -1145,9 +1145,6 @@ void CheckUnusedVar::checkFunctionVariableUsage() if (!mSettings->severity.isEnabled(Severity::style)) return; - if (mSettings->clang) - return; - // Parse all executing scopes.. const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); diff --git a/lib/checkvaarg.cpp b/lib/checkvaarg.cpp index ec2fc037e..b8179ee42 100644 --- a/lib/checkvaarg.cpp +++ b/lib/checkvaarg.cpp @@ -95,8 +95,6 @@ void CheckVaarg::referenceAs_va_start_error(const Token *tok, const std::string& void CheckVaarg::va_list_usage() { - if (mSettings->clang) - return; const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Variable* var : symbolDatabase->variableList()) { if (!var || var->isPointer() || var->isReference() || var->isArray() || !var->scope() || var->typeStartToken()->str() != "va_list") diff --git a/lib/clangimport.cpp b/lib/clangimport.cpp deleted file mode 100644 index 315af9998..000000000 --- a/lib/clangimport.cpp +++ /dev/null @@ -1,1616 +0,0 @@ -/* - * Cppcheck - A tool for static C/C++ code analysis - * Copyright (C) 2007-2021 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 "clangimport.h" -#include "settings.h" -#include "symboldatabase.h" -#include "tokenize.h" -#include "utils.h" - -#include -#include -#include -#include -#include -#include -#include - -static const std::string AccessSpecDecl = "AccessSpecDecl"; -static const std::string ArraySubscriptExpr = "ArraySubscriptExpr"; -static const std::string BinaryOperator = "BinaryOperator"; -static const std::string BreakStmt = "BreakStmt"; -static const std::string CallExpr = "CallExpr"; -static const std::string CaseStmt = "CaseStmt"; -static const std::string CharacterLiteral = "CharacterLiteral"; -static const std::string ClassTemplateDecl = "ClassTemplateDecl"; -static const std::string ClassTemplateSpecializationDecl = "ClassTemplateSpecializationDecl"; -static const std::string ConditionalOperator = "ConditionalOperator"; -static const std::string ConstantExpr = "ConstantExpr"; -static const std::string CompoundAssignOperator = "CompoundAssignOperator"; -static const std::string CompoundStmt = "CompoundStmt"; -static const std::string ContinueStmt = "ContinueStmt"; -static const std::string CStyleCastExpr = "CStyleCastExpr"; -static const std::string CXXBindTemporaryExpr = "CXXBindTemporaryExpr"; -static const std::string CXXBoolLiteralExpr = "CXXBoolLiteralExpr"; -static const std::string CXXConstructorDecl = "CXXConstructorDecl"; -static const std::string CXXConstructExpr = "CXXConstructExpr"; -static const std::string CXXDefaultArgExpr = "CXXDefaultArgExpr"; -static const std::string CXXDeleteExpr = "CXXDeleteExpr"; -static const std::string CXXDestructorDecl = "CXXDestructorDecl"; -static const std::string CXXForRangeStmt = "CXXForRangeStmt"; -static const std::string CXXFunctionalCastExpr = "CXXFunctionalCastExpr"; -static const std::string CXXMemberCallExpr = "CXXMemberCallExpr"; -static const std::string CXXMethodDecl = "CXXMethodDecl"; -static const std::string CXXNewExpr = "CXXNewExpr"; -static const std::string CXXNullPtrLiteralExpr = "CXXNullPtrLiteralExpr"; -static const std::string CXXOperatorCallExpr = "CXXOperatorCallExpr"; -static const std::string CXXRecordDecl = "CXXRecordDecl"; -static const std::string CXXStaticCastExpr = "CXXStaticCastExpr"; -static const std::string CXXStdInitializerListExpr = "CXXStdInitializerListExpr"; -static const std::string CXXTemporaryObjectExpr = "CXXTemporaryObjectExpr"; -static const std::string CXXThisExpr = "CXXThisExpr"; -static const std::string CXXThrowExpr = "CXXThrowExpr"; -static const std::string DeclRefExpr = "DeclRefExpr"; -static const std::string DeclStmt = "DeclStmt"; -static const std::string DefaultStmt = "DefaultStmt"; -static const std::string DoStmt = "DoStmt"; -static const std::string EnumConstantDecl = "EnumConstantDecl"; -static const std::string EnumDecl = "EnumDecl"; -static const std::string ExprWithCleanups = "ExprWithCleanups"; -static const std::string FieldDecl = "FieldDecl"; -static const std::string FloatingLiteral = "FloatingLiteral"; -static const std::string ForStmt = "ForStmt"; -static const std::string FunctionDecl = "FunctionDecl"; -static const std::string FunctionTemplateDecl = "FunctionTemplateDecl"; -static const std::string GotoStmt = "GotoStmt"; -static const std::string IfStmt = "IfStmt"; -static const std::string ImplicitCastExpr = "ImplicitCastExpr"; -static const std::string InitListExpr = "InitListExpr"; -static const std::string IntegerLiteral = "IntegerLiteral"; -static const std::string LabelStmt = "LabelStmt"; -static const std::string LinkageSpecDecl = "LinkageSpecDecl"; -static const std::string MaterializeTemporaryExpr = "MaterializeTemporaryExpr"; -static const std::string MemberExpr = "MemberExpr"; -static const std::string NamespaceDecl = "NamespaceDecl"; -static const std::string NullStmt = "NullStmt"; -static const std::string ParenExpr = "ParenExpr"; -static const std::string ParmVarDecl = "ParmVarDecl"; -static const std::string RecordDecl = "RecordDecl"; -static const std::string ReturnStmt = "ReturnStmt"; -static const std::string StringLiteral = "StringLiteral"; -static const std::string SwitchStmt = "SwitchStmt"; -static const std::string TemplateArgument = "TemplateArgument"; -static const std::string TypedefDecl = "TypedefDecl"; -static const std::string UnaryOperator = "UnaryOperator"; -static const std::string UnaryExprOrTypeTraitExpr = "UnaryExprOrTypeTraitExpr"; -static const std::string VarDecl = "VarDecl"; -static const std::string WhileStmt = "WhileStmt"; - -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 < line.size()) { - std::string::size_type pos2; - if (std::strchr("*()", line[pos1])) { - ret.push_back(line.substr(pos1,1)); - pos1 = line.find_first_not_of(" ", pos1 + 1); - continue; - } - if (line[pos1] == '<') - pos2 = line.find(">", pos1); - else if (line[pos1] == '\"') - pos2 = line.find("\"", pos1+1); - else if (line[pos1] == '\'') { - pos2 = line.find("\'", pos1+1); - if (pos2 < (int)line.size() - 3 && line.compare(pos2, 3, "\':\'", 0, 3) == 0) - pos2 = line.find("\'", pos2 + 3); - } 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; - } - } - - 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] == '_') && - line.find("<", pos1) < pos2 && - line.find("<<",pos1) != line.find("<",pos1) && - line.find(">", pos1) != std::string::npos && - line.find(">", pos1) > pos2) { - 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()) - return std::vector {}; - pos2 = line.find(" ", pos2); - if (pos2 != std::string::npos) - --pos2; - } - } - if (pos2 == std::string::npos) { - ret.push_back(line.substr(pos1)); - break; - } - ret.push_back(line.substr(pos1, pos2+1-pos1)); - pos1 = line.find_first_not_of(" ", pos2 + 1); - } - return ret; -} - -static bool contains(const std::vector &haystack, const std::string &needle) -{ - return std::find(haystack.begin(), haystack.end(), needle) != haystack.end(); -} - -namespace clangimport { - struct Data { - struct Decl { - explicit Decl(Scope *scope) : def(nullptr), enumerator(nullptr), function(nullptr), scope(scope), var(nullptr) {} - 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) {} - void ref(Token *tok) { - if (enumerator) - tok->enumerator(enumerator); - if (function) - tok->function(function); - if (var) { - tok->variable(var); - tok->varId(var->declarationId()); - } - } - Token *def; - Enumerator *enumerator; - Function *function; - Scope *scope; - Variable *var; - }; - - const Settings *mSettings = nullptr; - SymbolDatabase *mSymbolDatabase = nullptr; - - int enumValue = 0; - - void enumDecl(const std::string &addr, Token *nameToken, Enumerator *enumerator) { - Decl decl(nameToken, enumerator); - mDeclMap.insert(std::pair(addr, decl)); - nameToken->enumerator(enumerator); - notFound(addr); - } - - void funcDecl(const std::string &addr, Token *nameToken, Function *function) { - Decl decl(nameToken, function); - mDeclMap.insert(std::pair(addr, decl)); - nameToken->function(function); - notFound(addr); - } - - void scopeDecl(const std::string &addr, Scope *scope) { - Decl decl(scope); - mDeclMap.insert(std::pair(addr, decl)); - } - - void varDecl(const std::string &addr, Token *def, Variable *var) { - Decl decl(def, var); - mDeclMap.insert(std::pair(addr, decl)); - def->varId(++mVarId); - def->variable(var); - if (def->valueType()) - var->setValueType(*def->valueType()); - notFound(addr); - } - - void replaceVarDecl(const Variable *from, Variable *to) { - for (auto &it: mDeclMap) { - Decl &decl = it.second; - if (decl.var == from) - decl.var = to; - } - } - - void ref(const std::string &addr, Token *tok) { - auto it = mDeclMap.find(addr); - if (it != mDeclMap.end()) - it->second.ref(tok); - else - mNotFound[addr].push_back(tok); - } - - std::vector getVariableList() const { - std::vector 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(); - } - - 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 mNotScope; - - std::map scopeAccessControl; - 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); - } - } - - std::map mDeclMap; - std::map> mNotFound; - int mVarId = 0; - }; - - class AstNode; - using AstNodePtr = std::shared_ptr; - - class AstNode { - public: - AstNode(const std::string &nodeType, const std::string &ext, Data *data) - : nodeType(nodeType), mExtTokens(splitString(ext)), mData(data) - {} - 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; - void createTokens1(TokenList *tokenList) { - //dumpAst(); - if (!tokenList->back()) - setLocations(tokenList, 0, 1, 1); - else - setLocations(tokenList, tokenList->back()->fileIndex(), tokenList->back()->linenr(), 1); - createTokens(tokenList); - if (nodeType == VarDecl || nodeType == RecordDecl || nodeType == TypedefDecl) - addtoken(tokenList, ";"); - mData->mNotScope.clear(); - } - - AstNodePtr getChild(int c) { - if (c >= children.size()) { - std::ostringstream err; - err << "ClangImport: AstNodePtr::getChild(" << c << ") out of bounds. children.size=" << children.size() << " " << nodeType; - for (const std::string &s: mExtTokens) - err << " " << s; - throw InternalError(nullptr, err.str()); - } - return children[c]; - } - private: - Token *createTokens(TokenList *tokenList); - Token *addtoken(TokenList *tokenList, const std::string &str, bool valueType=true); - const ::Type *addTypeTokens(TokenList *tokenList, const std::string &str, const Scope *scope = nullptr); - 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 &children2, const Token *def); - Token *createTokensCall(TokenList *tokenList); - void createTokensFunctionDecl(TokenList *tokenList); - void createTokensForCXXRecord(TokenList *tokenList); - Token *createTokensVarDecl(TokenList *tokenList); - std::string getSpelling() const; - std::string getType(int index = 0) const; - std::string getFullType(int index = 0) const; - bool isDefinition() const; - std::string getTemplateParameters() const; - const Scope *getNestedInScope(TokenList *tokenList); - void setValueType(Token *tok); - - int mFile = 0; - int mLine = 1; - int mCol = 1; - std::vector mExtTokens; - Data *mData; - }; -} - -std::string clangimport::AstNode::getSpelling() const -{ - if (nodeType == CompoundAssignOperator) { - int typeIndex = 1; - while (typeIndex < mExtTokens.size() && mExtTokens[typeIndex][0] != '\'') - typeIndex++; - // name is next quoted token - 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]) : ""; - } - - int typeIndex = mExtTokens.size() - 1; - if (nodeType == FunctionDecl || nodeType == CXXConstructorDecl || nodeType == CXXMethodDecl) { - while (typeIndex >= 0 && mExtTokens[typeIndex][0] != '\'') - typeIndex--; - if (typeIndex <= 0) - return ""; - } - if (nodeType == DeclRefExpr) { - while (typeIndex > 0 && std::isalpha(mExtTokens[typeIndex][0])) - typeIndex--; - if (typeIndex <= 0) - return ""; - } - const std::string &str = mExtTokens[typeIndex - 1]; - if (str.compare(0,4,"col:") == 0) - return ""; - if (str.compare(0,8,"= 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 -{ - return contains(mExtTokens, "definition"); -} - -std::string clangimport::AstNode::getTemplateParameters() const -{ - 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 + ">"; -} - -void clangimport::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) { - if (children[c]) - children[c]->dumpAst(c, indent + 2); - else - std::cout << std::string(indent + 2, ' ') << "<<<>>>>" << std::endl; - } -} - -void clangimport::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, sep1 - 1)); - line = MathLib::toLongNumber(ext.substr(sep1+1, sep2-sep1)); - } - } - mFile = file; - mLine = line; - mCol = col; - for (auto child: children) { - if (child) - child->setLocations(tokenList, file, line, col); - } -} - -Token *clangimport::AstNode::addtoken(TokenList *tokenList, const std::string &str, bool valueType) -{ - const Scope *scope = getNestedInScope(tokenList); - tokenList->addtoken(str, mLine, mCol, mFile); - tokenList->back()->scope(scope); - if (valueType) - setValueType(tokenList->back()); - return tokenList->back(); -} - -const ::Type * clangimport::AstNode::addTypeTokens(TokenList *tokenList, const std::string &str, const Scope *scope) -{ - if (str.find("\':\'") != std::string::npos) { - return addTypeTokens(tokenList, str.substr(0, str.find("\':\'") + 1), scope); - } - - if (str.compare(0, 16, "'enum (anonymous") == 0) - return nullptr; - - 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 - type = unquote(str); - - if (type.find("(*)(") != std::string::npos) { - type.erase(type.find("(*)(")); - type += "*"; - } - if (type.find("(") != std::string::npos) - type.erase(type.find("(")); - - std::stack lpar; - for (const std::string &s: splitString(type)) { - Token *tok = addtoken(tokenList, s, false); - if (tok->str() == "(") - lpar.push(tok); - else if (tok->str() == ")") { - Token::createMutualLinks(tok, lpar.top()); - lpar.pop(); - } - } - - // 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); - if (recordType) { - const_cast(typeToken)->type(recordType); - return recordType; - } - } - return nullptr; -} - -void clangimport::AstNode::addFullScopeNameTokens(TokenList *tokenList, const Scope *recordScope) -{ - if (!recordScope) - return; - std::list 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, "::"); - } - } -} - -const Scope *clangimport::AstNode::getNestedInScope(TokenList *tokenList) -{ - if (!tokenList->back()) - return &mData->mSymbolDatabase->scopeList.front(); - if (tokenList->back()->str() == "}" && mData->mNotScope.find(tokenList->back()) == mData->mNotScope.end()) - return tokenList->back()->scope()->nestedIn; - return tokenList->back()->scope(); -} - -void clangimport::AstNode::setValueType(Token *tok) -{ - for (int i = 0; i < 2; i++) { - const std::string &type = getType(i); - - if (type.find("<") != std::string::npos) - // TODO - continue; - - TokenList decl(nullptr); - addTypeTokens(&decl, type, tok->scope()); - if (!decl.front()) - break; - - ValueType valueType = ValueType::parseDecl(decl.front(), mData->mSettings); - if (valueType.type != ValueType::Type::UNKNOWN_TYPE) { - tok->setValueType(new ValueType(valueType)); - break; - } - } -} - -Scope *clangimport::AstNode::createScope(TokenList *tokenList, Scope::ScopeType scopeType, AstNodePtr astNode, const Token *def) -{ - std::vector children2{astNode}; - return createScope(tokenList, scopeType, children2, def); -} - -Scope *clangimport::AstNode::createScope(TokenList *tokenList, Scope::ScopeType scopeType, const std::vector & children2, const Token *def) -{ - SymbolDatabase *symbolDatabase = mData->mSymbolDatabase; - - Scope *nestedIn = const_cast(getNestedInScope(tokenList)); - - symbolDatabase->scopeList.push_back(Scope(nullptr, nullptr, nestedIn)); - Scope *scope = &symbolDatabase->scopeList.back(); - if (scopeType == Scope::ScopeType::eEnum) - scope->enumeratorList.reserve(children2.size()); - nestedIn->nestedList.push_back(scope); - scope->type = scopeType; - scope->classDef = def; - scope->check = nestedIn->check; - if (Token::Match(def, "if|for|while (")) { - std::map replaceVar; - for (const Token *vartok = def->tokAt(2); vartok; vartok = vartok->next()) { - if (!vartok->variable()) - continue; - if (vartok->variable()->nameToken() == vartok) { - const Variable *from = vartok->variable(); - scope->varlist.emplace_back(*from, scope); - Variable *to = &scope->varlist.back(); - replaceVar[from] = to; - mData->replaceVarDecl(from, to); - } - if (replaceVar.find(vartok->variable()) != replaceVar.end()) - const_cast(vartok)->variable(replaceVar[vartok->variable()]); - } - std::list &varlist = const_cast(def->scope())->varlist; - for (std::list::iterator var = varlist.begin(); var != varlist.end();) { - if (replaceVar.find(&(*var)) != replaceVar.end()) - varlist.erase(var++); - else - ++var; - } - } - scope->bodyStart = addtoken(tokenList, "{"); - tokenList->back()->scope(scope); - mData->scopeAccessControl[scope] = scope->defaultAccess(); - if (!children2.empty()) { - for (AstNodePtr astNode: children2) { - if (astNode->nodeType == "VisibilityAttr") - continue; - 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(scope->bodyStart), const_cast(scope->bodyEnd)); - mData->scopeAccessControl.erase(scope); - return scope; -} - -Token *clangimport::AstNode::createTokens(TokenList *tokenList) -{ - if (nodeType == ArraySubscriptExpr) { - Token *array = getChild(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); - bracket2->link(bracket1); - return bracket1; - } - if (nodeType == BinaryOperator) { - Token *tok1 = getChild(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 == BreakStmt) - return addtoken(tokenList, "break"); - 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\'"); - if (c == '\\') - return addtoken(tokenList, "\'\\\\\'"); - 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("\'")); - } - if (nodeType == CallExpr) - return createTokensCall(tokenList); - if (nodeType == CaseStmt) { - Token *caseToken = addtoken(tokenList, "case"); - Token *exprToken = getChild(0)->createTokens(tokenList); - caseToken->astOperand1(exprToken); - addtoken(tokenList, ":"); - children.back()->createTokens(tokenList); - return nullptr; - } - if (nodeType == ClassTemplateDecl) { - for (AstNodePtr child: children) { - if (child->nodeType == ClassTemplateSpecializationDecl) - child->createTokens(tokenList); - } - return nullptr; - } - if (nodeType == ClassTemplateSpecializationDecl) { - createTokensForCXXRecord(tokenList); - return nullptr; - } - if (nodeType == ConditionalOperator) { - Token *expr1 = getChild(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); - tok2->astOperand2(expr3); - tok1->astOperand1(expr1); - tok1->astOperand2(tok2); - return tok1; - } - if (nodeType == CompoundAssignOperator) { - Token *lhs = getChild(0)->createTokens(tokenList); - Token *assign = addtoken(tokenList, getSpelling()); - Token *rhs = children[1]->createTokens(tokenList); - assign->astOperand1(lhs); - assign->astOperand2(rhs); - return assign; - } - if (nodeType == CompoundStmt) { - for (AstNodePtr child: children) { - child->createTokens(tokenList); - if (!Token::Match(tokenList->back(), "[;{}]")) - child->addtoken(tokenList, ";"); - } - return nullptr; - } - if (nodeType == ConstantExpr) - return children.back()->createTokens(tokenList); - if (nodeType == ContinueStmt) - return addtoken(tokenList, "continue"); - if (nodeType == CStyleCastExpr) { - Token *par1 = addtoken(tokenList, "("); - addTypeTokens(tokenList, '\'' + getType() + '\''); - Token *par2 = addtoken(tokenList, ")"); - par1->link(par2); - par2->link(par1); - par1->astOperand1(getChild(0)->createTokens(tokenList)); - return par1; - } - if (nodeType == CXXBindTemporaryExpr) - return getChild(0)->createTokens(tokenList); - 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 getChild(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; - } - if (nodeType == CXXDeleteExpr) { - addtoken(tokenList, "delete"); - getChild(0)->createTokens(tokenList); - return nullptr; - } - if (nodeType == CXXDestructorDecl) { - createTokensFunctionDecl(tokenList); - return nullptr; - } - if (nodeType == CXXForRangeStmt) { - Token *forToken = addtoken(tokenList, "for"); - Token *par1 = addtoken(tokenList, "("); - AstNodePtr varDecl; - if (children[6]->nodeType == DeclStmt) - varDecl = getChild(6)->getChild(0); - else - varDecl = getChild(5)->getChild(0); - varDecl->mExtTokens.pop_back(); - varDecl->children.clear(); - Token *expr1 = varDecl->createTokens(tokenList); - Token *colon = addtoken(tokenList, ":"); - AstNodePtr range; - for (int i = 0; i < 2; i++) { - if (children[i] && children[i]->nodeType == DeclStmt && children[i]->getChild(0)->nodeType == VarDecl) { - range = children[i]->getChild(0)->getChild(0); - break; - } - } - if (!range) - throw InternalError(tokenList->back(), "Failed to import CXXForRangeStmt. Range?"); - Token *expr2 = range->createTokens(tokenList); - 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); - 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; - } - if (nodeType == CXXMemberCallExpr) - return createTokensCall(tokenList); - if (nodeType == CXXNewExpr) { - Token *newtok = addtoken(tokenList, "new"); - if (children.size() == 1 && getChild(0)->nodeType == CXXConstructExpr) { - newtok->astOperand1(getChild(0)->createTokens(tokenList)); - return newtok; - } - 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, "["); - getChild(0)->createTokens(tokenList); - Token *bracket2 = addtoken(tokenList, "]"); - bracket1->link(bracket2); - bracket2->link(bracket1); - } - return newtok; - } - if (nodeType == CXXNullPtrLiteralExpr) - return addtoken(tokenList, "nullptr"); - if (nodeType == CXXOperatorCallExpr) - return createTokensCall(tokenList); - if (nodeType == CXXRecordDecl) { - createTokensForCXXRecord(tokenList); - return nullptr; - } - if (nodeType == CXXStaticCastExpr || nodeType == CXXFunctionalCastExpr) { - Token *cast = addtoken(tokenList, getSpelling()); - Token *par1 = addtoken(tokenList, "("); - Token *expr = getChild(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 getChild(0)->createTokens(tokenList); - if (nodeType == CXXTemporaryObjectExpr && !children.empty()) - return getChild(0)->createTokens(tokenList); - if (nodeType == CXXThisExpr) - return addtoken(tokenList, "this"); - if (nodeType == CXXThrowExpr) { - Token *t = addtoken(tokenList, "throw"); - t->astOperand1(getChild(0)->createTokens(tokenList)); - return t; - } - if (nodeType == DeclRefExpr) { - int addrIndex = mExtTokens.size() - 1; - while (addrIndex > 1 && mExtTokens[addrIndex].compare(0,2,"0x") != 0) - --addrIndex; - const std::string addr = mExtTokens[addrIndex]; - std::string name = unquote(getSpelling()); - Token *reftok = addtoken(tokenList, name.empty() ? "" : name); - mData->ref(addr, reftok); - return reftok; - } - if (nodeType == DeclStmt) - return getChild(0)->createTokens(tokenList); - if (nodeType == DefaultStmt) { - addtoken(tokenList, "default"); - addtoken(tokenList, ":"); - children.back()->createTokens(tokenList); - return nullptr; - } - if (nodeType == DoStmt) { - addtoken(tokenList, "do"); - createScope(tokenList, Scope::ScopeType::eDo, getChild(0), tokenList->back()); - 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; - } - if (nodeType == EnumConstantDecl) { - Token *nameToken = addtoken(tokenList, getSpelling()); - Scope *scope = const_cast(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; - } - if (nodeType == EnumDecl) { - int colIndex = mExtTokens.size() - 1; - while (colIndex > 0 && mExtTokens[colIndex].compare(0,4,"col:") != 0 && mExtTokens[colIndex].compare(0,5,"line:") != 0) - --colIndex; - if (colIndex == 0) - return nullptr; - - mData->enumValue = 0; - Token *enumtok = addtoken(tokenList, "enum"); - Token *nametok = nullptr; - { - int nameIndex = mExtTokens.size() - 1; - while (nameIndex > colIndex && mExtTokens[nameIndex][0] == '\'') - --nameIndex; - if (nameIndex > colIndex) - nametok = addtoken(tokenList, mExtTokens[nameIndex]); - if (mExtTokens.back()[0] == '\'') { - addtoken(tokenList, ":"); - addTypeTokens(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(enumscope->bodyEnd)->deletePrevious(); - - // Create enum type - mData->mSymbolDatabase->typeList.push_back(Type(enumtok, enumscope, enumtok->scope())); - enumscope->definedType = &mData->mSymbolDatabase->typeList.back(); - if (nametok) - const_cast(enumtok->scope())->definedTypesMap[nametok->str()] = enumscope->definedType; - - return nullptr; - } - if (nodeType == ExprWithCleanups) - return getChild(0)->createTokens(tokenList); - if (nodeType == FieldDecl) - return createTokensVarDecl(tokenList); - if (nodeType == FloatingLiteral) - return addtoken(tokenList, mExtTokens.back()); - if (nodeType == ForStmt) { - Token *forToken = addtoken(tokenList, "for"); - Token *par1 = addtoken(tokenList, "("); - Token *expr1 = getChild(0) ? children[0]->createTokens(tokenList) : nullptr; - Token *sep1 = addtoken(tokenList, ";"); - Token *expr2 = children[2] ? children[2]->createTokens(tokenList) : nullptr; - Token *sep2 = addtoken(tokenList, ";"); - Token *expr3 = children[3] ? children[3]->createTokens(tokenList) : nullptr; - Token *par2 = addtoken(tokenList, ")"); - par1->link(par2); - par2->link(par1); - 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); - return nullptr; - } - if (nodeType == FunctionDecl) { - createTokensFunctionDecl(tokenList); - return nullptr; - } - if (nodeType == FunctionTemplateDecl) { - bool first = true; - for (AstNodePtr child: children) { - if (child->nodeType == FunctionDecl) { - if (!first) - child->createTokens(tokenList); - first = false; - } - } - return nullptr; - } - if (nodeType == GotoStmt) { - addtoken(tokenList, "goto"); - addtoken(tokenList, unquote(mExtTokens[mExtTokens.size() - 2])); - addtoken(tokenList, ";"); - return nullptr; - } - if (nodeType == IfStmt) { - 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]; - } - - Token *iftok = addtoken(tokenList, "if"); - Token *par1 = addtoken(tokenList, "("); - par1->astOperand1(iftok); - par1->astOperand2(cond->createTokens(tokenList)); - Token *par2 = addtoken(tokenList, ")"); - par1->link(par2); - par2->link(par1); - createScope(tokenList, Scope::ScopeType::eIf, thenCode, iftok); - if (elseCode) { - elseCode->addtoken(tokenList, "else"); - createScope(tokenList, Scope::ScopeType::eElse, elseCode, tokenList->back()); - } - return nullptr; - } - if (nodeType == ImplicitCastExpr) { - Token *expr = getChild(0)->createTokens(tokenList); - if (!expr->valueType() || contains(mExtTokens, "")) - setValueType(expr); - return expr; - } - 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); - return start; - } - if (nodeType == IntegerLiteral) - return addtoken(tokenList, mExtTokens.back()); - if (nodeType == LabelStmt) { - addtoken(tokenList, unquote(mExtTokens.back())); - addtoken(tokenList, ":"); - for (auto child: children) - child->createTokens(tokenList); - return nullptr; - } - if (nodeType == LinkageSpecDecl) - return nullptr; - if (nodeType == MaterializeTemporaryExpr) - return getChild(0)->createTokens(tokenList); - if (nodeType == MemberExpr) { - Token *s = getChild(0)->createTokens(tokenList); - Token *dot = addtoken(tokenList, "."); - std::string memberName = getSpelling(); - if (memberName.compare(0, 2, "->") == 0) { - dot->originalName("->"); - memberName = memberName.substr(2); - } else if (memberName.compare(0, 1, ".") == 0) { - memberName = memberName.substr(1); - } - if (memberName.empty()) - memberName = ""; - Token *member = addtoken(tokenList, memberName); - mData->ref(mExtTokens.back(), member); - dot->astOperand1(s); - dot->astOperand2(member); - return dot; - } - if (nodeType == NamespaceDecl) { - if (children.empty()) - return nullptr; - Token *defToken = addtoken(tokenList, "namespace"); - const std::string &s = mExtTokens[mExtTokens.size() - 2]; - Token *nameToken = (s.compare(0,4,"col:")==0 || s.compare(0,5,"line:")==0) ? - addtoken(tokenList, mExtTokens.back()) : nullptr; - Scope *scope = createScope(tokenList, Scope::ScopeType::eNamespace, children, defToken); - if (nameToken) - scope->className = nameToken->str(); - return nullptr; - } - if (nodeType == NullStmt) - return addtoken(tokenList, ";"); - if (nodeType == ParenExpr) { - Token *par1 = addtoken(tokenList, "("); - Token *expr = getChild(0)->createTokens(tokenList); - Token *par2 = addtoken(tokenList, ")"); - par1->link(par2); - par2->link(par1); - return expr; - } - if (nodeType == RecordDecl) { - const Token *classDef = addtoken(tokenList, "struct"); - 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(); - if (!recordName.empty()) { - recordScope->className = recordName; - const_cast(classDef->scope())->definedTypesMap[recordName] = recordScope->definedType; - } - - return nullptr; - } - if (nodeType == ReturnStmt) { - Token *tok1 = addtoken(tokenList, "return"); - if (!children.empty()) { - getChild(0)->setValueType(tok1); - tok1->astOperand1(getChild(0)->createTokens(tokenList)); - } - return tok1; - } - if (nodeType == StringLiteral) - return addtoken(tokenList, mExtTokens.back()); - 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); - return nullptr; - } - if (nodeType == TypedefDecl) { - addtoken(tokenList, "typedef"); - addTypeTokens(tokenList, getType()); - return addtoken(tokenList, getSpelling()); - } - if (nodeType == UnaryOperator) { - int index = (int)mExtTokens.size() - 1; - while (index > 0 && mExtTokens[index][0] != '\'') - --index; - Token *unop = addtoken(tokenList, unquote(mExtTokens[index])); - unop->astOperand1(getChild(0)->createTokens(tokenList)); - return unop; - } - if (nodeType == UnaryExprOrTypeTraitExpr) { - Token *tok1 = addtoken(tokenList, getSpelling()); - Token *par1 = addtoken(tokenList, "("); - if (children.empty()) - addTypeTokens(tokenList, mExtTokens.back()); - else { - AstNodePtr child = getChild(0); - if (child && child->nodeType == ParenExpr) - child = child->getChild(0); - Token *expr = child->createTokens(tokenList); - child->setValueType(expr); - par1->astOperand2(expr); - } - Token *par2 = addtoken(tokenList, ")"); - par1->link(par2); - par2->link(par1); - par1->astOperand1(tok1); - par1->astOperand2(par1->next()); - setValueType(par1); - return par1; - } - if (nodeType == VarDecl) - return createTokensVarDecl(tokenList); - if (nodeType == WhileStmt) { - AstNodePtr cond = children[children.size() - 2]; - AstNodePtr body = children.back(); - Token *whiletok = addtoken(tokenList, "while"); - Token *par1 = addtoken(tokenList, "("); - par1->astOperand1(whiletok); - par1->astOperand2(cond->createTokens(tokenList)); - Token *par2 = addtoken(tokenList, ")"); - par1->link(par2); - par2->link(par1); - createScope(tokenList, Scope::ScopeType::eWhile, body, whiletok); - return nullptr; - } - return addtoken(tokenList, "?" + nodeType + "?"); -} - -Token * clangimport::AstNode::createTokensCall(TokenList *tokenList) -{ - int firstParam; - Token *f; - if (nodeType == CXXOperatorCallExpr) { - firstParam = 2; - Token *obj = getChild(1)->createTokens(tokenList); - Token *dot = addtoken(tokenList, "."); - Token *op = getChild(0)->createTokens(tokenList); - dot->astOperand1(obj); - dot->astOperand2(op); - f = dot; - } else { - firstParam = 1; - f = getChild(0)->createTokens(tokenList); - } - f->setValueType(nullptr); - Token *par1 = addtoken(tokenList, "("); - par1->astOperand1(f); - int args = 0; - while (args < children.size() && children[args]->nodeType != CXXDefaultArgExpr) - args++; - Token *child = nullptr; - for (int c = firstParam; c < args; ++c) { - if (child) { - Token *comma = addtoken(tokenList, ","); - comma->setValueType(nullptr); - comma->astOperand1(child); - comma->astOperand2(children[c]->createTokens(tokenList)); - child = comma; - } else { - child = children[c]->createTokens(tokenList); - } - } - par1->astOperand2(child); - Token *par2 = addtoken(tokenList, ")"); - par1->link(par2); - par2->link(par1); - return par1; -} - -void clangimport::AstNode::createTokensFunctionDecl(TokenList *tokenList) -{ - const bool prev = contains(mExtTokens, "prev"); - const bool hasBody = !children.empty() && children.back()->nodeType == CompoundStmt; - 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(); - } - - if (mExtTokens.size() > 4 && mExtTokens[1] == "parent") - addFullScopeNameTokens(tokenList, mData->getScope(mExtTokens[2])); - - Token *nameToken = addtoken(tokenList, getSpelling() + getTemplateParameters()); - Scope *nestedIn = const_cast(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; - else if (nodeType == CXXDestructorDecl) - nestedIn->functionList.back().type = Function::Type::eDestructor; - else - nestedIn->functionList.back().retDef = startToken; - } - - Function * const function = const_cast(nameToken->function()); - - 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, ","); - const Type *recordType = addTypeTokens(tokenList, child->mExtTokens.back(), nestedIn); - const Token *typeEndToken = tokenList->back(); - const std::string spelling = child->getSpelling(); - Token *vartok = nullptr; - if (!spelling.empty()) - vartok = child->addtoken(tokenList, spelling); - if (!prev) { - function->argumentList.push_back(Variable(vartok, child->getType(), nullptr, typeEndToken, i, AccessControl::Argument, recordType, scope)); - 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]; - mData->ref(addr, vartok); - } - } - Token *par2 = addtoken(tokenList, ")"); - par1->link(par2); - 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); - bodyEnd->link(bodyStart); - } else { - if (nodeType == CXXConstructorDecl && contains(mExtTokens, "default")) { - addtoken(tokenList, "="); - addtoken(tokenList, "default"); - } - - addtoken(tokenList, ";"); - } -} - -void clangimport::AstNode::createTokensForCXXRecord(TokenList *tokenList) -{ - 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(); - /*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 - if (isDefinition()) { - std::vector children2; - for (AstNodePtr child: children) { - if (child->nodeType == CXXConstructorDecl || - child->nodeType == CXXDestructorDecl || - child->nodeType == CXXMethodDecl || - child->nodeType == FieldDecl || - child->nodeType == VarDecl || - child->nodeType == AccessSpecDecl || - child->nodeType == TypedefDecl) - children2.push_back(child); - } - Scope *scope = createScope(tokenList, isStruct ? Scope::ScopeType::eStruct : Scope::ScopeType::eClass, children2, classToken); - const std::string addr = mExtTokens[0]; - mData->scopeDecl(addr, scope); - scope->className = className; - mData->mSymbolDatabase->typeList.push_back(Type(classToken, scope, classToken->scope())); - scope->definedType = &mData->mSymbolDatabase->typeList.back(); - const_cast(classToken->scope())->definedTypesMap[className] = scope->definedType; - } - addtoken(tokenList, ";"); - const_cast(tokenList->back())->scope(classToken->scope()); -} - -Token * clangimport::AstNode::createTokensVarDecl(TokenList *tokenList) -{ - const std::string addr = mExtTokens.front(); - if (contains(mExtTokens, "static")) - 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]; - const Token *startToken = tokenList->back(); - const ::Type *recordType = addTypeTokens(tokenList, type); - if (!startToken) - startToken = tokenList->front(); - else if (startToken->str() != "static") - startToken = startToken->next(); - Token *vartok1 = addtoken(tokenList, name); - Scope *scope = const_cast(tokenList->back()->scope()); - scope->varlist.push_back(Variable(vartok1, unquote(type), startToken, vartok1->previous(), 0, scope->defaultAccess(), recordType, scope)); - mData->varDecl(addr, vartok1, &scope->varlist.back()); - if (mExtTokens.back() == "cinit" && !children.empty()) { - Token *eq = addtoken(tokenList, "="); - eq->astOperand1(vartok1); - eq->astOperand2(children.back()->createTokens(tokenList)); - return eq; - } else if (mExtTokens.back() == "callinit") { - Token *par1 = addtoken(tokenList, "("); - par1->astOperand1(vartok1); - par1->astOperand2(getChild(0)->createTokens(tokenList)); - Token *par2 = addtoken(tokenList, ")"); - par1->link(par2); - par2->link(par1); - return par1; - } else if (mExtTokens.back() == "listinit") { - return getChild(0)->createTokens(tokenList); - } - return vartok1; -} - -static void setTypes(TokenList *tokenList) -{ - for (Token *tok = tokenList->front(); tok; tok = tok->next()) { - if (Token::simpleMatch(tok, "sizeof (")) { - for (Token *typeToken = tok->tokAt(2); typeToken->str() != ")"; typeToken = typeToken->next()) { - if (typeToken->type()) - continue; - typeToken->type(typeToken->scope()->findType(typeToken->str())); - } - } - } -} - -static void setValues(Tokenizer *tokenizer, SymbolDatabase *symbolDatabase) -{ - const Settings * const settings = tokenizer->getSettings(); - - for (Scope &scope: symbolDatabase->scopeList) { - if (!scope.definedType) - continue; - - int typeSize = 0; - for (const Variable &var: scope.varlist) { - int mul = 1; - for (const auto &dim: var.dimensions()) { - mul *= dim.num; - } - if (var.valueType()) - typeSize += mul * var.valueType()->typeSize(*settings, true); - } - scope.definedType->sizeOf = typeSize; - } - - for (Token *tok = const_cast(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); - } - } -} - -void clangimport::parseClangAstDump(Tokenizer *tokenizer, std::istream &f) -{ - TokenList *tokenList = &tokenizer->list; - - tokenizer->createSymbolDatabase(); - SymbolDatabase *symbolDatabase = const_cast(tokenizer->getSymbolDatabase()); - symbolDatabase->scopeList.push_back(Scope(nullptr, nullptr, nullptr)); - symbolDatabase->scopeList.back().type = Scope::ScopeType::eGlobal; - symbolDatabase->scopeList.back().check = symbolDatabase; - - clangimport::Data data; - data.mSettings = tokenizer->getSettings(); - data.mSymbolDatabase = symbolDatabase; - 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; - if (!tree.empty() && line.substr(pos1) == "-<<>>") { - const int level = (pos1 - 1) / 2; - tree[level - 1]->children.push_back(nullptr); - 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 (pos1 == 1 && endsWith(nodeType, "Decl", 4)) { - if (!tree.empty()) - tree[0]->createTokens1(tokenList); - tree.clear(); - tree.push_back(std::make_shared(nodeType, ext, &data)); - continue; - } - - const int level = (pos1 - 1) / 2; - if (level == 0 || level > tree.size()) - continue; - - AstNodePtr newNode = std::make_shared(nodeType, ext, &data); - tree[level - 1]->children.push_back(newNode); - if (level >= tree.size()) - tree.push_back(newNode); - else - tree[level] = newNode; - } - - if (!tree.empty()) - tree[0]->createTokens1(tokenList); - - // Validation - for (const Token *tok = tokenList->front(); tok; tok = tok->next()) { - if (Token::Match(tok, "(|)|[|]|{|}") && !tok->link()) - throw InternalError(tok, "Token::link() is not set properly"); - } - - if (tokenList->front()) - tokenList->front()->assignIndexes(); - symbolDatabase->clangSetVariables(data.getVariableList()); - symbolDatabase->createSymbolDatabaseExprIds(); - tokenList->clangSetOrigFiles(); - setTypes(tokenList); - setValues(tokenizer, symbolDatabase); -} - diff --git a/lib/clangimport.h b/lib/clangimport.h deleted file mode 100644 index b6e0e3cb0..000000000 --- a/lib/clangimport.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 clangimportH -#define clangimportH -//--------------------------------------------------------------------------- - -#include - -class Tokenizer; - -namespace clangimport { - void parseClangAstDump(Tokenizer *tokenizer, std::istream &f); -} - -#endif diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index a96acf1cb..c36552af0 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -19,7 +19,6 @@ #include "check.h" #include "checkunusedfunctions.h" -#include "clangimport.h" #include "ctu.h" #include "library.h" #include "mathlib.h" @@ -320,154 +319,8 @@ const char * CppCheck::extraVersion() return ExtraVersion; } -static bool reportClangErrors(std::istream &is, std::function reportErr) -{ - std::string line; - while (std::getline(is, line)) { - if (line.empty() || line[0] == ' ' || line[0] == '`' || line[0] == '-') - continue; - - std::string::size_type pos3 = line.find(": error: "); - if (pos3 == std::string::npos) - pos3 = line.find(": fatal error:"); - if (pos3 == std::string::npos) - continue; - - // file:line:column: error: .... - const std::string::size_type pos2 = line.rfind(":", pos3 - 1); - const std::string::size_type pos1 = line.rfind(":", pos2 - 1); - - if (pos1 >= pos2 || pos2 >= pos3) - continue; - - const std::string filename = line.substr(0, pos1); - const std::string linenr = line.substr(pos1+1, pos2-pos1-1); - const std::string colnr = line.substr(pos2+1, pos3-pos2-1); - const std::string msg = line.substr(line.find(":", pos3+1) + 2); - - std::list locationList; - ErrorMessage::FileLocation loc; - loc.setfile(Path::toNativeSeparators(filename)); - loc.line = std::atoi(linenr.c_str()); - loc.column = std::atoi(colnr.c_str()); - locationList.push_back(loc); - ErrorMessage errmsg(locationList, - loc.getfile(), - Severity::error, - msg, - "syntaxError", - Certainty::normal); - reportErr(errmsg); - - return true; - } - return false; -} - unsigned int CppCheck::check(const std::string &path) { - if (mSettings.clang) { - if (!mSettings.quiet) - mErrorLogger.reportOut(std::string("Checking ") + path + "..."); - - const std::string lang = Path::isCPP(path) ? "-x c++" : "-x c"; - const std::string analyzerInfo = mSettings.buildDir.empty() ? std::string() : AnalyzerInformation::getAnalyzerInfoFile(mSettings.buildDir, path, ""); - const std::string clangcmd = analyzerInfo + ".clang-cmd"; - const std::string clangStderr = analyzerInfo + ".clang-stderr"; - const std::string clangAst = analyzerInfo + ".clang-ast"; - std::string exe = mSettings.clangExecutable; -#ifdef _WIN32 - // append .exe if it is not a path - if (Path::fromNativeSeparators(mSettings.clangExecutable).find('/') == std::string::npos) { - exe += ".exe"; - } -#endif - - std::string flags(lang + " "); - if (Path::isCPP(path) && !mSettings.standards.stdValue.empty()) - flags += "-std=" + mSettings.standards.stdValue + " "; - - for (const std::string &i: mSettings.includePaths) - flags += "-I" + i + " "; - - flags += getDefinesFlags(mSettings.userDefines); - - const std::string args2 = "-fsyntax-only -Xclang -ast-dump -fno-color-diagnostics " + flags + path; - const std::string redirect2 = analyzerInfo.empty() ? std::string("2>&1") : ("2> " + clangStderr); - if (!mSettings.buildDir.empty()) { - std::ofstream fout(clangcmd); - fout << exe << " " << args2 << " " << redirect2 << std::endl; - } else if (mSettings.verbose && !mSettings.quiet) { - mErrorLogger.reportOut(exe + " " + args2); - } - - std::string output2; - if (!mExecuteCommand(exe,split(args2),redirect2,&output2) || output2.find("TranslationUnitDecl") == std::string::npos) { - std::cerr << "Failed to execute '" << exe << " " << args2 << " " << redirect2 << "'" << std::endl; - return 0; - } - - // Ensure there are not syntax errors... - if (!mSettings.buildDir.empty()) { - std::ifstream fin(clangStderr); - auto reportError = [this](const ErrorMessage& errorMessage) { - reportErr(errorMessage); - }; - if (reportClangErrors(fin, reportError)) - return 0; - } else { - std::istringstream istr(output2); - auto reportError = [this](const ErrorMessage& errorMessage) { - reportErr(errorMessage); - }; - if (reportClangErrors(istr, reportError)) - return 0; - } - - if (!mSettings.buildDir.empty()) { - std::ofstream fout(clangAst); - fout << output2 << std::endl; - } - - try { - std::istringstream ast(output2); - Tokenizer tokenizer(&mSettings, this); - tokenizer.list.appendFileIfNew(path); - clangimport::parseClangAstDump(&tokenizer, ast); - ValueFlow::setValues(&tokenizer.list, const_cast(tokenizer.getSymbolDatabase()), this, &mSettings); - if (mSettings.debugnormal) - tokenizer.printDebugOutput(1); - checkNormalTokens(tokenizer); - - // create dumpfile - std::ofstream fdump; - std::string dumpFile; - createDumpFile(mSettings, path, tokenizer.list.getFiles(), nullptr, fdump, dumpFile); - if (fdump.is_open()) { - fdump << "" << std::endl; - fdump << " " << std::endl; - fdump << " " << std::endl; - fdump << " " << std::endl; - fdump << " " << std::endl; - tokenizer.dump(fdump); - fdump << "" << std::endl; - fdump << "" << std::endl; - fdump.close(); - } - - // run addons - executeAddons(dumpFile); - - } catch (const InternalError &e) { - internalError(path, e.errorMessage); - mExitCode = 1; // e.g. reflect a syntax error - } catch (const std::exception &e) { - internalError(path, e.what()); - } - - return mExitCode; - } - std::ifstream fin(path); return checkFile(Path::simplifyPath(path), emptyString, fin); } @@ -484,10 +337,7 @@ unsigned int CppCheck::check(const ImportProject::FileSettings &fs) temp.mSettings = mSettings; if (!temp.mSettings.userDefines.empty()) temp.mSettings.userDefines += ';'; - if (mSettings.clang) - temp.mSettings.userDefines += fs.defines; - else - temp.mSettings.userDefines += fs.cppcheckDefines(); + temp.mSettings.userDefines += fs.cppcheckDefines(); temp.mSettings.includePaths = fs.includePaths; temp.mSettings.userUndefs.insert(fs.undefs.cbegin(), fs.undefs.cend()); if (fs.standard.find("++") != std::string::npos) @@ -496,10 +346,6 @@ unsigned int CppCheck::check(const ImportProject::FileSettings &fs) temp.mSettings.standards.setC(fs.standard); if (fs.platformType != Settings::Unspecified) temp.mSettings.platform(fs.platformType); - if (mSettings.clang) { - temp.mSettings.includePaths.insert(temp.mSettings.includePaths.end(), fs.systemIncludePaths.cbegin(), fs.systemIncludePaths.cend()); - return temp.check(Path::simplifyPath(fs.filename)); - } std::ifstream fin(fs.filename); unsigned int returnValue = temp.checkFile(Path::simplifyPath(fs.filename), fs.cfg, fin); mSettings.nomsg.addSuppressions(temp.mSettings.nomsg.getSuppressions()); @@ -954,10 +800,6 @@ void CppCheck::checkNormalTokens(const Tokenizer &tokenizer) check->runChecks(&tokenizer, &mSettings, this); } - if (mSettings.clang) - // TODO: Use CTU for Clang analysis - return; - // Analyse the tokens.. CTU::FileInfo *fi1 = CTU::getFileInfo(&tokenizer); diff --git a/lib/cppcheck.vcxproj b/lib/cppcheck.vcxproj index 2c40cfe10..44cb35f9d 100644 --- a/lib/cppcheck.vcxproj +++ b/lib/cppcheck.vcxproj @@ -75,7 +75,6 @@ - @@ -136,7 +135,6 @@ - @@ -572,4 +570,4 @@ xcopy "$(SolutionDir)platforms" "$(OutDir)platforms" /E /I /D /Y - \ No newline at end of file + diff --git a/lib/importproject.cpp b/lib/importproject.cpp index e2c525de0..773d79cda 100644 --- a/lib/importproject.cpp +++ b/lib/importproject.cpp @@ -1143,8 +1143,6 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings *setti guiProject.platform = node->GetText(); else if (strcmp(node->Name(), CppcheckXml::AnalyzeAllVsConfigsElementName) == 0) guiProject.analyzeAllVsConfigs = node->GetText(); - else if (strcmp(node->Name(), CppcheckXml::Parser) == 0) - temp.clang = true; else if (strcmp(node->Name(), CppcheckXml::AddonsElementName) == 0) temp.addons = readXmlStringList(node, "", CppcheckXml::AddonElementName, nullptr); else if (strcmp(node->Name(), CppcheckXml::TagsElementName) == 0) @@ -1190,7 +1188,6 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings *setti settings->userDefines = temp.userDefines; settings->userUndefs = temp.userUndefs; settings->addons = temp.addons; - settings->clang = temp.clang; settings->clangTidy = temp.clangTidy; for (const std::string &p : paths) diff --git a/lib/importproject.h b/lib/importproject.h index 7f0b99779..8dcf1eaad 100644 --- a/lib/importproject.h +++ b/lib/importproject.h @@ -125,7 +125,6 @@ namespace CppcheckXml { const char BuildDirElementName[] = "builddir"; const char ImportProjectElementName[] = "importproject"; const char AnalyzeAllVsConfigsElementName[] = "analyze-all-vs-configs"; - const char Parser[] = "parser"; const char BugHunting[] = "bug-hunting"; const char IncludeDirElementName[] = "includedir"; const char DirElementName[] = "dir"; diff --git a/lib/lib.pri b/lib/lib.pri index 164686bc6..25049033d 100644 --- a/lib/lib.pri +++ b/lib/lib.pri @@ -32,7 +32,6 @@ HEADERS += $${PWD}/analyzerinfo.h \ $${PWD}/checkunusedfunctions.h \ $${PWD}/checkunusedvar.h \ $${PWD}/checkvaarg.h \ - $${PWD}/clangimport.h \ $${PWD}/cppcheck.h \ $${PWD}/ctu.h \ $${PWD}/errorlogger.h \ @@ -90,7 +89,6 @@ SOURCES += $${PWD}/analyzerinfo.cpp \ $${PWD}/checkunusedfunctions.cpp \ $${PWD}/checkunusedvar.cpp \ $${PWD}/checkvaarg.cpp \ - $${PWD}/clangimport.cpp \ $${PWD}/cppcheck.cpp \ $${PWD}/ctu.cpp \ $${PWD}/errorlogger.cpp \ diff --git a/lib/settings.cpp b/lib/settings.cpp index f4e16ce5a..f02061faf 100644 --- a/lib/settings.cpp +++ b/lib/settings.cpp @@ -36,8 +36,6 @@ Settings::Settings() checkHeaders(true), checkLibrary(false), checkUnusedTemplates(true), - clang(false), - clangExecutable("clang"), clangTidy(false), daca(false), debugBugHunting(false), diff --git a/lib/settings.h b/lib/settings.h index 682a7932d..7a0543773 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -140,12 +140,6 @@ public: /** Check unused/uninstantiated templates */ bool checkUnusedTemplates; - /** Use Clang */ - bool clang; - - /** Custom Clang executable */ - std::string clangExecutable; - /** Use clang-tidy */ bool clangTidy; diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 28d4b2533..d9aa63256 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1823,69 +1823,6 @@ void SymbolDatabase::validate() const //validateVariables(); } -void SymbolDatabase::clangSetVariables(const std::vector &variableList) -{ - mVariableList = variableList; -} - -Variable::Variable(const Token *name_, const std::string &clangType, const Token *typeStart, - const Token *typeEnd, nonneg int index_, AccessControl access_, - const Type *type_, const Scope *scope_) - : mNameToken(name_), - mTypeStartToken(typeStart), - mTypeEndToken(typeEnd), - mIndex(index_), - mAccess(access_), - mFlags(0), - mType(type_), - mScope(scope_), - mValueType(nullptr) -{ - if (!mTypeStartToken && mTypeEndToken) { - mTypeStartToken = mTypeEndToken; - while (Token::Match(mTypeStartToken->previous(), "%type%|*|&")) - mTypeStartToken = mTypeStartToken->previous(); - } - - while (Token::Match(mTypeStartToken, "const|struct|static")) { - if (mTypeStartToken->str() == "static") - setFlag(fIsStatic, true); - mTypeStartToken = mTypeStartToken->next(); - } - - if (Token::simpleMatch(mTypeEndToken, "&")) - setFlag(fIsReference, true); - else if (Token::simpleMatch(mTypeEndToken, "&&")) { - setFlag(fIsReference, true); - setFlag(fIsRValueRef, true); - } - - std::string::size_type pos = clangType.find("["); - if (pos != std::string::npos) { - setFlag(fIsArray, true); - do { - const std::string::size_type pos1 = pos+1; - pos = clangType.find("]", pos1); - Dimension dim; - dim.tok = nullptr; - dim.known = pos > pos1; - if (pos > pos1) - dim.num = MathLib::toLongNumber(clangType.substr(pos1, pos-pos1)); - else - dim.num = 0; - mDimensions.push_back(dim); - ++pos; - } while (pos < clangType.size() && clangType[pos] == '['); - } - - // Is there initialization in variable declaration - const Token *initTok = mNameToken ? mNameToken->next() : nullptr; - while (initTok && initTok->str() == "[") - initTok = initTok->link()->next(); - if (Token::Match(initTok, "=|{") || (initTok && initTok->isSplittedVarDeclEq())) - setFlag(fIsInit, true); -} - Variable::Variable(const Variable &var, const Scope *scope) : mValueType(nullptr) { @@ -2233,39 +2170,6 @@ Function::Function(const Tokenizer *mTokenizer, } } -Function::Function(const Token *tokenDef, const std::string &clangType) - : 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), - functionPointerUsage(nullptr), - mFlags(0) -{ - // operator function - if (::isOperator(tokenDef)) { - isOperator(true); - - // 'operator =' is special - if (tokenDef->str() == "operator=") - type = Function::eOperatorEqual; - } - - setFlags(tokenDef, tokenDef->scope()); - - if (endsWith(clangType, " const", 6)) - isConst(true); -} - const Token *Function::setFlags(const Token *tok1, const Scope *scope) { // look for end of previous statement @@ -6028,30 +5932,7 @@ static const Token * parsedecl(const Token *type, ValueType * const valuetype, V parsedecl(type->type()->typeStart, valuetype, defaultSignedness, settings); else if (type->str() == "const") valuetype->constness |= (1 << (valuetype->pointer - pointer0)); - else if (settings->clang && type->str().size() > 2 && type->str().find("::") < type->str().find("<")) { - TokenList typeTokens(settings); - std::string::size_type pos1 = 0; - do { - std::string::size_type pos2 = type->str().find("::", pos1); - if (pos2 == std::string::npos) { - typeTokens.addtoken(type->str().substr(pos1), 0, 0, 0, false); - break; - } - typeTokens.addtoken(type->str().substr(pos1, pos2 - pos1), 0, 0, 0, false); - typeTokens.addtoken("::", 0, 0, 0, false); - pos1 = pos2 + 2; - } while (pos1 < type->str().size()); - const Library::Container *container = settings->library.detectContainer(typeTokens.front()); - if (container) { - valuetype->type = ValueType::Type::CONTAINER; - valuetype->container = container; - } else { - const Scope *scope = type->scope(); - valuetype->typeScope = scope->check->findScope(typeTokens.front(), scope); - if (valuetype->typeScope) - valuetype->type = (scope->type == Scope::ScopeType::eClass) ? ValueType::Type::RECORD : ValueType::Type::NONSTD; - } - } else if (const Library::Container *container = settings->library.detectContainer(type)) { + else if (const Library::Container *container = settings->library.detectContainer(type)) { valuetype->type = ValueType::Type::CONTAINER; valuetype->container = container; while (Token::Match(type, "%name%|::|<")) { diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 6a20da32c..da8a84550 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -237,10 +237,6 @@ public: evaluate(settings); } - Variable(const Token *name_, const std::string &clangType, const Token *typeStart, - const Token *typeEnd, nonneg int index_, AccessControl access_, - const Type *type_, const Scope *scope_); - Variable(const Variable &var, const Scope *scope); Variable(const Variable &var); @@ -746,7 +742,6 @@ 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 &clangType); const std::string &name() const { return tokenDef->str(); @@ -1384,7 +1379,6 @@ public: /** Set array dimensions when valueflow analysis is completed */ void setArrayDimensionsUsingValueFlow(); - void clangSetVariables(const std::vector &variableList); void createSymbolDatabaseExprIds(); private: diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index d2d95e0ff..e6a55903a 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -169,11 +169,6 @@ 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 7b644f935..ca8857129 100644 --- a/lib/tokenlist.h +++ b/lib/tokenlist.h @@ -186,8 +186,6 @@ public: */ void simplifyStdType(); - void clangSetOrigFiles(); - bool isKeyword(const std::string &str) const; private: diff --git a/man/manual.md b/man/manual.md index ef18a7981..4cdb6c125 100644 --- a/man/manual.md +++ b/man/manual.md @@ -132,18 +132,6 @@ directory individually. The following command ignores both the src/b and src/c d cppcheck -isrc/b -isrc/c -### Clang parser (experimental) - -By default Cppcheck uses an internal C/C++ parser. However there is an experimental option to use the Clang parser instead. - -Install `clang`. Then use Cppcheck option `--clang`. - -Technically, Cppcheck will execute `clang` with its `-ast-dump` option. The Clang output is then imported and converted into -the normal Cppcheck format. And then normal Cppcheck analysis is performed on that. - -You can also pass a custom Clang executable to the option by using for example `--clang=clang-10`. You can also pass it -with a path. On Windows it will append the `.exe` extension unless you use a path. - ## Severities The possible severities for messages are: diff --git a/test/cli/test-clang-import.py b/test/cli/test-clang-import.py deleted file mode 100644 index c4af2ce09..000000000 --- a/test/cli/test-clang-import.py +++ /dev/null @@ -1,124 +0,0 @@ - -# python -m pytest test-clang-import.py - -import os -import re -import subprocess -import pytest -from testutils import cppcheck - -try: - subprocess.call(['clang', '--version']) -except OSError: - pytest.skip("'clang' does not exist", allow_module_level=True) - - -def get_debug_section(title, stdout): - s = re.sub(r'0x[0-9a-fA-F]+', '0x12345678', stdout) - s = re.sub(r'nestedIn: Struct', 'nestedIn: Class', s) - s = re.sub(r'classDef: struct', 'classDef: class', s) - s = re.sub(r'isInline: [a-z]+', 'isInline: ---', s) - s = re.sub(r'needInitialization: .*', 'needInitialization: ---', s) - s = re.sub(r'functionOf: .*', 'functionOf: ---', s) - s = re.sub(r'0x12345678 Struct', '0x12345678 Class', s) - - if title == '##AST': - # TODO set types - s = re.sub(r"return '[a-zA-Z0-9: *]+'", "return", s) - - pos1 = s.find(title) - assert pos1 > 0, 'title not found' - pos1 = s.find('\n', pos1) + 1 - assert pos1 > 0 - pos2 = s.find("\n##", pos1) - if pos2 < 0: - return s[pos1:] - return s[pos1:pos2-1] - - -def check_symbol_database(code): - testfile = 'test.cpp' - with open(testfile, 'w+t') as f: - f.write(code) - ret1, stdout1, _ = cppcheck(['--clang', '--debug', '-v', testfile]) - ret2, stdout2, _ = cppcheck(['--debug', '-v', testfile]) - os.remove(testfile) - assert 0 == ret1, stdout1 - assert 0 == ret2, stdout2 - assert get_debug_section('### Symbol database', stdout1) == get_debug_section('### Symbol database', stdout2) - - -def check_ast(code): - testfile = 'test.cpp' - with open(testfile, 'w+t') as f: - f.write(code) - ret1, stdout1, _ = cppcheck(['--clang', '--debug', '-v', testfile]) - ret2, stdout2, _ = cppcheck(['--debug', '-v', testfile]) - os.remove(testfile) - assert 0 == ret1, stdout1 - assert 0 == ret2, stdout1 - assert get_debug_section('##AST', stdout1) == get_debug_section('##AST', stdout2) - - -def todo_check_ast(code): - testfile = 'test.cpp' - with open(testfile, 'w+t') as f: - f.write(code) - ret1, stdout1, _ = cppcheck(['--clang', '--debug', '-v', testfile]) - ret2, stdout2, _ = cppcheck(['--debug', '-v', testfile]) - os.remove(testfile) - assert 0 == ret1, stdout1 - assert 0 == ret2, stdout2 - assert get_debug_section('##AST', stdout1) != get_debug_section('##AST', stdout2) - - - -def test_symbol_database_1(): - check_symbol_database('int main(){return 0;}') - -def test_symbol_database_2(): - check_symbol_database('struct Foo { void f(); }; void Foo::f() {}') - -def test_symbol_database_3(): - check_symbol_database('struct Fred { int a; }; int b; void f(int c, int d) { int e; }') - -def test_symbol_database_4(): - check_symbol_database('void f(const int x) {}') - -def test_symbol_database_5(): - check_symbol_database('void f(int);') - -def test_symbol_database_6(): - check_symbol_database('inline static int foo(int x) { return x; }') - -def test_symbol_database_7(): - check_symbol_database('struct S {int x;}; void f(struct S *s) {}') - -def test_symbol_database_class_access_1(): - check_symbol_database('class Fred { void foo ( ) {} } ;') - -def test_symbol_database_class_access_2(): - check_symbol_database('class Fred { protected: void foo ( ) {} } ;') - -def test_symbol_database_class_access_3(): - check_symbol_database('class Fred { public: void foo ( ) {} } ;') - -def test_symbol_database_operator(): - check_symbol_database('struct Fred { void operator=(int x); };') - -def test_symbol_database_struct_1(): - check_symbol_database('struct S {};') - -def test_ast_calculations(): - check_ast('int x = 5; int y = (x + 4) * 2;') - check_ast('long long dostuff(int x) { return x ? 3 : 5; }') - -def test_ast_control_flow(): - check_ast('void foo(int x) { if (x > 5){} }') - check_ast('int dostuff() { for (int x = 0; x < 10; x++); }') - check_ast('void foo(int x) { switch (x) {case 1: break; } }') - check_ast('void foo(int a, int b, int c) { foo(a,b,c); }') - -def test_ast(): - check_ast('struct S { int x; }; S* foo() { return new S(); }') - diff --git a/test/testclangimport.cpp b/test/testclangimport.cpp deleted file mode 100644 index f5e5fcbd4..000000000 --- a/test/testclangimport.cpp +++ /dev/null @@ -1,1303 +0,0 @@ -// Cppcheck - A tool for static C/C++ code analysis -// Copyright (C) 2007-2021 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 "clangimport.h" -#include "settings.h" -#include "symboldatabase.h" -#include "tokenize.h" -#include "testsuite.h" - - -class TestClangImport: public TestFixture { -public: - TestClangImport() - :TestFixture("TestClangImport") { - } - - -private: - void run() OVERRIDE { - TEST_CASE(breakStmt); - TEST_CASE(callExpr); - TEST_CASE(caseStmt1); - TEST_CASE(characterLiteral); - TEST_CASE(class1); - TEST_CASE(classTemplateDecl1); - TEST_CASE(classTemplateDecl2); - TEST_CASE(conditionalExpr); - TEST_CASE(compoundAssignOperator); - TEST_CASE(continueStmt); - TEST_CASE(cstyleCastExpr); - TEST_CASE(cxxBoolLiteralExpr); - TEST_CASE(cxxConstructorDecl1); - TEST_CASE(cxxConstructorDecl2); - TEST_CASE(cxxConstructExpr1); - TEST_CASE(cxxConstructExpr2); - TEST_CASE(cxxConstructExpr3); - TEST_CASE(cxxDeleteExpr); - TEST_CASE(cxxDestructorDecl); - TEST_CASE(cxxForRangeStmt1); - TEST_CASE(cxxForRangeStmt2); - TEST_CASE(cxxFunctionalCastExpr); - TEST_CASE(cxxMemberCall); - TEST_CASE(cxxMethodDecl1); - TEST_CASE(cxxMethodDecl2); - TEST_CASE(cxxMethodDecl3); - TEST_CASE(cxxMethodDecl4); - TEST_CASE(cxxNewExpr1); - TEST_CASE(cxxNewExpr2); - TEST_CASE(cxxNullPtrLiteralExpr); - TEST_CASE(cxxOperatorCallExpr); - TEST_CASE(cxxRecordDecl1); - TEST_CASE(cxxRecordDecl2); - TEST_CASE(cxxRecordDeclDerived); - TEST_CASE(cxxStaticCastExpr1); - TEST_CASE(cxxStaticCastExpr2); - TEST_CASE(cxxStaticCastExpr3); - TEST_CASE(cxxStdInitializerListExpr); - TEST_CASE(cxxThrowExpr); - TEST_CASE(defaultStmt); - TEST_CASE(doStmt); - TEST_CASE(enumDecl1); - TEST_CASE(enumDecl2); - TEST_CASE(enumDecl3); - TEST_CASE(enumDecl4); - TEST_CASE(forStmt); - TEST_CASE(funcdecl1); - TEST_CASE(funcdecl2); - TEST_CASE(funcdecl3); - TEST_CASE(funcdecl4); - TEST_CASE(funcdecl5); - TEST_CASE(funcdecl6); - TEST_CASE(functionTemplateDecl1); - TEST_CASE(functionTemplateDecl2); - TEST_CASE(initListExpr); - TEST_CASE(ifelse); - TEST_CASE(ifStmt); - TEST_CASE(labelStmt); - TEST_CASE(memberExpr); - TEST_CASE(namespaceDecl1); - TEST_CASE(namespaceDecl2); - TEST_CASE(recordDecl); - TEST_CASE(switchStmt); - TEST_CASE(typedefDecl1); - TEST_CASE(typedefDecl2); - TEST_CASE(typedefDecl3); - TEST_CASE(unaryExprOrTypeTraitExpr1); - TEST_CASE(unaryExprOrTypeTraitExpr2); - TEST_CASE(unaryOperator); - TEST_CASE(vardecl1); - TEST_CASE(vardecl2); - TEST_CASE(vardecl3); - TEST_CASE(vardecl4); - TEST_CASE(vardecl5); - TEST_CASE(vardecl6); - TEST_CASE(vardecl7); - TEST_CASE(whileStmt1); - TEST_CASE(whileStmt2); - - TEST_CASE(tokenIndex); - TEST_CASE(symbolDatabaseEnum1); - TEST_CASE(symbolDatabaseFunction1); - TEST_CASE(symbolDatabaseFunction2); - TEST_CASE(symbolDatabaseFunction3); - TEST_CASE(symbolDatabaseFunctionConst); - TEST_CASE(symbolDatabaseVariableRef); - TEST_CASE(symbolDatabaseVariableRRef); - TEST_CASE(symbolDatabaseVariablePointerRef); - TEST_CASE(symbolDatabaseNodeType1); - TEST_CASE(symbolDatabaseForVariable); - - TEST_CASE(valueFlow1); - TEST_CASE(valueFlow2); - - TEST_CASE(valueType1); - TEST_CASE(valueType2); - } - - std::string parse(const char clang[]) { - Settings settings; - settings.clang = true; - Tokenizer tokenizer(&settings, this); - std::istringstream istr(clang); - clangimport::parseClangAstDump(&tokenizer, istr); - if (!tokenizer.tokens()) { - return std::string(); - } - return tokenizer.tokens()->stringifyList(true, false, false, false, false); - } - - void breakStmt() { - const char clang[] = "`-FunctionDecl 0x2c31b18 <1.c:1:1, col:34> col:6 foo 'void ()'\n" - " `-CompoundStmt 0x2c31c40 \n" - " `-WhileStmt 0x2c31c20 \n" - " |-<<>>\n" - " |-IntegerLiteral 0x2c31bf8 'int' 0\n" - " `-BreakStmt 0x3687c18 "; - ASSERT_EQUALS("void foo ( ) { while ( 0 ) { break ; } }", parse(clang)); - } - - void callExpr() { - const char clang[] = "`-FunctionDecl 0x2444b60 <1.c:1:1, line:8:1> line:1:6 foo 'void (int)'\n" - " |-ParmVarDecl 0x2444aa0 col:14 used x 'int'\n" - " `-CompoundStmt 0x2444e00 \n" - " `-CallExpr 0x7f5a6c04b158 'bool'\n" - " |-ImplicitCastExpr 0x7f5a6c04b140 'bool (*)(const Token *, const char *, int)' \n" - " | `-DeclRefExpr 0x7f5a6c04b0a8 'bool (const Token *, const char *, int)' lvalue CXXMethod 0x43e5600 'Match' 'bool (const Token *, const char *, int)'\n" - " |-ImplicitCastExpr 0x7f5a6c04b1c8 'const Token *' \n" - " | `-ImplicitCastExpr 0x7f5a6c04b1b0 'Token *' \n" - " | `-DeclRefExpr 0x7f5a6c04b0e0 'Token *' lvalue Var 0x7f5a6c045968 'tokAfterCondition' 'Token *'\n" - " |-ImplicitCastExpr 0x7f5a6c04b1e0 'const char *' \n" - " | `-StringLiteral 0x7f5a6c04b108 'const char [11]' lvalue \"%name% : {\"\n" - " `-CXXDefaultArgExpr 0x7f5a6c04b1f8 <> 'int'\n"; - ASSERT_EQUALS("void foo ( int x@1 ) { Match ( tokAfterCondition , \"%name% : {\" ) ; }", parse(clang)); - } - - void caseStmt1() { - const char clang[] = "`-FunctionDecl 0x2444b60 <1.c:1:1, line:8:1> line:1:6 foo 'void (int)'\n" - " |-ParmVarDecl 0x2444aa0 col:14 used x 'int'\n" - " `-CompoundStmt 0x2444e00 \n" - " `-SwitchStmt 0x2444c88 \n" - " |-<<>>\n" - " |-<<>>\n" - " |-ImplicitCastExpr 0x2444c70 'int' \n" - " | `-DeclRefExpr 0x2444c48 'int' lvalue ParmVar 0x2444aa0 'x' 'int'\n" - " `-CompoundStmt 0x2444de0 \n" - " |-CaseStmt 0x2444cd8 \n" - " | |-IntegerLiteral 0x2444cb8 'int' 16\n" - " | |-<<>>\n" - " | `-CaseStmt 0x2444d30 \n" - " | |-IntegerLiteral 0x2444d10 'int' 32\n" - " | |-<<>>\n" - " | `-BinaryOperator 0x2444db0 'int' '='\n" - " | |-DeclRefExpr 0x2444d68 'int' lvalue ParmVar 0x2444aa0 'x' 'int'\n" - " | `-IntegerLiteral 0x2444d90 'int' 123\n" - " `-BreakStmt 0x2444dd8 "; - ASSERT_EQUALS("void foo ( int x@1 ) { switch ( x@1 ) { case 16 : case 32 : x@1 = 123 ; break ; } }", parse(clang)); - } - - void characterLiteral() { - const char clang[] = "`-VarDecl 0x3df8608 col:6 c 'char' cinit\n" - " `-CharacterLiteral 0x3df86a8 'char' 120"; - ASSERT_EQUALS("char c@1 = 'x' ;", parse(clang)); - } - - void class1() { - const char clang[] = "`-CXXRecordDecl 0x274c638 col:7 class C definition\n" - " |-DefinitionData pass_in_registers empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init\n" - " | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr\n" - " | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param\n" - " | |-MoveConstructor exists simple trivial needs_implicit\n" - " | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param\n" - " | |-MoveAssignment exists simple trivial needs_implicit\n" - " | `-Destructor simple irrelevant trivial needs_implicit\n" - " |-CXXRecordDecl 0x274c758 col:7 implicit class C\n" - " `-CXXMethodDecl 0x274c870 col:16 foo 'void ()'\n" - " `-CompoundStmt 0x274c930 "; - ASSERT_EQUALS("class C { void foo ( ) { } } ;", parse(clang)); - } - - void classTemplateDecl1() { - const char clang[] = "`-ClassTemplateDecl 0x29d1748 col:25 C\n" - " |-TemplateTypeParmDecl 0x29d15f8 col:16 referenced class depth 0 index 0 T\n" - " `-CXXRecordDecl 0x29d16b0 col:25 class C definition\n" - " |-DefinitionData empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init\n" - " | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr\n" - " | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param\n" - " | |-MoveConstructor exists simple trivial needs_implicit\n" - " | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param\n" - " | |-MoveAssignment exists simple trivial needs_implicit\n" - " | `-Destructor simple irrelevant trivial needs_implicit\n" - " |-CXXRecordDecl 0x29d19b0 col:25 implicit class C\n" - " |-AccessSpecDecl 0x29d1a48 col:29 public\n" - " `-CXXMethodDecl 0x29d1b20 col:39 foo 'T ()'\n" - " `-CompoundStmt 0x29d1c18 \n" - " `-ReturnStmt 0x29d1c00 \n" - " `-IntegerLiteral 0x29d1be0 'int' 0"; - ASSERT_EQUALS("", parse(clang)); - } - - void classTemplateDecl2() { - const char clang[] = "|-ClassTemplateDecl 0x244e748 col:25 C\n" - "| |-TemplateTypeParmDecl 0x244e5f8 col:16 referenced class depth 0 index 0 T\n" - "| |-CXXRecordDecl 0x244e6b0 col:25 class C definition\n" - "| | |-DefinitionData empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init\n" - "| | | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr\n" - "| | | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param\n" - "| | | |-MoveConstructor exists simple trivial needs_implicit\n" - "| | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param\n" - "| | | |-MoveAssignment exists simple trivial needs_implicit\n" - "| | | `-Destructor simple irrelevant trivial needs_implicit\n" - "| | |-CXXRecordDecl 0x244e9b0 col:25 implicit class C\n" - "| | |-AccessSpecDecl 0x244ea48 col:29 public\n" - "| | `-CXXMethodDecl 0x244eb20 col:39 foo 'T ()'\n" - "| | `-CompoundStmt 0x244ec18 \n" - "| | `-ReturnStmt 0x244ec00 \n" - "| | `-IntegerLiteral 0x244ebe0 'int' 0\n" - "| `-ClassTemplateSpecializationDecl 0x244ed78 col:25 class C definition\n" - "| |-DefinitionData pass_in_registers empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init\n" - "| | |-DefaultConstructor exists trivial constexpr defaulted_is_constexpr\n" - "| | |-CopyConstructor simple trivial has_const_param implicit_has_const_param\n" - "| | |-MoveConstructor exists simple trivial\n" - "| | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param\n" - "| | |-MoveAssignment exists simple trivial needs_implicit\n" - "| | `-Destructor simple irrelevant trivial needs_implicit\n" - "| |-TemplateArgument type 'int'\n" - "| |-CXXRecordDecl 0x244eff0 prev 0x244ed78 col:25 implicit class C\n" - "| |-AccessSpecDecl 0x244f088 col:29 public\n" - "| |-CXXMethodDecl 0x244f160 col:39 used foo 'int ()'\n" - "| | `-CompoundStmt 0x247cb40 \n" - "| | `-ReturnStmt 0x247cb28 \n" - "| | `-IntegerLiteral 0x244ebe0 'int' 0\n" - "| |-CXXConstructorDecl 0x247c540 col:25 implicit used constexpr C 'void () noexcept' inline default trivial\n" - "| | `-CompoundStmt 0x247ca00 \n" - "| |-CXXConstructorDecl 0x247c658 col:25 implicit constexpr C 'void (const C &)' inline default trivial noexcept-unevaluated 0x247c658\n" - "| | `-ParmVarDecl 0x247c790 col:25 'const C &'\n" - "| `-CXXConstructorDecl 0x247c828 col:25 implicit constexpr C 'void (C &&)' inline default trivial noexcept-unevaluated 0x247c828\n" - "| `-ParmVarDecl 0x247c960 col:25 'C &&'\n"; - ASSERT_EQUALS("class C { int foo ( ) { return 0 ; } C ( ) { } C ( const C & ) = default ; C ( C && ) = default ; } ;", parse(clang)); - } - - void conditionalExpr() { - const char clang[] = "`-VarDecl 0x257cc88 col:5 x 'int' cinit\n" - " `-ConditionalOperator 0x257cda8 'int'\n" - " |-ImplicitCastExpr 0x257cd60 'int' \n" - " | `-DeclRefExpr 0x257cce8 'int' lvalue Var 0x257cae0 'a' 'int'\n" - " |-ImplicitCastExpr 0x257cd78 'int' \n" - " | `-DeclRefExpr 0x257cd10 'int' lvalue Var 0x257cb98 'b' 'int'\n" - " `-ImplicitCastExpr 0x257cd90 'int' \n" - " `-DeclRefExpr 0x257cd38 'int' lvalue Var 0x257cc10 'c' 'int'"; - ASSERT_EQUALS("int x@1 = a ? b : c ;", parse(clang)); - } - - void compoundAssignOperator() { - const char clang[] = "`-FunctionDecl 0x3570690 <1.cpp:2:1, col:25> col:6 f 'void ()'\n" - " `-CompoundStmt 0x3570880 \n" - " `-CompoundAssignOperator 0x3570848 'int' lvalue '+=' ComputeLHSTy='int' ComputeResultTy='int'\n" - " |-DeclRefExpr 0x3570800 'int' lvalue Var 0x3570788 'x' 'int'\n" - " `-IntegerLiteral 0x3570828 'int' 1"; - ASSERT_EQUALS("void f ( ) { x += 1 ; }", parse(clang)); - } - - void continueStmt() { - const char clang[] = "`-FunctionDecl 0x2c31b18 <1.c:1:1, col:34> col:6 foo 'void ()'\n" - " `-CompoundStmt 0x2c31c40 \n" - " `-WhileStmt 0x2c31c20 \n" - " |-<<>>\n" - " |-IntegerLiteral 0x2c31bf8 'int' 0\n" - " `-ContinueStmt 0x2c31c18 "; - ASSERT_EQUALS("void foo ( ) { while ( 0 ) { continue ; } }", parse(clang)); - } - - void cstyleCastExpr() { - const char clang[] = "`-VarDecl 0x2336aa0 <1.c:1:1, col:14> col:5 x 'int' cinit\n" - " `-CStyleCastExpr 0x2336b70 'int' \n" - " `-CharacterLiteral 0x2336b40 'int' 97"; - ASSERT_EQUALS("int x@1 = ( int ) 'a' ;", parse(clang)); - } - - void cxxBoolLiteralExpr() { - const char clang[] = "`-VarDecl 0x3940608 col:6 x 'bool' cinit\n" - " `-CXXBoolLiteralExpr 0x39406a8 'bool' true"; - ASSERT_EQUALS("bool x@1 = true ;", parse(clang)); - } - - void cxxConstructorDecl1() { - const char clang[] = "|-CXXConstructorDecl 0x428e890 col:11 C 'void ()'\n" - "| `-CompoundStmt 0x428ea58 \n" - "| `-BinaryOperator 0x428ea30 'int' lvalue '='\n" - "| |-MemberExpr 0x428e9d8 'int' lvalue ->x 0x428e958\n" - "| | `-CXXThisExpr 0x428e9c0 'C *' this\n" - "| `-IntegerLiteral 0x428ea10 'int' 0\n" - "`-FieldDecl 0x428e958 col:30 referenced x 'int'"; - ASSERT_EQUALS("C ( ) { this . x@1 = 0 ; } int x@1", parse(clang)); - } - - void cxxConstructorDecl2() { - const char clang[] = "`-CXXConstructorDecl 0x1c208c0 col:11 implicit constexpr basic_string 'void (std::basic_string &&)' inline default trivial noexcept-unevaluated 0x1c208c0\n" - " `-ParmVarDecl 0x1c209f0 col:11 'std::basic_string &&'"; - ASSERT_EQUALS("basic_string ( std::basic_string && ) = default ;", parse(clang)); - } - - void cxxConstructExpr1() { - const char clang[] = "`-FunctionDecl 0x2dd7940 col:5 f 'Foo (Foo)'\n" - " |-ParmVarDecl 0x2dd7880 col:11 used foo 'Foo'\n" - " `-CompoundStmt 0x2dd80c0 \n" - " `-ReturnStmt 0x2dd80a8 \n" - " `-CXXConstructExpr 0x2dd8070 'Foo' 'void (Foo &&) noexcept'\n" - " `-ImplicitCastExpr 0x2dd7f28 'Foo' xvalue \n" - " `-DeclRefExpr 0x2dd7a28 'Foo' lvalue ParmVar 0x2dd7880 'foo' 'Foo'"; - ASSERT_EQUALS("Foo f ( Foo foo@1 ) { return foo@1 ; }", parse(clang)); - } - - void cxxConstructExpr2() { - const char clang[] = "`-FunctionDecl 0x3e44180 <1.cpp:2:1, col:30> col:13 f 'std::string ()'\n" - " `-CompoundStmt 0x3e4cb80 \n" - " `-ReturnStmt 0x3e4cb68 \n" - " `-CXXConstructExpr 0x3e4cb38 'std::string':'std::__cxx11::basic_string' '....' list"; - ASSERT_EQUALS("std :: string f ( ) { return std :: string ( ) ; }", parse(clang)); - } - - void cxxConstructExpr3() { - const char clang[] = "`-FunctionDecl 0x2c585b8 <1.cpp:4:1, col:39> col:6 f 'void ()'\n" - " `-CompoundStmt 0x2c589d0 \n" - " |-DeclStmt 0x2c586d0 \n" - " | `-VarDecl 0x2c58670 col:18 used p 'char *'\n" - " `-DeclStmt 0x2c589b8 \n" - " `-VarDecl 0x2c58798 col:33 s 'std::string':'std::__cxx11::basic_string' callinit\n" - " `-ExprWithCleanups 0x2c589a0 'std::string':'std::__cxx11::basic_string'\n" - " `-CXXConstructExpr 0x2c58960 'std::string':'std::__cxx11::basic_string' 'void (const char *, const std::allocator &)'\n" - " |-ImplicitCastExpr 0x2c58870 'const char *' \n" - " | `-ImplicitCastExpr 0x2c58858 'char *' \n" - " | `-DeclRefExpr 0x2c58750 'char *' lvalue Var 0x2c58670 'p' 'char *'\n" - " `-CXXDefaultArgExpr 0x2c58940 <> 'const std::allocator':'const std::allocator' lvalue\n"; - ASSERT_EQUALS("void f ( ) { char * p@1 ; std :: string s@2 ( p@1 ) ; }", parse(clang)); - } - - void cxxDeleteExpr() { - const char clang[] = "|-FunctionDecl 0x2e0e740 <1.cpp:1:1, col:28> col:6 f 'void (int *)'\n" - "| |-ParmVarDecl 0x2e0e680 col:13 used p 'int *'\n" - "| `-CompoundStmt 0x2e0ee70 \n" - "| `-CXXDeleteExpr 0x2e0ee48 'void' Function 0x2e0ebb8 'operator delete' 'void (void *) noexcept'\n" - "| `-ImplicitCastExpr 0x2e0e850 'int *' \n" - "| `-DeclRefExpr 0x2e0e828 'int *' lvalue ParmVar 0x2e0e680 'p' 'int *'"; - ASSERT_EQUALS("void f ( int * p@1 ) { delete p@1 ; }", parse(clang)); - } - - void cxxDestructorDecl() { - const char clang[] = "`-CXXRecordDecl 0x8ecd60 <1.cpp:1:1, line:4:1> line:1:8 struct S definition\n" - " `-CXXDestructorDecl 0x8ed088 col:3 ~S 'void () noexcept'\n" - " `-CompoundStmt 0x8ed1a8 "; - ASSERT_EQUALS("struct S { ~S ( ) { } } ;", parse(clang)); - } - - void cxxForRangeStmt1() { - const char clang[] = "`-FunctionDecl 0x4280820 line:4:6 foo 'void ()'\n" - " `-CompoundStmt 0x42810f0 \n" - " `-CXXForRangeStmt 0x4281090 \n" - " |-DeclStmt 0x4280c30 \n" - " | `-VarDecl 0x42809c8 col:17 implicit referenced __range1 'char const (&)[6]' cinit\n" - " | `-DeclRefExpr 0x42808c0 'const char [6]' lvalue Var 0x4280678 'hello' 'const char [6]'\n" - " |-DeclStmt 0x4280ef8 \n" - " | `-VarDecl 0x4280ca8 col:15 implicit used __begin1 'const char *':'const char *' cinit\n" - " | `-ImplicitCastExpr 0x4280e10 'const char *' \n" - " | `-DeclRefExpr 0x4280c48 'char const[6]' lvalue Var 0x42809c8 '__range1' 'char const (&)[6]'\n" - " |-DeclStmt 0x4280f10 \n" - " | `-VarDecl 0x4280d18 col:15 implicit used __end1 'const char *':'const char *' cinit\n" - " | `-BinaryOperator 0x4280e60 'const char *' '+'\n" - " | |-ImplicitCastExpr 0x4280e48 'const char *' \n" - " | | `-DeclRefExpr 0x4280c70 'char const[6]' lvalue Var 0x42809c8 '__range1' 'char const (&)[6]'\n" - " | `-IntegerLiteral 0x4280e28 'long' 6\n" - " |-BinaryOperator 0x4280fa8 'bool' '!='\n" - " | |-ImplicitCastExpr 0x4280f78 'const char *':'const char *' \n" - " | | `-DeclRefExpr 0x4280f28 'const char *':'const char *' lvalue Var 0x4280ca8 '__begin1' 'const char *':'const char *'\n" - " | `-ImplicitCastExpr 0x4280f90 'const char *':'const char *' \n" - " | `-DeclRefExpr 0x4280f50 'const char *':'const char *' lvalue Var 0x4280d18 '__end1' 'const char *':'const char *'\n" - " |-UnaryOperator 0x4280ff8 'const char *':'const char *' lvalue prefix '++'\n" - " | `-DeclRefExpr 0x4280fd0 'const char *':'const char *' lvalue Var 0x4280ca8 '__begin1' 'const char *':'const char *'\n" - " |-DeclStmt 0x4280958 \n" - " | `-VarDecl 0x42808f8 col:13 c1 'char' cinit\n" - " | `-ImplicitCastExpr 0x4281078 'char' \n" - " | `-UnaryOperator 0x4281058 'const char' lvalue prefix '*' cannot overflow\n" - " | `-ImplicitCastExpr 0x4281040 'const char *':'const char *' \n" - " | `-DeclRefExpr 0x4281018 'const char *':'const char *' lvalue Var 0x4280ca8 '__begin1' 'const char *':'const char *'\n" - " `-CompoundStmt 0x42810e0 "; - ASSERT_EQUALS("void foo ( ) { for ( char c1@1 : hello ) { } }", - parse(clang)); - } - - void cxxForRangeStmt2() { - // clang 9 - const char clang[] = "`-FunctionDecl 0xc15d98 col:6 foo 'void ()'\n" - " `-CompoundStmt 0xc16668 \n" - " `-CXXForRangeStmt 0xc165f8 \n" - " |-<<>>\n" - " |-DeclStmt 0xc161c0 \n" - " | `-VarDecl 0xc15f48 col:25 implicit referenced __range1 'int const (&)[4]' cinit\n" - " | `-DeclRefExpr 0xc15e38 'const int [4]' lvalue Var 0xc15ac0 'values' 'const int [4]'\n" - " |-DeclStmt 0xc16498 \n" - " | `-VarDecl 0xc16228 col:24 implicit used __begin1 'const int *':'const int *' cinit\n" - " | `-ImplicitCastExpr 0xc163b0 'const int *' \n" - " | `-DeclRefExpr 0xc161d8 'int const[4]' lvalue Var 0xc15f48 '__range1' 'int const (&)[4]' non_odr_use_constant\n" - " |-DeclStmt 0xc164b0 \n" - " | `-VarDecl 0xc162a0 col:24 implicit used __end1 'const int *':'const int *' cinit\n" - " | `-BinaryOperator 0xc16400 'const int *' '+'\n" - " | |-ImplicitCastExpr 0xc163e8 'const int *' \n" - " | | `-DeclRefExpr 0xc161f8 'int const[4]' lvalue Var 0xc15f48 '__range1' 'int const (&)[4]' non_odr_use_constant\n" - " | `-IntegerLiteral 0xc163c8 'long' 4\n" - " |-BinaryOperator 0xc16538 'bool' '!='\n" - " | |-ImplicitCastExpr 0xc16508 'const int *':'const int *' \n" - " | | `-DeclRefExpr 0xc164c8 'const int *':'const int *' lvalue Var 0xc16228 '__begin1' 'const int *':'const int *'\n" - " | `-ImplicitCastExpr 0xc16520 'const int *':'const int *' \n" - " | `-DeclRefExpr 0xc164e8 'const int *':'const int *' lvalue Var 0xc162a0 '__end1' 'const int *':'const int *'\n" - " |-UnaryOperator 0xc16578 'const int *':'const int *' lvalue prefix '++'\n" - " | `-DeclRefExpr 0xc16558 'const int *':'const int *' lvalue Var 0xc16228 '__begin1' 'const int *':'const int *'\n" - " |-DeclStmt 0xc15ed8 \n" - " | `-VarDecl 0xc15e70 col:23 v 'int' cinit\n" - " | `-ImplicitCastExpr 0xc165e0 'int' \n" - " | `-UnaryOperator 0xc165c8 'const int' lvalue prefix '*' cannot overflow\n" - " | `-ImplicitCastExpr 0xc165b0 'const int *':'const int *' \n" - " | `-DeclRefExpr 0xc16590 'const int *':'const int *' lvalue Var 0xc16228 '__begin1' 'const int *':'const int *'\n" - " `-CompoundStmt 0xc16658 "; - ASSERT_EQUALS("void foo ( ) { for ( int v@1 : values ) { } }", - parse(clang)); - } - - void cxxFunctionalCastExpr() { - const char clang[] = "`-FunctionDecl 0x156fe98 line:1:5 main 'int (int, char **)'\n" - " |-ParmVarDecl 0x156fd00 col:14 argc 'int'\n" - " |-ParmVarDecl 0x156fdb8 col:27 argv 'char **'\n" - " `-CompoundStmt 0x1596410 \n" - " |-DeclStmt 0x15946a8 \n" - " | `-VarDecl 0x1570118 col:11 used setCode 'MyVar':'MyVar' cinit\n" - " | `-ExprWithCleanups 0x1594690 'MyVar':'MyVar'\n" - " | `-CXXConstructExpr 0x1594660 'MyVar':'MyVar' 'void (MyVar &&) noexcept' elidable\n" - " | `-MaterializeTemporaryExpr 0x1592b68 'MyVar':'MyVar' xvalue\n" - " | `-CXXFunctionalCastExpr 0x1592b40 'MyVar':'MyVar' functional cast to MyVar \n" - " | `-CXXConstructExpr 0x15929f0 'MyVar':'MyVar' 'void (int)'\n" - " | `-IntegerLiteral 0x1570248 'int' 5\n"; - ASSERT_EQUALS("int main ( int argc@1 , char * * argv@2 ) { MyVar setCode@3 = MyVar ( 5 ) ; }", - parse(clang)); - } - - void cxxMemberCall() { - const char clang[] = "`-FunctionDecl 0x320dc80 col:6 bar 'void ()'\n" - " `-CompoundStmt 0x323bb08 \n" - " |-DeclStmt 0x323ba40 \n" - " | `-VarDecl 0x320df28 col:21 used c 'C':'C' callinit\n" - " | `-CXXConstructExpr 0x323ba10 'C':'C' 'void () noexcept'\n" - " `-CXXMemberCallExpr 0x323bab8 'int':'int'\n" - " `-MemberExpr 0x323ba80 '' .foo 0x320e160\n" - " `-DeclRefExpr 0x323ba58 'C':'C' lvalue Var 0x320df28 'c' 'C':'C'"; - ASSERT_EQUALS("void bar ( ) { C c@1 ( C ( ) ) ; c@1 . foo ( ) ; }", parse(clang)); - } - - void cxxMethodDecl1() { - const char clang[] = "|-CXXMethodDecl 0x55c786f5ad60 col:10 analyzeFile '_Bool (const std::string &, const std::string &, const std::string &, unsigned long long, std::list *)'\n" - "| |-ParmVarDecl 0x55c786f5a4c8 col:41 buildDir 'const std::string &'\n" - "| |-ParmVarDecl 0x55c786f5a580 col:70 sourcefile 'const std::string &'\n" - "| |-ParmVarDecl 0x55c786f5a638 col:101 cfg 'const std::string &'\n" - "| |-ParmVarDecl 0x55c786f5a6a8 col:125 checksum 'unsigned long long'\n" - "| |-ParmVarDecl 0x55c786f5ac00 col:173 errors 'std::list *'\n" - " `-CompoundStmt 0x0 <>"; - ASSERT_EQUALS("_Bool analyzeFile ( const std :: string & buildDir@1 , const std :: string & sourcefile@2 , const std :: string & cfg@3 , unsigned long long checksum@4 , std::list * errors@5 ) { }", parse(clang)); - } - - void cxxMethodDecl2() { // "unexpanded" template method - const char clang[] = "`-CXXMethodDecl 0x220ecb0 parent 0x21e4c28 prev 0x21e5338 line:14:1 find 'const typename char_traits<_CharT>::char_type *(const char_traits::char_type *, int, const char_traits::char_type &)'\n" - " `-CompoundStmt 0x220ede0 \n" - " `-ReturnStmt 0x220edd0 \n" - " `-IntegerLiteral 0x220edb0 'int' 0"; - ASSERT_EQUALS("", parse(clang)); - } - - void cxxMethodDecl3() { - const char clang[] = "|-CXXRecordDecl 0x21cca40 <2.cpp:2:1, line:4:1> line:2:7 class Fred definition\n" - "| |-DefinitionData pass_in_registers empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init\n" - "| | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr\n" - "| | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param\n" - "| | |-MoveConstructor exists simple trivial needs_implicit\n" - "| | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param\n" - "| | |-MoveAssignment exists simple trivial needs_implicit\n" - "| | `-Destructor simple irrelevant trivial needs_implicit\n" - "| |-CXXRecordDecl 0x21ccb58 col:7 implicit class Fred\n" - "| `-CXXMethodDecl 0x21ccc68 col:6 foo 'void ()'\n" - "`-CXXMethodDecl 0x21ccd60 parent 0x21cca40 prev 0x21ccc68 col:12 foo 'void ()'\n" - " `-CompoundStmt 0x21cce50 "; - ASSERT_EQUALS("class Fred { void foo ( ) ; } ; void Fred :: foo ( ) { }", parse(clang)); - } - - void cxxMethodDecl4() { - const char clang[] = "|-ClassTemplateSpecializationDecl 0x15d82f8 line:8:12 struct char_traits definition\n" - "| |-TemplateArgument type 'char'\n" - "| | `-BuiltinType 0x15984c0 'char'\n" - "| |-CXXRecordDecl 0x15d8520 col:12 implicit struct char_traits\n" - "| |-CXXMethodDecl 0x15d8738 line:13:7 move 'char *(char *)' static\n" - "| | |-ParmVarDecl 0x15d8630 col:18 used __s1 'char *'\n" - "| | `-CompoundStmt 0x15d88e8 \n"; - ASSERT_EQUALS("struct char_traits { static char * move ( char * __s1@1 ) { } } ;", - parse(clang)); - } - - void cxxNewExpr1() { - const char clang[] = "|-VarDecl 0x3a97680 <1.cpp:2:1, col:14> col:6 i 'int *' cinit\n" - "| `-CXXNewExpr 0x3a97d18 'int *' Function 0x3a97778 'operator new' 'void *(unsigned long)'\n" - "`-VarDecl 0x3a97d80 col:6 j 'int *' cinit\n" - " `-CXXNewExpr 0x3a97e68 'int *' array Function 0x3a978c0 'operator new[]' 'void *(unsigned long)'\n" - " `-ImplicitCastExpr 0x3a97e18 'unsigned long' \n" - " `-IntegerLiteral 0x3a97de0 'int' 100"; - ASSERT_EQUALS("int * i@1 = new int ; int * j@2 = new int [ 100 ] ;", - parse(clang)); - } - - void cxxNewExpr2() { - const char clang[] = "|-FunctionDecl 0x59a188 line:7:11 f 'struct S *()'\n" - "| `-CompoundStmt 0x5c4318 \n" - "| `-ReturnStmt 0x5c4308 \n" - "| `-CXXNewExpr 0x5c42c8 'S *' Function 0x59a378 'operator new' 'void *(unsigned long)'\n" - "| `-CXXConstructExpr 0x5c42a0 'S' 'void () noexcept'"; - ASSERT_EQUALS("struct S * f ( ) { return new S ( ) ; }", - parse(clang)); - } - - void cxxNullPtrLiteralExpr() { - const char clang[] = "`-VarDecl 0x2a7d650 <1.cpp:1:1, col:17> col:13 p 'const char *' cinit\n" - " `-ImplicitCastExpr 0x2a7d708 'const char *' \n" - " `-CXXNullPtrLiteralExpr 0x2a7d6f0 'nullptr_t'"; - ASSERT_EQUALS("const char * p@1 = nullptr ;", parse(clang)); - } - - void cxxOperatorCallExpr() { - const char clang[] = "`-FunctionDecl 0x3c099f0 col:6 foo 'void ()'\n" - " `-CompoundStmt 0x3c37308 \n" - " |-DeclStmt 0x3c0a060 \n" - " | `-VarDecl 0x3c09ae0 col:16 used c 'C' callinit\n" - " | `-CXXConstructExpr 0x3c0a030 'C' 'void () noexcept'\n" - " `-CXXOperatorCallExpr 0x3c372c0 'void'\n" - " |-ImplicitCastExpr 0x3c372a8 'void (*)(int)' \n" - " | `-DeclRefExpr 0x3c37250 'void (int)' lvalue CXXMethod 0x3c098c0 'operator=' 'void (int)'\n" - " |-DeclRefExpr 0x3c0a078 'C' lvalue Var 0x3c09ae0 'c' 'C'\n" - " `-IntegerLiteral 0x3c0a0a0 'int' 4"; - ASSERT_EQUALS("void foo ( ) { C c@1 ( C ( ) ) ; c@1 . operator= ( 4 ) ; }", parse(clang)); - } - - void cxxRecordDecl1() { - const char clang[] = "`-CXXRecordDecl 0x34cc5f8 <1.cpp:2:1, col:7> col:7 class Foo"; - ASSERT_EQUALS("class Foo ;", parse(clang)); - } - - void cxxRecordDecl2() { - const char clang[] = "`-CXXRecordDecl 0x34cc5f8 <1.cpp:2:1, col:7> col:7 struct Foo definition"; - ASSERT_EQUALS("struct Foo { } ;", parse(clang)); - } - - void cxxRecordDeclDerived() { - const char clang[] = "|-CXXRecordDecl 0x19ccd38 line:4:8 referenced struct base definition\n" - "| `-VarDecl 0x19ccf00 col:27 value 'const bool' static constexpr cinit\n" - "| |-value: Int 0\n" - "| `-CXXBoolLiteralExpr 0x19ccf68 'bool' false\n" - "`-CXXRecordDecl 0x19ccfe8 col:8 struct derived definition\n" - " |-public 'base'\n" - " `-CXXRecordDecl 0x19cd150 col:8 implicit struct derived"; - - ASSERT_EQUALS("struct base { static const bool value@1 = false ; } ; struct derived : public base { } ;", parse(clang)); - } - - void cxxStaticCastExpr1() { - const char clang[] = "`-VarDecl 0x2e0e650 col:5 a 'int' cinit\n" - " `-CXXStaticCastExpr 0x2e0e728 'int' static_cast \n" - " `-IntegerLiteral 0x2e0e6f0 'int' 0"; - ASSERT_EQUALS("int a@1 = static_cast ( 0 ) ;", parse(clang)); - } - - void cxxStaticCastExpr2() { - const char clang[] = "`-VarDecl 0x2e0e650 col:5 a 'int' cinit\n" - " `-CXXStaticCastExpr 0x3e453e8 'std::_Rb_tree_iterator, Library::AllocFunc> >' xvalue static_cast, struct Library::AllocFunc> > &&> \n" - " `-DeclRefExpr 0x3e453b0 'std::_Rb_tree_iterator, Library::AllocFunc> >' lvalue ParmVar 0x3e45250 '' 'std::_Rb_tree_iterator, Library::AllocFunc> > &&'"; - ASSERT_EQUALS("int a@1 = static_cast,structLibrary::AllocFunc>>&&> ( ) ;", parse(clang)); - } - - void cxxStaticCastExpr3() { - const char clang[] = "`-ClassTemplateSpecializationDecl 0xd842d8 line:4:21 struct char_traits definition\n" - " |-TemplateArgument type 'char'\n" - " | `-BuiltinType 0xd444c0 'char'\n" - " |-CXXRecordDecl 0xd84500 col:21 implicit struct char_traits\n" - " |-TypedefDecl 0xd845a0 col:20 referenced char_type 'char'\n" - " | `-BuiltinType 0xd444c0 'char'\n" - " `-CXXMethodDecl 0xd847b0 col:18 assign 'char_traits::char_type *(char_traits::char_type *)'\n" - " |-ParmVarDecl 0xd84670 col:36 used __s 'char_traits::char_type *'\n" - " `-CompoundStmt 0xd848f8 \n" - " `-ReturnStmt 0xd848e8 \n" - " `-CXXStaticCastExpr 0xd848b8 'char_traits::char_type *' static_cast::char_type *> \n" - " `-ImplicitCastExpr 0xd848a0 'char_traits::char_type *' part_of_explicit_cast\n" - " `-DeclRefExpr 0xd84870 'char_traits::char_type *' lvalue ParmVar 0xd84670 '__s' 'char_traits::char_type *'\n"; - - ASSERT_EQUALS("struct char_traits { typedef char char_type ; char_traits::char_type * assign ( char_traits::char_type * __s@1 ) { return static_cast::char_type*> ( __s@1 ) ; } } ;", parse(clang)); - } - - void cxxStdInitializerListExpr() { - const char clang[] = "`-VarDecl 0x2f92060 <1.cpp:3:1, col:25> col:18 x 'std::vector':'std::vector >' listinit\n" - " `-ExprWithCleanups 0x2fb0b40 'std::vector':'std::vector >'\n" - " `-CXXConstructExpr 0x2fb0b00 'std::vector':'std::vector >' 'void (initializer_list >::value_type>, const std::vector >::allocator_type &)' list std::initializer_list\n" - " |-CXXStdInitializerListExpr 0x2fb0928 'initializer_list >::value_type>':'std::initializer_list'\n" - " | `-MaterializeTemporaryExpr 0x2fb0910 'const int [3]' xvalue\n" - " | `-InitListExpr 0x2fb08b8 'const int [3]'\n" - " | |-IntegerLiteral 0x2f920c0 'int' 1\n" - " | |-IntegerLiteral 0x2f920e0 'int' 2\n" - " | `-IntegerLiteral 0x2f92100 'int' 3\n" - " `-CXXDefaultArgExpr 0x2fb0ae0 <> 'const std::vector >::allocator_type':'const std::allocator' lvalue"; - ASSERT_EQUALS("std :: vector x@1 { 1 , 2 , 3 } ;", parse(clang)); - } - - void cxxThrowExpr() { - const char clang[] = "`-FunctionDecl 0x3701690 <1.cpp:2:1, col:23> col:6 foo 'void ()'\n" - " `-CompoundStmt 0x37017b0 \n" - " `-CXXThrowExpr 0x3701790 'void'\n" - " `-IntegerLiteral 0x3701770 'int' 1"; - ASSERT_EQUALS("void foo ( ) { throw 1 ; }", parse(clang)); - } - - void defaultStmt() { - const char clang[] = "`-FunctionDecl 0x18476b8 <1.c:3:1, line:9:1> line:3:5 foo 'int (int)'\n" - " |-ParmVarDecl 0x18475e0 col:13 used rc 'int'\n" - " `-CompoundStmt 0x1847868 \n" - " `-SwitchStmt 0x18477e0 \n" - " |-ImplicitCastExpr 0x18477c8 'int' \n" - " | `-DeclRefExpr 0x18477a8 'int' lvalue ParmVar 0x18475e0 'rc' 'int'\n" - " `-CompoundStmt 0x1847850 \n" - " `-DefaultStmt 0x1847830 \n" - " `-ReturnStmt 0x1847820 \n" - " `-IntegerLiteral 0x1847800 'int' 1"; - ASSERT_EQUALS("int foo ( int rc@1 ) { switch ( rc@1 ) { default : return 1 ; } }", parse(clang)); - } - - void doStmt() { - const char clang[] = "`-FunctionDecl 0x27fbbc8 col:6 foo 'void ()'\n" - " `-CompoundStmt 0x27fbd08 \n" - " `-DoStmt 0x27fbce8 \n" - " |-CompoundStmt 0x27fbcb0 \n" - " | `-UnaryOperator 0x27fbc90 'int' postfix '++'\n" - " | `-DeclRefExpr 0x27fbc68 'int' lvalue Var 0x27fbae0 'x' 'int'\n" - " `-IntegerLiteral 0x27fbcc8 'int' 1"; - ASSERT_EQUALS("void foo ( ) { do { ++ x ; } while ( 1 ) ; }", parse(clang)); - } - - void enumDecl1() { - const char clang[] = "`-EnumDecl 0x2660660 col:6 referenced abc\n" - " |-EnumConstantDecl 0x2660720 col:11 referenced a 'abc'\n" - " |-EnumConstantDecl 0x2660768 col:13 b 'abc'\n" - " `-EnumConstantDecl 0x26607b0 col:15 c 'abc'"; - ASSERT_EQUALS("enum abc { a , b , c }", parse(clang)); - } - - void enumDecl2() { - const char clang[] = "`-EnumDecl 0xb55d50 <2.cpp:4:3, col:44> col:8 syntax_option_type 'unsigned int'"; - ASSERT_EQUALS("enum syntax_option_type : unsigned int { }", parse(clang)); - } - - void enumDecl3() { - const char clang[] = "|-EnumDecl 0x1586e48 <2.cpp:1:3, line:5:3> line:1:8 __syntax_option\n" - "| |-EnumConstantDecl 0x1586f18 col:5 referenced _S_polynomial '__syntax_option'\n" - "| `-EnumConstantDecl 0x1586f68 col:5 _S_syntax_last '__syntax_option'"; - ASSERT_EQUALS("enum __syntax_option { _S_polynomial , _S_syntax_last }", parse(clang)); - } - - void enumDecl4() { - const char clang[] = "|-EnumDecl 0xace1f8 col:1\n" - "| |-EnumConstantDecl 0xace2c8 col:7 A '(anonymous enum at e1.cpp:3:1)'\n" - "| |-EnumConstantDecl 0xace318 col:16 B '(anonymous enum at e1.cpp:3:1)'\n" - "| `-EnumConstantDecl 0xace3b8 col:46 referenced C '(anonymous enum at e1.cpp:3:1)'\n" - "`-VarDecl 0xace470 col:53 x 'enum (anonymous enum at e1.cpp:3:1)':'(anonymous enum at e1.cpp:3:1)' cinit\n" - " `-DeclRefExpr 0xace520 '(anonymous enum at e1.cpp:3:1)' EnumConstant 0xace3b8 'C' '(anonymous enum at e1.cpp:3:1)'"; - ASSERT_EQUALS("enum { A , B , C } x@1 = C ;", parse(clang)); - } - - void forStmt() { - const char clang[] = "`-FunctionDecl 0x2f93ae0 <1.c:1:1, col:56> col:5 main 'int ()'\n" - " `-CompoundStmt 0x2f93dc0 \n" - " |-ForStmt 0x2f93d50 \n" - " | |-DeclStmt 0x2f93c58 \n" - " | | `-VarDecl 0x2f93bd8 col:23 used i 'int' cinit\n" - " | | `-IntegerLiteral 0x2f93c38 'int' 0\n" - " | |-<<>>\n" - " | |-BinaryOperator 0x2f93cd0 'int' '<'\n" - " | | |-ImplicitCastExpr 0x2f93cb8 'int' \n" - " | | | `-DeclRefExpr 0x2f93c70 'int' lvalue Var 0x2f93bd8 'i' 'int'\n" - " | | `-IntegerLiteral 0x2f93c98 'int' 10\n" - " | |-UnaryOperator 0x2f93d20 'int' postfix '++'\n" - " | | `-DeclRefExpr 0x2f93cf8 'int' lvalue Var 0x2f93bd8 'i' 'int'\n" - " | `-CompoundStmt 0x2f93d40 \n" - " `-ReturnStmt 0x2f93da8 \n" - " `-IntegerLiteral 0x2f93d88 'int' 0"; - ASSERT_EQUALS("int main ( ) { for ( int i@1 = 0 ; i@1 < 10 ; ++ i@1 ) { } return 0 ; }", parse(clang)); - } - - void funcdecl1() { - const char clang[] = "`-FunctionDecl 0x3122c30 <1.c:1:1, col:22> col:6 foo 'void (int, int)'\n" - " |-ParmVarDecl 0x3122ae0 col:14 x 'int'\n" - " `-ParmVarDecl 0x3122b58 col:21 y 'int'"; - ASSERT_EQUALS("void foo ( int x@1 , int y@2 ) ;", parse(clang)); - } - - void funcdecl2() { - const char clang[] = "`-FunctionDecl 0x24b2c38 <1.c:1:1, line:4:1> line:1:5 foo 'int (int, int)'\n" - " |-ParmVarDecl 0x24b2ae0 col:13 used x 'int'\n" - " |-ParmVarDecl 0x24b2b58 col:20 used y 'int'\n" - " `-CompoundStmt 0x24b2de8 \n" - " `-ReturnStmt 0x24b2dd0 \n" - " `-BinaryOperator 0x24b2da8 'int' '/'\n" - " |-ImplicitCastExpr 0x24b2d78 'int' \n" - " | `-DeclRefExpr 0x24b2d28 'int' lvalue ParmVar 0x24b2ae0 'x' 'int'\n" - " `-ImplicitCastExpr 0x24b2d90 'int' \n" - " `-DeclRefExpr 0x24b2d50 'int' lvalue ParmVar 0x24b2b58 'y' 'int'"; - ASSERT_EQUALS("int foo ( int x@1 , int y@2 ) { return x@1 / y@2 ; }", parse(clang)); - } - - void funcdecl3() { - const char clang[] = "|-FunctionDecl 0x27cb6b8 col:12 __overflow 'int (FILE *, int)' extern\n" - "| |-ParmVarDecl 0x27cb528 col:30 'FILE *'\n" - "| `-ParmVarDecl 0x27cb5a0 col:35 'int'"; - ASSERT_EQUALS("int __overflow ( FILE * , int ) ;", parse(clang)); - } - - void funcdecl4() { - const char clang[] = "|-FunctionDecl 0x272bb60 col:15 implicit fwrite 'unsigned long (const void *, unsigned long, unsigned long, FILE *)' extern\n" - "| |-ParmVarDecl 0x272cc40 <> 'const void *'\n" - "| |-ParmVarDecl 0x272cca0 <> 'unsigned long'\n" - "| |-ParmVarDecl 0x272cd00 <> 'unsigned long'\n" - "| `-ParmVarDecl 0x272cd60 <> 'FILE *'"; - ASSERT_EQUALS("unsigned long fwrite ( const void * , unsigned long , unsigned long , FILE * ) ;", parse(clang)); - } - - void funcdecl5() { - const char clang[] = "`-FunctionDecl 0x59d670 <1.c:1:1, col:28> col:20 foo 'void (void)' static inline"; - ASSERT_EQUALS("static inline void foo ( ) ;", parse(clang)); - } - - void funcdecl6() { - const char clang[] = "`-FunctionDecl 0x196eea8 <1.cpp:3:5, col:27> col:12 foo 'void **(int)'\n" - " `-ParmVarDecl 0x196eda0 col:21 count 'int'"; - ASSERT_EQUALS("void * * foo ( int count@1 ) ;", parse(clang)); - } - - void functionTemplateDecl1() { - const char clang[] = "`-FunctionTemplateDecl 0x3242860 col:21 foo"; - ASSERT_EQUALS("", parse(clang)); - } - - void functionTemplateDecl2() { - const char clang[] = "|-FunctionTemplateDecl 0x333a860 col:21 foo\n" - "| |-TemplateTypeParmDecl 0x333a5f8 col:16 referenced class depth 0 index 0 T\n" - "| |-FunctionDecl 0x333a7c0 col:21 foo 'T (T)'\n" - "| | |-ParmVarDecl 0x333a6c0 col:27 referenced t 'T'\n" - "| | `-CompoundStmt 0x333a980 \n" - "| | `-ReturnStmt 0x333a968 \n" - "| | `-BinaryOperator 0x333a940 '' '+'\n" - "| | |-DeclRefExpr 0x333a8f8 'T' lvalue ParmVar 0x333a6c0 't' 'T'\n" - "| | `-IntegerLiteral 0x333a920 'int' 1\n" - "| `-FunctionDecl 0x333ae00 col:21 used foo 'int (int)'\n" - "| |-TemplateArgument type 'int'\n" - "| |-ParmVarDecl 0x333ad00 col:27 used t 'int':'int'\n" - "| `-CompoundStmt 0x333b0a8 \n" - "| `-ReturnStmt 0x333b090 \n" - "| `-BinaryOperator 0x333b068 'int' '+'\n" - "| |-ImplicitCastExpr 0x333b050 'int':'int' \n" - "| | `-DeclRefExpr 0x333b028 'int':'int' lvalue ParmVar 0x333ad00 't' 'int':'int'\n" - "| `-IntegerLiteral 0x333a920 'int' 1\n" - "`-FunctionDecl 0x333a9f8 col:1 invalid bar 'int ()'\n" - " `-CompoundStmt 0x333b010 \n" - " `-CallExpr 0x333afe0 'int':'int'\n" - " |-ImplicitCastExpr 0x333afc8 'int (*)(int)' \n" - " | `-DeclRefExpr 0x333af00 'int (int)' lvalue Function 0x333ae00 'foo' 'int (int)' (FunctionTemplate 0x333a860 'foo')\n" - " `-IntegerLiteral 0x333ab48 'int' 1"; - ASSERT_EQUALS("int foo ( int t@1 ) { return t@1 + 1 ; } int bar ( ) { foo ( 1 ) ; }", parse(clang)); - } - - void ifelse() { - const char clang[] = "`-FunctionDecl 0x2637ba8 <1.c:1:1, line:4:1> line:1:5 foo 'int (int)'\n" - " |-ParmVarDecl 0x2637ae0 col:13 used x 'int'\n" - " `-CompoundStmt 0x2637d70 \n" - " `-IfStmt 0x2637d38 \n" - " |-<<>>\n" - " |-<<>>\n" - " |-BinaryOperator 0x2637cf0 'int' '>'\n" - " | |-ImplicitCastExpr 0x2637cd8 'int' \n" - " | | `-DeclRefExpr 0x2637c90 'int' lvalue ParmVar 0x2637ae0 'x' 'int'\n" - " | `-IntegerLiteral 0x2637cb8 'int' 10\n" - " |-CompoundStmt 0x2637d18 \n" - " `-CompoundStmt 0x2637d28 "; - ASSERT_EQUALS("int foo ( int x@1 ) { if ( x@1 > 10 ) { } else { } }", parse(clang)); - } - - void ifStmt() { - // Clang 8 in cygwin - const char clang[] = "`-FunctionDecl 0x41d0690 <2.cpp:1:1, col:24> col:6 foo 'void ()'\n" - " `-CompoundStmt 0x41d07f0 \n" - " `-IfStmt 0x41d07b8 \n" - " |-ImplicitCastExpr 0x41d0790 'bool' \n" - " | `-IntegerLiteral 0x41d0770 'int' 1\n" - " |-CompoundStmt 0x41d07a8 \n"; - ASSERT_EQUALS("void foo ( ) { if ( 1 ) { } }", parse(clang)); - } - - void initListExpr() { - const char clang[] = "|-VarDecl 0x397c680 <1.cpp:2:1, col:26> col:11 used ints 'const int [3]' cinit\n" - "| `-InitListExpr 0x397c7d8 'const int [3]'\n" - "| |-IntegerLiteral 0x397c720 'int' 1\n" - "| |-IntegerLiteral 0x397c740 'int' 2\n" - "| `-IntegerLiteral 0x397c760 'int' 3"; - ASSERT_EQUALS("const int [3] ints@1 = { 1 , 2 , 3 } ;", parse(clang)); - } - - void labelStmt() { - const char clang[] = "`-FunctionDecl 0x2ed1ba0 <1.c:1:1, col:36> col:6 foo 'void (int)'\n" - " `-CompoundStmt 0x2ed1d00 \n" - " `-LabelStmt 0x2ed1ce8 'loop'\n" - " `-GotoStmt 0x2ed1cd0 'loop' 0x2ed1c88"; - ASSERT_EQUALS("void foo ( ) { loop : goto loop ; }", parse(clang)); - } - - void memberExpr() { - // C code: - // struct S { int x }; - // int foo(struct S s) { return s.x; } - const char clang[] = "|-RecordDecl 0x2441a88 <1.c:1:1, col:18> col:8 struct S definition\n" - "| `-FieldDecl 0x2441b48 col:16 referenced x 'int'\n" - "`-FunctionDecl 0x2441cf8 col:5 foo 'int (struct S)'\n" - " |-ParmVarDecl 0x2441be8 col:18 used s 'struct S':'struct S'\n" - " `-CompoundStmt 0x2441e70 \n" - " `-ReturnStmt 0x2441e58 \n" - " `-ImplicitCastExpr 0x2441e40 'int' \n" - " `-MemberExpr 0x2441e08 'int' lvalue .x 0x2441b48\n" - " `-DeclRefExpr 0x2441de0 'struct S':'struct S' lvalue ParmVar 0x2441be8 's' 'struct S':'struct S'"; - ASSERT_EQUALS("struct S { int x@1 ; } ; int foo ( struct S s@2 ) { return s@2 . x@1 ; }", - parse(clang)); - } - - void namespaceDecl1() { - const char clang[] = "`-NamespaceDecl 0x2e5f658 col:11 x\n" - " `-VarDecl 0x2e5f6d8 col:19 var 'int'"; - ASSERT_EQUALS("namespace x { int var@1 ; }", - parse(clang)); - } - - void namespaceDecl2() { - const char clang[] = "`-NamespaceDecl 0x1753e60 <1.cpp:1:1, line:4:1> line:1:11 std\n" - " |-VisibilityAttr 0x1753ed0 Default\n" - " `-VarDecl 0x1753f40 col:9 x 'int'"; - ASSERT_EQUALS("namespace std { int x@1 ; }", - parse(clang)); - } - - void recordDecl() { - const char clang[] = "`-RecordDecl 0x354eac8 <1.c:1:1, line:4:1> line:1:8 struct S definition\n" - " |-FieldDecl 0x354eb88 col:7 x 'int'\n" - " `-FieldDecl 0x354ebe8 col:7 y 'int'"; - ASSERT_EQUALS("struct S { int x@1 ; int y@2 ; } ;", - parse(clang)); - } - - void switchStmt() { - const char clang[] = "`-FunctionDecl 0x2796ba0 <1.c:1:1, col:35> col:6 foo 'void (int)'\n" - " |-ParmVarDecl 0x2796ae0 col:14 used x 'int'\n" - " `-CompoundStmt 0x2796d18 \n" - " |-SwitchStmt 0x2796cc8 \n" - " | |-<<>>\n" - " | |-<<>>\n" - " | |-ImplicitCastExpr 0x2796cb0 'int' \n" - " | | `-DeclRefExpr 0x2796c88 'int' lvalue ParmVar 0x2796ae0 'x' 'int'\n" - " | `-CompoundStmt 0x2796cf8 \n" - " `-NullStmt 0x2796d08 "; - ASSERT_EQUALS("void foo ( int x@1 ) { switch ( x@1 ) { } ; }", - parse(clang)); - } - - void typedefDecl1() { - const char clang[] = "|-TypedefDecl 0x2d60180 <> implicit __int128_t '__int128'\n" - "| `-BuiltinType 0x2d5fe80 '__int128'"; - ASSERT_EQUALS("typedef __int128 __int128_t ;", parse(clang)); - } - - void typedefDecl2() { - const char clang[] = "|-TypedefDecl 0x2d604a8 <> implicit __NSConstantString 'struct __NSConstantString_tag'\n" - "| `-RecordType 0x2d602c0 'struct __NSConstantString_tag'\n" - "| `-Record 0x2d60238 '__NSConstantString_tag'"; - ASSERT_EQUALS("typedef struct __NSConstantString_tag __NSConstantString ;", parse(clang)); - } - - void typedefDecl3() { - const char clang[] = "|-TypedefDecl 0x2d60540 <> implicit __builtin_ms_va_list 'char *'\n" - "| `-PointerType 0x2d60500 'char *'\n" - "| `-BuiltinType 0x2d5f980 'char'"; - ASSERT_EQUALS("typedef char * __builtin_ms_va_list ;", parse(clang)); - } - - void unaryExprOrTypeTraitExpr1() { - const char clang[] = "`-VarDecl 0x24cc610 col:5 x 'int' cinit\n" - " `-ImplicitCastExpr 0x24cc6e8 'int' \n" - " `-UnaryExprOrTypeTraitExpr 0x24cc6c8 'unsigned long' sizeof 'int'\n"; - ASSERT_EQUALS("int x@1 = sizeof ( int ) ;", parse(clang)); - } - - void unaryExprOrTypeTraitExpr2() { - const char clang[] = "`-VarDecl 0x27c6c00 col:9 x 'int' cinit\n" - " `-ImplicitCastExpr 0x27c6cc8 'int' \n" - " `-UnaryExprOrTypeTraitExpr 0x27c6ca8 'unsigned long' sizeof\n" - " `-ParenExpr 0x27c6c88 'char [10]' lvalue\n" - " `-DeclRefExpr 0x27c6c60 'char [10]' lvalue Var 0x27c6b48 'buf' 'char [10]'"; - ASSERT_EQUALS("int x@1 = sizeof ( buf ) ;", parse(clang)); - } - - void unaryOperator() { - const char clang[] = "`-FunctionDecl 0x2dd9748 <1.cpp:2:1, col:44> col:5 foo 'int (int *)'\n" - " |-ParmVarDecl 0x2dd9680 col:19 used p 'int *'\n" - " `-CompoundStmt 0x2dd9908 \n" - " `-ReturnStmt 0x2dd98f0 \n" - " `-BinaryOperator 0x2dd98c8 'int' '/'\n" - " |-IntegerLiteral 0x2dd9830 'int' 100000\n" - " `-ImplicitCastExpr 0x2dd98b0 'int' \n" - " `-UnaryOperator 0x2dd9890 'int' lvalue prefix '*' cannot overflow\n" - " `-ImplicitCastExpr 0x2dd9878 'int *' \n" - " `-DeclRefExpr 0x2dd9850 'int *' lvalue ParmVar 0x2dd9680 'p' 'int *'"; - ASSERT_EQUALS("int foo ( int * p@1 ) { return 100000 / * p@1 ; }", parse(clang)); - } - - void vardecl1() { - const char clang[] = "|-VarDecl 0x32b8aa0 <1.c:1:1, col:9> col:5 used a 'int' cinit\n" - "| `-IntegerLiteral 0x32b8b40 'int' 1\n" - "`-VarDecl 0x32b8b78 col:5 b 'int' cinit\n" - " `-ImplicitCastExpr 0x32b8c00 'int' \n" - " `-DeclRefExpr 0x32b8bd8 'int' lvalue Var 0x32b8aa0 'a' 'int'"; - - ASSERT_EQUALS("int a@1 = 1 ; int b@2 = a@1 ;", - parse(clang)); - } - - void vardecl2() { - const char clang[] = "|-VarDecl 0x3873b50 <1.c:1:1, col:9> col:5 used a 'int [10]'\n" - "`-FunctionDecl 0x3873c38 line:3:6 foo 'void ()'\n" - " `-CompoundStmt 0x3873dd0 \n" - " `-BinaryOperator 0x3873da8 'int' '='\n" - " |-ArraySubscriptExpr 0x3873d60 'int' lvalue\n" - " | |-ImplicitCastExpr 0x3873d48 'int *' \n" - " | | `-DeclRefExpr 0x3873cd8 'int [10]' lvalue Var 0x3873b50 'a' 'int [10]'\n" - " | `-IntegerLiteral 0x3873d00 'int' 0\n" - " `-IntegerLiteral 0x3873d88 'int' 0\n"; - - ASSERT_EQUALS("int [10] a@1 ; void foo ( ) { a@1 [ 0 ] = 0 ; }", - parse(clang)); - } - - void vardecl3() { - const char clang[] = "`-VarDecl 0x25a8aa0 <1.c:1:1, col:12> col:12 p 'const int *'"; - ASSERT_EQUALS("const int * p@1 ;", parse(clang)); - } - - void vardecl4() { - const char clang[] = "|-VarDecl 0x23d6c78 col:14 stdin 'FILE *' extern"; - ASSERT_EQUALS("FILE * stdin@1 ;", parse(clang)); - } - - void vardecl5() { - const char clang[] = "|-VarDecl 0x2e31fc0 col:26 sys_errlist 'const char *const []' extern"; - ASSERT_EQUALS("const char * const [] sys_errlist@1 ;", parse(clang)); - } - - void vardecl6() { - const char clang[] = "`-VarDecl 0x278e170 <1.c:1:1, col:16> col:12 x 'int' static cinit\n" - " `-IntegerLiteral 0x278e220 'int' 3"; - ASSERT_EQUALS("static int x@1 = 3 ;", parse(clang)); - } - - void vardecl7() { - const char clang[] = "`-VarDecl 0x2071f20 <1.cpp:2:1, col:23> col:9 start 'void *(*)(void *)'"; - ASSERT_EQUALS("void * * start@1 ;", parse(clang)); - } - - void whileStmt1() { - const char clang[] = "`-FunctionDecl 0x3d45b18 <1.c:1:1, line:3:1> line:1:6 foo 'void ()'\n" - " `-CompoundStmt 0x3d45c48 \n" - " `-WhileStmt 0x3d45c28 \n" - " |-<<>>\n" - " |-IntegerLiteral 0x3d45bf8 'int' 0\n" - " `-NullStmt 0x3d45c18 "; - ASSERT_EQUALS("void foo ( ) { while ( 0 ) { ; } }", - parse(clang)); - } - - void whileStmt2() { - // clang 9 - const char clang[] = "`-FunctionDecl 0x1c99ac8 <1.cpp:1:1, col:27> col:6 foo 'void ()'\n" - " `-CompoundStmt 0x1c99c10 \n" - " `-WhileStmt 0x1c99bf8 \n" - " |-ImplicitCastExpr 0x1c99bd0 'bool' \n" - " | `-IntegerLiteral 0x1c99bb0 'int' 1\n" - " `-CompoundStmt 0x1c99be8 "; - ASSERT_EQUALS("void foo ( ) { while ( 1 ) { } }", parse(clang)); - } - - -#define GET_SYMBOL_DB(AST) \ - Settings settings; \ - settings.clang = true; \ - settings.platform(cppcheck::Platform::PlatformType::Unix64); \ - Tokenizer tokenizer(&settings, this); \ - std::istringstream istr(AST); \ - clangimport::parseClangAstDump(&tokenizer, istr); \ - const SymbolDatabase *db = tokenizer.getSymbolDatabase(); \ - ASSERT(db) - - void tokenIndex() { - const char clang[] = "`-FunctionDecl 0x1e07dd0 <67.cpp:1:1, col:13> col:6 foo 'void ()'\n" - " `-CompoundStmt 0x1e07eb8 "; - ASSERT_EQUALS("void foo ( ) { }", parse(clang)); - - GET_SYMBOL_DB(clang); - const Token *tok = tokenizer.tokens(); - ASSERT_EQUALS(tok->index() + 1, tok->next()->index()); - } - - void symbolDatabaseEnum1() { - const char clang[] = "|-NamespaceDecl 0x29ad5f8 <1.cpp:1:1, line:3:1> line:1:11 ns\n" - "| `-EnumDecl 0x29ad660 col:6 referenced abc\n" - "| |-EnumConstantDecl 0x29ad720 col:11 a 'ns::abc'\n" - "| |-EnumConstantDecl 0x29ad768 col:13 b 'ns::abc'\n" - "| `-EnumConstantDecl 0x29ad7b0 col:15 referenced c 'ns::abc'\n" - "`-VarDecl 0x29ad898 col:9 x 'ns::abc':'ns::abc' cinit\n" - " `-DeclRefExpr 0x29ad998 'ns::abc' EnumConstant 0x29ad7b0 'c' 'ns::abc'\n"; - - ASSERT_EQUALS("namespace ns { enum abc { a , b , c } } ns :: abc x@1 = c ;", parse(clang)); - - GET_SYMBOL_DB(clang); - - // Enum scope and type - ASSERT_EQUALS(3, db->scopeList.size()); - const Scope &enumScope = db->scopeList.back(); - ASSERT_EQUALS(Scope::ScopeType::eEnum, enumScope.type); - ASSERT_EQUALS("abc", enumScope.className); - const Type *enumType = enumScope.definedType; - ASSERT_EQUALS("abc", enumType->name()); - - // Variable - const Token *vartok = Token::findsimplematch(tokenizer.tokens(), "x"); - ASSERT(vartok); - ASSERT(vartok->variable()); - ASSERT(vartok->variable()->valueType()); - ASSERT_EQUALS(uintptr_t(&enumScope), uintptr_t(vartok->variable()->valueType()->typeScope)); - } - - void symbolDatabaseFunction1() { - const char clang[] = "|-FunctionDecl 0x3aea7a0 <1.cpp:2:1, col:22> col:6 used foo 'void (int, int)'\n" - " |-ParmVarDecl 0x3aea650 col:14 x 'int'\n" - " |-ParmVarDecl 0x3aea6c8 col:21 y 'int'\n" - " `-CompoundStmt 0x3d45c48 \n"; - - GET_SYMBOL_DB(clang); - - // There is a function foo that has 2 arguments - ASSERT_EQUALS(1, db->functionScopes.size()); - const Scope *scope = db->functionScopes[0]; - const Function *func = scope->function; - ASSERT_EQUALS(2, func->argCount()); - ASSERT_EQUALS("x", func->getArgumentVar(0)->name()); - ASSERT_EQUALS("y", func->getArgumentVar(1)->name()); - ASSERT_EQUALS(ValueType::Type::INT, func->getArgumentVar(0)->valueType()->type); - ASSERT_EQUALS(ValueType::Type::INT, func->getArgumentVar(1)->valueType()->type); - } - - void symbolDatabaseFunction2() { - const char clang[] = "|-FunctionDecl 0x3aea7a0 <1.cpp:2:1, col:22> col:6 used foo 'void (int, int)'\n" - "| |-ParmVarDecl 0x3aea650 col:14 'int'\n" - "| |-ParmVarDecl 0x3aea6c8 col:21 'int'\n" - " `-CompoundStmt 0x3d45c48 \n"; - - GET_SYMBOL_DB(clang); - - // There is a function foo that has 2 arguments - ASSERT_EQUALS(1, db->functionScopes.size()); - const Scope *scope = db->functionScopes[0]; - const Function *func = scope->function; - ASSERT_EQUALS(2, func->argCount()); - ASSERT_EQUALS(0, (long long)func->getArgumentVar(0)->nameToken()); - ASSERT_EQUALS(0, (long long)func->getArgumentVar(1)->nameToken()); - } - - void symbolDatabaseFunction3() { // #9640 - const char clang[] = "`-FunctionDecl 0x238fcd8 <9640.cpp:1:1, col:26> col:6 used bar 'bool (const char, int &)'\n" - " |-ParmVarDecl 0x238fb10 col:20 'const char'\n" - " |-ParmVarDecl 0x238fbc0 col:26 'int &'\n" - " `-CompoundStmt 0x3d45c48 \n"; - - GET_SYMBOL_DB(clang); - - // There is a function foo that has 2 arguments - ASSERT_EQUALS(1, db->functionScopes.size()); - const Scope *scope = db->functionScopes[0]; - const Function *func = scope->function; - ASSERT_EQUALS(2, func->argCount()); - ASSERT_EQUALS(false, func->getArgumentVar(0)->isReference()); - ASSERT_EQUALS(true, func->getArgumentVar(1)->isReference()); - } - - void symbolDatabaseFunctionConst() { - const char clang[] = "`-CXXRecordDecl 0x7e2d98 <1.cpp:2:1, line:5:1> line:2:7 class foo definition\n" - " `-CXXMethodDecl 0x7e3000 col:8 f 'void () const'"; - - GET_SYMBOL_DB(clang); - - // There is a function f that is const - ASSERT_EQUALS(2, db->scopeList.size()); - ASSERT_EQUALS(1, db->scopeList.back().functionList.size()); - const Function &func = db->scopeList.back().functionList.back(); - ASSERT(func.isConst()); - } - - void symbolDatabaseVariableRef() { - const char clang[] = "`-FunctionDecl 0x1593df0 <3.cpp:1:1, line:4:1> line:1:6 foo 'void ()'\n" - " `-CompoundStmt 0x15940b0 \n" - " |-DeclStmt 0x1593f58 \n" - " | `-VarDecl 0x1593ef0 col:7 used x 'int'\n" - " `-DeclStmt 0x1594098 \n" - " `-VarDecl 0x1593fb8 col:8 ref 'int &' cinit\n" - " `-DeclRefExpr 0x1594020 'int' lvalue Var 0x1593ef0 'x' 'int'"; - GET_SYMBOL_DB(clang); - const Variable *refVar = db->variableList().back(); - ASSERT(refVar->isReference()); - } - - void symbolDatabaseVariableRRef() { - const char clang[] = "`-FunctionDecl 0x1a40df0 <3.cpp:1:1, line:4:1> line:1:6 foo 'void ()'\n" - " `-CompoundStmt 0x1a41180 \n" - " |-DeclStmt 0x1a40f58 \n" - " | `-VarDecl 0x1a40ef0 col:7 used x 'int'\n" - " `-DeclStmt 0x1a41168 \n" - " `-VarDecl 0x1a40fb8 col:9 ref 'int &&' cinit\n" - " `-ExprWithCleanups 0x1a410f8 'int' xvalue\n" - " `-MaterializeTemporaryExpr 0x1a41098 'int' xvalue extended by Var 0x1a40fb8 'ref' 'int &&'\n" - " `-BinaryOperator 0x1a41078 'int' '+'\n" - " |-ImplicitCastExpr 0x1a41060 'int' \n" - " | `-DeclRefExpr 0x1a41020 'int' lvalue Var 0x1a40ef0 'x' 'int'\n" - " `-IntegerLiteral 0x1a41040 'int' 1\n"; - - ASSERT_EQUALS("void foo ( ) { int x@1 ; int && ref@2 = x@1 + 1 ; }", parse(clang)); - - GET_SYMBOL_DB(clang); - const Variable *refVar = db->variableList().back(); - ASSERT(refVar->isReference()); - ASSERT(refVar->isRValueReference()); - } - - void symbolDatabaseVariablePointerRef() { - const char clang[] = "`-FunctionDecl 0x9b4f10 <3.cpp:1:1, col:17> col:6 used foo 'void (int *&)'\n" - " `-ParmVarDecl 0x9b4e40 col:16 p 'int *&'\n"; - - ASSERT_EQUALS("void foo ( int * & p@1 ) ;", parse(clang)); - - GET_SYMBOL_DB(clang); - const Variable *p = db->variableList().back(); - ASSERT(p->isPointer()); - ASSERT(p->isReference()); - } - - void symbolDatabaseNodeType1() { - const char clang[] = "`-FunctionDecl 0x32438c0 line:5:6 foo 'a::b (a::b)'\n" - " |-ParmVarDecl 0x32437b0 col:15 used i 'a::b':'long'\n" - " `-CompoundStmt 0x3243a60 \n" - " `-ReturnStmt 0x3243a48 \n" - " `-BinaryOperator 0x3243a20 'long' '+'\n" - " |-ImplicitCastExpr 0x32439f0 'a::b':'long' \n" - " | `-DeclRefExpr 0x32439a8 'a::b':'long' lvalue ParmVar 0x32437b0 'i' 'a::b':'long'\n" - " `-ImplicitCastExpr 0x3243a08 'long' \n" - " `-IntegerLiteral 0x32439d0 'int' 1\n"; - - GET_SYMBOL_DB(clang); - - const Token *tok = Token::findsimplematch(tokenizer.tokens(), "i + 1"); - ASSERT(!!tok); - ASSERT(!!tok->valueType()); - ASSERT_EQUALS("signed long", tok->valueType()->str()); - } - - void symbolDatabaseForVariable() { - const char clang[] = "`-FunctionDecl 0x38f8bb0 <10100.c:2:1, line:4:1> line:2:6 f 'void (void)'\n" - " `-CompoundStmt 0x38f8d88 \n" - " `-ForStmt 0x38f8d50 \n" - " |-DeclStmt 0x38f8d28 \n" - " | `-VarDecl 0x38f8ca8 col:14 i 'int' cinit\n" - " | `-IntegerLiteral 0x38f8d08 'int' 0\n" - " |-<<>>\n" - " |-<<>>\n" - " |-<<>>\n" - " `-CompoundStmt 0x38f8d40 "; - - ASSERT_EQUALS("void f ( ) { for ( int i@1 = 0 ; ; ) { } }", parse(clang)); - - GET_SYMBOL_DB(clang); - - const Token *tok = Token::findsimplematch(tokenizer.tokens(), "i"); - ASSERT(!!tok); - ASSERT(!!tok->variable()); - ASSERT_EQUALS(Scope::ScopeType::eFor, tok->variable()->scope()->type); - } - - void valueFlow1() { - // struct S { int x; int buf[10]; } ; int sz = sizeof(struct S); - const char clang[] = "|-RecordDecl 0x2fc5a88 <1.c:1:1, line:4:1> line:1:8 struct S definition\n" - "| |-FieldDecl 0x2fc5b48 col:7 x 'int'\n" - "| `-FieldDecl 0x2fc5c10 col:7 buf 'int [10]'\n" - "`-VarDecl 0x2fc5c70 col:5 sz 'int' cinit\n" - " `-ImplicitCastExpr 0x2fc5d88 'int' \n" - " `-UnaryExprOrTypeTraitExpr 0x2fc5d68 'unsigned long' sizeof 'struct S':'struct S'"; - GET_SYMBOL_DB(clang); - - const Token *tok = Token::findsimplematch(tokenizer.tokens(), "sizeof ("); - ASSERT(!!tok); - tok = tok->next(); - ASSERT(tok->hasKnownIntValue()); - ASSERT_EQUALS(44, tok->getKnownIntValue()); - } - - void valueFlow2() { - // int buf[42]; - // int x = sizeof(buf); - const char clang[] = "|-VarDecl 0x10f6de8 <66.cpp:3:1, col:11> col:5 referenced buf 'int [42]'\n" - "`-VarDecl 0x10f6eb0 col:5 x 'int' cinit\n" - " `-ImplicitCastExpr 0x10f6f78 'int' \n" - " `-UnaryExprOrTypeTraitExpr 0x10f6f58 'unsigned long' sizeof\n" - " `-ParenExpr 0x10f6f38 'int [42]' lvalue\n" - " `-DeclRefExpr 0x10f6f18 'int [42]' lvalue Var 0x10f6de8 'buf' 'int [42]' non_odr_use_unevaluated"; - - GET_SYMBOL_DB(clang); - - const Token *tok = Token::findsimplematch(tokenizer.tokens(), "sizeof ("); - ASSERT(!!tok); - tok = tok->next(); - // TODO ASSERT(tok->hasKnownIntValue()); - // TODO ASSERT_EQUALS(10, tok->getKnownIntValue()); - } - - void valueType1() { - const char clang[] = "`-FunctionDecl 0x32438c0 line:5:6 foo 'a::b (a::b)'\n" - " |-ParmVarDecl 0x32437b0 col:15 used i 'a::b':'long'\n" - " `-CompoundStmt 0x3243a60 \n" - " `-ReturnStmt 0x3243a48 \n" - " `-ImplicitCastExpr 0x2176ca8 'int' \n" - " `-ImplicitCastExpr 0x2176c90 'bool' \n" - " `-DeclRefExpr 0x2176c60 'bool' lvalue Var 0x2176bd0 'e' 'bool'\n"; - - GET_SYMBOL_DB(clang); - - const Token *tok = Token::findsimplematch(tokenizer.tokens(), "e"); - ASSERT(!!tok); - ASSERT(!!tok->valueType()); - ASSERT_EQUALS("bool", tok->valueType()->str()); - } - - void valueType2() { - const char clang[] = "`-VarDecl 0xc9eda0 <1.cpp:2:1, col:17> col:13 s 'const char *' cinit\n" - " `-ImplicitCastExpr 0xc9eef0 'const char *' \n" - " `-StringLiteral 0xc9eed0 'const char [6]' lvalue \"hello\"\n"; - - GET_SYMBOL_DB(clang); - - const Token *tok = Token::findsimplematch(tokenizer.tokens(), "\"hello\""); - ASSERT(!!tok); - ASSERT(!!tok->valueType()); - ASSERT_EQUALS("const signed char *", tok->valueType()->str()); - } -}; - -REGISTER_TEST(TestClangImport)