Bug hunting: basic handling of contracts through GUI
This commit is contained in:
parent
72e0a4be29
commit
f7096a2232
|
@ -40,7 +40,9 @@ ErrorItem::ErrorItem()
|
|||
}
|
||||
|
||||
ErrorItem::ErrorItem(const ErrorLogger::ErrorMessage &errmsg)
|
||||
: errorId(QString::fromStdString(errmsg.id))
|
||||
: file0(QString::fromStdString(errmsg.file0))
|
||||
, function(QString::fromStdString(errmsg.function))
|
||||
, errorId(QString::fromStdString(errmsg.id))
|
||||
, severity(errmsg.severity)
|
||||
, inconclusive(errmsg.inconclusive)
|
||||
, summary(QString::fromStdString(errmsg.shortMessage()))
|
||||
|
|
|
@ -80,6 +80,7 @@ public:
|
|||
QString tool() const;
|
||||
|
||||
QString file0;
|
||||
QString function;
|
||||
QString errorId;
|
||||
Severity::SeverityType severity;
|
||||
bool inconclusive;
|
||||
|
|
|
@ -142,6 +142,7 @@ MainWindow::MainWindow(TranslationHandler* th, QSettings* settings) :
|
|||
connect(mUI.mResults, &ResultsView::checkSelected, this, &MainWindow::performSelectedFilesCheck);
|
||||
connect(mUI.mResults, &ResultsView::tagged, this, &MainWindow::tagged);
|
||||
connect(mUI.mResults, &ResultsView::suppressIds, this, &MainWindow::suppressIds);
|
||||
connect(mUI.mResults, &ResultsView::addFunctionContract, this, &MainWindow::addFunctionContract);
|
||||
connect(mUI.mMenuView, &QMenu::aboutToShow, this, &MainWindow::aboutToShowViewMenu);
|
||||
|
||||
// File menu
|
||||
|
@ -844,6 +845,8 @@ Settings MainWindow::getCppcheckSettings()
|
|||
result.bugHunting = mProjectFile->bugHunting;
|
||||
result.bugHuntingReport = " ";
|
||||
|
||||
result.functionContracts = mProjectFile->getFunctionContracts();
|
||||
|
||||
const QStringList undefines = mProjectFile->getUndefines();
|
||||
foreach (QString undefine, undefines)
|
||||
result.userUndefs.insert(undefine.toStdString());
|
||||
|
@ -1790,3 +1793,20 @@ void MainWindow::suppressIds(QStringList ids)
|
|||
mProjectFile->setSuppressions(suppressions);
|
||||
mProjectFile->write();
|
||||
}
|
||||
|
||||
void MainWindow::addFunctionContract(QString function)
|
||||
{
|
||||
if (!mProjectFile)
|
||||
return;
|
||||
bool ok;
|
||||
const QString expects = QInputDialog::getText(this,
|
||||
tr("Add contract"),
|
||||
"Function:" + function + "\nExpects:",
|
||||
QLineEdit::Normal,
|
||||
QString(),
|
||||
&ok);
|
||||
if (ok) {
|
||||
mProjectFile->setFunctionContract(function, expects);
|
||||
mProjectFile->write();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -225,6 +225,8 @@ protected slots:
|
|||
/** Suppress error ids */
|
||||
void suppressIds(QStringList ids);
|
||||
|
||||
/** Add contract for function */
|
||||
void addFunctionContract(QString function);
|
||||
private:
|
||||
|
||||
/** Get filename for last results */
|
||||
|
|
|
@ -55,6 +55,7 @@ void ProjectFile::clear()
|
|||
mUndefines.clear();
|
||||
mPaths.clear();
|
||||
mExcludedPaths.clear();
|
||||
mFunctionContracts.clear();
|
||||
mLibraries.clear();
|
||||
mPlatform.clear();
|
||||
mSuppressions.clear();
|
||||
|
@ -145,6 +146,10 @@ bool ProjectFile::read(const QString &filename)
|
|||
if (xmlReader.name() == CppcheckXml::IgnoreElementName)
|
||||
readExcludes(xmlReader);
|
||||
|
||||
// Function contracts
|
||||
if (xmlReader.name() == CppcheckXml::FunctionContracts)
|
||||
readFunctionContracts(xmlReader);
|
||||
|
||||
// Find libraries list from inside project element
|
||||
if (xmlReader.name() == CppcheckXml::LibrariesElementName)
|
||||
readStringList(mLibraries, xmlReader, CppcheckXml::LibraryElementName);
|
||||
|
@ -477,6 +482,43 @@ void ProjectFile::readExcludes(QXmlStreamReader &reader)
|
|||
} while (!allRead);
|
||||
}
|
||||
|
||||
void ProjectFile::readFunctionContracts(QXmlStreamReader &reader)
|
||||
{
|
||||
QXmlStreamReader::TokenType type;
|
||||
bool allRead = false;
|
||||
do {
|
||||
type = reader.readNext();
|
||||
switch (type) {
|
||||
case QXmlStreamReader::StartElement:
|
||||
if (reader.name().toString() == CppcheckXml::FunctionContract) {
|
||||
QXmlStreamAttributes attribs = reader.attributes();
|
||||
QString function = attribs.value(QString(), CppcheckXml::ContractFunction).toString();
|
||||
QString expects = attribs.value(QString(), CppcheckXml::ContractExpects).toString();
|
||||
if (!function.isEmpty() && !expects.isEmpty())
|
||||
mFunctionContracts[function.toStdString()] = expects.toStdString();
|
||||
}
|
||||
break;
|
||||
|
||||
case QXmlStreamReader::EndElement:
|
||||
if (reader.name().toString() == CppcheckXml::FunctionContracts)
|
||||
allRead = true;
|
||||
break;
|
||||
|
||||
// Not handled
|
||||
case QXmlStreamReader::NoToken:
|
||||
case QXmlStreamReader::Invalid:
|
||||
case QXmlStreamReader::StartDocument:
|
||||
case QXmlStreamReader::EndDocument:
|
||||
case QXmlStreamReader::Characters:
|
||||
case QXmlStreamReader::Comment:
|
||||
case QXmlStreamReader::DTD:
|
||||
case QXmlStreamReader::EntityReference:
|
||||
case QXmlStreamReader::ProcessingInstruction:
|
||||
break;
|
||||
}
|
||||
} while (!allRead);
|
||||
}
|
||||
|
||||
void ProjectFile::readVsConfigurations(QXmlStreamReader &reader)
|
||||
{
|
||||
QXmlStreamReader::TokenType type;
|
||||
|
@ -653,6 +695,11 @@ void ProjectFile::setLibraries(const QStringList &libraries)
|
|||
mLibraries = libraries;
|
||||
}
|
||||
|
||||
void ProjectFile::setFunctionContract(QString function, QString expects)
|
||||
{
|
||||
mFunctionContracts[function.toStdString()] = expects.toStdString();
|
||||
}
|
||||
|
||||
void ProjectFile::setPlatform(const QString &platform)
|
||||
{
|
||||
mPlatform = platform;
|
||||
|
@ -796,6 +843,17 @@ bool ProjectFile::write(const QString &filename)
|
|||
CppcheckXml::LibrariesElementName,
|
||||
CppcheckXml::LibraryElementName);
|
||||
|
||||
if (!mFunctionContracts.empty()) {
|
||||
xmlWriter.writeStartElement(CppcheckXml::FunctionContracts);
|
||||
for (const auto contract: mFunctionContracts) {
|
||||
xmlWriter.writeStartElement(CppcheckXml::FunctionContract);
|
||||
xmlWriter.writeAttribute(CppcheckXml::ContractFunction, QString::fromStdString(contract.first));
|
||||
xmlWriter.writeAttribute(CppcheckXml::ContractExpects, QString::fromStdString(contract.second));
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
|
||||
if (!mSuppressions.isEmpty()) {
|
||||
xmlWriter.writeStartElement(CppcheckXml::SuppressionsElementName);
|
||||
foreach (const Suppressions::Suppression &suppression, mSuppressions) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#ifndef PROJECT_FILE_H
|
||||
#define PROJECT_FILE_H
|
||||
|
||||
#include <map>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
@ -200,6 +201,10 @@ public:
|
|||
mMaxCtuDepth = maxCtuDepth;
|
||||
}
|
||||
|
||||
const std::map<std::string,std::string> getFunctionContracts() const {
|
||||
return mFunctionContracts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get filename for the project file.
|
||||
* @return file name.
|
||||
|
@ -264,6 +269,9 @@ public:
|
|||
*/
|
||||
void setLibraries(const QStringList &libraries);
|
||||
|
||||
/** Set contract for a function */
|
||||
void setFunctionContract(QString function, QString expects);
|
||||
|
||||
/**
|
||||
* @brief Set platform.
|
||||
* @param platform platform.
|
||||
|
@ -377,6 +385,12 @@ protected:
|
|||
*/
|
||||
void readExcludes(QXmlStreamReader &reader);
|
||||
|
||||
/**
|
||||
* @brief Read function contracts.
|
||||
* @param reader XML stream reader.
|
||||
*/
|
||||
void readFunctionContracts(QXmlStreamReader &reader);
|
||||
|
||||
/**
|
||||
* @brief Read lists of Visual Studio configurations
|
||||
* @param reader XML stream reader.
|
||||
|
@ -486,6 +500,8 @@ private:
|
|||
*/
|
||||
QStringList mLibraries;
|
||||
|
||||
std::map<std::string, std::string> mFunctionContracts;
|
||||
|
||||
/**
|
||||
* @brief Platform
|
||||
*/
|
||||
|
|
|
@ -191,6 +191,7 @@ bool ResultsTree::addErrorItem(const ErrorItem &item)
|
|||
data["id"] = item.errorId;
|
||||
data["inconclusive"] = item.inconclusive;
|
||||
data["file0"] = stripPath(item.file0, true);
|
||||
data["function"] = item.function;
|
||||
data["sinceDate"] = item.sinceDate;
|
||||
data["tags"] = item.tags;
|
||||
data["hide"] = hide;
|
||||
|
@ -212,7 +213,7 @@ bool ResultsTree::addErrorItem(const ErrorItem &item)
|
|||
if (!child_item)
|
||||
continue;
|
||||
|
||||
//Add user data to that item
|
||||
// Add user data to that item
|
||||
QMap<QString, QVariant> child_data;
|
||||
child_data["severity"] = ShowTypes::SeverityToShowType(line.severity);
|
||||
child_data["summary"] = line.summary;
|
||||
|
@ -561,6 +562,7 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e)
|
|||
QModelIndex index = indexAt(e->pos());
|
||||
if (index.isValid()) {
|
||||
bool multipleSelection = false;
|
||||
|
||||
mSelectionModel = selectionModel();
|
||||
if (mSelectionModel->selectedRows().count() > 1)
|
||||
multipleSelection = true;
|
||||
|
@ -609,12 +611,20 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e)
|
|||
menu.addSeparator();
|
||||
}
|
||||
|
||||
const bool bughunting = !multipleSelection && mContextItem->data().toMap().value("id").toString().startsWith("bughunting");
|
||||
|
||||
if (bughunting) {
|
||||
QAction *addContract = new QAction(tr("Add contract.."), &menu);
|
||||
connect(addContract, SIGNAL(triggered()), this, SLOT(addContract()));
|
||||
menu.addAction(addContract);
|
||||
menu.addSeparator();
|
||||
}
|
||||
|
||||
//Create an action for the application
|
||||
QAction *recheckSelectedFiles = new QAction(tr("Recheck"), &menu);
|
||||
QAction *copy = new QAction(tr("Copy"), &menu);
|
||||
QAction *hide = new QAction(tr("Hide"), &menu);
|
||||
QAction *hideallid = new QAction(tr("Hide all with id"), &menu);
|
||||
QAction *suppress = new QAction(tr("Suppress selected id(s)"), &menu);
|
||||
QAction *opencontainingfolder = new QAction(tr("Open containing folder"), &menu);
|
||||
|
||||
if (multipleSelection) {
|
||||
|
@ -632,7 +642,11 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e)
|
|||
menu.addSeparator();
|
||||
menu.addAction(hide);
|
||||
menu.addAction(hideallid);
|
||||
menu.addAction(suppress);
|
||||
if (!bughunting) {
|
||||
QAction *suppress = new QAction(tr("Suppress selected id(s)"), &menu);
|
||||
menu.addAction(suppress);
|
||||
connect(suppress, SIGNAL(triggered()), this, SLOT(suppressSelectedIds()));
|
||||
}
|
||||
menu.addSeparator();
|
||||
menu.addAction(opencontainingfolder);
|
||||
|
||||
|
@ -640,7 +654,6 @@ void ResultsTree::contextMenuEvent(QContextMenuEvent * e)
|
|||
connect(copy, SIGNAL(triggered()), this, SLOT(copy()));
|
||||
connect(hide, SIGNAL(triggered()), this, SLOT(hideResult()));
|
||||
connect(hideallid, SIGNAL(triggered()), this, SLOT(hideAllIdResult()));
|
||||
connect(suppress, SIGNAL(triggered()), this, SLOT(suppressSelectedIds()));
|
||||
connect(opencontainingfolder, SIGNAL(triggered()), this, SLOT(openContainingFolder()));
|
||||
|
||||
if (!mTags.isEmpty()) {
|
||||
|
@ -1020,6 +1033,12 @@ void ResultsTree::openContainingFolder()
|
|||
}
|
||||
}
|
||||
|
||||
void ResultsTree::addContract()
|
||||
{
|
||||
QString function = mContextItem->data().toMap().value("function").toString();
|
||||
emit addFunctionContract(function);
|
||||
}
|
||||
|
||||
void ResultsTree::tagSelectedItems(const QString &tag)
|
||||
{
|
||||
if (!mSelectionModel)
|
||||
|
|
|
@ -208,6 +208,8 @@ signals:
|
|||
/** Suppress Ids */
|
||||
void suppressIds(QStringList ids);
|
||||
|
||||
/** Add contract for function */
|
||||
void addFunctionContract(QString function);
|
||||
public slots:
|
||||
|
||||
/**
|
||||
|
@ -282,6 +284,11 @@ protected slots:
|
|||
*/
|
||||
void openContainingFolder();
|
||||
|
||||
/**
|
||||
* @brief Allow user to add contract to fix bughunting warning
|
||||
*/
|
||||
void addContract();
|
||||
|
||||
/**
|
||||
* @brief Slot for selection change in the results tree.
|
||||
*
|
||||
|
|
|
@ -55,6 +55,7 @@ ResultsView::ResultsView(QWidget * parent) :
|
|||
connect(mUI.mTree, &ResultsTree::treeSelectionChanged, this, &ResultsView::updateDetails);
|
||||
connect(mUI.mTree, &ResultsTree::tagged, this, &ResultsView::tagged);
|
||||
connect(mUI.mTree, &ResultsTree::suppressIds, this, &ResultsView::suppressIds);
|
||||
connect(mUI.mTree, &ResultsTree::addFunctionContract, this, &ResultsView::addFunctionContract);
|
||||
connect(this, &ResultsView::showResults, mUI.mTree, &ResultsTree::showResults);
|
||||
connect(this, &ResultsView::showCppcheckResults, mUI.mTree, &ResultsTree::showCppcheckResults);
|
||||
connect(this, &ResultsView::showClangResults, mUI.mTree, &ResultsTree::showClangResults);
|
||||
|
|
|
@ -228,6 +228,9 @@ signals:
|
|||
/** Suppress Ids */
|
||||
void suppressIds(QStringList ids);
|
||||
|
||||
/** Add contract for function */
|
||||
void addFunctionContract(QString function);
|
||||
|
||||
/**
|
||||
* @brief Show/hide certain type of errors
|
||||
* Refreshes the tree.
|
||||
|
|
|
@ -314,8 +314,10 @@ public:
|
|||
std::list<FileLocation> callStack;
|
||||
std::string id;
|
||||
|
||||
/** source file (not header) */
|
||||
/** For GUI rechecking; source file (not header) */
|
||||
std::string file0;
|
||||
/** For GUI bug hunting; function name */
|
||||
std::string function;
|
||||
|
||||
Severity::SeverityType severity;
|
||||
CWE cwe;
|
||||
|
|
|
@ -158,8 +158,8 @@ namespace {
|
|||
|
||||
class Data : public ExprEngine::DataBase {
|
||||
public:
|
||||
Data(int *symbolValueIndex, const Tokenizer *tokenizer, const Settings *settings, const std::vector<ExprEngine::Callback> &callbacks, TrackExecution *trackExecution)
|
||||
: DataBase(settings)
|
||||
Data(int *symbolValueIndex, const Tokenizer *tokenizer, const Settings *settings, const std::string ¤tFunction, const std::vector<ExprEngine::Callback> &callbacks, TrackExecution *trackExecution)
|
||||
: DataBase(currentFunction, settings)
|
||||
, symbolValueIndex(symbolValueIndex)
|
||||
, tokenizer(tokenizer)
|
||||
, callbacks(callbacks)
|
||||
|
@ -172,6 +172,28 @@ namespace {
|
|||
const std::vector<ExprEngine::Callback> &callbacks;
|
||||
std::vector<ExprEngine::ValuePtr> constraints;
|
||||
|
||||
void contractConstraints(const Function *function, ExprEngine::ValuePtr (*executeExpression)(const Token*, Data&)) {
|
||||
const auto it = settings->functionContracts.find(currentFunction);
|
||||
if (it == settings->functionContracts.end())
|
||||
return;
|
||||
const std::string &expects = it->second;
|
||||
TokenList tokenList(settings);
|
||||
std::istringstream istr(expects);
|
||||
tokenList.createTokens(istr);
|
||||
tokenList.createAst();
|
||||
SymbolDatabase *symbolDatabase = const_cast<SymbolDatabase*>(tokenizer->getSymbolDatabase());
|
||||
for (Token *tok = tokenList.front(); tok; tok = tok->next()) {
|
||||
for (const Variable &arg: function->argumentList) {
|
||||
if (arg.name() == tok->str()) {
|
||||
tok->variable(&arg);
|
||||
tok->varId(arg.declarationId());
|
||||
}
|
||||
}
|
||||
}
|
||||
symbolDatabase->setValueTypeInTokenList(false, tokenList.front());
|
||||
constraints.push_back(executeExpression(tokenList.front()->astTop(), *this));
|
||||
}
|
||||
|
||||
void addError(int linenr) OVERRIDE {
|
||||
mTrackExecution->addError(linenr);
|
||||
}
|
||||
|
@ -1756,13 +1778,17 @@ void ExprEngine::executeFunction(const Scope *functionScope, const Tokenizer *to
|
|||
// TODO.. what about functions in headers?
|
||||
return;
|
||||
|
||||
const std::string currentFunction = function->fullName();
|
||||
|
||||
int symbolValueIndex = 0;
|
||||
TrackExecution trackExecution;
|
||||
Data data(&symbolValueIndex, tokenizer, settings, callbacks, &trackExecution);
|
||||
Data data(&symbolValueIndex, tokenizer, settings, currentFunction, callbacks, &trackExecution);
|
||||
|
||||
for (const Variable &arg : function->argumentList)
|
||||
data.assignValue(functionScope->bodyStart, arg.declarationId(), createVariableValue(arg, data));
|
||||
|
||||
data.contractConstraints(function, executeExpression1);
|
||||
|
||||
try {
|
||||
execute(functionScope->bodyStart, functionScope->bodyEnd, data);
|
||||
} catch (VerifyException &e) {
|
||||
|
@ -1829,6 +1855,7 @@ void ExprEngine::runChecks(ErrorLogger *errorLogger, const Tokenizer *tokenizer,
|
|||
std::list<const Token*> callstack{settings->clang ? tok : tok->astParent()};
|
||||
const char * const id = (tok->valueType() && tok->valueType()->isFloat()) ? "bughuntingDivByZeroFloat" : "bughuntingDivByZero";
|
||||
ErrorLogger::ErrorMessage errmsg(callstack, &tokenizer->list, Severity::SeverityType::error, id, "There is division, cannot determine that there can't be a division by zero.", CWE(369), false);
|
||||
errmsg.function = dataBase->currentFunction;
|
||||
errorLogger->reportErr(errmsg);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -71,8 +71,12 @@ namespace ExprEngine {
|
|||
|
||||
class DataBase {
|
||||
public:
|
||||
explicit DataBase(const Settings *settings) : settings(settings) {}
|
||||
explicit DataBase(const std::string ¤tFunction, const Settings *settings)
|
||||
: currentFunction(currentFunction)
|
||||
, settings(settings) {
|
||||
}
|
||||
virtual std::string getNewSymbolName() = 0;
|
||||
const std::string currentFunction;
|
||||
const Settings * const settings;
|
||||
virtual void addError(int linenr) {
|
||||
(void)linenr;
|
||||
|
|
|
@ -1018,7 +1018,9 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings *setti
|
|||
if (strcmp(node->Name(), CppcheckXml::RootPathName) == 0 && node->Attribute(CppcheckXml::RootPathNameAttrib)) {
|
||||
temp.basePaths.push_back(joinRelativePath(path, node->Attribute(CppcheckXml::RootPathNameAttrib)));
|
||||
temp.relativePaths = true;
|
||||
} else if (strcmp(node->Name(), CppcheckXml::BuildDirElementName) == 0)
|
||||
} else if (strcmp(node->Name(), CppcheckXml::BugHunting) == 0)
|
||||
temp.bugHunting = true;
|
||||
else if (strcmp(node->Name(), CppcheckXml::BuildDirElementName) == 0)
|
||||
temp.buildDir = joinRelativePath(path, node->GetText() ? node->GetText() : "");
|
||||
else if (strcmp(node->Name(), CppcheckXml::IncludeDirElementName) == 0)
|
||||
temp.includePaths = readXmlStringList(node, path, CppcheckXml::DirElementName, CppcheckXml::DirNameAttrib);
|
||||
|
@ -1033,6 +1035,16 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings *setti
|
|||
paths = readXmlStringList(node, path, CppcheckXml::PathName, CppcheckXml::PathNameAttrib);
|
||||
else if (strcmp(node->Name(), CppcheckXml::ExcludeElementName) == 0)
|
||||
guiProject.excludedPaths = readXmlStringList(node, "", CppcheckXml::ExcludePathName, CppcheckXml::ExcludePathNameAttrib);
|
||||
else if (strcmp(node->Name(), CppcheckXml::FunctionContracts) == 0) {
|
||||
for (const tinyxml2::XMLElement *child = node->FirstChildElement(); child; child = child->NextSiblingElement()) {
|
||||
if (strcmp(child->Name(), CppcheckXml::FunctionContract) == 0) {
|
||||
const char *function = child->Attribute(CppcheckXml::ContractFunction);
|
||||
const char *expects = child->Attribute(CppcheckXml::ContractExpects);
|
||||
if (function && expects)
|
||||
temp.functionContracts[function] = expects;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (strcmp(node->Name(), CppcheckXml::IgnoreElementName) == 0)
|
||||
guiProject.excludedPaths = readXmlStringList(node, "", CppcheckXml::IgnorePathName, CppcheckXml::IgnorePathNameAttrib);
|
||||
else if (strcmp(node->Name(), CppcheckXml::LibrariesElementName) == 0)
|
||||
|
@ -1099,6 +1111,8 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings *setti
|
|||
settings->checkUnusedTemplates = temp.checkUnusedTemplates;
|
||||
settings->maxCtuDepth = temp.maxCtuDepth;
|
||||
settings->safeChecks = temp.safeChecks;
|
||||
settings->bugHunting = temp.bugHunting;
|
||||
settings->functionContracts = temp.functionContracts;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -146,6 +146,10 @@ namespace CppcheckXml {
|
|||
const char ExcludeElementName[] = "exclude";
|
||||
const char ExcludePathName[] = "path";
|
||||
const char ExcludePathNameAttrib[] = "name";
|
||||
const char FunctionContracts[] = "function-contracts";
|
||||
const char FunctionContract[] = "contract";
|
||||
const char ContractFunction[] = "function";
|
||||
const char ContractExpects[] = "expects";
|
||||
const char LibrariesElementName[] = "libraries";
|
||||
const char LibraryElementName[] = "library";
|
||||
const char PlatformElementName[] = "platform";
|
||||
|
|
|
@ -173,6 +173,8 @@ public:
|
|||
/** @brief Force checking the files with "too many" configurations (--force). */
|
||||
bool force;
|
||||
|
||||
std::map<std::string, std::string> functionContracts;
|
||||
|
||||
/** @brief List of include paths, e.g. "my/includes/" which should be used
|
||||
for finding include files inside source files. (-I) */
|
||||
std::list<std::string> includePaths;
|
||||
|
|
|
@ -2157,6 +2157,18 @@ Function::Function(const Token *tokenDef)
|
|||
{
|
||||
}
|
||||
|
||||
std::string Function::fullName() const
|
||||
{
|
||||
std::string ret = name();
|
||||
for (const Scope *s = nestedIn; s; s = s->nestedIn) {
|
||||
if (!s->className.empty())
|
||||
ret = s->className + "::" + ret;
|
||||
}
|
||||
ret += "(";
|
||||
for (const Variable &arg : argumentList)
|
||||
ret += (arg.index() == 0 ? "" : ",") + arg.name();
|
||||
return ret + ")";
|
||||
}
|
||||
|
||||
static std::string qualifiedName(const Scope *scope)
|
||||
{
|
||||
|
@ -5763,9 +5775,10 @@ static const Function *getOperatorFunction(const Token * const tok)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings)
|
||||
void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *tokens)
|
||||
{
|
||||
Token * tokens = const_cast<Tokenizer *>(mTokenizer)->list.front();
|
||||
if (!tokens)
|
||||
tokens = const_cast<Tokenizer *>(mTokenizer)->list.front();
|
||||
|
||||
for (Token *tok = tokens; tok; tok = tok->next())
|
||||
tok->setValueType(nullptr);
|
||||
|
|
|
@ -743,6 +743,8 @@ public:
|
|||
return tokenDef->str();
|
||||
}
|
||||
|
||||
std::string fullName() const;
|
||||
|
||||
nonneg int argCount() const {
|
||||
return argumentList.size();
|
||||
}
|
||||
|
@ -1310,7 +1312,7 @@ public:
|
|||
void validateVariables() const;
|
||||
|
||||
/** Set valuetype in provided tokenlist */
|
||||
void setValueTypeInTokenList(bool reportDebugWarnings);
|
||||
void setValueTypeInTokenList(bool reportDebugWarnings, Token *tokens=nullptr);
|
||||
|
||||
/**
|
||||
* Calculates sizeof value for given type.
|
||||
|
|
Loading…
Reference in New Issue