Skip to content

Commit

Permalink
Merge branch 'main' into wincomp
Browse files Browse the repository at this point in the history
  • Loading branch information
chrchr-github committed Feb 9, 2024
2 parents 857729c + 503c109 commit eb35d69
Show file tree
Hide file tree
Showing 15 changed files with 143 additions and 46 deletions.
7 changes: 5 additions & 2 deletions addons/misra_9.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,8 +372,11 @@ def unwindAndContinue(self):
while self.token:
if self.token.astParent.astOperand1 == self.token and self.token.astParent.astOperand2:
if self.ed:
self.ed.markAsCurrent()
self.ed = self.ed.getNextValueElement(self.root)
if self.token.astParent.astOperand2.str == "{" and self.ed.isDesignated:
self.popFromStackIfExitElement()
else:
self.ed.markAsCurrent()
self.ed = self.ed.getNextValueElement(self.root)

self.token = self.token.astParent.astOperand2
break
Expand Down
1 change: 1 addition & 0 deletions addons/test/misra/misra-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,7 @@ static void misra_9_array_initializers_with_designators(void) {
char c[2][2] = { [0] = {1, 2, 3} };
char d[1][2] = { [0] = 1 }; // 9.2
char e[2][2] = { { 1, 2 }, [1][0] = {3, 4} }; // 9.2
int e1[2][2] = { [ 0 ][ 1 ] = 0, { 5, 6 } }; // no warning #12419
char f[2] = { [0] = 1, 2 };
char g[2] = { [1] = 2, [0] = 1 };
char h[2][2] = { { 1, 2 }, [1] = { 3 } }; // 9.3
Expand Down
8 changes: 0 additions & 8 deletions cfg/windows.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -7010,14 +7010,6 @@ HFONT CreateFont(
<define name="afx_msg" value=""/>
<define name="AFX_EXT_CLASS" value=""/>
<define name="DEBUG_NEW" value="new"/>
<define name="DECLARE_MESSAGE_MAP()" value=""/>
<define name="DECLARE_DYNAMIC(x)" value=""/>
<define name="DECLARE_DYNAMIC_CLASS(x)" value=""/>
<define name="DECLARE_DYNCREATE(x)" value=""/>
<define name="DECLARE_SERIAL(x)" value=""/>
<define name="IMPLEMENT_DYNAMIC(name,base)" value=""/>
<define name="IMPLEMENT_DYNCREATE(name,base)" value=""/>
<define name="IMPLEMENT_SERIAL(name,base,schema)" value=""/>
<define name="INVALID_HANDLE_VALUE" value="0"/>
<define name="INVALID_SOCKET" value="0"/>
<define name="WINAPI" value="__stdcall"/>
Expand Down
26 changes: 7 additions & 19 deletions lib/checkio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1358,7 +1358,7 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * arg, const Settings *settings,
top = top->astParent();
const ValueType *valuetype = top->argumentType();
if (valuetype && valuetype->type >= ValueType::Type::BOOL) {
typeToken = tempToken = new Token();
typeToken = tempToken = new Token(top);
if (valuetype->pointer && valuetype->constness & 1) {
tempToken->str("const");
tempToken->insertToken("a");
Expand Down Expand Up @@ -1440,9 +1440,7 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * arg, const Settings *settings,
if (function->retType->classScope->enumType)
typeToken = function->retType->classScope->enumType;
else {
tempToken = new Token();
tempToken->fileIndex(tok1->fileIndex());
tempToken->linenr(tok1->linenr());
tempToken = new Token(tok1);
tempToken->str("int");
typeToken = tempToken;
}
Expand All @@ -1461,9 +1459,7 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * arg, const Settings *settings,
if (function->retType->classScope->enumType)
typeToken = function->retType->classScope->enumType;
else {
tempToken = new Token();
tempToken->fileIndex(tok1->fileIndex());
tempToken->linenr(tok1->linenr());
tempToken = new Token(tok1);
tempToken->str("int");
typeToken = tempToken;
}
Expand All @@ -1487,9 +1483,7 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * arg, const Settings *settings,
// check for some common well known functions
else if (isCPP && ((Token::Match(tok1->previous(), "%var% . size|empty|c_str ( ) [,)]") && isStdContainer(tok1->previous())) ||
(Token::Match(tok1->previous(), "] . size|empty|c_str ( ) [,)]") && isStdContainer(tok1->previous()->link()->previous())))) {
tempToken = new Token();
tempToken->fileIndex(tok1->fileIndex());
tempToken->linenr(tok1->linenr());
tempToken = new Token(tok1);
if (tok1->next()->str() == "size") {
// size_t is platform dependent
if (settings->platform.sizeof_size_t == 8) {
Expand Down Expand Up @@ -1548,9 +1542,7 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * arg, const Settings *settings,
if (variableInfo->type() && variableInfo->type()->classScope && variableInfo->type()->classScope->enumType)
typeToken = variableInfo->type()->classScope->enumType;
else {
tempToken = new Token();
tempToken->fileIndex(tok1->fileIndex());
tempToken->linenr(tok1->linenr());
tempToken = new Token(tok1);
tempToken->str("int");
typeToken = tempToken;
}
Expand Down Expand Up @@ -1588,9 +1580,7 @@ bool CheckIO::ArgumentInfo::isStdVectorOrString()
return true;
}
if (variableInfo->isStlType(stl_string)) {
tempToken = new Token();
tempToken->fileIndex(variableInfo->typeStartToken()->fileIndex());
tempToken->linenr(variableInfo->typeStartToken()->linenr());
tempToken = new Token(variableInfo->typeStartToken());
if (variableInfo->typeStartToken()->strAt(2) == "string")
tempToken->str("char");
else
Expand All @@ -1608,9 +1598,7 @@ bool CheckIO::ArgumentInfo::isStdVectorOrString()
return true;
}
if (Token::Match(nameTok, "std :: string|wstring")) {
tempToken = new Token();
tempToken->fileIndex(variableInfo->typeStartToken()->fileIndex());
tempToken->linenr(variableInfo->typeStartToken()->linenr());
tempToken = new Token(variableInfo->typeStartToken());
if (nameTok->strAt(2) == "string")
tempToken->str("char");
else
Expand Down
30 changes: 24 additions & 6 deletions lib/checkstl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -686,11 +686,19 @@ void CheckStl::sameIteratorExpressionError(const Token *tok)
reportError(tok, Severity::style, "sameIteratorExpression", "Same iterators expression are used for algorithm.", CWE664, Certainty::normal);
}

static const Token* getAddressContainer(const Token* tok)
static std::vector<const Token*> getAddressContainer(const Token* tok)
{
if (Token::simpleMatch(tok, "[") && tok->astOperand1())
return tok->astOperand1();
return tok;
return { tok->astOperand1() };
std::vector<ValueFlow::Value> values = ValueFlow::getLifetimeObjValues(tok, /*inconclusive*/ false);
std::vector<const Token*> res;
for (const auto& v : values) {
if (v.tokvalue)
res.emplace_back(v.tokvalue);
}
if (res.empty())
res.emplace_back(tok);
return res;
}

static bool isSameIteratorContainerExpression(const Token* tok1,
Expand All @@ -701,10 +709,18 @@ static bool isSameIteratorContainerExpression(const Token* tok1,
if (isSameExpression(true, false, tok1, tok2, library, false, false)) {
return !astIsContainerOwned(tok1) || !isTemporary(true, tok1, &library);
}
if (kind == ValueFlow::Value::LifetimeKind::Address) {
return isSameExpression(true, false, getAddressContainer(tok1), getAddressContainer(tok2), library, false, false);
if (astContainerYield(tok2) == Library::Container::Yield::ITEM)
return true;
if (kind == ValueFlow::Value::LifetimeKind::Address || kind == ValueFlow::Value::LifetimeKind::Iterator) {
const auto address1 = getAddressContainer(tok1);
const auto address2 = getAddressContainer(tok2);
return std::any_of(address1.begin(), address1.end(), [&](const Token* tok1) {
return std::any_of(address2.begin(), address2.end(), [&](const Token* tok2) {
return isSameExpression(true, false, tok1, tok2, library, false, false);
});
});
}
return astContainerYield(tok2) == Library::Container::Yield::ITEM;
return false;
}

static ValueFlow::Value getLifetimeIteratorValue(const Token* tok, MathLib::bigint path = 0)
Expand Down Expand Up @@ -866,6 +882,8 @@ void CheckStl::mismatchingContainerIterator()
ValueFlow::Value val = getLifetimeIteratorValue(iterTok);
if (!val.tokvalue)
continue;
if (!val.isKnown() && Token::simpleMatch(val.tokvalue->astParent(), ":"))
continue;
if (val.lifetimeKind != ValueFlow::Value::LifetimeKind::Iterator)
continue;
if (iterTok->str() == "*" && iterTok->astOperand1()->valueType() && iterTok->astOperand1()->valueType()->type == ValueType::ITERATOR)
Expand Down
19 changes: 15 additions & 4 deletions lib/token.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,23 @@ namespace {

const std::list<ValueFlow::Value> TokenImpl::mEmptyValueList;

Token::Token()
: Token(static_cast<TokensFrontBack*>(nullptr))
{}

Token::Token(TokensFrontBack *tokensFrontBack) :
mTokensFrontBack(tokensFrontBack)
{
mImpl = new TokenImpl();
}

Token::Token(const Token* tok)
: Token(const_cast<Token*>(tok)->mTokensFrontBack)
{
fileIndex(tok->fileIndex());
linenr(tok->linenr());
}

Token::~Token()
{
delete mImpl;
Expand Down Expand Up @@ -139,7 +150,7 @@ void Token::update_property_info()
else if (std::isalpha((unsigned char)mStr[0]) || mStr[0] == '_' || mStr[0] == '$') { // Name
if (mImpl->mVarId)
tokType(eVariable);
else if (mTokensFrontBack && mTokensFrontBack->list && mTokensFrontBack->list->isKeyword(mStr))
else if (mTokensFrontBack && mTokensFrontBack->list.isKeyword(mStr))
tokType(eKeyword);
else if (baseKeywords.count(mStr) > 0)
tokType(eKeyword);
Expand Down Expand Up @@ -1809,7 +1820,7 @@ void Token::printValueFlow(bool xml, std::ostream &out) const
else {
if (fileIndex != tok->fileIndex()) {
outs += "File ";
outs += tok->mTokensFrontBack->list->getFiles()[tok->fileIndex()];
outs += tok->mTokensFrontBack->list.getFiles()[tok->fileIndex()];
outs += '\n';
line = 0;
}
Expand Down Expand Up @@ -2738,8 +2749,8 @@ const Token* findLambdaEndScope(const Token* tok) {

bool Token::isCpp() const
{
if (mTokensFrontBack && mTokensFrontBack->list) {
return mTokensFrontBack->list->isCPP();
if (mTokensFrontBack) {
return mTokensFrontBack->list.isCPP();
}
return true; // assume C++ by default
}
7 changes: 6 additions & 1 deletion lib/token.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ class CPPCHECKLIB Token {
friend class TestToken;

private:
// for usage in TestToken only
Token();

TokensFrontBack* mTokensFrontBack{};

public:
Expand All @@ -168,7 +171,9 @@ class CPPCHECKLIB Token {
eNone
};

explicit Token(TokensFrontBack *tokensFrontBack = nullptr);
explicit Token(TokensFrontBack *tokensFrontBack);
// for usage in CheckIO::ArgumentInfo only
explicit Token(const Token *tok);
~Token();

ConstTokenRange until(const Token * t) const;
Expand Down
6 changes: 3 additions & 3 deletions lib/tokenlist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@
static constexpr int AST_MAX_DEPTH = 150;


TokenList::TokenList(const Settings* settings) :
mSettings(settings)
TokenList::TokenList(const Settings* settings)
: mTokensFrontBack(*this)
, mSettings(settings)
{
mTokensFrontBack.list = this;
if (mSettings && (mSettings->enforcedLang != Standards::Language::None)) {
mLang = mSettings->enforcedLang;
}
Expand Down
3 changes: 2 additions & 1 deletion lib/tokenlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,10 @@ namespace simplecpp {
* @brief This struct stores pointers to the front and back tokens of the list this token is in.
*/
struct TokensFrontBack {
explicit TokensFrontBack(const TokenList& list) : list(list) {}
Token *front{};
Token* back{};
const TokenList* list{};
const TokenList& list;
};

class CPPCHECKLIB TokenList {
Expand Down
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ if (BUILD_TESTS)
add_cfg(libcurl.c)
add_cfg(libsigc++.cpp)
add_cfg(lua.c)
add_cfg(mfc.cpp)
add_cfg(opencv2.cpp)
add_cfg(openmp.c)
add_cfg(openssl.c)
Expand Down
16 changes: 16 additions & 0 deletions test/cfg/mfc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

// Test library configuration for mfc.cfg

#include <afxwin.h>


class MyClass : public CObject {
DECLARE_DYNAMIC(MyClass)
DECLARE_DYNCREATE(MyClass)
DECLARE_SERIAL(MyClass)
public:
MyClass() {}
};
IMPLEMENT_DYNAMIC(MyClass, CObject)
IMPLEMENT_DYNCREATE(MyClass, CObject)
IMPLEMENT_SERIAL(MyClass,CObject, 42)
10 changes: 10 additions & 0 deletions test/cfg/runtests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ function windows_fn {
true
}

# mfc.cpp
function mfc_fn {
# TODO: Add syntax check
true
}

# wxwidgets.cpp
function wxwidgets_fn {
# TODO: get rid of the error enabling/disabling?
Expand Down Expand Up @@ -480,6 +486,10 @@ function check_file {
lua_fn
${CPPCHECK} ${CPPCHECK_OPT} --library=$lib ${DIR}$f
;;
mfc.cpp)
mfc_fn
${CPPCHECK} ${CPPCHECK_OPT} --platform=win64 --library=$lib ${DIR}$f
;;
opencv2.cpp)
# TODO: "opencv.pc" is not commonly available in distros
#opencv2_fn
Expand Down
4 changes: 4 additions & 0 deletions test/testlibrary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1076,6 +1076,10 @@ class TestLibrary : public TestFixture {
const Settings s = settingsBuilder().library("std.cfg").library("microsoft_sal.cfg").build();
ASSERT_EQUALS(s.library.defines.empty(), false);
}
{
const Settings s = settingsBuilder().library("std.cfg").library("windows.cfg").library("mfc.cfg").build();
ASSERT_EQUALS(s.library.defines.empty(), false);
}
}
};

Expand Down
45 changes: 45 additions & 0 deletions test/teststl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2134,6 +2134,51 @@ class TestStl : public TestFixture {
"}\n");
ASSERT_EQUALS("", errout.str());

// #11093
check("struct S {\n"
" std::vector<int> v1, v2;\n"
" void f(bool b) {\n"
" std::vector<int>& v = b ? v1 : v2;\n"
" v.erase(v.begin());\n"
" }\n"
"};\n");
ASSERT_EQUALS("", errout.str());

// #12377
check("void f(bool b) {\n"
" std::vector<int> *pv;\n"
" if (b) {\n"
" std::vector<int>& r = get1();\n"
" pv = &r;\n"
" }\n"
" else {\n"
" std::vector<int>& r = get2();\n"
" pv = &r;\n"
" }\n"
" std::vector<int>::iterator it = pv->begin();\n"
" it = pv->erase(it, it + 2);\n"
"}\n");
ASSERT_EQUALS("", errout.str());

check("struct S {\n"
" std::vector<int> v;\n"
" void f() {\n"
" std::vector<int>* p = &v;\n"
" p->insert(std::find(p->begin(), p->end(), 0), 1);\n"
" }\n"
"};\n");
ASSERT_EQUALS("", errout.str());

check("struct S {\n"
" std::vector<int> v;\n"
" void f(int i) {\n"
" std::vector<int>* p = &v;\n"
" if (p->size() > i)\n"
" p->erase(p->begin() + i, p->end());\n"
" }\n"
"};\n");
ASSERT_EQUALS("", errout.str());

// #11067
check("struct S {\n"
" std::vector<int> v;\n"
Expand Down
6 changes: 4 additions & 2 deletions test/testtoken.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,8 @@ class TestToken : public TestFixture {
}

void deleteLast() const {
TokensFrontBack listEnds;
TokenList list(nullptr);
TokensFrontBack listEnds(list);
Token ** const tokensBack = &(listEnds.back);
Token tok(&listEnds);
tok.insertToken("aba");
Expand All @@ -492,7 +493,8 @@ class TestToken : public TestFixture {
}

void deleteFirst() const {
TokensFrontBack listEnds;
TokenList list(nullptr);
TokensFrontBack listEnds(list);
Token ** const tokensFront = &(listEnds.front);
Token tok(&listEnds);

Expand Down

0 comments on commit eb35d69

Please sign in to comment.