Skip to content

Commit 37a5ec8

Browse files
committed
Summaries: Moved to its own files
1 parent 5701f6d commit 37a5ec8

File tree

12 files changed

+295
-192
lines changed

12 files changed

+295
-192
lines changed

Makefile

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ LIBOBJ = $(libcppdir)/analyzerinfo.o \
203203
$(libcppdir)/programmemory.o \
204204
$(libcppdir)/reverseanalyzer.o \
205205
$(libcppdir)/settings.o \
206+
$(libcppdir)/summaries.o \
206207
$(libcppdir)/suppressions.o \
207208
$(libcppdir)/symboldatabase.o \
208209
$(libcppdir)/templatesimplifier.o \
@@ -270,6 +271,7 @@ TESTOBJ = test/options.o \
270271
test/teststl.o \
271272
test/teststring.o \
272273
test/testsuite.o \
274+
test/testsummaries.o \
273275
test/testsuppressions.o \
274276
test/testsymboldatabase.o \
275277
test/testthreadexecutor.o \
@@ -542,9 +544,12 @@ $(libcppdir)/programmemory.o: lib/programmemory.cpp lib/astutils.h lib/config.h
542544
$(libcppdir)/reverseanalyzer.o: lib/reverseanalyzer.cpp lib/analyzer.h lib/astutils.h lib/config.h lib/errortypes.h lib/forwardanalyzer.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/reverseanalyzer.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/utils.h lib/valueflow.h lib/valueptr.h
543545
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/reverseanalyzer.o $(libcppdir)/reverseanalyzer.cpp
544546

545-
$(libcppdir)/settings.o: lib/settings.cpp 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/timer.h lib/utils.h lib/valueflow.h
547+
$(libcppdir)/settings.o: lib/settings.cpp 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/summaries.h lib/suppressions.h lib/timer.h lib/utils.h lib/valueflow.h
546548
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/settings.o $(libcppdir)/settings.cpp
547549

550+
$(libcppdir)/summaries.o: lib/summaries.cpp 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/summaries.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/utils.h lib/valueflow.h
551+
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/summaries.o $(libcppdir)/summaries.cpp
552+
548553
$(libcppdir)/suppressions.o: lib/suppressions.cpp externals/tinyxml2/tinyxml2.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/mathlib.h lib/path.h lib/suppressions.h lib/utils.h
549554
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/suppressions.o $(libcppdir)/suppressions.cpp
550555

@@ -560,7 +565,7 @@ $(libcppdir)/timer.o: lib/timer.cpp lib/config.h lib/timer.h
560565
$(libcppdir)/token.o: lib/token.cpp lib/astutils.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/tokenlist.h lib/utils.h lib/valueflow.h
561566
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/token.o $(libcppdir)/token.cpp
562567

563-
$(libcppdir)/tokenize.o: lib/tokenize.cpp externals/simplecpp/simplecpp.h lib/check.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.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
568+
$(libcppdir)/tokenize.o: lib/tokenize.cpp externals/simplecpp/simplecpp.h lib/analyzerinfo.h lib/check.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.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
564569
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/tokenize.o $(libcppdir)/tokenize.cpp
565570

566571
$(libcppdir)/tokenlist.o: lib/tokenlist.cpp externals/simplecpp/simplecpp.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenlist.h lib/utils.h lib/valueflow.h
@@ -731,6 +736,9 @@ test/teststring.o: test/teststring.cpp lib/check.h lib/checkstring.h lib/config.
731736
test/testsuite.o: test/testsuite.cpp lib/config.h lib/errorlogger.h lib/errortypes.h lib/suppressions.h test/options.h test/redirect.h test/testsuite.h
732737
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testsuite.o test/testsuite.cpp
733738

739+
test/testsummaries.o: test/testsummaries.cpp 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/summaries.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
740+
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testsummaries.o test/testsummaries.cpp
741+
734742
test/testsuppressions.o: test/testsuppressions.cpp cli/threadexecutor.h lib/analyzerinfo.h lib/check.h lib/config.h lib/cppcheck.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/timer.h lib/utils.h test/testsuite.h
735743
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testsuppressions.o test/testsuppressions.cpp
736744

