Skip to content

Commit

Permalink
fix1
Browse files Browse the repository at this point in the history
  • Loading branch information
danmar committed Jun 2, 2024
1 parent ab9def9 commit f36c7c1
Show file tree
Hide file tree
Showing 10 changed files with 212 additions and 28 deletions.
22 changes: 21 additions & 1 deletion lib/cppcheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,7 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
}

// Parse comments and then remove them
mRemarkComments = preprocessor.getRemarkComments(tokens1);
preprocessor.inlineSuppressions(tokens1, mSettings.supprs.nomsg);
if (mSettings.dump || !mSettings.addons.empty()) {
std::ostringstream oss;
Expand Down Expand Up @@ -1613,7 +1614,26 @@ void CppCheck::reportErr(const ErrorMessage &msg)
mExitCode = 1;
}

mErrorLogger.reportErr(msg);
std::string remark;
if (!msg.callStack.empty()) {
for (const auto& r: mRemarkComments) {
if (r.file != msg.callStack.back().getfile(false))
continue;
if (r.lineNumber != msg.callStack.back().line)
continue;
remark = r.str;
break;
}
}

if (!remark.empty()) {
ErrorMessage msg2(msg);
msg2.remark = remark;
mErrorLogger.reportErr(msg2);
} else {
mErrorLogger.reportErr(msg);
}

