Skip to content

Commit 60f59b9

Browse files
Merge branch 'danmar:main' into chr_11522
2 parents 7dfe32e + 2d0326d commit 60f59b9

File tree

12 files changed

+254
-98
lines changed

12 files changed

+254
-98
lines changed

cli/singleexecutor.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ unsigned int SingleExecutor::check()
6767
reportStatus(c, mFileSettings.size(), c, mFileSettings.size());
6868
}
6969

70+
// TODO: CppCheckExecutor::check_internal() is also invoking the whole program analysis - is it run twice?
7071
if (mCppcheck.analyseWholeProgram())
7172
result++;
7273

lib/checkersreport.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,13 @@ void CheckersReport::countCheckers()
143143
++mAllCheckersCount;
144144
}
145145
if (mSettings.premiumArgs.find("misra-c-") != std::string::npos || mSettings.addons.count("misra")) {
146+
const bool doUnusedFunctionOnly = Settings::unusedFunctionOnly();
146147
for (const checkers::MisraInfo& info: checkers::misraC2012Rules) {
147148
const std::string rule = std::to_string(info.a) + "." + std::to_string(info.b);
148-
const bool active = isMisraRuleActive(mActiveCheckers, rule);
149+
// this will return some rules as always active even if they are not in the active checkers.
150+
// this leads to a difference in the shown count and in the checkers stored in the builddir
151+
// TODO: fix this?
152+
const bool active = !doUnusedFunctionOnly && isMisraRuleActive(mActiveCheckers, rule);
149153
if (active)
150154
++mActiveCheckersCount;
151155
++mAllCheckersCount;

lib/cppcheck.cpp

Lines changed: 50 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,11 +1142,31 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
11421142
try {
11431143
TokenList tokenlist{mSettings, file.lang()};
11441144

1145-
// Create tokens, skip rest of iteration if failed
1146-
Timer::run("Tokenizer::createTokens", mSettings.showtime, &s_timerResults, [&]() {
1147-
simplecpp::TokenList tokensP = preprocessor.preprocess(currentConfig, files, true);
1148-
tokenlist.createTokens(std::move(tokensP));
1149-
});
1145+
{
1146+
bool skipCfg = false;
1147+
// Create tokens, skip rest of iteration if failed
1148+
Timer::run("Tokenizer::createTokens", mSettings.showtime, &s_timerResults, [&]() {
1149+
simplecpp::OutputList outputList_cfg;
1150+
simplecpp::TokenList tokensP = preprocessor.preprocess(currentConfig, files, outputList_cfg);
1151+
const simplecpp::Output* o = preprocessor.handleErrors(outputList_cfg);
1152+
if (!o) {
1153+
tokenlist.createTokens(std::move(tokensP));
1154+
}
1155+
else {
1156+
// #error etc during preprocessing
1157+
configurationError.push_back((currentConfig.empty() ? "\'\'" : currentConfig) + " : [" + o->location.file() + ':' + std::to_string(o->location.line) + "] " + o->msg);
1158+
--checkCount; // don't count invalid configurations
1159+
1160+
if (!hasValidConfig && currCfg == *configurations.rbegin()) {
1161+
// If there is no valid configuration then report error..
1162+
preprocessor.error(o->location.file(), o->location.line, o->location.col, o->msg, o->type);
1163+
}
1164+
skipCfg = true;
1165+
}
1166+
});
1167+
if (skipCfg)
1168+
continue;
1169+
}
11501170
hasValidConfig = true;
11511171

11521172
Tokenizer tokenizer(std::move(tokenlist), mErrorLogger);
@@ -1215,17 +1235,6 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
12151235
ErrorMessage errmsg = ErrorMessage::fromInternalError(e, &tokenizer.list, file.spath());
12161236
mErrorLogger.reportErr(errmsg);
12171237
}
1218-
} catch (const simplecpp::Output &o) {
1219-
// #error etc during preprocessing
1220-
configurationError.push_back((currentConfig.empty() ? "\'\'" : currentConfig) + " : [" + o.location.file() + ':' + std::to_string(o.location.line) + "] " + o.msg);
1221-
--checkCount; // don't count invalid configurations
1222-
1223-
if (!hasValidConfig && currCfg == *configurations.rbegin()) {
1224-
// If there is no valid configuration then report error..
1225-
preprocessor.error(o.location.file(), o.location.line, o.location.col, o.msg, o.type);
1226-
}
1227-
continue;
1228-
12291238
} catch (const TerminateException &) {
12301239
// Analysis is terminated
12311240
if (analyzerInformation)
@@ -1486,7 +1495,7 @@ void CppCheck::executeAddons(const std::string& dumpFile, const FileWithDetails&
14861495

14871496
void CppCheck::executeAddons(const std::vector<std::string>& files, const std::string& file0)
14881497
{
1489-
if (mSettings.addons.empty() || files.empty())
1498+
if (mSettings.addons.empty() || files.empty() || Settings::unusedFunctionOnly())
14901499
return;
14911500

14921501
const bool isCtuInfo = endsWith(files[0], ".ctu-info");
@@ -1798,22 +1807,25 @@ void CppCheck::analyseClangTidy(const FileSettings &fileSettings)
17981807
bool CppCheck::analyseWholeProgram()
17991808
{
18001809
bool errors = false;
1801-
// Analyse the tokens
1802-
CTU::FileInfo ctu;
1803-
if (mSettings.useSingleJob() || !mSettings.buildDir.empty())
1804-
{
1805-
for (const Check::FileInfo *fi : mFileInfo) {
1806-
const auto *fi2 = dynamic_cast<const CTU::FileInfo *>(fi);
1807-
if (fi2) {
1808-
ctu.functionCalls.insert(ctu.functionCalls.end(), fi2->functionCalls.cbegin(), fi2->functionCalls.cend());
1809-
ctu.nestedCalls.insert(ctu.nestedCalls.end(), fi2->nestedCalls.cbegin(), fi2->nestedCalls.cend());
1810+
1811+
if (!Settings::unusedFunctionOnly()) {
1812+
// Analyse the tokens
1813+
CTU::FileInfo ctu;
1814+
if (mSettings.useSingleJob() || !mSettings.buildDir.empty())
1815+
{
1816+
for (const Check::FileInfo *fi : mFileInfo) {
1817+
const auto *fi2 = dynamic_cast<const CTU::FileInfo *>(fi);
1818+
if (fi2) {
1819+
ctu.functionCalls.insert(ctu.functionCalls.end(), fi2->functionCalls.cbegin(), fi2->functionCalls.cend());
1820+
ctu.nestedCalls.insert(ctu.nestedCalls.end(), fi2->nestedCalls.cbegin(), fi2->nestedCalls.cend());
1821+
}
18101822
}
18111823
}
1812-
}
18131824

1814-
// cppcheck-suppress shadowFunction - TODO: fix this
1815-
for (Check *check : Check::instances())
1816-
errors |= check->analyseWholeProgram(ctu, mFileInfo, mSettings, mErrorLogger); // TODO: ctu
1825+
// cppcheck-suppress shadowFunction - TODO: fix this
1826+
for (Check *check : Check::instances())
1827+
errors |= check->analyseWholeProgram(ctu, mFileInfo, mSettings, mErrorLogger); // TODO: ctu
1828+
}
18171829

18181830
if (mUnusedFunctionsCheck)
18191831
errors |= mUnusedFunctionsCheck->check(mSettings, mErrorLogger);
@@ -1823,9 +1835,16 @@ bool CppCheck::analyseWholeProgram()
18231835

18241836
unsigned int CppCheck::analyseWholeProgram(const std::string &buildDir, const std::list<FileWithDetails> &files, const std::list<FileSettings>& fileSettings, const std::string& ctuInfo)
18251837
{
1826-
executeAddonsWholeProgram(files, fileSettings, ctuInfo);
18271838
if (mSettings.checks.isEnabled(Checks::unusedFunction))
18281839
CheckUnusedFunctions::analyseWholeProgram(mSettings, mErrorLogger, buildDir);
1840+
1841+
if (mUnusedFunctionsCheck)
1842+
mUnusedFunctionsCheck->check(mSettings, mErrorLogger);
1843+
1844+
if (Settings::unusedFunctionOnly())
1845+
return mLogger->exitcode();
1846+
1847+
executeAddonsWholeProgram(files, fileSettings, ctuInfo);
18291848
std::list<Check::FileInfo*> fileInfoList;
18301849
CTU::FileInfo ctuFileInfo;
18311850

@@ -1876,9 +1895,6 @@ unsigned int CppCheck::analyseWholeProgram(const std::string &buildDir, const st
18761895
for (Check *check : Check::instances())
18771896
check->analyseWholeProgram(ctuFileInfo, fileInfoList, mSettings, mErrorLogger);
18781897

1879-
if (mUnusedFunctionsCheck)
1880-
mUnusedFunctionsCheck->check(mSettings, mErrorLogger);
1881-
18821898
for (Check::FileInfo *fi : fileInfoList)
18831899
delete fi;
18841900

lib/cppcheck.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ class CPPCHECKLIB CppCheck {
203203
* @brief Check a file using stream
204204
* @param file the file
205205
* @param cfgname cfg name
206-
* @param createTokenList a function to create the simplecpp::TokenList with - throws simplecpp::Output
206+
* @param createTokenList a function to create the simplecpp::TokenList with
207207
* @return number of errors found
208208
*/
209209
unsigned int checkInternal(const FileWithDetails& file, const std::string &cfgname, int fileIndex, const CreateTokenListFn& createTokenList);

lib/preprocessor.cpp

Lines changed: 20 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,11 @@ static bool parseInlineSuppressionCommentToken(const simplecpp::Token *tok, std:
105105

106106
// determine prefix if specified
107107
if (posEndComment >= (pos1 + cppchecksuppress.size() + 1)) {
108-
if (comment.at(pos1 + cppchecksuppress.size()) != '-')
108+
const std::string suppressCmdString = comment.substr(pos1, pos2-pos1-1);
109+
if (comment.at(pos1 + cppchecksuppress.size()) != '-') {
110+
bad.emplace_back(tok->location.file(), tok->location.line, 0, "unknown suppression type '" + suppressCmdString + "'"); // TODO: set column
109111
return false;
112+
}
110113

111114
const unsigned int argumentLength =
112115
posEndComment - (pos1 + cppchecksuppress.size() + 1);
@@ -122,8 +125,10 @@ static bool parseInlineSuppressionCommentToken(const simplecpp::Token *tok, std:
122125
errorType = SuppressionList::Type::blockEnd;
123126
else if ("macro" == suppressTypeString)
124127
errorType = SuppressionList::Type::macro;
125-
else
128+
else {
129+
bad.emplace_back(tok->location.file(), tok->location.line, 0, "unknown suppression type '" + suppressCmdString + "'"); // TODO: set column
126130
return false;
131+
}
127132
}
128133

129134
if (comment[pos2] == '[') {
@@ -742,38 +747,10 @@ static simplecpp::DUI createDUI(const Settings &mSettings, const std::string &cf
742747
return dui;
743748
}
744749

745-
bool Preprocessor::hasErrors(const simplecpp::Output &output)
746-
{
747-
switch (output.type) {
748-
case simplecpp::Output::ERROR:
749-
case simplecpp::Output::INCLUDE_NESTED_TOO_DEEPLY:
750-
case simplecpp::Output::SYNTAX_ERROR:
751-
case simplecpp::Output::UNHANDLED_CHAR_ERROR:
752-
case simplecpp::Output::EXPLICIT_INCLUDE_NOT_FOUND:
753-
case simplecpp::Output::FILE_NOT_FOUND:
754-
case simplecpp::Output::DUI_ERROR:
755-
return true;
756-
case simplecpp::Output::WARNING:
757-
case simplecpp::Output::MISSING_HEADER:
758-
case simplecpp::Output::PORTABILITY_BACKSLASH:
759-
break;
760-
}
761-
return false;
762-
}
763-
764-
bool Preprocessor::handleErrors(const simplecpp::OutputList& outputList, bool throwError)
750+
const simplecpp::Output* Preprocessor::handleErrors(const simplecpp::OutputList& outputList)
765751
{
766752
const bool showerror = (!mSettings.userDefines.empty() && !mSettings.force);
767-
const bool hasError = reportOutput(outputList, showerror);
768-
if (throwError) {
769-
const auto it = std::find_if(outputList.cbegin(), outputList.cend(), [](const simplecpp::Output &output){
770-
return hasErrors(output);
771-
});
772-
if (it != outputList.cend()) {
773-
throw *it;
774-
}
775-
}
776-
return hasError;
753+
return reportOutput(outputList, showerror);
777754
}
778755

779756
bool Preprocessor::loadFiles(std::vector<std::string> &files)
@@ -782,7 +759,7 @@ bool Preprocessor::loadFiles(std::vector<std::string> &files)
782759

783760
simplecpp::OutputList outputList;
784761
mFileCache = simplecpp::load(mTokens, files, dui, &outputList);
785-
return !handleErrors(outputList, false);
762+
return !handleErrors(outputList);
786763
}
787764

788765
void Preprocessor::removeComments()
@@ -813,28 +790,27 @@ void Preprocessor::setPlatformInfo()
813790
mTokens.sizeOfType["long double *"] = mSettings.platform.sizeof_pointer;
814791
}
815792

816-
simplecpp::TokenList Preprocessor::preprocess(const std::string &cfg, std::vector<std::string> &files, bool throwError)
793+
simplecpp::TokenList Preprocessor::preprocess(const std::string &cfg, std::vector<std::string> &files, simplecpp::OutputList& outputList)
817794
{
818795
const simplecpp::DUI dui = createDUI(mSettings, cfg, mLang);
819796

820-
simplecpp::OutputList outputList;
821797
std::list<simplecpp::MacroUsage> macroUsage;
822798
std::list<simplecpp::IfCond> ifCond;
823799
simplecpp::TokenList tokens2(files);
824800
simplecpp::preprocess(tokens2, mTokens, files, mFileCache, dui, &outputList, &macroUsage, &ifCond);
825801
mMacroUsage = std::move(macroUsage);
826802
mIfCond = std::move(ifCond);
827803

828-
(void)handleErrors(outputList, throwError);
829-
830804
tokens2.removeComments();
831805

832806
return tokens2;
833807
}
834808

835809
std::string Preprocessor::getcode(const std::string &cfg, std::vector<std::string> &files, const bool writeLocations)
836810
{
837-
simplecpp::TokenList tokens2 = preprocess(cfg, files, false);
811+
simplecpp::OutputList outputList;
812+
simplecpp::TokenList tokens2 = preprocess(cfg, files, outputList);
813+
handleErrors(outputList);
838814
unsigned int prevfile = 0;
839815
unsigned int line = 1;
840816
std::ostringstream ret;
@@ -859,14 +835,14 @@ std::string Preprocessor::getcode(const std::string &cfg, std::vector<std::strin
859835
return ret.str();
860836
}
861837

862-
bool Preprocessor::reportOutput(const simplecpp::OutputList &outputList, bool showerror)
838+
const simplecpp::Output* Preprocessor::reportOutput(const simplecpp::OutputList &outputList, bool showerror)
863839
{
864-
bool hasError = false;
840+
const simplecpp::Output* out_ret = nullptr;
865841

866842
for (const simplecpp::Output &out : outputList) {
867843
switch (out.type) {
868844
case simplecpp::Output::ERROR:
869-
hasError = true;
845+
out_ret = &out;
870846
if (!startsWith(out.msg,"#error") || showerror)
871847
error(out.location.file(), out.location.line, out.location.col, out.msg, out.type);
872848
break;
@@ -884,19 +860,19 @@ bool Preprocessor::reportOutput(const simplecpp::OutputList &outputList, bool sh
884860
case simplecpp::Output::INCLUDE_NESTED_TOO_DEEPLY:
885861
case simplecpp::Output::SYNTAX_ERROR:
886862
case simplecpp::Output::UNHANDLED_CHAR_ERROR:
887-
hasError = true;
863+
out_ret = &out;
888864
error(out.location.file(), out.location.line, out.location.col, out.msg, out.type);
889865
break;
890866
case simplecpp::Output::EXPLICIT_INCLUDE_NOT_FOUND:
891867
case simplecpp::Output::FILE_NOT_FOUND:
892868
case simplecpp::Output::DUI_ERROR:
893-
hasError = true;
869+
out_ret = &out;
894870
error("", 0, 0, out.msg, out.type);
895871
break;
896872
}
897873
}
898874

899-
return hasError;
875+
return out_ret;
900876
}
901877

902878
static std::string simplecppErrToId(simplecpp::Output::Type type)

lib/preprocessor.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ class CPPCHECKLIB WARN_UNUSED Preprocessor {
118118

119119
void setPlatformInfo();
120120

121-
simplecpp::TokenList preprocess(const std::string &cfg, std::vector<std::string> &files, bool throwError = false);
121+
simplecpp::TokenList preprocess(const std::string &cfg, std::vector<std::string> &files, simplecpp::OutputList& outputList);
122122

123123
std::string getcode(const std::string &cfg, std::vector<std::string> &files, bool writeLocations);
124124

@@ -139,15 +139,13 @@ class CPPCHECKLIB WARN_UNUSED Preprocessor {
139139
*/
140140
void dump(std::ostream &out) const;
141141

142-
bool reportOutput(const simplecpp::OutputList &outputList, bool showerror);
142+
const simplecpp::Output* reportOutput(const simplecpp::OutputList &outputList, bool showerror);
143143

144144
void error(const std::string &filename, unsigned int linenr, unsigned int col, const std::string &msg, simplecpp::Output::Type type);
145145

146-
private:
147-
static bool hasErrors(const simplecpp::Output &output);
148-
149-
bool handleErrors(const simplecpp::OutputList &outputList, bool throwError);
146+
const simplecpp::Output* handleErrors(const simplecpp::OutputList &outputList);
150147

148+
private:
151149
static void simplifyPragmaAsmPrivate(simplecpp::TokenList &tokenList);
152150

153151
/**

0 commit comments

Comments
 (0)