Skip to content

Commit 44cb133

Browse files
committed
moved directives from Preprocessor to Tokenizer
1 parent 789be1c commit 44cb133

9 files changed

Lines changed: 148 additions & 121 deletions

File tree

lib/cppcheck.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,7 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
796796
}
797797

798798
// Get directives
799-
preprocessor.setDirectives(tokens1);
799+
std::list<Directive> directives = preprocessor.createDirectives(tokens1);
800800
preprocessor.simplifyPragmaAsm(&tokens1);
801801

802802
preprocessor.setPlatformInfo(&tokens1);
@@ -821,7 +821,7 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
821821
// Run define rules on raw code
822822
if (hasRule("define")) {
823823
std::string code;
824-
for (const Directive &dir : preprocessor.getDirectives()) {
824+
for (const Directive &dir : directives) {
825825
if (startsWith(dir.str,"#define ") || startsWith(dir.str,"#include "))
826826
code += "#line " + std::to_string(dir.linenr) + " \"" + dir.file + "\"\n" + dir.str + '\n';
827827
}
@@ -890,6 +890,7 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
890890
Tokenizer tokenizer(mSettings, this, &preprocessor);
891891
if (mSettings.showtime != SHOWTIME_MODES::SHOWTIME_NONE)
892892
tokenizer.setTimerResults(&s_timerResults);
893+
tokenizer.setDirectives(directives); // TODO: how to avoid repeated copies?
893894

894895
try {
895896
// Create tokens, skip rest of iteration if failed

lib/preprocessor.cpp

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -308,10 +308,10 @@ void Preprocessor::inlineSuppressions(const simplecpp::TokenList &tokens, Suppre
308308
}
309309
}
310310

311-
void Preprocessor::setDirectives(const simplecpp::TokenList &tokens)
311+
std::list<Directive> Preprocessor::createDirectives(const simplecpp::TokenList &tokens) const
312312
{
313313
// directive list..
314-
mDirectives.clear();
314+
std::list<Directive> directives;
315315

316316
std::vector<const simplecpp::TokenList *> list;
317317
list.reserve(1U + mTokenLists.size());
@@ -337,9 +337,11 @@ void Preprocessor::setDirectives(const simplecpp::TokenList &tokens)
337337
else
338338
directive.str += tok2->str();
339339
}
340-
mDirectives.push_back(std::move(directive));
340+
directives.push_back(std::move(directive));
341341
}
342342
}
343+
344+
return directives;
343345
}
344346

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

