Skip to content

Commit 17be050

Browse files
committed
made it possible to issue debug messages through a Token [skip ci]
1 parent e5c4a73 commit 17be050

5 files changed

Lines changed: 62 additions & 58 deletions

File tree

lib/cppcheck.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,16 @@ unsigned int CppCheck::checkClang(const FileWithDetails &file)
736736

737737
try {
738738
TokenList tokenlist{mSettings, file.lang()};
739+
tokenlist.setDebugMsgHandler([&](const Token* tok, const std::string& type, const std::string& msg) {
740+
ErrorMessage::FileLocation loc(tok, &tokenlist);
741+
ErrorMessage errmsg({std::move(loc)},
742+
tokenlist.getSourceFilePath(),
743+
Severity::debug,
744+
msg,
745+
type,
746+
Certainty::normal);
747+
mErrorLogger.reportErr(errmsg);
748+
});
739749
tokenlist.appendFileIfNew(file.spath());
740750
Tokenizer tokenizer(std::move(tokenlist), mErrorLogger);
741751
std::istringstream ast(output2);

lib/token.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2757,3 +2757,8 @@ bool Token::isMutableExpr() const
27572757
mImpl->mMutableExpr = isMutableExpression(this);
27582758
return !!mImpl->mMutableExpr;
27592759
}
2760+
2761+
void Token::debugMsg(const std::string& type, const std::string& msg) const
2762+
{
2763+
mList.debugMsg(this, type, msg);
2764+
}

lib/token.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1689,6 +1689,8 @@ class CPPCHECKLIB Token {
16891689
{
16901690
return mIsC;
16911691
}
1692+
1693+
void debugMsg(const std::string& type, const std::string& msg) const;
16921694
};
16931695

16941696
Token* findTypeEnd(Token* tok);

lib/tokenlist.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#include <cstddef>
2828
#include <cstdint>
29+
#include <functional>
2930
#include <memory>
3031
#include <string>
3132
#include <vector>
@@ -215,6 +216,15 @@ class CPPCHECKLIB TokenList {
215216
return mSettings;
216217
}
217218

219+
void setDebugMsgHandler(std::function<void(const Token*, const std::string&, const std::string&)> debugMsgHandler) {
220+
mDebugMsgHandler = std::move(debugMsgHandler);
221+
}
222+
223+
void debugMsg(const Token* tok, const std::string& type, const std::string& msg) const {
224+
if (mSettings.debugwarnings && mDebugMsgHandler)
225+
mDebugMsgHandler(tok, type, msg);
226+
}
227+
218228
private:
219229
bool createTokensFromBufferInternal(const char* data, std::size_t size, const std::string& file0);
220230

@@ -232,6 +242,9 @@ class CPPCHECKLIB TokenList {
232242

233243
/** File is known to be C/C++ code */
234244
Standards::Language mLang{Standards::Language::None};
245+
246+
/** The handler for debug messages */
247+
std::function<void(const Token*, const std::string&, const std::string&)> mDebugMsgHandler;
235248
};
236249

237250
/// @}

lib/valueflow.cpp

Lines changed: 32 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,6 @@
129129
#include <vector>
130130

