Fixed #6978 (False positive: unusedLabel shown for labels that are used in some preprocessor configurations)
This commit is contained in:
parent
0583763cc6
commit
ddd21a260f
|
@ -2637,6 +2637,7 @@ void CheckOther::checkUnusedLabel()
|
|||
|
||||
const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
|
||||
for (const Scope * scope : symbolDatabase->functionScopes) {
|
||||
const bool hasIfdef = mTokenizer->hasIfdef(scope->bodyStart, scope->bodyEnd);
|
||||
for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) {
|
||||
if (!tok->scope()->isExecutable())
|
||||
tok = tok->scope()->bodyEnd;
|
||||
|
@ -2644,25 +2645,35 @@ void CheckOther::checkUnusedLabel()
|
|||
if (Token::Match(tok, "{|}|; %name% :") && tok->strAt(1) != "default") {
|
||||
const std::string tmp("goto " + tok->strAt(1));
|
||||
if (!Token::findsimplematch(scope->bodyStart->next(), tmp.c_str(), tmp.size(), scope->bodyEnd->previous()))
|
||||
unusedLabelError(tok->next(), tok->next()->scope()->type == Scope::eSwitch);
|
||||
unusedLabelError(tok->next(), tok->next()->scope()->type == Scope::eSwitch, hasIfdef);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CheckOther::unusedLabelError(const Token* tok, bool inSwitch)
|
||||
void CheckOther::unusedLabelError(const Token* tok, bool inSwitch, bool hasIfdef)
|
||||
{
|
||||
if (inSwitch) {
|
||||
if (!tok || mSettings->isEnabled(Settings::WARNING))
|
||||
reportError(tok, Severity::warning, "unusedLabelSwitch",
|
||||
"$symbol:" + (tok ? tok->str() : emptyString) + "\n"
|
||||
"Label '$symbol' is not used. Should this be a 'case' of the enclosing switch()?", CWE398, false);
|
||||
} else {
|
||||
if (!tok || mSettings->isEnabled(Settings::STYLE))
|
||||
reportError(tok, Severity::style, "unusedLabel",
|
||||
"$symbol:" + (tok ? tok->str() : emptyString) + "\n"
|
||||
"Label '$symbol' is not used.", CWE398, false);
|
||||
}
|
||||
if (tok && !mSettings->isEnabled(inSwitch ? Settings::WARNING : Settings::STYLE))
|
||||
return;
|
||||
|
||||
std::string id = "unusedLabel";
|
||||
if (inSwitch)
|
||||
id += "Switch";
|
||||
if (hasIfdef)
|
||||
id += "Configuration";
|
||||
|
||||
std::string msg = "$symbol:" + (tok ? tok->str() : emptyString) + "\nLabel '$symbol' is not used.";
|
||||
if (hasIfdef)
|
||||
msg += " There is #if in function body so the label might be used in code that is removed by the preprocessor.";
|
||||
if (inSwitch)
|
||||
msg += " Should this be a 'case' of the enclosing switch()?";
|
||||
|
||||
reportError(tok,
|
||||
inSwitch ? Severity::warning : Severity::style,
|
||||
id,
|
||||
msg,
|
||||
CWE398,
|
||||
false);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -266,7 +266,7 @@ private:
|
|||
void commaSeparatedReturnError(const Token *tok);
|
||||
void redundantPointerOpError(const Token* tok, const std::string& varname, bool inconclusive);
|
||||
void raceAfterInterlockedDecrementError(const Token* tok);
|
||||
void unusedLabelError(const Token* tok, bool inSwitch);
|
||||
void unusedLabelError(const Token* tok, bool inSwitch, bool hasIfdef);
|
||||
void unknownEvaluationOrder(const Token* tok);
|
||||
static bool isMovedParameterAllowedForInconclusiveFunction(const Token * tok);
|
||||
void accessMovedError(const Token *tok, const std::string &varname, const ValueFlow::Value *value, bool inconclusive);
|
||||
|
@ -331,8 +331,10 @@ private:
|
|||
c.nanInArithmeticExpressionError(nullptr);
|
||||
c.commaSeparatedReturnError(nullptr);
|
||||
c.redundantPointerOpError(nullptr, "varname", false);
|
||||
c.unusedLabelError(nullptr, true);
|
||||
c.unusedLabelError(nullptr, false);
|
||||
c.unusedLabelError(nullptr, false, false);
|
||||
c.unusedLabelError(nullptr, false, true);
|
||||
c.unusedLabelError(nullptr, true, false);
|
||||
c.unusedLabelError(nullptr, true, true);
|
||||
c.unknownEvaluationOrder(nullptr);
|
||||
c.accessMovedError(nullptr, "v", nullptr, false);
|
||||
c.funcArgNamesDifferent("function", 1, nullptr, nullptr);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "library.h"
|
||||
#include "mathlib.h"
|
||||
#include "platform.h"
|
||||
#include "preprocessor.h"
|
||||
#include "settings.h"
|
||||
#include "standards.h"
|
||||
#include "symboldatabase.h"
|
||||
|
@ -11773,3 +11774,19 @@ bool Tokenizer::VariableMap::hasVariable(const std::string &varname) const
|
|||
{
|
||||
return mVariableId.find(varname) != mVariableId.end();
|
||||
}
|
||||
|
||||
bool Tokenizer::hasIfdef(const Token *start, const Token *end) const
|
||||
{
|
||||
if (!mPreprocessor)
|
||||
return false;
|
||||
for (const Directive &d: mPreprocessor->getDirectives()) {
|
||||
if (d.str.compare(0,3,"#if") == 0 &&
|
||||
d.linenr >= start->linenr() &&
|
||||
d.linenr <= end->linenr() &&
|
||||
start->fileIndex() < list.getFiles().size() &&
|
||||
d.file == list.getFiles()[start->fileIndex()])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -568,6 +568,8 @@ public:
|
|||
return mPreprocessor;
|
||||
}
|
||||
|
||||
bool hasIfdef(const Token *start, const Token *end) const;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue