Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tokenizer: removed Preprocessor dependency #6265

Merged
merged 3 commits into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions lib/cppcheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -506,8 +506,7 @@ unsigned int CppCheck::checkClang(const std::string &path)
}

try {
Preprocessor preprocessor(mSettings, this);
Tokenizer tokenizer(mSettings, this, &preprocessor);
Tokenizer tokenizer(mSettings, this);
tokenizer.list.appendFileIfNew(path);
std::istringstream ast(output2);
clangimport::parseClangAstDump(tokenizer, ast);
Expand Down Expand Up @@ -796,7 +795,7 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
}

// Get directives
preprocessor.setDirectives(tokens1);
std::list<Directive> directives = preprocessor.createDirectives(tokens1);
preprocessor.simplifyPragmaAsm(&tokens1);

preprocessor.setPlatformInfo(&tokens1);
Expand All @@ -821,7 +820,7 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
// Run define rules on raw code
if (hasRule("define")) {
std::string code;
for (const Directive &dir : preprocessor.getDirectives()) {
for (const Directive &dir : directives) {
if (startsWith(dir.str,"#define ") || startsWith(dir.str,"#include "))
code += "#line " + std::to_string(dir.linenr) + " \"" + dir.file + "\"\n" + dir.str + '\n';
}
Expand Down Expand Up @@ -887,9 +886,10 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
continue;
}

Tokenizer tokenizer(mSettings, this, &preprocessor);
Tokenizer tokenizer(mSettings, this);
if (mSettings.showtime != SHOWTIME_MODES::SHOWTIME_NONE)
tokenizer.setTimerResults(&s_timerResults);
tokenizer.setDirectives(directives); // TODO: how to avoid repeated copies?

try {
// Create tokens, skip rest of iteration if failed
Expand Down
19 changes: 5 additions & 14 deletions lib/preprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,10 +308,10 @@ void Preprocessor::inlineSuppressions(const simplecpp::TokenList &tokens, Suppre
}
}

void Preprocessor::setDirectives(const simplecpp::TokenList &tokens)
std::list<Directive> Preprocessor::createDirectives(const simplecpp::TokenList &tokens) const
{
// directive list..
mDirectives.clear();
std::list<Directive> directives;

std::vector<const simplecpp::TokenList *> list;
list.reserve(1U + mTokenLists.size());
Expand All @@ -337,9 +337,11 @@ void Preprocessor::setDirectives(const simplecpp::TokenList &tokens)
else
directive.str += tok2->str();
}
mDirectives.push_back(std::move(directive));
directives.push_back(std::move(directive));
}
}

return directives;
}

