Skip to content

Commit

Permalink
Merge
Browse files Browse the repository at this point in the history
  • Loading branch information
chrchr-github committed Aug 19, 2023
2 parents 26e4493 + a9dc8bf commit c053c3d
Show file tree
Hide file tree
Showing 16 changed files with 135 additions and 45 deletions.
12 changes: 12 additions & 0 deletions cfg/std.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -6884,6 +6884,18 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
<not-uninit/>
</arg>
</function>
<!-- constexpr bool std::string::starts_with( std::basic_string_view<CharT,Traits> sv ) const noexcept; // since C++20 -->
<!-- constexpr bool starts_with( CharT ch ) const noexcept; // since C++20 -->
<!-- constexpr bool starts_with( const CharT* s ) const; // since C++20 -->
<function name="std::string::startsWith,std::wstring::startsWith,std::string::endsWith,std::wstring::endsWith">
<noreturn>false</noreturn>
<use-retval/>
<returnValue type="bool"/>
<const/>
<arg nr="1" direction="in">
<not-uninit/>
</arg>
</function>
<!-- size_type std::string::copy( CharT* dest, size_type count, size_type pos = 0) const; -->
<!-- size_type std::wstring::copy( CharT* dest, size_type count, size_type pos = 0) const; -->
<function name="std::string::copy,std::wstring::copy">
Expand Down
2 changes: 1 addition & 1 deletion lib/astutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@ std::vector<ValueType> getParentValueTypes(const Token* tok, const Settings* set
const ValueType* vtCont = contTok->valueType();
if (!vtCont->containerTypeToken)
return {};
ValueType vtParent = ValueType::parseDecl(vtCont->containerTypeToken, *settings, true); // TODO: set isCpp
ValueType vtParent = ValueType::parseDecl(vtCont->containerTypeToken, *settings);
return {std::move(vtParent)};
}
if (Token::Match(tok->astParent(), "return|(|{|%assign%") && parent) {
Expand Down
2 changes: 1 addition & 1 deletion lib/checkclass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3228,7 +3228,7 @@ void CheckClass::checkThisUseAfterFree()
for (const Variable &var : classScope->varlist) {
// Find possible "self pointer".. pointer/smartpointer member variable of "self" type.
if (var.valueType() && var.valueType()->smartPointerType != classScope->definedType && var.valueType()->typeScope != classScope) {
const ValueType valueType = ValueType::parseDecl(var.typeStartToken(), *mSettings, true); // this is only called for C++
const ValueType valueType = ValueType::parseDecl(var.typeStartToken(), *mSettings);
if (valueType.smartPointerType != classScope->definedType)
continue;
}
Expand Down
24 changes: 17 additions & 7 deletions lib/checkother.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3647,17 +3647,23 @@ void CheckOther::checkKnownArgument()
const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
for (const Scope *functionScope : symbolDatabase->functionScopes) {
for (const Token *tok = functionScope->bodyStart; tok != functionScope->bodyEnd; tok = tok->next()) {
if (!Token::simpleMatch(tok->astParent(), "("))
if (!tok->hasKnownIntValue())
continue;
if (!Token::Match(tok->astParent()->previous(), "%name%"))
if (Token::Match(tok, "++|--|%assign%"))
continue;
if (Token::Match(tok->astParent()->previous(), "if|while|switch|sizeof"))
if (!Token::Match(tok->astParent(), "(|{|,"))
continue;
if (tok == tok->astParent()->previous())
if (tok->astParent()->isCast())
continue;
if (!tok->hasKnownIntValue())
int argn = -1;
const Token* ftok = getTokenArgumentFunction(tok, argn);
if (!ftok)
continue;
if (tok->tokType() == Token::eIncDecOp)
if (ftok->isCast())
continue;
if (Token::Match(ftok, "if|while|switch|sizeof"))
continue;
if (tok == tok->astParent()->previous())
continue;
if (isConstVarExpression(tok))
continue;
Expand All @@ -3668,6 +3674,10 @@ void CheckOther::checkKnownArgument()
tok2 = tok2->astOperand2();
if (isVariableExpression(tok2))
continue;
if (tok->isComparisonOp() &&
isSameExpression(
mTokenizer->isCPP(), true, tok->astOperand1(), tok->astOperand2(), mSettings->library, true, true))
continue;
// ensure that there is a integer variable in expression with unknown value
std::string varexpr;
bool isVariableExprHidden = false; // Is variable expression explicitly hidden
Expand Down Expand Up @@ -3706,7 +3716,7 @@ void CheckOther::checkKnownArgument()
strTolower(funcname);
if (funcname.find("assert") != std::string::npos)
continue;
knownArgumentError(tok, tok->astParent()->previous(), &tok->values().front(), varexpr, isVariableExprHidden);
knownArgumentError(tok, ftok, &tok->values().front(), varexpr, isVariableExprHidden);
}
}
}
Expand Down
8 changes: 1 addition & 7 deletions lib/checkstring.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,13 +288,7 @@ void CheckString::checkIncorrectStringCompare()
incorrectStringCompareError(tok->next(), "substr", end->strAt(1));
}
}
} else if (Token::Match(tok, "&&|%oror%|( %str%|%char% &&|%oror%|)") && !Token::Match(tok, "( %str%|%char% )")) {
incorrectStringBooleanError(tok->next(), tok->strAt(1));
} else if (Token::Match(tok, "if|while ( %str%|%char% )") && !tok->tokAt(2)->getValue(0)) {
incorrectStringBooleanError(tok->tokAt(2), tok->strAt(2));
} else if (tok->str() == "?" && Token::Match(tok->astOperand1(), "%str%|%char%")) {
incorrectStringBooleanError(tok->astOperand1(), tok->astOperand1()->str());
} else if (Token::Match(tok, "%str%") && isUsedAsBool(tok))
} else if (Token::Match(tok, "%str%|%char%") && isUsedAsBool(tok))
incorrectStringBooleanError(tok, tok->str());
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/checktype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ void CheckType::checkFloatToIntegerOverflow()
while (scope && scope->type != Scope::ScopeType::eLambda && scope->type != Scope::ScopeType::eFunction)
scope = scope->nestedIn;
if (scope && scope->type == Scope::ScopeType::eFunction && scope->function && scope->function->retDef) {
const ValueType &valueType = ValueType::parseDecl(scope->function->retDef, *mSettings, mTokenizer->isCPP());
const ValueType &valueType = ValueType::parseDecl(scope->function->retDef, *mSettings);
vtfloat = tok->astOperand1()->valueType();
checkFloatToIntegerOverflow(tok, &valueType, vtfloat, tok->astOperand1()->values());
}
Expand Down
4 changes: 2 additions & 2 deletions lib/clangimport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ void clangimport::AstNode::setValueType(Token *tok)
if (!decl.front())
break;

