|
19 | 19 | //--------------------------------------------------------------------------- |
20 | 20 | #include "tokenize.h" |
21 | 21 |
|
| 22 | +#include "analyzerinfo.h" |
22 | 23 | #include "check.h" |
23 | 24 | #include "errorlogger.h" |
24 | 25 | #include "library.h" |
@@ -2377,6 +2378,9 @@ bool Tokenizer::simplifyTokens1(const std::string &configuration) |
2377 | 2378 | mSymbolDatabase->setValueTypeInTokenList(true); |
2378 | 2379 | } |
2379 | 2380 |
|
| 2381 | + if (!mSettings->buildDir.empty()) |
| 2382 | + createSummaries(configuration); |
| 2383 | + |
2380 | 2384 | if (mTimerResults) { |
2381 | 2385 | Timer t("Tokenizer::simplifyTokens1::ValueFlow", mSettings->showtime, mTimerResults); |
2382 | 2386 | ValueFlow::setValues(&list, mSymbolDatabase, mErrorLogger, mSettings); |
@@ -8720,6 +8724,11 @@ bool Tokenizer::isScopeNoReturn(const Token *endScopeToken, bool *unknown) const |
8720 | 8724 | { |
8721 | 8725 | std::string unknownFunc; |
8722 | 8726 | const bool ret = mSettings->library.isScopeNoReturn(endScopeToken,&unknownFunc); |
| 8727 | + if (!unknownFunc.empty()) { |
| 8728 | + const std::map<std::string, bool>::const_iterator it = mSettings->summaryNoreturn.find(unknownFunc); |
| 8729 | + if (it != mSettings->summaryNoreturn.end() && !it->second) |
| 8730 | + return false; |
| 8731 | + } |
8723 | 8732 | if (unknown) |
8724 | 8733 | *unknown = !unknownFunc.empty(); |
8725 | 8734 | if (!unknownFunc.empty() && mSettings->checkLibrary && mSettings->isEnabled(Settings::INFORMATION)) { |
@@ -12064,3 +12073,60 @@ bool Tokenizer::hasIfdef(const Token *start, const Token *end) const |
12064 | 12073 | return false; |
12065 | 12074 | } |
12066 | 12075 |
|
| 12076 | +std::string Tokenizer::createSummaries(const std::string &configuration) const |
| 12077 | +{ |
| 12078 | + std::ostringstream ostr; |
| 12079 | + for (const Scope *scope : mSymbolDatabase->functionScopes) { |
| 12080 | + const Function *f = scope->function; |
| 12081 | + if (!f) |
| 12082 | + continue; |
| 12083 | + |
| 12084 | + // Summarize function |
| 12085 | + std::set<std::string> noreturn; |
| 12086 | + std::set<std::string> globalVars; |
| 12087 | + std::set<std::string> calledFunctions; |
| 12088 | + for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { |
| 12089 | + if (tok->variable() && tok->variable()->isGlobal()) |
| 12090 | + globalVars.insert(tok->variable()->name()); |
| 12091 | + if (Token::Match(tok, "%name% (") && !Token::simpleMatch(tok->linkAt(1), ") {")) { |
| 12092 | + calledFunctions.insert(tok->str()); |
| 12093 | + if (Token::simpleMatch(tok->linkAt(1), ") ; }")) |
| 12094 | + noreturn.insert(tok->str()); |
| 12095 | + } |
| 12096 | + } |
| 12097 | + |
| 12098 | + // Write summary for function |
| 12099 | + auto join = [](const std::set<std::string> &data) -> std::string { |
| 12100 | + std::string ret; |
| 12101 | + const char *sep = ""; |
| 12102 | + for (std::string d: data) |
| 12103 | + { |
| 12104 | + ret += sep + d; |
| 12105 | + sep = ","; |
| 12106 | + } |
| 12107 | + return ret; |
| 12108 | + }; |
| 12109 | + |
| 12110 | + ostr << f->name(); |
| 12111 | + if (!globalVars.empty()) |
| 12112 | + ostr << " global:[" << join(globalVars) << "]"; |
| 12113 | + if (!calledFunctions.empty()) |
| 12114 | + ostr << " call:[" << join(calledFunctions) << "]"; |
| 12115 | + if (!noreturn.empty()) |
| 12116 | + ostr << " noreturn:[" << join(noreturn) << "]"; |
| 12117 | + ostr << std::endl; |
| 12118 | + } |
| 12119 | + |
| 12120 | + if (!mSettings->buildDir.empty()) { |
| 12121 | + std::string filename = AnalyzerInformation::getAnalyzerInfoFile(mSettings->buildDir, list.getSourceFilePath(), configuration); |
| 12122 | + std::string::size_type pos = filename.rfind(".a"); |
| 12123 | + if (pos != std::string::npos) { |
| 12124 | + filename[pos+1] = 's'; |
| 12125 | + std::ofstream fout(filename); |
| 12126 | + fout << ostr.str(); |
| 12127 | + } |
| 12128 | + } |
| 12129 | + |
| 12130 | + return ostr.str(); |
| 12131 | +} |
| 12132 | + |
0 commit comments