Token: add flag for splitted variable declaration with initialization
This commit is contained in:
parent
bfe53fce04
commit
687b44dbb7
|
@ -137,7 +137,8 @@ class Token:
|
||||||
isUnsigned Is this token a unsigned type
|
isUnsigned Is this token a unsigned type
|
||||||
isSigned Is this token a signed type
|
isSigned Is this token a signed type
|
||||||
isExpandedMacro Is this token a expanded macro token
|
isExpandedMacro Is this token a expanded macro token
|
||||||
isSplittedVarDecl Is this token a splitted variable declaration. "int a,b; => int a; int b;"
|
isSplittedVarDeclComma Is this a comma changed to semicolon in a splitted variable declaration ('int a,b;' => 'int a; int b;')
|
||||||
|
isSplittedVarDeclEq Is this a '=' changed to semicolon in a splitted variable declaration ('int a=5;' => 'int a; a=5;')
|
||||||
varId varId for token, each variable has a unique non-zero id
|
varId varId for token, each variable has a unique non-zero id
|
||||||
variable Variable information for this token. See the Variable class.
|
variable Variable information for this token. See the Variable class.
|
||||||
function If this token points at a function call, this attribute has the Function
|
function If this token points at a function call, this attribute has the Function
|
||||||
|
@ -186,7 +187,8 @@ class Token:
|
||||||
isUnsigned = False
|
isUnsigned = False
|
||||||
isSigned = False
|
isSigned = False
|
||||||
isExpandedMacro = False
|
isExpandedMacro = False
|
||||||
isSplittedVarDecl = False
|
isSplittedVarDeclComma = False
|
||||||
|
isSplittedVarDeclEq = False
|
||||||
varId = None
|
varId = None
|
||||||
variableId = None
|
variableId = None
|
||||||
variable = None
|
variable = None
|
||||||
|
@ -247,8 +249,10 @@ class Token:
|
||||||
self.isLogicalOp = True
|
self.isLogicalOp = True
|
||||||
if element.get('isExpandedMacro'):
|
if element.get('isExpandedMacro'):
|
||||||
self.isExpandedMacro = True
|
self.isExpandedMacro = True
|
||||||
if element.get('isSplittedVarDecl'):
|
if element.get('isSplittedVarDeclComma'):
|
||||||
self.isSplittedVarDecl = True
|
self.isSplittedVarDeclComma = True
|
||||||
|
if element.get('isSplittedVarDeclEq'):
|
||||||
|
self.isSplittedVarDeclEq = True
|
||||||
self.linkId = element.get('link')
|
self.linkId = element.get('link')
|
||||||
self.link = None
|
self.link = None
|
||||||
if element.get('varId'):
|
if element.get('varId'):
|
||||||
|
@ -279,10 +283,10 @@ class Token:
|
||||||
attrs = ["Id", "str", "scopeId", "isName", "isUnsigned", "isSigned",
|
attrs = ["Id", "str", "scopeId", "isName", "isUnsigned", "isSigned",
|
||||||
"isNumber", "isInt", "isFloat", "isString", "strlen",
|
"isNumber", "isInt", "isFloat", "isString", "strlen",
|
||||||
"isChar", "isOp", "isArithmeticalOp", "isComparisonOp",
|
"isChar", "isOp", "isArithmeticalOp", "isComparisonOp",
|
||||||
"isLogicalOp", "isExpandedMacro", "isSplittedVarDecl",
|
"isLogicalOp", "isExpandedMacro", "isSplittedVarDeclComma",
|
||||||
"linkId", "varId", "variableId", "functionId", "valuesId",
|
"isSplittedVarDeclEq","linkId", "varId", "variableId",
|
||||||
"valueType", "typeScopeId", "astParentId", "astOperand1Id",
|
"functionId", "valuesId", "valueType", "typeScopeId",
|
||||||
"file", "linenr", "column"]
|
"astParentId", "astOperand1Id", "file", "linenr", "column"]
|
||||||
return "{}({})".format(
|
return "{}({})".format(
|
||||||
"Token",
|
"Token",
|
||||||
", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs))
|
", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs))
|
||||||
|
|
|
@ -1640,7 +1640,7 @@ class MisraChecker:
|
||||||
|
|
||||||
def misra_12_3(self, data):
|
def misra_12_3(self, data):
|
||||||
for token in data.tokenlist:
|
for token in data.tokenlist:
|
||||||
if token.str == ';' and (token.isSplittedVarDecl is True):
|
if token.str == ';' and (token.isSplittedVarDeclComma is True):
|
||||||
self.reportError(token, 12, 3)
|
self.reportError(token, 12, 3)
|
||||||
if token.str == ',' and token.astParent and token.astParent.str == ';':
|
if token.str == ',' and token.astParent and token.astParent.str == ';':
|
||||||
self.reportError(token, 12, 3)
|
self.reportError(token, 12, 3)
|
||||||
|
|
|
@ -306,7 +306,7 @@ static void uninit(const Token *tok, const ExprEngine::Value &value, ExprEngine:
|
||||||
if (!var->isLocal() || var->isStatic())
|
if (!var->isLocal() || var->isStatic())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (var && (Token::Match(var->nameToken(), "%name% [=:({)]") || Token::Match(var->nameToken(), "%varid% ; %varid% =", var->declarationId())))
|
if (var && (Token::Match(var->nameToken(), "%name% [=:({)]") || var->isInit()))
|
||||||
return;
|
return;
|
||||||
if (var && var->nameToken() == tok)
|
if (var && var->nameToken() == tok)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -111,11 +111,7 @@ void CheckClass::constructors()
|
||||||
if (scope->numConstructors == 0 && printStyle && !usedInUnion) {
|
if (scope->numConstructors == 0 && printStyle && !usedInUnion) {
|
||||||
// If there is a private variable, there should be a constructor..
|
// If there is a private variable, there should be a constructor..
|
||||||
for (const Variable &var : scope->varlist) {
|
for (const Variable &var : scope->varlist) {
|
||||||
const Token *initTok = var.nameToken();
|
if (var.isPrivate() && !var.isStatic() && !var.isInit() &&
|
||||||
while (Token::simpleMatch(initTok->next(), "["))
|
|
||||||
initTok = initTok->linkAt(1);
|
|
||||||
if (var.isPrivate() && !var.isStatic() && !Token::Match(var.nameToken(), "%varid% ; %varid% =", var.declarationId()) &&
|
|
||||||
!Token::Match(initTok, "%var%|] {|=") &&
|
|
||||||
(!var.isClass() || (var.type() && var.type()->needInitialization == Type::NeedInitialization::True))) {
|
(!var.isClass() || (var.type() && var.type()->needInitialization == Type::NeedInitialization::True))) {
|
||||||
noConstructorError(scope->classDef, scope->className, scope->classDef->str() == "struct");
|
noConstructorError(scope->classDef, scope->className, scope->classDef->str() == "struct");
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -432,7 +432,7 @@ void CheckOther::checkRedundantAssignment()
|
||||||
// Do not warn about redundant initialization when rhs is trivial
|
// Do not warn about redundant initialization when rhs is trivial
|
||||||
// TODO : do not simplify the variable declarations
|
// TODO : do not simplify the variable declarations
|
||||||
bool isInitialization = false;
|
bool isInitialization = false;
|
||||||
if (Token::Match(tok->tokAt(-3), "%var% ; %var% =") && tok->previous()->variable() && tok->previous()->variable()->nameToken() == tok->tokAt(-3) && tok->tokAt(-3)->linenr() == tok->previous()->linenr()) {
|
if (Token::Match(tok->tokAt(-2), "; %var% =") && tok->tokAt(-2)->isSplittedVarDeclEq()) {
|
||||||
isInitialization = true;
|
isInitialization = true;
|
||||||
bool trivial = true;
|
bool trivial = true;
|
||||||
visitAstNodes(tok->astOperand2(),
|
visitAstNodes(tok->astOperand2(),
|
||||||
|
|
|
@ -1870,6 +1870,13 @@ Variable::Variable(const Token *name_, const std::string &clangType, const Token
|
||||||
++pos;
|
++pos;
|
||||||
} while (pos < clangType.size() && clangType[pos] == '[');
|
} while (pos < clangType.size() && clangType[pos] == '[');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is there initialization in variable declaration
|
||||||
|
const Token *initTok = mNameToken ? mNameToken->next() : nullptr;
|
||||||
|
while (initTok && initTok->str() == "[")
|
||||||
|
initTok = initTok->link()->next();
|
||||||
|
if (Token::Match(initTok, "=|{") || (initTok && initTok->isSplittedVarDeclEq()))
|
||||||
|
setFlag(fIsInit, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable::~Variable()
|
Variable::~Variable()
|
||||||
|
@ -1900,6 +1907,13 @@ const Token * Variable::declEndToken() const
|
||||||
|
|
||||||
void Variable::evaluate(const Settings* settings)
|
void Variable::evaluate(const Settings* settings)
|
||||||
{
|
{
|
||||||
|
// Is there initialization in variable declaration
|
||||||
|
const Token *initTok = mNameToken ? mNameToken->next() : nullptr;
|
||||||
|
while (initTok && initTok->str() == "[")
|
||||||
|
initTok = initTok->link()->next();
|
||||||
|
if (Token::Match(initTok, "=|{") || (initTok && initTok->isSplittedVarDeclEq()))
|
||||||
|
setFlag(fIsInit, true);
|
||||||
|
|
||||||
if (!settings)
|
if (!settings)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -199,6 +199,7 @@ class CPPCHECKLIB Variable {
|
||||||
fIsVolatile = (1 << 13), /** @brief volatile */
|
fIsVolatile = (1 << 13), /** @brief volatile */
|
||||||
fIsSmartPointer = (1 << 14),/** @brief std::shared_ptr|unique_ptr */
|
fIsSmartPointer = (1 << 14),/** @brief std::shared_ptr|unique_ptr */
|
||||||
fIsMaybeUnused = (1 << 15), /** @brief marked [[maybe_unused]] */
|
fIsMaybeUnused = (1 << 15), /** @brief marked [[maybe_unused]] */
|
||||||
|
fIsInit = (1 << 16), /** @brief Is variable initialized in declaration */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -501,6 +502,14 @@ public:
|
||||||
return getFlag(fHasDefault);
|
return getFlag(fHasDefault);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is variable initialized in its declaration
|
||||||
|
* @return true if variable declaration contains initialization
|
||||||
|
*/
|
||||||
|
bool isInit() const {
|
||||||
|
return getFlag(fIsInit);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Type pointer of known type.
|
* Get Type pointer of known type.
|
||||||
* @return pointer to type if known, NULL if not known
|
* @return pointer to type if known, NULL if not known
|
||||||
|
|
18
lib/token.h
18
lib/token.h
|
@ -612,11 +612,18 @@ public:
|
||||||
setFlag(fExternC, b);
|
setFlag(fExternC, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSplittedVarDecl() const {
|
bool isSplittedVarDeclComma() const {
|
||||||
return getFlag(fIsSplitVarDecl);
|
return getFlag(fIsSplitVarDeclComma);
|
||||||
}
|
}
|
||||||
void isSplittedVarDecl(bool b) {
|
void isSplittedVarDeclComma(bool b) {
|
||||||
setFlag(fIsSplitVarDecl, b);
|
setFlag(fIsSplitVarDeclComma, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isSplittedVarDeclEq() const {
|
||||||
|
return getFlag(fIsSplitVarDeclEq);
|
||||||
|
}
|
||||||
|
void isSplittedVarDeclEq(bool b) {
|
||||||
|
setFlag(fIsSplitVarDeclEq, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isBitfield() const {
|
bool isBitfield() const {
|
||||||
|
@ -1201,7 +1208,8 @@ private:
|
||||||
fIncompleteVar = (1 << 26),
|
fIncompleteVar = (1 << 26),
|
||||||
fConstexpr = (1 << 27),
|
fConstexpr = (1 << 27),
|
||||||
fExternC = (1 << 28),
|
fExternC = (1 << 28),
|
||||||
fIsSplitVarDecl = (1 << 29), // int a,b; <-- vardecl is split up
|
fIsSplitVarDeclComma = (1 << 29), // set to true when variable declarations are split up ('int a,b;' => 'int a; int b;')
|
||||||
|
fIsSplitVarDeclEq = (1 << 30) // set to true when variable declaration with initialization is split up ('int a=5;' => 'int a; a=5;')
|
||||||
};
|
};
|
||||||
|
|
||||||
Token::Type mTokType;
|
Token::Type mTokType;
|
||||||
|
|
|
@ -4974,8 +4974,10 @@ void Tokenizer::dump(std::ostream &out) const
|
||||||
}
|
}
|
||||||
if (tok->isExpandedMacro())
|
if (tok->isExpandedMacro())
|
||||||
out << " isExpandedMacro=\"true\"";
|
out << " isExpandedMacro=\"true\"";
|
||||||
if (tok->isSplittedVarDecl())
|
if (tok->isSplittedVarDeclComma())
|
||||||
out << " isSplittedVarDecl=\"true\"";
|
out << " isSplittedVarDeclComma=\"true\"";
|
||||||
|
if (tok->isSplittedVarDeclEq())
|
||||||
|
out << " isSplittedVarDeclEq=\"true\"";
|
||||||
if (tok->link())
|
if (tok->link())
|
||||||
out << " link=\"" << tok->link() << '\"';
|
out << " link=\"" << tok->link() << '\"';
|
||||||
if (tok->varId() > 0)
|
if (tok->varId() > 0)
|
||||||
|
@ -6859,7 +6861,7 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, co
|
||||||
|
|
||||||
if (tok2->str() == ",") {
|
if (tok2->str() == ",") {
|
||||||
tok2->str(";");
|
tok2->str(";");
|
||||||
tok2->isSplittedVarDecl(true);
|
tok2->isSplittedVarDeclComma(true);
|
||||||
//TODO: should we have to add also template '<>' links?
|
//TODO: should we have to add also template '<>' links?
|
||||||
TokenList::insertTokens(tok2, type0, typelen);
|
TokenList::insertTokens(tok2, type0, typelen);
|
||||||
}
|
}
|
||||||
|
@ -6883,11 +6885,12 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, co
|
||||||
syntaxError(tok2); // invalid code
|
syntaxError(tok2); // invalid code
|
||||||
TokenList::insertTokens(eq, varTok, 2);
|
TokenList::insertTokens(eq, varTok, 2);
|
||||||
eq->str(";");
|
eq->str(";");
|
||||||
|
eq->isSplittedVarDeclEq(true);
|
||||||
|
|
||||||
// "= x, " => "= x; type "
|
// "= x, " => "= x; type "
|
||||||
if (tok2->str() == ",") {
|
if (tok2->str() == ",") {
|
||||||
tok2->str(";");
|
tok2->str(";");
|
||||||
tok2->isSplittedVarDecl(true);
|
tok2->isSplittedVarDeclComma(true);
|
||||||
TokenList::insertTokens(tok2, type0, typelen);
|
TokenList::insertTokens(tok2, type0, typelen);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -5645,10 +5645,8 @@ static void valueFlowUninit(TokenList *tokenlist, SymbolDatabase * /*symbolDatab
|
||||||
// continue;
|
// continue;
|
||||||
if (!Token::Match(vardecl, "%var% ;"))
|
if (!Token::Match(vardecl, "%var% ;"))
|
||||||
continue;
|
continue;
|
||||||
if (Token::Match(vardecl, "%varid% ; %varid% =", vardecl->varId()))
|
|
||||||
continue;
|
|
||||||
const Variable *var = vardecl->variable();
|
const Variable *var = vardecl->variable();
|
||||||
if (!var || var->nameToken() != vardecl)
|
if (!var || var->nameToken() != vardecl || var->isInit())
|
||||||
continue;
|
continue;
|
||||||
if ((!var->isPointer() && var->type() && var->type()->needInitialization != Type::NeedInitialization::True) ||
|
if ((!var->isPointer() && var->type() && var->type()->needInitialization != Type::NeedInitialization::True) ||
|
||||||
!var->isLocal() || var->isStatic() || var->isExtern() || var->isReference() || var->isThrow())
|
!var->isLocal() || var->isStatic() || var->isExtern() || var->isReference() || var->isThrow())
|
||||||
|
|
Loading…
Reference in New Issue