static std::string readcondition(const simplecpp::Token *iftok, const std::set<std::string> &defined, const std::set<std::string> &undefined)
Expand Down Expand Up @@ -912,17 +914,6 @@ void Preprocessor::dump(std::ostream &out) const
{
// Create a xml dump.

out << " <directivelist>" << std::endl;
for (const Directive &dir : mDirectives) {
out << " <directive "
<< "file=\"" << ErrorLogger::toxml(dir.file) << "\" "
<< "linenr=\"" << dir.linenr << "\" "
// str might contain characters such as '"', '<' or '>' which
// could result in invalid XML, so run it through toxml().
<< "str=\"" << ErrorLogger::toxml(dir.str) << "\"/>" << std::endl;
}
out << " </directivelist>" << std::endl;

if (!mMacroUsage.empty()) {
out << " <macro-usage>" << std::endl;
for (const simplecpp::MacroUsage &macroUsage: mMacroUsage) {
Expand Down
14 changes: 2 additions & 12 deletions lib/preprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ struct CPPCHECKLIB Directive {
* The preprocessor has special functionality for extracting the various ifdef
* configurations that exist in a source file.
*/
class CPPCHECKLIB Preprocessor {
class CPPCHECKLIB WARN_UNUSED Preprocessor {
// TODO: get rid of this
friend class PreprocessorHelper;
friend class TestPreprocessor;
Expand All @@ -92,12 +92,7 @@ class CPPCHECKLIB Preprocessor {

void inlineSuppressions(const simplecpp::TokenList &tokens, SuppressionList &suppressions);

void setDirectives(const simplecpp::TokenList &tokens);

/** list of all directives met while preprocessing file */
const std::list<Directive> &getDirectives() const {
return mDirectives;
}
std::list<Directive> createDirectives(const simplecpp::TokenList &tokens) const;

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

Expand Down Expand Up @@ -143,15 +138,10 @@ class CPPCHECKLIB Preprocessor {

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

void setDirectives(const std::list<Directive> &directives) {
mDirectives = directives;
}

const Settings& mSettings;
ErrorLogger *mErrorLogger;

/** list of all directives met while preprocessing file */
std::list<Directive> mDirectives;

std::map<std::string, simplecpp::TokenList *> mTokenLists;

Expand Down
40 changes: 30 additions & 10 deletions lib/tokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,11 @@ static bool isClassStructUnionEnumStart(const Token * tok)

//---------------------------------------------------------------------------

Tokenizer::Tokenizer(const Settings &settings, ErrorLogger *errorLogger, const Preprocessor *preprocessor) :
Tokenizer::Tokenizer(const Settings &settings, ErrorLogger *errorLogger) :
list(&settings),
mSettings(settings),
mErrorLogger(errorLogger),
mTemplateSimplifier(new TemplateSimplifier(*this)),
mPreprocessor(preprocessor)
mTemplateSimplifier(new TemplateSimplifier(*this))
{}

Tokenizer::~Tokenizer()
Expand Down Expand Up @@ -5913,6 +5912,26 @@ void Tokenizer::dump(std::ostream &out) const

std::set<const Library::Container*> containers;

outs += " <directivelist>";
outs += '\n';
for (const Directive &dir : mDirectives) {
outs += " <directive ";
outs += "file=\"";
outs += ErrorLogger::toxml(dir.file);
outs += "\" ";
outs += "linenr=\"";
outs += std::to_string(dir.linenr);
outs += "\" ";
// str might contain characters such as '"', '<' or '>' which
// could result in invalid XML, so run it through toxml().
outs += "str=\"";
outs += ErrorLogger::toxml(dir.str);
outs +="\"/>";
outs += '\n';
}
outs += " </directivelist>";
outs += '\n';

// tokens..
outs += " <tokenlist>";
outs += '\n';
Expand Down Expand Up @@ -10649,12 +10668,15 @@ void Tokenizer::simplifyNamespaceAliases()
}
}

// TODO: how to move the Preprocessor dependency out of here?
bool Tokenizer::hasIfdef(const Token *start, const Token *end) const
void Tokenizer::setDirectives(std::list<Directive> directives)
{
assert(mPreprocessor);
mDirectives = std::move(directives);
}

return std::any_of(mPreprocessor->getDirectives().cbegin(), mPreprocessor->getDirectives().cend(), [&](const Directive& d) {
bool Tokenizer::hasIfdef(const Token *start, const Token *end) const
{
const auto& directives = mDirectives;
return std::any_of(directives.cbegin(), directives.cend(), [&](const Directive& d) {
return startsWith(d.str, "#if") &&
d.linenr >= start->linenr() &&
d.linenr <= end->linenr() &&
Expand All @@ -10665,9 +10687,7 @@ bool Tokenizer::hasIfdef(const Token *start, const Token *end) const

bool Tokenizer::isPacked(const Token * bodyStart) const
{
assert(mPreprocessor);

const auto& directives = mPreprocessor->getDirectives();
const auto& directives = mDirectives;
// TODO: should this return true if the #pragma exists in any line before the start token?
return std::any_of(directives.cbegin(), directives.cend(), [&](const Directive& d) {
return d.linenr < bodyStart->linenr() && d.str == "#pragma pack(1)" && d.file == list.getFiles().front();
Expand Down
10 changes: 6 additions & 4 deletions lib/tokenize.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class TimerResults;
class Token;
class TemplateSimplifier;
class ErrorLogger;
class Preprocessor;
struct Directive;
enum class Severity;

/// @addtogroup Core
Expand All @@ -53,7 +53,7 @@ class CPPCHECKLIB Tokenizer {
friend class TestTokenizer;

public:
explicit Tokenizer(const Settings & settings, ErrorLogger *errorLogger, const Preprocessor *preprocessor = nullptr);
explicit Tokenizer(const Settings & settings, ErrorLogger *errorLogger);
~Tokenizer();

void setTimerResults(TimerResults *tr) {
Expand Down Expand Up @@ -624,6 +624,8 @@ class CPPCHECKLIB Tokenizer {
/** Disable assignment operator */
Tokenizer &operator=(const Tokenizer &) = delete;

void setDirectives(std::list<Directive> directives);

private:
const Token *processFunc(const Token *tok2, bool inOperator) const;
Token *processFunc(Token *tok2, bool inOperator);
Expand Down Expand Up @@ -666,6 +668,8 @@ class CPPCHECKLIB Tokenizer {
};
std::vector<TypedefInfo> mTypedefInfo;

std::list<Directive> mDirectives;

/** variable count */
nonneg int mVarId{};

Expand All @@ -676,8 +680,6 @@ class CPPCHECKLIB Tokenizer {
* TimerResults
*/
TimerResults* mTimerResults{};

const Preprocessor * const mPreprocessor;
};

/// @}
Expand Down
25 changes: 5 additions & 20 deletions test/helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
class SuppressionList;

const Settings SimpleTokenizer::s_settings;
const Preprocessor SimpleTokenizer::s_preprocessor{s_settings, nullptr}; // TODO: provide ErrorLogger

// TODO: better path-only usage
ScopedFile::ScopedFile(std::string name, const std::string &content, std::string path)
Expand Down Expand Up @@ -124,7 +123,6 @@ std::string PreprocessorHelper::getcode(Preprocessor &preprocessor, const std::s
tokens1.removeComments();
preprocessor.simplifyPragmaAsm(&tokens1);
preprocessor.removeComments();
preprocessor.setDirectives(tokens1);

preprocessor.reportOutput(outputList, true);

Expand All @@ -148,25 +146,10 @@ std::string PreprocessorHelper::getcode(Preprocessor &preprocessor, const std::s

void PreprocessorHelper::preprocess(const char code[], std::vector<std::string> &files, Tokenizer& tokenizer)
{
// Raw Tokens..
std::istringstream istr(code);
const simplecpp::TokenList tokens1(istr, files, files[0]);

// Preprocess..
simplecpp::TokenList tokens2(files);
std::map<std::string, simplecpp::TokenList*> filedata;
simplecpp::preprocess(tokens2, tokens1, files, filedata, simplecpp::DUI());

// Tokenizer..
tokenizer.list.createTokens(std::move(tokens2));
}

void PreprocessorHelper::preprocess(Preprocessor &preprocessor, const char code[], std::vector<std::string> &files, Tokenizer& tokenizer)
{
preprocess(preprocessor, code, files, tokenizer, simplecpp::DUI());
preprocess(code, files, tokenizer, simplecpp::DUI());
}

void PreprocessorHelper::preprocess(Preprocessor &preprocessor, const char code[], std::vector<std::string> &files, Tokenizer& tokenizer, const simplecpp::DUI& dui)
void PreprocessorHelper::preprocess(const char code[], std::vector<std::string> &files, Tokenizer& tokenizer, const simplecpp::DUI& dui)
{
std::istringstream istr(code);
const simplecpp::TokenList tokens1(istr, files, files[0]);
Expand All @@ -179,5 +162,7 @@ void PreprocessorHelper::preprocess(Preprocessor &preprocessor, const char code[
// Tokenizer..
tokenizer.list.createTokens(std::move(tokens2));

preprocessor.setDirectives(tokens1);
const Preprocessor preprocessor(tokenizer.getSettings());
std::list<Directive> directives = preprocessor.createDirectives(tokens1);
tokenizer.setDirectives(std::move(directives));
danmar marked this conversation as resolved.
Show resolved Hide resolved
}
12 changes: 3 additions & 9 deletions test/helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,14 @@ namespace simplecpp {
class SimpleTokenizer : public Tokenizer {
public:
SimpleTokenizer(ErrorLogger& errorlogger, const char code[], bool cpp = true)
: Tokenizer{s_settings, &errorlogger, &s_preprocessor}
: Tokenizer{s_settings, &errorlogger}
{
if (!tokenize(code, cpp))
throw std::runtime_error("creating tokens failed");
}

SimpleTokenizer(const Settings& settings, ErrorLogger& errorlogger)
: Tokenizer{settings, &errorlogger, &s_preprocessor}
{}

SimpleTokenizer(const Settings& settings, ErrorLogger& errorlogger, const Preprocessor* preprocessor)
: Tokenizer{settings, &errorlogger, preprocessor}
: Tokenizer{settings, &errorlogger}
{}

/*
Expand Down Expand Up @@ -87,7 +83,6 @@ class SimpleTokenizer : public Tokenizer {
private:
// TODO. find a better solution
static const Settings s_settings;
static const Preprocessor s_preprocessor;
};

class SimpleTokenList
Expand Down Expand Up @@ -156,8 +151,7 @@ class PreprocessorHelper
static std::string getcode(Preprocessor &preprocessor, const std::string &filedata, const std::string &cfg, const std::string &filename, SuppressionList *inlineSuppression = nullptr);

static void preprocess(const char code[], std::vector<std::string> &files, Tokenizer& tokenizer);
static void preprocess(Preprocessor &preprocessor, const char code[], std::vector<std::string> &files, Tokenizer& tokenizer);
static void preprocess(Preprocessor &preprocessor, const char code[], std::vector<std::string> &files, Tokenizer& tokenizer, const simplecpp::DUI& dui);
static void preprocess(const char code[], std::vector<std::string> &files, Tokenizer& tokenizer, const simplecpp::DUI& dui);
};

namespace cppcheck {
Expand Down
Loading
Loading