lib/cppcheck.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
<ClCompile Include="importproject.cpp" />
9292
<ClCompile Include="programmemory.cpp" />
9393
<ClCompile Include="settings.cpp" />
94+
<ClCompile Include="summaries.cpp" />
9495
<ClCompile Include="suppressions.cpp" />
9596
<ClCompile Include="symboldatabase.cpp" />
9697
<ClCompile Include="templatesimplifier.cpp" />
@@ -150,6 +151,7 @@
150151
<ClInclude Include="importproject.h" />
151152
<ClInclude Include="programmemory.h" />
152153
<ClInclude Include="settings.h" />
154+
<ClInclude Include="summaries.h" />
153155
<ClInclude Include="suppressions.h" />
154156
<ClInclude Include="symboldatabase.h" />
155157
<ClInclude Include="templatesimplifier.h" />

lib/lib.pri

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ HEADERS += $${PWD}/analyzerinfo.h \
5050
$${PWD}/programmemory.h \
5151
$${PWD}/reverseanalyzer.h \
5252
$${PWD}/settings.h \
53+
$${PWD}/summaries.h \
5354
$${PWD}/suppressions.h \
5455
$${PWD}/symboldatabase.h \
5556
$${PWD}/templatesimplifier.h \
@@ -107,6 +108,7 @@ SOURCES += $${PWD}/analyzerinfo.cpp \
107108
$${PWD}/programmemory.cpp \
108109
$${PWD}/reverseanalyzer.cpp \
109110
$${PWD}/settings.cpp \
111+
$${PWD}/summaries.cpp \
110112
$${PWD}/suppressions.cpp \
111113
$${PWD}/symboldatabase.cpp \
112114
$${PWD}/templatesimplifier.cpp \

lib/settings.cpp

Lines changed: 2 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,9 @@
1717
*/
1818

1919
#include "settings.h"
20-
20+
#include "summaries.h"
2121
#include "valueflow.h"
2222

23-
#include <algorithm>
24-
#include <fstream>
25-
2623
std::atomic<bool> Settings::mTerminated;
2724

2825
const char Settings::SafeChecks::XmlRootName[] = "safe-checks";
@@ -159,100 +156,7 @@ bool Settings::isEnabled(const ValueFlow::Value *value, bool inconclusiveCheck)
159156
return true;
160157
}
161158

162-
static std::vector<std::string> getSummaryFiles(const std::string &filename)
163-
{
164-
std::vector<std::string> ret;
165-
std::ifstream fin(filename);
166-
if (!fin.is_open())
167-
return ret;
168-
std::string line;
169-
while (std::getline(fin, line)) {
170-
std::string::size_type dotA = line.find(".a");
171-
std::string::size_type colon = line.find(":");
172-
if (colon > line.size() || dotA > colon)
173-
continue;
174-
std::string f = line.substr(0,colon);
175-
f[dotA + 1] = 's';
176-
ret.push_back(f);
177-
}
178-
return ret;
179-
}
180-
181-
static std::vector<std::string> getSummaryData(const std::string &line, const std::string &data)
182-
{
183-
std::vector<std::string> ret;
184-
const std::string::size_type start = line.find(" " + data + ":[");
185-
if (start == std::string::npos)
186-
return ret;
187-
const std::string::size_type end = line.find("]", start);
188-
if (end >= line.size())
189-
return ret;
190-
191-
std::string::size_type pos1 = start + 3 + data.size();
192-
while (pos1 < end) {
193-
std::string::size_type pos2 = line.find_first_of(",]",pos1);
194-
ret.push_back(line.substr(pos1, pos2-pos1-1));
195-
pos1 = pos2 + 1;
196-
}
197-
198-
return ret;
199-
}
200-
201-
static void removeFunctionCalls(const std::string& calledFunction,
202-
std::map<std::string, std::vector<std::string>> &functionCalledBy,
203-
std::map<std::string, std::vector<std::string>> &functionCalls,
204-
std::vector<std::string> &add)
205-
{
206-
std::vector<std::string> calledBy = functionCalledBy[calledFunction];
207-
functionCalledBy.erase(calledFunction);
208-
for (const std::string &c: calledBy) {
209-
std::vector<std::string> &calls = functionCalls[c];
210-
calls.erase(std::remove(calls.begin(), calls.end(), calledFunction), calls.end());
211-
if (calls.empty()) {
212-
add.push_back(calledFunction);
213-
removeFunctionCalls(c, functionCalledBy, functionCalls, add);
214-
}
215-
}
216-
}
217-
218159
void Settings::loadSummaries()
219160
{
220-
if (buildDir.empty())
221-
return;
222-
223-
std::vector<std::string> return1;
224-
std::map<std::string, std::vector<std::string>> functionCalls;
225-
std::map<std::string, std::vector<std::string>> functionCalledBy;
226-
227-
// extract "functionNoreturn" and "functionCalledBy" from summaries
228-
std::vector<std::string> summaryFiles = getSummaryFiles(buildDir + "/files.txt");
229-
for (const std::string &filename: summaryFiles) {
230-
std::ifstream fin(buildDir + '/' + filename);
231-
if (!fin.is_open())
232-
continue;
233-
std::string line;
234-
while (std::getline(fin, line)) {
235-
// Get function name
236-
const std::string::size_type pos1 = 0;
237-
const std::string::size_type pos2 = line.find(" ", pos1);
238-
const std::string functionName = (pos2 == std::string::npos) ? line : line.substr(0, pos2);
239-
std::vector<std::string> call = getSummaryData(line, "call");
240-
functionCalls[functionName] = call;
241-
if (call.empty())
242-
return1.push_back(functionName);
243-
else {
244-
for (const std::string &c: call) {
245-
functionCalledBy[c].push_back(functionName);
246-
}
247-
}
248-
}
249-
}
250-
summaryReturn.insert(return1.cbegin(), return1.cend());
251-
252-
// recursively set "summaryNoreturn"
253-
for (const std::string &f: return1) {
254-
std::vector<std::string> return2;
255-
removeFunctionCalls(f, functionCalledBy, functionCalls, return2);
256-
summaryReturn.insert(return2.cbegin(), return2.cend());
257-
}
161+
Summaries::loadReturn(buildDir, summaryReturn);
258162
}