// check if plistOutput should be populated and the current output file is open and the error is not suppressed
if (!mSettings.plistOutput.empty() && mPlistFile.is_open() && !mSettings.supprs.nomsg.isSuppressed(errorMessage)) {
// add error to plist output file
Expand Down
3 changes: 3 additions & 0 deletions lib/cppcheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ struct FileSettings;
class CheckUnusedFunctions;
class Tokenizer;
class FileWithDetails;
class RemarkComment;

namespace simplecpp { class TokenList; }

Expand Down Expand Up @@ -254,6 +255,8 @@ class CPPCHECKLIB CppCheck : ErrorLogger {
std::ofstream mPlistFile;

std::unique_ptr<CheckUnusedFunctions> mUnusedFunctionsCheck;

std::vector<RemarkComment> mRemarkComments;
};

/// @}
Expand Down
30 changes: 15 additions & 15 deletions lib/errorlogger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,11 +274,9 @@ std::string ErrorMessage::serialize() const
serializeString(oss, severityToString(severity));
serializeString(oss, std::to_string(cwe.id));
serializeString(oss, std::to_string(hash));
serializeString(oss, fixInvalidChars(remark));
serializeString(oss, file0);
if (certainty == Certainty::inconclusive) {
const std::string text("inconclusive");
serializeString(oss, text);
}
serializeString(oss, (certainty == Certainty::inconclusive) ? "1" : "0");

const std::string saneShortMessage = fixInvalidChars(mShortMessage);
const std::string saneVerboseMessage = fixInvalidChars(mVerboseMessage);
Expand Down Expand Up @@ -312,9 +310,9 @@ void ErrorMessage::deserialize(const std::string &data)
callStack.clear();

std::istringstream iss(data);
std::array<std::string, 7> results;
std::array<std::string, 9> results;
std::size_t elem = 0;
while (iss.good() && elem < 7) {
while (iss.good() && elem < 9) {
unsigned int len = 0;
if (!(iss >> len))
throw InternalError(nullptr, "Internal Error: Deserialization of error message failed - invalid length");
Expand All @@ -332,11 +330,6 @@ void ErrorMessage::deserialize(const std::string &data)

if (!iss.good())
throw InternalError(nullptr, "Internal Error: Deserialization of error message failed - premature end of data");

if (temp == "inconclusive") {
certainty = Certainty::inconclusive;
continue;
}
}

results[elem++] = std::move(temp);
Expand All @@ -345,7 +338,7 @@ void ErrorMessage::deserialize(const std::string &data)
if (!iss.good())
throw InternalError(nullptr, "Internal Error: Deserialization of error message failed - premature end of data");

if (elem != 7)
if (elem != 9)
throw InternalError(nullptr, "Internal Error: Deserialization of error message failed - insufficient elements");

id = std::move(results[0]);
Expand All @@ -362,9 +355,12 @@ void ErrorMessage::deserialize(const std::string &data)
if (!strToInt(results[3], hash, &err))
throw InternalError(nullptr, "Internal Error: Deserialization of error message failed - invalid hash - " + err);
}
file0 = std::move(results[4]);
mShortMessage = std::move(results[5]);
mVerboseMessage = std::move(results[6]);
remark = std::move(results[4]);
file0 = std::move(results[5]);
if (results[6] == "1")
certainty = Certainty::inconclusive;
mShortMessage = std::move(results[7]);
mVerboseMessage = std::move(results[8]);

unsigned int stackSize = 0;
if (!(iss >> stackSize))
Expand Down Expand Up @@ -496,6 +492,9 @@ std::string ErrorMessage::toXML() const
if (!file0.empty())
printer.PushAttribute("file0", file0.c_str());

if (!remark.empty())
printer.PushAttribute("remark", fixInvalidChars(remark).c_str());

for (std::list<FileLocation>::const_reverse_iterator it = callStack.crbegin(); it != callStack.crend(); ++it) {
printer.OpenElement("location", false);
printer.PushAttribute("file", it->getfile().c_str());
Expand Down Expand Up @@ -641,6 +640,7 @@ std::string ErrorMessage::toString(bool verbose, const std::string &templateForm
findAndReplace(result, "{severity}", severityToString(severity));
findAndReplace(result, "{cwe}", std::to_string(cwe.id));
findAndReplace(result, "{message}", verbose ? mVerboseMessage : mShortMessage);
findAndReplace(result, "{remark}", remark);
if (!callStack.empty()) {
if (result.find("{callstack}") != std::string::npos)
findAndReplace(result, "{callstack}", ErrorLogger::callStackToString(callStack));
Expand Down
3 changes: 3 additions & 0 deletions lib/errorlogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@ class CPPCHECKLIB ErrorMessage {
CWE cwe;
Certainty certainty;

/** remark from REMARK comment */
std::string remark;

/** Warning hash */
std::size_t hash;

Expand Down
84 changes: 74 additions & 10 deletions lib/preprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,19 @@ static bool parseInlineSuppressionCommentToken(const simplecpp::Token *tok, std:
return true;
}

static std::string getRelativeFilename(const simplecpp::Token* tok, const Settings &settings) {
std::string relativeFilename(tok->location.file());
if (settings.relativePaths) {
for (const std::string & basePath : settings.basePaths) {
const std::string bp = basePath + "/";
if (relativeFilename.compare(0,bp.size(),bp)==0) {
relativeFilename = relativeFilename.substr(bp.size());
}
}
}
return Path::simplifyPath(relativeFilename);
}

static void addInlineSuppressions(const simplecpp::TokenList &tokens, const Settings &settings, SuppressionList &suppressions, std::list<BadInlineSuppression> &bad)
{
std::list<SuppressionList::Suppression> inlineSuppressionsBlockBegin;
Expand Down Expand Up @@ -193,16 +206,7 @@ static void addInlineSuppressions(const simplecpp::TokenList &tokens, const Sett
continue;

// Relative filename
std::string relativeFilename(tok->location.file());
if (settings.relativePaths) {
for (const std::string & basePath : settings.basePaths) {
const std::string bp = basePath + "/";
if (relativeFilename.compare(0,bp.size(),bp)==0) {
relativeFilename = relativeFilename.substr(bp.size());
}
}
}
relativeFilename = Path::simplifyPath(relativeFilename);
const std::string relativeFilename = getRelativeFilename(tok, settings);

// Macro name
std::string macroName;
Expand Down Expand Up @@ -295,6 +299,17 @@ void Preprocessor::inlineSuppressions(const simplecpp::TokenList &tokens, Suppre
}
}

std::vector<RemarkComment> Preprocessor::getRemarkComments(const simplecpp::TokenList &tokens) const
{
std::vector<RemarkComment> ret;
addRemarkComments(tokens, ret);
for (std::map<std::string,simplecpp::TokenList*>::const_iterator it = mTokenLists.cbegin(); it != mTokenLists.cend(); ++it) {
if (it->second)
addRemarkComments(*it->second, ret);
}
return ret;
}

std::list<Directive> Preprocessor::createDirectives(const simplecpp::TokenList &tokens) const
{
// directive list..
Expand Down Expand Up @@ -998,3 +1013,52 @@ void Preprocessor::simplifyPragmaAsmPrivate(simplecpp::TokenList *tokenList)
tokenList->deleteToken(tok4->next);
}
}


void Preprocessor::addRemarkComments(const simplecpp::TokenList &tokens, std::vector<RemarkComment> &remarkComments) const
{
for (const simplecpp::Token *tok = tokens.cfront(); tok; tok = tok->next) {
if (!tok->comment)
continue;

const std::string& comment = tok->str();

// is it a remark comment?
const std::string::size_type pos1 = comment.find_first_not_of("/* \t");
if (pos1 == std::string::npos)
continue;
const std::string::size_type pos2 = comment.find_first_of(": \t", pos1);
if (pos2 != pos1 + 6 || comment.compare(pos1, 6, "REMARK") != 0)
continue;
const std::string::size_type pos3 = comment.find_first_not_of(": \t", pos2);
if (pos3 == std::string::npos)
continue;
if (comment.compare(0,2,"/*") == 0 && pos3 + 2 >= tok->str().size())
continue;

const std::string::size_type pos4 = (comment.compare(0,2,"/*") == 0) ? comment.size()-2 : comment.size();
const std::string remarkText = comment.substr(pos3, pos4-pos3);

// Get remarked token
const simplecpp::Token* remarkedToken = nullptr;
for (const simplecpp::Token* after = tok->next; after; after = after->next) {
if (after->comment)
continue;
remarkedToken = after;
break;
}
for (const simplecpp::Token* prev = tok->previous; prev; prev = prev->previous) {
if (prev->comment)
continue;
if (sameline(prev, tok))
remarkedToken = prev;
break;
}

// Relative filename
const std::string relativeFilename = getRelativeFilename(remarkedToken, mSettings);

// Add the suppressions.
remarkComments.emplace_back(relativeFilename, remarkedToken->location.line, remarkText);
}
}
22 changes: 22 additions & 0 deletions lib/preprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,24 @@ struct CPPCHECKLIB Directive {
Directive(std::string _file, const int _linenr, const std::string &_str);
};

class CPPCHECKLIB RemarkComment {
public:
RemarkComment(const std::string &file, const unsigned int lineNumber, const std::string &str)
: file(file)
, lineNumber(lineNumber)
, str(str)
{}

/** name of file */
std::string file;

/** line number for the code that the remark comment is about */
unsigned int lineNumber;

/** remark text */
std::string str;
};

/// @addtogroup Core
/// @{

Expand Down Expand Up @@ -96,6 +114,8 @@ class CPPCHECKLIB WARN_UNUSED Preprocessor {

std::set<std::string> getConfigs(const simplecpp::TokenList &tokens) const;

std::vector<RemarkComment> getRemarkComments(const simplecpp::TokenList &tokens) const;

void handleErrors(const simplecpp::OutputList &outputList, bool throwError);

bool loadFiles(const simplecpp::TokenList &rawtokens, std::vector<std::string> &files);
Expand Down Expand Up @@ -138,6 +158,8 @@ class CPPCHECKLIB WARN_UNUSED Preprocessor {

static bool hasErrors(const simplecpp::OutputList &outputList);

void addRemarkComments(const simplecpp::TokenList &tokens, std::vector<RemarkComment> &remarkComments) const;

const Settings& mSettings;
ErrorLogger &mErrorLogger;

Expand Down
12 changes: 12 additions & 0 deletions test/helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,18 @@ void PreprocessorHelper::preprocess(const char code[], std::vector<std::string>
tokenizer.setDirectives(std::move(directives));
}

std::vector<RemarkComment> PreprocessorHelper::getRemarkComments(const char code[], ErrorLogger& errorLogger)
{
std::vector<std::string> files{"test.cpp"};
std::istringstream istr(code);
const simplecpp::TokenList tokens1(istr, files, files[0]);

const Settings settings;

const Preprocessor preprocessor(settings, errorLogger);
return preprocessor.getRemarkComments(tokens1);
}

bool LibraryHelper::loadxmldata(Library &lib, const char xmldata[], std::size_t len)
{
tinyxml2::XMLDocument doc;
Expand Down
4 changes: 4 additions & 0 deletions test/helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#define helpersH

#include "config.h"
#include "preprocessor.h"
#include "settings.h"
#include "standards.h"
#include "tokenize.h"
Expand Down Expand Up @@ -170,6 +171,9 @@ class PreprocessorHelper
static void preprocess(const char code[], std::vector<std::string> &files, Tokenizer& tokenizer, ErrorLogger& errorlogger);
static void preprocess(const char code[], std::vector<std::string> &files, Tokenizer& tokenizer, ErrorLogger& errorlogger, const simplecpp::DUI& dui);

/** get remark comments */
static std::vector<RemarkComment> getRemarkComments(const char code[], ErrorLogger& errorLogger);

private:
static std::map<std::string, std::string> getcode(const Settings& settings, ErrorLogger& errorlogger, const char code[], std::set<std::string> cfgs, const std::string &filename = "file.c", SuppressionList *inlineSuppression = nullptr);
};
Expand Down
Loading

0 comments on commit f36c7c1

Please sign in to comment.