| 2224 | } |
| 2225 | |
| 2226 | static bool isConstStatement(const Token *tok, const Library& library, bool platformIndependent, bool isNestedBracket = false) |
| 2227 | { |
| 2228 | if (!tok) |
| 2229 | return false; |
| 2230 | if (tok->isExpandedMacro()) |
| 2231 | return false; |
| 2232 | if (tok->varId() != 0) |
| 2233 | return true; |
| 2234 | if (isConstant(tok)) |
| 2235 | return true; |
| 2236 | if (Token::Match(tok, "*|&|&&") && |
| 2237 | (Token::Match(tok->previous(), "::|.|const|volatile|restrict") || isVarDeclOp(tok))) |
| 2238 | return false; |
| 2239 | if (Token::Match(tok, "<<|>>") && !astIsIntegral(tok, false)) |
| 2240 | return false; |
| 2241 | const Token* tok2 = tok; |
| 2242 | while (tok2) { |
| 2243 | if (Token::simpleMatch(tok2->astOperand1(), "delete")) |
| 2244 | return false; |
| 2245 | tok2 = tok2->astParent(); |
| 2246 | } |
| 2247 | if (Token::Match(tok, "&&|%oror%")) |
| 2248 | return isConstStatement(tok->astOperand1(), library, platformIndependent) && isConstStatement(tok->astOperand2(), library, platformIndependent); |
| 2249 | if (Token::Match(tok, "!|~|%cop%") && (tok->astOperand1() || tok->astOperand2())) |
| 2250 | return true; |
| 2251 | if (Token::simpleMatch(tok->previous(), "sizeof (")) |
| 2252 | return !platformIndependent; |
| 2253 | if (Token::Match(tok->previous(), "alignof|noexcept|typeid (") && tok->previous()->isKeyword()) |
| 2254 | return true; |
| 2255 | if (isCPPCast(tok)) { |
| 2256 | if (Token::simpleMatch(tok->astOperand1(), "dynamic_cast") && Token::simpleMatch(tok->astOperand1()->linkAt(1)->previous(), "& >")) |
| 2257 | return false; |
| 2258 | return isWithoutSideEffects(tok) && isConstStatement(tok->astOperand2(), library, platformIndependent); |
| 2259 | } |
| 2260 | if (tok->isCast() && tok->next() && tok->next()->isStandardType()) |
| 2261 | return isWithoutSideEffects(tok->astOperand1()) && isConstStatement(tok->astOperand1(), library, platformIndependent); |
| 2262 | if (Token::simpleMatch(tok, ".")) |
| 2263 | return isConstStatement(tok->astOperand2(), library, platformIndependent); |
| 2264 | if (Token::simpleMatch(tok, ",")) { |
| 2265 | if (tok->astParent()) // warn about const statement on rhs at the top level |
| 2266 | return isConstStatement(tok->astOperand1(), library, platformIndependent) && |
| 2267 | isConstStatement(tok->astOperand2(), library, platformIndependent); |
| 2268 | |
| 2269 | const Token* lml = previousBeforeAstLeftmostLeaf(tok); // don't warn about matrix/vector assignment (e.g. Eigen) |
| 2270 | if (lml) |
| 2271 | lml = lml->next(); |
| 2272 | const Token* stream = lml; |
| 2273 | while (stream && Token::Match(stream->astParent(), ".|[|(|*")) |
| 2274 | stream = stream->astParent(); |
| 2275 | return (!stream || !isLikelyStream(stream)) && isConstStatement(tok->astOperand2(), library, platformIndependent); |
| 2276 | } |
| 2277 | if (Token::simpleMatch(tok, "?") && Token::simpleMatch(tok->astOperand2(), ":")) // ternary operator |
| 2278 | return isConstStatement(tok->astOperand1(), library, platformIndependent) && |
| 2279 | isConstStatement(tok->astOperand2()->astOperand1(), library, platformIndependent) && |
| 2280 | isConstStatement(tok->astOperand2()->astOperand2(), library, platformIndependent); |
| 2281 | if (isBracketAccess(tok) && isWithoutSideEffects(tok->astOperand1(), /*checkArrayAccess*/ true, /*checkReference*/ false)) { |
| 2282 | const bool isChained = succeeds(tok->astParent(), tok); |
| 2283 | if (Token::simpleMatch(tok->astParent(), "[")) { |
no test coverage detected