131131
static void bailoutInternal(const std::string& type,
132-
const TokenList& tokenlist,
133-
ErrorLogger& errorLogger,
134132
const Token* tok,
135133
const std::string& what,
136134
const std::string& file,
@@ -139,25 +137,19 @@ static void bailoutInternal(const std::string& type,
139137
{
140138
if (function.find("operator") != std::string::npos)
141139
function = "(valueFlow)";
142-
ErrorMessage::FileLocation loc(tok, &tokenlist);
143140
const std::string location = Path::stripDirectoryPart(file) + ":" + std::to_string(line) + ":";
144-
ErrorMessage errmsg({std::move(loc)},
145-
tokenlist.getSourceFilePath(),
146-
Severity::debug,
147-
(file.empty() ? "" : location) + function + " bailout: " + what,
148-
type,
149-
Certainty::normal);
150-
errorLogger.reportErr(errmsg);
141+
const std::string msg = (file.empty() ? "" : location) + function + " bailout: " + what;
142+
tok->debugMsg(type, msg);
151143
}
152144

153-
#define bailout2(type, tokenlist, errorLogger, tok, what) \
154-
bailoutInternal((type), (tokenlist), (errorLogger), (tok), (what), __FILE__, __LINE__, __func__)
145+
#define bailout2(type, tok, what) \
146+
bailoutInternal((type), (tok), (what), __FILE__, __LINE__, __func__)
155147

156-
#define bailout(tokenlist, errorLogger, tok, what) \
157-
bailout2("valueFlowBailout", (tokenlist), (errorLogger), (tok), (what))
148+
#define bailout(tok, what) \
149+
bailout2("valueFlowBailout", (tok), (what))
158150

159-
#define bailoutIncompleteVar(tokenlist, errorLogger, tok, what) \
160-
bailoutInternal("valueFlowBailoutIncompleteVar", (tokenlist), (errorLogger), (tok), (what), "", 0, __func__)
151+
#define bailoutIncompleteVar(tok, what) \
152+
bailoutInternal("valueFlowBailoutIncompleteVar", (tok), (what), "", 0, __func__)
161153

162154
static void changeKnownToPossible(std::list<ValueFlow::Value>& values, int indirect = -1)
163155
{
@@ -2083,7 +2075,7 @@ struct LifetimeStore {
20832075
}
20842076
}
20852077

2086-
static LifetimeStore fromFunctionArg(const Function * f, const Token *tok, const Variable *var, const TokenList &tokenlist, const Settings& settings, ErrorLogger &errorLogger) {
2078+
static LifetimeStore fromFunctionArg(const Function * f, const Token *tok, const Variable *var, const Settings& settings) {
20872079
if (!var)
20882080
return LifetimeStore{};
20892081
if (!var->isArgument())
@@ -2094,9 +2086,7 @@ struct LifetimeStore {
20942086
std::vector<const Token *> args = getArguments(tok);
20952087
if (n >= args.size()) {
20962088
if (settings.debugwarnings)
2097-
bailout(tokenlist,
2098-
errorLogger,
2099-
tok,
2089+
bailout(tok,
21002090
"Argument mismatch: Function '" + tok->str() + "' returning lifetime from argument index " +
21012091
std::to_string(n) + " but only " + std::to_string(args.size()) +
21022092
" arguments are available.");
@@ -2521,7 +2511,7 @@ static void valueFlowLifetimeFunction(Token *tok, const TokenList &tokenlist, Er
25212511
continue;
25222512
const Variable *returnVar = ValueFlow::getLifetimeVariable(returnTok, settings);
25232513
if (returnVar && returnVar->isArgument() && (returnVar->isConst() || !isVariableChanged(returnVar, settings))) {
2524-
LifetimeStore ls = LifetimeStore::fromFunctionArg(f, tok, returnVar, tokenlist, settings, errorLogger);
2514+
LifetimeStore ls = LifetimeStore::fromFunctionArg(f, tok, returnVar, settings);
25252515
ls.inconclusive = inconclusive;
25262516
ls.forward = false;
25272517
update |= ls.byVal(tok->next(), tokenlist, errorLogger, settings);
@@ -2554,7 +2544,7 @@ static void valueFlowLifetimeFunction(Token *tok, const TokenList &tokenlist, Er
25542544
continue;
25552545
}
25562546
const Variable *var = v.tokvalue->variable();
2557-
LifetimeStore ls = LifetimeStore::fromFunctionArg(f, tok, var, tokenlist, settings, errorLogger);
2547+
LifetimeStore ls = LifetimeStore::fromFunctionArg(f, tok, var, settings);
25582548
if (!ls.argtok)
25592549
continue;
25602550
ls.forward = false;
@@ -3406,9 +3396,7 @@ static void valueFlowConditionExpressions(const TokenList& tokenlist,
34063396
for (const Scope* scope : symboldatabase.functionScopes) {
34073397
if (const Token* incompleteTok = findIncompleteVar(scope->bodyStart, scope->bodyEnd)) {
34083398
if (settings.debugwarnings)
3409-
bailoutIncompleteVar(tokenlist,
3410-
errorLogger,
3411-
incompleteTok,
3399+
bailoutIncompleteVar(incompleteTok,
34123400
"Skipping function due to incomplete variable " + incompleteTok->str());
34133401
continue;
34143402
}
@@ -4492,19 +4480,15 @@ struct ConditionHandler {
44924480

44934481
if (Token::simpleMatch(tok->astParent(), "?") && tok->astParent()->isExpandedMacro()) {
44944482
if (settings.debugwarnings)
4495-
bailout(tokenlist,
4496-
errorLogger,
4497-
tok,
4483+
bailout(tok,
44984484
"variable '" + cond.vartok->expressionString() + "', condition is defined in macro");
44994485
return;
45004486
}
45014487

45024488
// if,macro => bailout
45034489
if (Token::simpleMatch(top->previous(), "if (") && top->previous()->isExpandedMacro()) {
45044490
if (settings.debugwarnings)
4505-
bailout(tokenlist,
4506-
errorLogger,
4507-
tok,
4491+
bailout(tok,
45084492
"variable '" + cond.vartok->expressionString() + "', condition is defined in macro");
45094493
return;
45104494
}
@@ -4539,9 +4523,7 @@ struct ConditionHandler {
45394523
findExpressionChanged(
45404524
cond.vartok, top->astOperand2()->astOperand2(), top->link(), settings)) {
45414525
if (settings.debugwarnings)
4542-
bailout(tokenlist,
4543-
errorLogger,
4544-
tok,
4526+
bailout(tok,
45454527
"variable '" + cond.vartok->expressionString() + "' used in loop");
45464528
return;
45474529
}
@@ -4563,9 +4545,7 @@ struct ConditionHandler {
45634545
reverse(bodyTok->link(), bodyTok, cond.vartok, values, tokenlist, errorLogger, settings);
45644546
}
45654547
if (settings.debugwarnings)
4566-
bailout(tokenlist,
4567-
errorLogger,
4568-
tok,
4548+
bailout(tok,
45694549
"variable '" + cond.vartok->expressionString() + "' used in loop");
45704550
return;
45714551
}
@@ -4827,18 +4807,14 @@ struct ConditionHandler {
48274807
}
48284808
if (changeBlock >= 0 && !Token::simpleMatch(top->previous(), "while (")) {
48294809
if (settings.debugwarnings)
4830-
bailout(tokenlist,
4831-
errorLogger,
4832-
startTokens[changeBlock]->link(),
4810+
bailout(startTokens[changeBlock]->link(),
48334811
"valueFlowAfterCondition: " + cond.vartok->expressionString() +
48344812
" is changed in conditional block");
48354813
return;
48364814
}
48374815
if (bailBlock >= 0) {
48384816
if (settings.debugwarnings)
4839-
bailout(tokenlist,
4840-
errorLogger,
4841-
startTokens[bailBlock]->link(),
4817+
bailout(startTokens[bailBlock]->link(),
48424818
"valueFlowAfterCondition: bailing in conditional block");
48434819
return;
48444820
}
@@ -4856,7 +4832,7 @@ struct ConditionHandler {
48564832

48574833
if (!dead_if && unknownFunction) {
48584834
if (settings.debugwarnings)
4859-
bailout(tokenlist, errorLogger, unknownFunction, "possible noreturn scope");
4835+
bailout(unknownFunction, "possible noreturn scope");
48604836
return;
48614837
}
48624838

@@ -4867,7 +4843,7 @@ struct ConditionHandler {
48674843
dead_else = isReturnScope(after, settings.library, &unknownFunction);
48684844
if (!dead_else && unknownFunction) {
48694845
if (settings.debugwarnings)
4870-
bailout(tokenlist, errorLogger, unknownFunction, "possible noreturn scope");
4846+
bailout(unknownFunction, "possible noreturn scope");
48714847
return;
48724848
}
48734849
}
@@ -5222,8 +5198,6 @@ static void valueFlowForLoopSimplify(Token* const bodyStart,
52225198
const Token* expr,
52235199
bool globalvar,
52245200
const MathLib::bigint value,
5225-
const TokenList& tokenlist,
5226-
ErrorLogger& errorLogger,
52275201
const Settings& settings)
52285202
{
52295203
// TODO: Refactor this to use arbitrary expressions
@@ -5236,7 +5210,7 @@ static void valueFlowForLoopSimplify(Token* const bodyStart,
52365210

52375211
if (const Token* escape = findEscapeStatement(bodyStart->scope(), settings.library)) {
52385212
if (settings.debugwarnings)
5239-
bailout(tokenlist, errorLogger, escape, "For loop variable bailout on escape statement");
5213+
bailout(escape, "For loop variable bailout on escape statement");
52405214
return;
52415215
}
52425216

@@ -5256,7 +5230,7 @@ static void valueFlowForLoopSimplify(Token* const bodyStart,
52565230
}
52575231
if (parent) {
52585232
if (settings.debugwarnings)
5259-
bailout(tokenlist, errorLogger, tok2, "For loop variable " + tok2->str() + " stopping on ?");
5233+
bailout(tok2, "For loop variable " + tok2->str() + " stopping on ?");
52605234
continue;
52615235
}
52625236

@@ -5302,15 +5276,15 @@ static void valueFlowForLoopSimplify(Token* const bodyStart,
53025276
if (Token::simpleMatch(tok2, ") {")) {
53035277
if (vartok->varId() && Token::findmatch(tok2->link(), "%varid%", tok2, vartok->varId())) {
53045278
if (settings.debugwarnings)
5305-
bailout(tokenlist, errorLogger, tok2, "For loop variable skipping conditional scope");
5279+
bailout(tok2, "For loop variable skipping conditional scope");
53065280
tok2 = tok2->linkAt(1);
53075281
if (Token::simpleMatch(tok2, "} else {")) {
53085282
tok2 = tok2->linkAt(2);
53095283
}
53105284
}
53115285
else {
53125286
if (settings.debugwarnings)
5313-
bailout(tokenlist, errorLogger, tok2, "For loop skipping {} code");
5287+
bailout(tok2, "For loop skipping {} code");
53145288
tok2 = tok2->linkAt(1);
53155289
if (Token::simpleMatch(tok2, "} else {"))
53165290
tok2 = tok2->linkAt(2);
@@ -5395,7 +5369,7 @@ static void valueFlowForLoop(const TokenList &tokenlist, const SymbolDatabase& s
53955369
continue;
53965370
if (p.first.tok->varId() == 0)
53975371
continue;
5398-
valueFlowForLoopSimplify(bodyStart, p.first.tok, false, p.second.intvalue, tokenlist, errorLogger, settings);
5372+
valueFlowForLoopSimplify(bodyStart, p.first.tok, false, p.second.intvalue, settings);
53995373
}
54005374
for (const auto& p : mem2) {
54015375
if (!p.second.isIntValue())
@@ -5404,7 +5378,7 @@ static void valueFlowForLoop(const TokenList &tokenlist, const SymbolDatabase& s
54045378
continue;
54055379
if (p.first.tok->varId() == 0)
54065380
continue;
5407-
valueFlowForLoopSimplify(bodyStart, p.first.tok, false, p.second.intvalue, tokenlist, errorLogger, settings);
5381+
valueFlowForLoopSimplify(bodyStart, p.first.tok, false, p.second.intvalue, settings);
54085382
}
54095383
for (const auto& p : memAfter) {
54105384
if (!p.second.isIntValue())
@@ -5500,7 +5474,7 @@ static void valueFlowInjectParameter(const TokenList& tokenlist,
55005474
if (const Function* f = functionScope->function)
55015475
fname = f->name();
55025476
if (settings.debugwarnings)
5503-
bailout(tokenlist, errorLogger, functionScope->bodyStart, "Too many argument passed to " + fname);
5477+
bailout(functionScope->bodyStart, "Too many argument passed to " + fname);
55045478
}
55055479
}
55065480

@@ -5547,7 +5521,7 @@ static void valueFlowSwitchVariable(const TokenList& tokenlist,
55475521
// bailout: global non-const variables
55485522
if (!(var->isLocal() || var->isArgument()) && !var->isConst()) {
55495523
if (settings.debugwarnings)
5550-
bailout(tokenlist, errorLogger, vartok, "switch variable " + var->name() + " is global");
5524+
bailout(vartok, "switch variable " + var->name() + " is global");
55515525
continue;
55525526
}
55535527

@@ -5809,7 +5783,7 @@ static void setFunctionReturnValue(const Function* f,
58095783
setTokenValue(tok, std::move(v), settings);
58105784
}
58115785

5812-
static void valueFlowFunctionReturn(TokenList& tokenlist, ErrorLogger& errorLogger, const Settings& settings)
5786+
static void valueFlowFunctionReturn(TokenList& tokenlist, const Settings& settings)
58135787
{
58145788
for (Token* tok = tokenlist.back(); tok; tok = tok->previous()) {
58155789
if (tok->str() != "(" || !tok->astOperand1() || tok->isCast())
@@ -5852,7 +5826,7 @@ static void valueFlowFunctionReturn(TokenList& tokenlist, ErrorLogger& errorLogg
58525826
const Variable* const arg = function->getArgumentVar(i);
58535827
if (!arg) {
58545828
if (settings.debugwarnings)
5855-
bailout(tokenlist, errorLogger, tok, "function return; unhandled argument type");
5829+
bailout(tok, "function return; unhandled argument type");
58565830
programMemory.clear();
58575831
break;
58585832
}
@@ -7438,7 +7412,7 @@ void ValueFlow::setValues(TokenList& tokenlist,
74387412
VFA(valueFlowSwitchVariable(tokenlist, symboldatabase, errorLogger, settings)),
74397413
VFA(valueFlowForLoop(tokenlist, symboldatabase, errorLogger, settings)),
74407414
VFA(valueFlowSubFunction(tokenlist, symboldatabase, errorLogger, settings)),
7441-
VFA(valueFlowFunctionReturn(tokenlist, errorLogger, settings)),
7415+
VFA(valueFlowFunctionReturn(tokenlist, settings)),
74427416
VFA(valueFlowLifetime(tokenlist, errorLogger, settings)),
74437417
VFA(valueFlowFunctionDefaultParameter(tokenlist, symboldatabase, errorLogger, settings)),
74447418
VFA(valueFlowUninit(tokenlist, errorLogger, settings)),

0 commit comments

Comments
 (0)