lib/settings.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,6 @@ class CPPCHECKLIB Settings : public cppcheck::Platform {
419419
std::set<std::string> summaryReturn;
420420

421421
void loadSummaries();
422-
423422
};
424423

425424
/// @}

lib/summaries.cpp

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
2+
#include "summaries.h"
3+
4+
#include "analyzerinfo.h"
5+
#include "settings.h"
6+
#include "symboldatabase.h"
7+
#include "tokenize.h"
8+
9+
#include <algorithm>
10+
#include <fstream>
11+
#include <map>
12+
#include <vector>
13+
14+
15+
16+
std::string Summaries::create(const Tokenizer *tokenizer, const std::string &cfg)
17+
{
18+
const SymbolDatabase *symbolDatabase = tokenizer->getSymbolDatabase();
19+
const Settings *settings = tokenizer->getSettings();
20+
21+
std::ostringstream ostr;
22+
for (const Scope *scope : symbolDatabase->functionScopes) {
23+
const Function *f = scope->function;
24+
if (!f)
25+
continue;
26+
27+
// Summarize function
28+
std::set<std::string> noreturn;
29+
std::set<std::string> globalVars;
30+
std::set<std::string> calledFunctions;
31+
for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) {
32+
if (tok->variable() && tok->variable()->isGlobal())
33+
globalVars.insert(tok->variable()->name());
34+
if (Token::Match(tok, "%name% (") && !Token::simpleMatch(tok->linkAt(1), ") {")) {
35+
calledFunctions.insert(tok->str());
36+
if (Token::simpleMatch(tok->linkAt(1), ") ; }"))
37+
noreturn.insert(tok->str());
38+
}
39+
}
40+
41+
// Write summary for function
42+
auto join = [](const std::set<std::string> &data) -> std::string {
43+
std::string ret;
44+
const char *sep = "";
45+
for (std::string d: data)
46+
{
47+
ret += sep + d;
48+
sep = ",";
49+
}
50+
return ret;
51+
};
52+
53+
ostr << f->name();
54+
if (!globalVars.empty())
55+
ostr << " global:[" << join(globalVars) << "]";
56+
if (!calledFunctions.empty())
57+
ostr << " call:[" << join(calledFunctions) << "]";
58+
if (!noreturn.empty())
59+
ostr << " noreturn:[" << join(noreturn) << "]";
60+
ostr << std::endl;
61+
}
62+
63+
if (!settings->buildDir.empty()) {
64+
std::string filename = AnalyzerInformation::getAnalyzerInfoFile(settings->buildDir, tokenizer->list.getSourceFilePath(), cfg);
65+
std::string::size_type pos = filename.rfind(".a");
66+
if (pos != std::string::npos) {
67+
filename[pos+1] = 's';
68+
std::ofstream fout(filename);
69+
fout << ostr.str();
70+
}
71+
}
72+
73+
return ostr.str();
74+
}
75+
76+
77+
78+
79+
static std::vector<std::string> getSummaryFiles(const std::string &filename)
80+
{
81+
std::vector<std::string> ret;
82+
std::ifstream fin(filename);
83+
if (!fin.is_open())
84+
return ret;
85+
std::string line;
86+
while (std::getline(fin, line)) {
87+
std::string::size_type dotA = line.find(".a");
88+
std::string::size_type colon = line.find(":");
89+
if (colon > line.size() || dotA > colon)
90+
continue;
91+
std::string f = line.substr(0,colon);
92+
f[dotA + 1] = 's';
93+
ret.push_back(f);
94+
}
95+
return ret;
96+
}
97+
98+
static std::vector<std::string> getSummaryData(const std::string &line, const std::string &data)
99+
{
100+
std::vector<std::string> ret;
101+
const std::string::size_type start = line.find(" " + data + ":[");
102+
if (start == std::string::npos)
103+
return ret;
104+
const std::string::size_type end = line.find("]", start);
105+
if (end >= line.size())
106+
return ret;
107+
108+
std::string::size_type pos1 = start + 3 + data.size();
109+
while (pos1 < end) {
110+
std::string::size_type pos2 = line.find_first_of(",]",pos1);
111+
ret.push_back(line.substr(pos1, pos2-pos1-1));
112+
pos1 = pos2 + 1;
113+
}
114+
115+
return ret;
116+
}
117+
118+
static void removeFunctionCalls(const std::string& calledFunction,
119+
std::map<std::string, std::vector<std::string>> &functionCalledBy,
120+
std::map<std::string, std::vector<std::string>> &functionCalls,
121+
std::vector<std::string> &add)
122+
{
123+
std::vector<std::string> calledBy = functionCalledBy[calledFunction];
124+
functionCalledBy.erase(calledFunction);
125+
for (const std::string &c: calledBy) {
126+
std::vector<std::string> &calls = functionCalls[c];
127+
calls.erase(std::remove(calls.begin(), calls.end(), calledFunction), calls.end());
128+
if (calls.empty()) {
129+
add.push_back(calledFunction);
130+
removeFunctionCalls(c, functionCalledBy, functionCalls, add);
131+
}
132+
}
133+
}
134+
135+
void Summaries::loadReturn(const std::string &buildDir, std::set<std::string> &summaryReturn)
136+
{
137+
if (buildDir.empty())
138+
return;
139+
140+
std::vector<std::string> return1;
141+
std::map<std::string, std::vector<std::string>> functionCalls;
142+
std::map<std::string, std::vector<std::string>> functionCalledBy;
143+
144+
// extract "functionNoreturn" and "functionCalledBy" from summaries
145+
std::vector<std::string> summaryFiles = getSummaryFiles(buildDir + "/files.txt");
146+
for (const std::string &filename: summaryFiles) {
147+
std::ifstream fin(buildDir + '/' + filename);
148+
if (!fin.is_open())
149+
continue;
150+
std::string line;
151+
while (std::getline(fin, line)) {
152+
// Get function name
153+
const std::string::size_type pos1 = 0;
154+
const std::string::size_type pos2 = line.find(" ", pos1);
155+
const std::string functionName = (pos2 == std::string::npos) ? line : line.substr(0, pos2);
156+
std::vector<std::string> call = getSummaryData(line, "call");
157+
functionCalls[functionName] = call;
158+
if (call.empty())
159+
return1.push_back(functionName);
160+
else {
161+
for (const std::string &c: call) {
162+
functionCalledBy[c].push_back(functionName);
163+
}
164+
}
165+
}
166+
}
167+
summaryReturn.insert(return1.cbegin(), return1.cend());
168+
169+
// recursively set "summaryNoreturn"
170+
for (const std::string &f: return1) {
171+
std::vector<std::string> return2;
172+
removeFunctionCalls(f, functionCalledBy, functionCalls, return2);
173+
summaryReturn.insert(return2.cbegin(), return2.cend());
174+
}
175+
}

0 commit comments

Comments
 (0)