const ValueType valueType = ValueType::parseDecl(decl.front(), *mData->mSettings, true); // TODO: set isCpp
const ValueType valueType = ValueType::parseDecl(decl.front(), *mData->mSettings);
if (valueType.type != ValueType::Type::UNKNOWN_TYPE) {
tok->setValueType(new ValueType(valueType));
break;
Expand Down Expand Up @@ -1545,7 +1545,7 @@ static void setValues(const Tokenizer *tokenizer, const SymbolDatabase *symbolDa

for (Token *tok = const_cast<Token*>(tokenizer->tokens()); tok; tok = tok->next()) {
if (Token::simpleMatch(tok, "sizeof (")) {
ValueType vt = ValueType::parseDecl(tok->tokAt(2), *settings, tokenizer->isCPP());
ValueType vt = ValueType::parseDecl(tok->tokAt(2), *settings);
const int sz = vt.typeSize(settings->platform, true);
if (sz <= 0)
continue;
Expand Down
23 changes: 12 additions & 11 deletions lib/symboldatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2214,12 +2214,13 @@ void Variable::evaluate(const Settings* settings)

const Library * const lib = &settings->library;

// TODO: ValueType::parseDecl() is also performing a container lookup
bool isContainer = false;
if (mNameToken)
setFlag(fIsArray, arrayDimensions(settings, isContainer));

if (mTypeStartToken)
setValueType(ValueType::parseDecl(mTypeStartToken,*settings, true)); // TODO: set isCpp
setValueType(ValueType::parseDecl(mTypeStartToken,*settings));

const Token* tok = mTypeStartToken;
while (tok && tok->previous() && tok->previous()->isName())
Expand Down Expand Up @@ -2275,7 +2276,7 @@ void Variable::evaluate(const Settings* settings)
setFlag(fIsClass, !lib->podtype(strtype) && !mTypeStartToken->isStandardType() && !isEnumType() && !isPointer() && !isReference() && strtype != "...");
setFlag(fIsStlType, Token::simpleMatch(mTypeStartToken, "std ::"));
setFlag(fIsStlString, ::isStlStringType(mTypeStartToken));
setFlag(fIsSmartPointer, lib->isSmartPointer(mTypeStartToken));
setFlag(fIsSmartPointer, mTypeStartToken->isCpp() && lib->isSmartPointer(mTypeStartToken));
}
if (mAccess == AccessControl::Argument) {
tok = mNameToken;
Expand Down Expand Up @@ -3558,7 +3559,7 @@ bool Type::isDerivedFrom(const std::string & ancestor) const
bool Variable::arrayDimensions(const Settings* settings, bool& isContainer)
{
isContainer = false;
const Library::Container* container = settings->library.detectContainer(mTypeStartToken);
const Library::Container* container = (mTypeStartToken && mTypeStartToken->isCpp()) ? settings->library.detectContainer(mTypeStartToken) : nullptr;
if (container && container->arrayLike_indexOp && container->size_templateArgNo > 0) {
const Token* tok = Token::findsimplematch(mTypeStartToken, "<");
if (tok) {
Expand Down Expand Up @@ -5653,7 +5654,7 @@ const Function* SymbolDatabase::findFunction(const Token* const tok) const
return tok1->valueType()->typeScope->findFunction(tok, tok1->valueType()->constness == 1);
if (tok1 && Token::Match(tok1->previous(), "%name% (") && tok1->previous()->function() &&
tok1->previous()->function()->retDef) {
ValueType vt = ValueType::parseDecl(tok1->previous()->function()->retDef, mSettings, mIsCpp);
ValueType vt = ValueType::parseDecl(tok1->previous()->function()->retDef, mSettings);
if (vt.typeScope)
return vt.typeScope->findFunction(tok, vt.constness == 1);
} else if (Token::Match(tok1, "%var% .")) {
Expand All @@ -5667,7 +5668,7 @@ const Function* SymbolDatabase::findFunction(const Token* const tok) const
} else if (Token::simpleMatch(tok->previous()->astOperand1(), "(")) {
const Token *castTok = tok->previous()->astOperand1();
if (castTok->isCast()) {
ValueType vt = ValueType::parseDecl(castTok->next(),mSettings, mIsCpp);
ValueType vt = ValueType::parseDecl(castTok->next(),mSettings);
if (vt.typeScope)
return vt.typeScope->findFunction(tok, vt.constness == 1);
}
Expand Down Expand Up @@ -5697,7 +5698,7 @@ const Function* SymbolDatabase::findFunction(const Token* const tok) const
}
// Check for constructor
if (Token::Match(tok, "%name% (|{")) {
ValueType vt = ValueType::parseDecl(tok, mSettings, mIsCpp);
ValueType vt = ValueType::parseDecl(tok, mSettings);
if (vt.typeScope)
return vt.typeScope->findFunction(tok, false);
}
Expand Down Expand Up @@ -6991,7 +6992,7 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to
}

// Construct smart pointer
else if (mSettings.library.isSmartPointer(start)) {
else if (mIsCpp && mSettings.library.isSmartPointer(start)) {
ValueType valuetype;
if (parsedecl(start, &valuetype, mDefaultSignedness, mSettings, mIsCpp)) {
setValueType(tok, valuetype);
Expand Down Expand Up @@ -7066,7 +7067,7 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to
}
}
}
if (tok->astParent() && Token::Match(tok->astOperand1(), "%name%|::")) {
if (mIsCpp && tok->astParent() && Token::Match(tok->astOperand1(), "%name%|::")) {
const Token *typeStartToken = tok->astOperand1();
while (typeStartToken && typeStartToken->str() == "::")
typeStartToken = typeStartToken->astOperand1();
Expand Down Expand Up @@ -7216,7 +7217,7 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to
functionScope = functionScope->nestedIn;
if (functionScope && functionScope->type == Scope::eFunction && functionScope->function &&
functionScope->function->retDef) {
ValueType vt = ValueType::parseDecl(functionScope->function->retDef, mSettings, mIsCpp);
ValueType vt = ValueType::parseDecl(functionScope->function->retDef, mSettings);
setValueType(tok, vt);
if (Token::simpleMatch(tok, "return {"))
setValueType(tok->next(), vt);
Expand Down Expand Up @@ -7314,10 +7315,10 @@ void SymbolDatabase::setValueTypeInTokenList(bool reportDebugWarnings, Token *to
createSymbolDatabaseSetVariablePointers();
}

ValueType ValueType::parseDecl(const Token *type, const Settings &settings, bool isCpp)
ValueType ValueType::parseDecl(const Token *type, const Settings &settings)
{
ValueType vt;
parsedecl(type, &vt, settings.platform.defaultSign == 'u' ? Sign::UNSIGNED : Sign::SIGNED, settings, isCpp);
parsedecl(type, &vt, settings.platform.defaultSign == 'u' ? Sign::UNSIGNED : Sign::SIGNED, settings, type->isCpp());
return vt;
}

Expand Down
2 changes: 1 addition & 1 deletion lib/symboldatabase.h
Original file line number Diff line number Diff line change
Expand Up @@ -1268,7 +1268,7 @@ class CPPCHECKLIB ValueType {
originalTypeName(std::move(otn))
{}

static ValueType parseDecl(const Token *type, const Settings &settings, bool isCpp);
static ValueType parseDecl(const Token *type, const Settings &settings);

static Type typeFromString(const std::string &typestr, bool longType);

Expand Down
31 changes: 28 additions & 3 deletions lib/token.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,13 @@ const std::string &Token::strAt(int index) const
return tok ? tok->mStr : emptyString;
}

static int multiComparePercent(const Token *tok, const char*& haystack, nonneg int varid)
static
#if defined(__GNUC__)
// GCC does not inline this by itself
// need to use the old syntax since the C++11 [[xxx:always_inline]] cannot be used here
inline __attribute__((always_inline))
#endif
int multiComparePercent(const Token *tok, const char*& haystack, nonneg int varid)
{
++haystack;
// Compare only the first character of the string for optimization reasons
Expand Down Expand Up @@ -556,7 +562,12 @@ static int multiComparePercent(const Token *tok, const char*& haystack, nonneg i
return 0xFFFF;
}

int Token::multiCompare(const Token *tok, const char *haystack, nonneg int varid)
static
#if defined(__GNUC__)
// need to use the old syntax since the C++11 [[xxx:always_inline]] cannot be used here
inline __attribute__((always_inline))
#endif
int multiCompareImpl(const Token *tok, const char *haystack, nonneg int varid)
{
const char *needle = tok->str().c_str();
const char *needlePointer = needle;
Expand Down Expand Up @@ -609,6 +620,12 @@ int Token::multiCompare(const Token *tok, const char *haystack, nonneg int varid
return -1;
}

// cppcheck-suppress unusedFunction - used in tests only
int Token::multiCompare(const Token *tok, const char *haystack, nonneg int varid)
{
return multiCompareImpl(tok, haystack, varid);
}

bool Token::simpleMatch(const Token *tok, const char pattern[], size_t pattern_len)
{
if (!tok)
Expand Down Expand Up @@ -730,7 +747,7 @@ bool Token::Match(const Token *tok, const char pattern[], nonneg int varid)

// Parse multi options, such as void|int|char (accept token which is one of these 3)
else {
const int res = multiCompare(tok, p, varid);
const int res = multiCompareImpl(tok, p, varid);
if (res == 0) {
// Empty alternative matches, use the same token on next round
while (*p && *p != ' ')
Expand Down Expand Up @@ -2569,3 +2586,11 @@ Token* findLambdaEndScope(Token* tok)
const Token* findLambdaEndScope(const Token* tok) {
return findLambdaEndScope(const_cast<Token*>(tok));
}

bool Token::isCpp() const
{
if (mTokensFrontBack && mTokensFrontBack->list) {
return mTokensFrontBack->list->isCPP();
}
return true; // assume C++ by default
}
7 changes: 7 additions & 0 deletions lib/token.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ struct TokenImpl {
* The Token class also has other functions for management of token list, matching tokens, etc.
*/
class CPPCHECKLIB Token {
friend class TestToken;

private:
TokensFrontBack* mTokensFrontBack{};

Expand Down Expand Up @@ -788,6 +790,7 @@ class CPPCHECKLIB Token {
return const_cast<Token *>(findmatch(const_cast<const Token *>(startTok), pattern, end, varId));
}

private:
/**
* Needle is build from multiple alternatives. If one of
* them is equal to haystack, return value is 1. If there
Expand All @@ -804,6 +807,7 @@ class CPPCHECKLIB Token {
*/
static int multiCompare(const Token *tok, const char *haystack, nonneg int varid);

public:
nonneg int fileIndex() const {
return mImpl->mFileIndex;
}
Expand Down Expand Up @@ -1480,6 +1484,9 @@ class CPPCHECKLIB Token {
void setTokenDebug(TokenDebug td) {
mImpl->mDebug = td;
}

/** defaults to C++ if it cannot be determined */
bool isCpp() const;
};

Token* findTypeEnd(Token* tok);
Expand Down
Loading

0 comments on commit c053c3d

Please sign in to comment.