915-
out << " <directivelist>" << std::endl;
916-
for (const Directive &dir : mDirectives) {
917-
out << " <directive "
918-
<< "file=\"" << ErrorLogger::toxml(dir.file) << "\" "
919-
<< "linenr=\"" << dir.linenr << "\" "
920-
// str might contain characters such as '"', '<' or '>' which
921-
// could result in invalid XML, so run it through toxml().
922-
<< "str=\"" << ErrorLogger::toxml(dir.str) << "\"/>" << std::endl;
923-
}
924-
out << " </directivelist>" << std::endl;
925-
926917
if (!mMacroUsage.empty()) {
927918
out << " <macro-usage>" << std::endl;
928919
for (const simplecpp::MacroUsage &macroUsage: mMacroUsage) {

lib/preprocessor.h

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,7 @@ class CPPCHECKLIB Preprocessor {
9292

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

95-
void setDirectives(const simplecpp::TokenList &tokens);
96-
97-
/** list of all directives met while preprocessing file */
98-
const std::list<Directive> &getDirectives() const {
99-
return mDirectives;
100-
}
95+
std::list<Directive> createDirectives(const simplecpp::TokenList &tokens) const;
10196

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

@@ -143,15 +138,10 @@ class CPPCHECKLIB Preprocessor {
143138

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

146-
void setDirectives(const std::list<Directive> &directives) {
147-
mDirectives = directives;
148-
}
149-
150141
const Settings& mSettings;
151142
ErrorLogger *mErrorLogger;
152143

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

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

lib/tokenize.cpp

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5913,6 +5913,26 @@ void Tokenizer::dump(std::ostream &out) const
59135913

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

5916+
outs += " <directivelist>";
5917+
outs += '\n';
5918+
for (const Directive &dir : mDirectives) {
5919+
outs += " <directive ";
5920+
outs += "file=\"";
5921+
outs += ErrorLogger::toxml(dir.file);
5922+
outs += "\" ";
5923+
outs += "linenr=\"";
5924+
outs += std::to_string(dir.linenr);
5925+
outs += "\" ";
5926+
// str might contain characters such as '"', '<' or '>' which
5927+
// could result in invalid XML, so run it through toxml().
5928+
outs += "str=\"";
5929+
outs += ErrorLogger::toxml(dir.str);
5930+
outs +="\"/>";
5931+
outs += '\n';
5932+
}
5933+
outs += " </directivelist>";
5934+
outs += '\n';
5935+
59165936
// tokens..
59175937
outs += " <tokenlist>";
59185938
outs += '\n';
@@ -10649,12 +10669,17 @@ void Tokenizer::simplifyNamespaceAliases()
1064910669
}
1065010670
}
1065110671

10652-
// TODO: how to move the Preprocessor dependency out of here?
10672+
void Tokenizer::setDirectives(std::list<Directive> directives)
10673+
{
10674+
mDirectives = std::move(directives);
10675+
}
10676+
1065310677
bool Tokenizer::hasIfdef(const Token *start, const Token *end) const
1065410678
{
1065510679
assert(mPreprocessor);
1065610680

10657-
return std::any_of(mPreprocessor->getDirectives().cbegin(), mPreprocessor->getDirectives().cend(), [&](const Directive& d) {
10681+
const auto& directives = mDirectives;
10682+
return std::any_of(directives.cbegin(), directives.cend(), [&](const Directive& d) {
1065810683
return startsWith(d.str, "#if") &&
1065910684
d.linenr >= start->linenr() &&
1066010685
d.linenr <= end->linenr() &&
@@ -10667,7 +10692,7 @@ bool Tokenizer::isPacked(const Token * bodyStart) const
1066710692
{
1066810693
assert(mPreprocessor);
1066910694

10670-
const auto& directives = mPreprocessor->getDirectives();
10695+
const auto& directives = mDirectives;
1067110696
// TODO: should this return true if the #pragma exists in any line before the start token?
1067210697
return std::any_of(directives.cbegin(), directives.cend(), [&](const Directive& d) {
1067310698
return d.linenr < bodyStart->linenr() && d.str == "#pragma pack(1)" && d.file == list.getFiles().front();

lib/tokenize.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class Token;
3737
class TemplateSimplifier;
3838
class ErrorLogger;
3939
class Preprocessor;
40+
struct Directive;
4041
enum class Severity;
4142

4243
/// @addtogroup Core
@@ -624,6 +625,8 @@ class CPPCHECKLIB Tokenizer {
624625
/** Disable assignment operator */
625626
Tokenizer &operator=(const Tokenizer &) = delete;
626627

628+
void setDirectives(std::list<Directive> directives);
629+
627630
private:
628631
const Token *processFunc(const Token *tok2, bool inOperator) const;
629632
Token *processFunc(Token *tok2, bool inOperator);
@@ -666,6 +669,8 @@ class CPPCHECKLIB Tokenizer {
666669
};
667670
std::vector<TypedefInfo> mTypedefInfo;
668671

672+
std::list<Directive> mDirectives;
673+
669674
/** variable count */
670675
nonneg int mVarId{};
671676

test/helpers.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@ std::string PreprocessorHelper::getcode(Preprocessor &preprocessor, const std::s
124124
tokens1.removeComments();
125125
preprocessor.simplifyPragmaAsm(&tokens1);
126126
preprocessor.removeComments();
127-
preprocessor.setDirectives(tokens1);
128127

129128
preprocessor.reportOutput(outputList, true);
130129

@@ -179,5 +178,6 @@ void PreprocessorHelper::preprocess(Preprocessor &preprocessor, const char code[
179178
// Tokenizer..
180179
tokenizer.list.createTokens(std::move(tokens2));
181180

182-
preprocessor.setDirectives(tokens1);
181+
std::list<Directive> directives = preprocessor.createDirectives(tokens1);
182+
tokenizer.setDirectives(std::move(directives));
183183
}

test/testpreprocessor.cpp

Lines changed: 1 addition & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -245,10 +245,6 @@ class TestPreprocessor : public TestFixture {
245245

246246
TEST_CASE(wrongPathOnErrorDirective);
247247

248-
TEST_CASE(testDirectiveIncludeTypes);
249-
TEST_CASE(testDirectiveIncludeLocations);
250-
TEST_CASE(testDirectiveIncludeComments);
251-
252248
TEST_CASE(testMissingInclude);
253249
TEST_CASE(testMissingInclude2);
254250
TEST_CASE(testMissingInclude3);
@@ -275,7 +271,7 @@ class TestPreprocessor : public TestFixture {
275271
tokens.removeComments();
276272
preprocessor0.simplifyPragmaAsm(&tokens);
277273
preprocessor0.removeComments();
278-
preprocessor0.setDirectives(tokens);
274+
std::list<Directive> directives = preprocessor0.createDirectives(tokens); // TODO
279275

280276
preprocessor0.reportOutput(outputList, true);
281277

@@ -2313,88 +2309,6 @@ class TestPreprocessor : public TestFixture {
23132309
ASSERT_EQUALS("[test.c:1]: (error) #error hello world!\n", errout_str());
23142310
}
23152311

2316-
void testDirectiveIncludeTypes() {
2317-
const char filedata[] = "#define macro some definition\n"
2318-
"#undef macro\n"
2319-
"#ifdef macro\n"
2320-
"#elif some (complex) condition\n"
2321-
"#else\n"
2322-
"#endif\n"
2323-
"#if some other condition\n"
2324-
"#pragma some proprietary content\n"
2325-
"#\n" /* may appear in old C code */
2326-
"#ident some text\n" /* may appear in old C code */
2327-
"#unknownmacro some unpredictable text\n"
2328-
"#warning some warning message\n"
2329-
"#error some error message\n";
2330-
const char dumpdata[] = " <directivelist>\n"
2331-
2332-
" <directive file=\"test.c\" linenr=\"1\" str=\"#define macro some definition\"/>\n"
2333-
" <directive file=\"test.c\" linenr=\"2\" str=\"#undef macro\"/>\n"
2334-
" <directive file=\"test.c\" linenr=\"3\" str=\"#ifdef macro\"/>\n"
2335-
" <directive file=\"test.c\" linenr=\"4\" str=\"#elif some (complex) condition\"/>\n"
2336-
" <directive file=\"test.c\" linenr=\"5\" str=\"#else\"/>\n"
2337-
" <directive file=\"test.c\" linenr=\"6\" str=\"#endif\"/>\n"
2338-
" <directive file=\"test.c\" linenr=\"7\" str=\"#if some other condition\"/>\n"
2339-
" <directive file=\"test.c\" linenr=\"8\" str=\"#pragma some proprietary content\"/>\n"
2340-
" <directive file=\"test.c\" linenr=\"9\" str=\"#\"/>\n"
2341-
" <directive file=\"test.c\" linenr=\"10\" str=\"#ident some text\"/>\n"
2342-
" <directive file=\"test.c\" linenr=\"11\" str=\"#unknownmacro some unpredictable text\"/>\n"
2343-
" <directive file=\"test.c\" linenr=\"12\" str=\"#warning some warning message\"/>\n"
2344-
" <directive file=\"test.c\" linenr=\"13\" str=\"#error some error message\"/>\n"
2345-
" </directivelist>\n";
2346-
2347-
std::ostringstream ostr;
2348-
Preprocessor preprocessor(settings0, this);
2349-
PreprocessorHelper::getcode(preprocessor, filedata, "", "test.c");
2350-
preprocessor.dump(ostr);
2351-
ASSERT_EQUALS(dumpdata, ostr.str());
2352-
}
2353-
2354-
void testDirectiveIncludeLocations() {
2355-
const char filedata[] = "#define macro1 val\n"
2356-
"#file \"inc1.h\"\n"
2357-
"#define macro2 val\n"
2358-
"#file \"inc2.h\"\n"
2359-
"#define macro3 val\n"
2360-
"#endfile\n"
2361-
"#define macro4 val\n"
2362-
"#endfile\n"
2363-
"#define macro5 val\n";
2364-
const char dumpdata[] = " <directivelist>\n"
2365-
" <directive file=\"test.c\" linenr=\"1\" str=\"#define macro1 val\"/>\n"
2366-
" <directive file=\"test.c\" linenr=\"2\" str=\"#include &quot;inc1.h&quot;\"/>\n"
2367-
" <directive file=\"inc1.h\" linenr=\"1\" str=\"#define macro2 val\"/>\n"
2368-
" <directive file=\"inc1.h\" linenr=\"2\" str=\"#include &quot;inc2.h&quot;\"/>\n"
2369-
" <directive file=\"inc2.h\" linenr=\"1\" str=\"#define macro3 val\"/>\n"
2370-
" <directive file=\"inc1.h\" linenr=\"3\" str=\"#define macro4 val\"/>\n"
2371-
" <directive file=\"test.c\" linenr=\"3\" str=\"#define macro5 val\"/>\n"
2372-
" </directivelist>\n";
2373-
2374-
std::ostringstream ostr;
2375-
Preprocessor preprocessor(settings0, this);
2376-
PreprocessorHelper::getcode(preprocessor, filedata, "", "test.c");
2377-
preprocessor.dump(ostr);
2378-
ASSERT_EQUALS(dumpdata, ostr.str());
2379-
}
2380-
2381-
void testDirectiveIncludeComments() {
2382-
const char filedata[] = "#ifdef macro2 /* this will be removed */\n"
2383-
"#else /* this will be removed too */\n"
2384-
"#endif /* this will also be removed */\n";
2385-
const char dumpdata[] = " <directivelist>\n"
2386-
" <directive file=\"test.c\" linenr=\"1\" str=\"#ifdef macro2\"/>\n"
2387-
" <directive file=\"test.c\" linenr=\"2\" str=\"#else\"/>\n"
2388-
" <directive file=\"test.c\" linenr=\"3\" str=\"#endif\"/>\n"
2389-
" </directivelist>\n";
2390-
2391-
std::ostringstream ostr;
2392-
Preprocessor preprocessor(settings0, this);
2393-
PreprocessorHelper::getcode(preprocessor, filedata, "", "test.c");
2394-
preprocessor.dump(ostr);
2395-
ASSERT_EQUALS(dumpdata, ostr.str());
2396-
}
2397-
23982312
// test for existing local include
23992313
void testMissingInclude() {
24002314
/*const*/ Settings settings;

0 commit comments

Comments
 (0)