Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

utilize returns_nonnull function attribute #6759

Merged
merged 4 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/astutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -991,7 +991,7 @@ static const Token * getVariableInitExpression(const Variable * var)
const Token* isInLoopCondition(const Token* tok)
{
const Token* top = tok->astTop();
return top && Token::Match(top->previous(), "for|while (") ? top : nullptr;
return Token::Match(top->previous(), "for|while (") ? top : nullptr;
}

/// If tok2 comes after tok1
Expand Down
4 changes: 1 addition & 3 deletions lib/checkcondition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -834,8 +834,6 @@ static std::string innerSmtString(const Token * tok)
{
if (!tok)
return "if";
if (!tok->astTop())
return "if";
const Token * top = tok->astTop();
if (top->str() == "(" && top->astOperand1())
return top->astOperand1()->str();
Expand Down Expand Up @@ -1119,7 +1117,7 @@ static std::string conditionString(const Token * tok)

static bool isIfConstexpr(const Token* tok) {
const Token* const top = tok->astTop();
return top && Token::simpleMatch(top->astOperand1(), "if") && top->astOperand1()->isConstexpr();
return Token::simpleMatch(top->astOperand1(), "if") && top->astOperand1()->isConstexpr();
}

void CheckCondition::checkIncorrectLogicOperator()
Expand Down
2 changes: 0 additions & 2 deletions lib/checkother.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2307,8 +2307,6 @@ static const Token * getSingleExpressionInBlock(const Token * tok)
if (!tok)
return nullptr;
const Token * top = tok->astTop();
if (!top)
return nullptr;
const Token * nextExpression = nextAfterAstRightmostLeaf(top);
if (!Token::simpleMatch(nextExpression, "; }"))
return nullptr;
Expand Down
16 changes: 1 addition & 15 deletions lib/checkstl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1613,22 +1613,8 @@ static const Token* skipLocalVars(const Token* const tok)
if (Token::simpleMatch(tok, "{"))
return skipLocalVars(tok->next());

const Token *top = tok->astTop();
if (!top) {
const Token *semi = Token::findsimplematch(tok, ";");
if (!semi)
return tok;
if (!Token::Match(semi->previous(), "%var% ;"))
return tok;
const Token *varTok = semi->previous();
const Variable *var = varTok->variable();
if (!var)
return tok;
if (var->nameToken() != varTok)
return tok;
return skipLocalVars(semi->next());
}
if (tok->isAssignmentOp()) {
const Token *top = tok->astTop();
const Token *varTok = top->astOperand1();
const Variable *var = varTok->variable();
if (!var)
Expand Down
10 changes: 10 additions & 0 deletions lib/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,16 @@
# define DEPRECATED
#endif

// TODO: GCC apparently also supports this but there is no documentation on it
// returns_nonnull
#if __has_cpp_attribute (gnu::returns_nonnull)
# define RET_NONNULL [[gnu::returns_nonnull]]
#elif (defined(__clang__) && ((__clang_major__ > 3) || ((__clang_major__ == 3) && (__clang_minor__ >= 7))))
# define RET_NONNULL __attribute__((returns_nonnull))
#else
# define RET_NONNULL
#endif

#define REQUIRES(msg, ...) class=typename std::enable_if<__VA_ARGS__::value>::type

#include <string>
Expand Down
2 changes: 1 addition & 1 deletion lib/forwardanalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ namespace {
return Break(Analyzer::Terminate::Bail);
} else if (tok->str() == ";" && tok->astParent()) {
Token* top = tok->astTop();
if (top && Token::Match(top->previous(), "for|while (") && Token::simpleMatch(top->link(), ") {")) {
if (Token::Match(top->previous(), "for|while (") && Token::simpleMatch(top->link(), ") {")) {
Token* endCond = top->link();
Token* endBlock = endCond->linkAt(1);
Token* condTok = getCondTok(top);
Expand Down
4 changes: 1 addition & 3 deletions lib/programmemory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ void ProgramMemoryState::assume(const Token* tok, bool b, bool isEmpty)
programMemoryParseCondition(pm, tok, nullptr, *settings, b);
const Token* origin = tok;
const Token* top = tok->astTop();
if (top && Token::Match(top->previous(), "for|while|if (") && !Token::simpleMatch(tok->astParent(), "?")) {
if (Token::Match(top->previous(), "for|while|if (") && !Token::simpleMatch(tok->astParent(), "?")) {
origin = top->link()->next();
if (!b && origin->link()) {
origin = origin->link();
Expand Down Expand Up @@ -1727,8 +1727,6 @@ namespace {
return {unknown()};
for (const Token* tok = scope->bodyStart->next(); precedes(tok, scope->bodyEnd); tok = tok->next()) {
const Token* top = tok->astTop();
if (!top)
return {unknown()};

if (Token::simpleMatch(top, "return") && top->astOperand1())
return {execute(top->astOperand1())};
Expand Down
2 changes: 1 addition & 1 deletion lib/reverseanalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ namespace {
if (!condTok)
break;
Analyzer::Action condAction = analyzeRecursive(condTok);
const bool inLoop = condTok->astTop() && Token::Match(condTok->astTop()->previous(), "for|while (");
const bool inLoop = Token::Match(condTok->astTop()->previous(), "for|while (");
// Evaluate condition of for and while loops first
if (inLoop) {
if (Token::findmatch(tok->link(), "goto|break", tok))
Expand Down
14 changes: 7 additions & 7 deletions lib/token.h
Original file line number Diff line number Diff line change
Expand Up @@ -919,9 +919,9 @@ class CPPCHECKLIB Token {
* @param prepend Insert the new token before this token when it's not
* the first one on the tokens list.
*/
Token* insertToken(const std::string& tokenStr, const std::string& originalNameStr = emptyString, const std::string& macroNameStr = emptyString, bool prepend = false);
RET_NONNULL Token* insertToken(const std::string& tokenStr, const std::string& originalNameStr = emptyString, const std::string& macroNameStr = emptyString, bool prepend = false);

Token* insertTokenBefore(const std::string& tokenStr, const std::string& originalNameStr = emptyString, const std::string& macroNameStr = emptyString)
RET_NONNULL Token* insertTokenBefore(const std::string& tokenStr, const std::string& originalNameStr = emptyString, const std::string& macroNameStr = emptyString)
{
return insertToken(tokenStr, originalNameStr, macroNameStr, true);
}
Expand Down Expand Up @@ -1224,22 +1224,22 @@ class CPPCHECKLIB Token {
/**
* @return the first token of the next argument. Does only work on argument
* lists. Requires that Tokenizer::createLinks2() has been called before.
* Returns 0, if there is no next argument.
* Returns nullptr, if there is no next argument.
*/
const Token* nextArgument() const;
Token *nextArgument();

/**
* @return the first token of the next argument. Does only work on argument
* lists. Should be used only before Tokenizer::createLinks2() was called.
* Returns 0, if there is no next argument.
* Returns nullptr, if there is no next argument.
*/
const Token* nextArgumentBeforeCreateLinks2() const;

/**
* @return the first token of the next template argument. Does only work on template argument
* lists. Requires that Tokenizer::createLinks2() has been called before.
* Returns 0, if there is no next argument.
* Returns nullptr, if there is no next argument.
*/
const Token* nextTemplateArgument() const;

Expand Down Expand Up @@ -1477,14 +1477,14 @@ class CPPCHECKLIB Token {
return nullptr;

}
Token *astTop() {
RET_NONNULL Token *astTop() {
Token *ret = this;
while (ret->mImpl->mAstParent)
ret = ret->mImpl->mAstParent;
return ret;
}

const Token *astTop() const {
RET_NONNULL const Token *astTop() const {
const Token *ret = this;
while (ret->mImpl->mAstParent)
ret = ret->mImpl->mAstParent;
Expand Down
13 changes: 4 additions & 9 deletions lib/valueflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ static bool isConditionKnown(const Token* tok, bool then)
while (parent && (parent->str() == op || parent->str() == "!" || parent->isCast()))
parent = parent->astParent();
const Token* top = tok->astTop();
if (top && Token::Match(top->previous(), "if|while|for ("))
if (Token::Match(top->previous(), "if|while|for ("))
return parent == top || Token::simpleMatch(parent, ";");
return parent && parent->str() != op;
}
Expand Down Expand Up @@ -2372,7 +2372,7 @@ const Token* ValueFlow::getEndOfExprScope(const Token* tok, const Scope* default
end = varEnd;

const Token* top = var->nameToken()->astTop();
if (top && Token::simpleMatch(top->tokAt(-1), "if (")) { // variable declared in if (...)
if (Token::simpleMatch(top->tokAt(-1), "if (")) { // variable declared in if (...)
const Token* elseTok = top->link()->linkAt(1);
if (Token::simpleMatch(elseTok, "} else {") && tok->scope()->isNestedIn(elseTok->tokAt(2)->scope()))
end = tok->scope()->bodyEnd;
Expand Down Expand Up @@ -4751,8 +4751,6 @@ struct ConditionHandler {
continue;

const Token* top = tok->astTop();
if (!top)
continue;

if (!Token::Match(top->previous(), "if|while|for (") && !Token::Match(tok->astParent(), "&&|%oror%|?|!"))
continue;
Expand Down Expand Up @@ -4927,8 +4925,6 @@ struct ConditionHandler {
const Settings& settings,
const std::set<const Scope*>& skippedFunctions) const {
traverseCondition(symboldatabase, settings, skippedFunctions, [&](const Condition& cond, Token* condTok, const Scope* scope) {
Token* top = condTok->astTop();

const MathLib::bigint path = cond.getPath();
const bool allowKnown = path == 0;

Expand Down Expand Up @@ -5003,8 +4999,7 @@ struct ConditionHandler {
}
}

if (!top)
return;
Token* top = condTok->astTop();

if (top->previous()->isExpandedMacro()) {
for (std::list<ValueFlow::Value>* values : {&thenValues, &elseValues}) {
Expand Down Expand Up @@ -7086,7 +7081,7 @@ static void valueFlowContainerSize(const TokenList& tokenlist,
!Token::Match(nameToken, "%name% ("))
continue;
}
if (nameToken->astTop() && Token::Match(nameToken->astTop()->previous(), "for|while"))
if (Token::Match(nameToken->astTop()->previous(), "for|while"))
known = !isVariableChanged(var, settings);
std::vector<ValueFlow::Value> values{ValueFlow::Value{size}};
values.back().valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;
Expand Down
Loading