Skip to content

Commit

Permalink
Merge branch 'main' into chr_Fix12690
Browse files Browse the repository at this point in the history
  • Loading branch information
chrchr-github committed May 1, 2024
2 parents edc7c1b + 858b5ea commit 56207c8
Show file tree
Hide file tree
Showing 17 changed files with 140 additions and 27 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/CI-unixish-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ jobs:

strategy:
matrix:
image: ["ubuntu:16.04", "ubuntu:18.04", "ubuntu:23.10"]
image: ["ubuntu:16.04", "ubuntu:18.04", "ubuntu:24.04"]
include:
- build_gui: false
- image: "ubuntu:23.10"
- image: "ubuntu:24.04"
build_gui: true
fail-fast: false # Prefer quick result

Expand Down Expand Up @@ -92,7 +92,7 @@ jobs:

strategy:
matrix:
image: ["ubuntu:16.04", "ubuntu:18.04", "ubuntu:23.10"]
image: ["ubuntu:16.04", "ubuntu:18.04", "ubuntu:24.04"]
fail-fast: false # Prefer quick result

runs-on: ubuntu-22.04
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ $(libcppdir)/check.o: lib/check.cpp lib/addoninfo.h lib/check.h lib/color.h lib/
$(libcppdir)/check64bit.o: lib/check64bit.cpp lib/addoninfo.h lib/check.h lib/check64bit.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/check64bit.cpp

$(libcppdir)/checkassert.o: lib/checkassert.cpp lib/addoninfo.h lib/check.h lib/checkassert.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h
$(libcppdir)/checkassert.o: lib/checkassert.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkassert.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkassert.cpp

$(libcppdir)/checkautovariables.o: lib/checkautovariables.cpp lib/addoninfo.h lib/astutils.h lib/check.h lib/checkautovariables.h lib/config.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h
Expand Down
1 change: 1 addition & 0 deletions cfg/gtk.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -4112,6 +4112,7 @@
<!-- int g_strcmp0 (const char *str1, const char *str2); -->
<function name="g_strcmp0">
<leak-ignore/>
<pure/>
<noreturn>false</noreturn>
<returnValue type="int"/>
<use-retval/>
Expand Down
36 changes: 36 additions & 0 deletions cfg/kde.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,40 @@
<not-uninit/>
</arg>
</function>
<!-- QString i18n(const char*) -->
<!-- QString xi18n(const char*) -->
<function name="i18n,xi18n">
<noreturn>false</noreturn>
<pure/>
<leak-ignore/>
<returnValue type="QString"/>
<arg nr="1" direction="in"/>
</function>
<!-- KLocalizedString ki18n(const char*) -->
<function name="ki18n">
<noreturn>false</noreturn>
<pure/>
<leak-ignore/>
<returnValue type="KLocalizedString"/>
<arg nr="1" direction="in"/>
</function>
<!-- QString i18nc(const char*, const char*) -->
<!-- QString xi18nc(const char*, const char*) -->
<function name="i18nc,xi18nc">
<noreturn>false</noreturn>
<pure/>
<leak-ignore/>
<returnValue type="QString"/>
<arg nr="1" direction="in"/>
<arg nr="2" direction="in"/>
</function>
<!-- KLocalizedString ki18nc(const char*, const char*) -->
<function name="ki18nc">
<noreturn>false</noreturn>
<pure/>
<leak-ignore/>
<returnValue type="KLocalizedString"/>
<arg nr="1" direction="in"/>
<arg nr="2" direction="in"/>
</function>
</def>
15 changes: 14 additions & 1 deletion lib/checkassert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include "checkassert.h"

#include "astutils.h"
#include "errortypes.h"
#include "settings.h"
#include "symboldatabase.h"
Expand Down Expand Up @@ -57,8 +58,20 @@ void CheckAssert::assertWithSideEffects()

checkVariableAssignment(tmp, tok->scope());

if (tmp->tokType() != Token::eFunction)
if (tmp->tokType() != Token::eFunction) {
if (const Library::Function* f = mSettings->library.getFunction(tmp)) {
if (f->isconst || f->ispure)
continue;
if (Library::getContainerYield(tmp->next()) != Library::Container::Yield::NO_YIELD) // bailout, assume read access
continue;
if (std::any_of(f->argumentChecks.begin(), f->argumentChecks.end(), [](const std::pair<int, Library::ArgumentChecks>& ac) {
return ac.second.iteratorInfo.container > 0; // bailout, takes iterators -> assume read access
}))
continue;
sideEffectInAssertError(tmp, mSettings->library.getFunctionName(tmp));
}
continue;
}

const Function* f = tmp->function();
const Scope* scope = f->functionScope;
Expand Down
16 changes: 16 additions & 0 deletions lib/library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1266,6 +1266,22 @@ bool Library::isContainerYield(const Token * const cond, Library::Container::Yie
return false;
}

Library::Container::Yield Library::getContainerYield(const Token* const cond)
{
if (Token::simpleMatch(cond, "(")) {
const Token* tok = cond->astOperand1();
if (tok && tok->str() == ".") {
if (tok->astOperand1() && tok->astOperand1()->valueType()) {
if (const Library::Container *container = tok->astOperand1()->valueType()->container) {
if (tok->astOperand2())
return container->getYield(tok->astOperand2()->str());
}
}
}
}
return Library::Container::Yield::NO_YIELD;
}

// returns true if ftok is not a library function
bool Library::isNotLibraryFunction(const Token *ftok) const
{
Expand Down
5 changes: 3 additions & 2 deletions lib/library.h
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,9 @@ class CPPCHECKLIB Library {
const Token* getContainerFromYield(const Token* tok, Container::Yield yield) const;
const Token* getContainerFromAction(const Token* tok, Container::Action action) const;

static bool isContainerYield(const Token* const cond, Library::Container::Yield y, const std::string& fallback = emptyString);
static Library::Container::Yield getContainerYield(const Token* const cond);

bool isreflection(const std::string &token) const {
return mReflection.find(token) != mReflection.end();
}
Expand Down Expand Up @@ -496,8 +499,6 @@ class CPPCHECKLIB Library {
*/
std::string getFunctionName(const Token *ftok) const;

static bool isContainerYield(const Token * const cond, Library::Container::Yield y, const std::string& fallback=emptyString);

/** Suppress/check a type */
enum class TypeCheck { def,
check,
Expand Down
15 changes: 10 additions & 5 deletions lib/tokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8674,8 +8674,6 @@ void Tokenizer::findGarbageCode() const
if (Token::Match(tok->next(), ")|]|>|%assign%|%or%|%oror%|==|!=|/|>=|<=|&&"))
syntaxError(tok);
}
if ((!isCPP() || !Token::simpleMatch(tok->previous(), "operator")) && Token::Match(tok, "[,;] ,"))
syntaxError(tok);
if (Token::simpleMatch(tok, ".") &&
!Token::simpleMatch(tok->previous(), ".") &&
!Token::simpleMatch(tok->next(), ".") &&
Expand Down Expand Up @@ -8703,22 +8701,29 @@ void Tokenizer::findGarbageCode() const
syntaxError(tok);
if (Token::Match(tok, "! %comp%"))
syntaxError(tok);
if (Token::Match(tok, "] %name%") && (!isCPP() || !(tok->tokAt(-1) && Token::simpleMatch(tok->tokAt(-2), "delete ["))))
syntaxError(tok);
if (Token::Match(tok, "] %name%") && (!isCPP() || !(tok->tokAt(-1) && Token::simpleMatch(tok->tokAt(-2), "delete [")))) {
if (tok->next()->isUpperCaseName())
unknownMacroError(tok->next());
else
syntaxError(tok);
}

if (tok->link() && Token::Match(tok, "[([]") && (!tok->tokAt(-1) || !tok->tokAt(-1)->isControlFlowKeyword())) {
const Token* const end = tok->link();
for (const Token* inner = tok->next(); inner != end; inner = inner->next()) {
if (inner->str() == "{")
inner = inner->link();
else if (inner->str() == ";") {
else if (inner->str() == ";" || (Token::simpleMatch(inner, ", ,") && (!isCPP() || !Token::simpleMatch(inner->previous(), "operator")))) {
if (tok->tokAt(-1) && tok->tokAt(-1)->isUpperCaseName())
unknownMacroError(tok->tokAt(-1));
else
syntaxError(inner);
}
}
}

if ((!isCPP() || !Token::simpleMatch(tok->previous(), "operator")) && Token::Match(tok, "[,;] ,"))
syntaxError(tok);
if (tok->str() == "typedef") {
for (const Token* tok2 = tok->next(); tok2 && tok2->str() != ";"; tok2 = tok2->next()) {
if (!tok2->next() || tok2->isControlFlowKeyword() || Token::Match(tok2, "typedef|static|."))
Expand Down
2 changes: 1 addition & 1 deletion oss-fuzz/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ $(libcppdir)/check.o: ../lib/check.cpp ../lib/addoninfo.h ../lib/check.h ../lib/
$(libcppdir)/check64bit.o: ../lib/check64bit.cpp ../lib/addoninfo.h ../lib/check.h ../lib/check64bit.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/settings.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h
$(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/check64bit.cpp

$(libcppdir)/checkassert.o: ../lib/checkassert.cpp ../lib/addoninfo.h ../lib/check.h ../lib/checkassert.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/settings.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h
$(libcppdir)/checkassert.o: ../lib/checkassert.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkassert.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h
$(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/checkassert.cpp

$(libcppdir)/checkautovariables.o: ../lib/checkautovariables.cpp ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkautovariables.h ../lib/config.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/platform.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/vfvalue.h
Expand Down
1 change: 1 addition & 0 deletions test/cfg/gtk.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ void validCode(int argInt, GHashTableIter * hash_table_iter, GHashTable * hash_t
// NULL is handled graciously
char* str = g_strdup(NULL);
if (g_strcmp0(str, NULL) || g_strcmp0(NULL, str))
// cppcheck-suppress valueFlowBailout // TODO: caused by <pure/>?
printf("%s", str);
g_free(str);
}
Expand Down
11 changes: 11 additions & 0 deletions test/cfg/kde.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <cstdio>
#include <KDE/KGlobal>
#include <KDE/KConfigGroup>
#include <klocalizedstring.h>

class k_global_static_testclass1 {};
K_GLOBAL_STATIC(k_global_static_testclass1, k_global_static_testinstance1);
Expand All @@ -30,3 +31,13 @@ void ignoredReturnValue(const KConfigGroup& cfgGroup)
// cppcheck-suppress ignoredReturnValue
cfgGroup.readEntry("test");
}

void i18n_test()
{
(void)i18n("Text");
(void)xi18n("Text");
(void)ki18n("Text");
(void)i18nc("Text", "Context");
(void)xi18nc("Text", "Context");
(void)ki18nc("Text", "Context");
}
6 changes: 6 additions & 0 deletions test/cfg/std.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5016,3 +5016,9 @@ void eraseIteratorOutOfBounds_std_deque(std::deque<int>& x) // #8690
// cppcheck-suppress eraseIteratorOutOfBounds
x.erase(x.end());
}

void assertWithSideEffect_system()
{
// cppcheck-suppress [assertWithSideEffect,checkLibraryNoReturn] // TODO: #8329
assert(std::system("abc"));
}
9 changes: 9 additions & 0 deletions test/testassert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,15 @@ class TestAssert : public TestFixture {
" assert(empty());\n"
"}");
ASSERT_EQUALS("", errout_str());

check("struct S {\n" // #4811
" void f() const;\n"
" bool g(std::ostream& os = std::cerr) const;\n"
"};\n"
"void S::f() const {\n"
" assert(g());\n"
"}\n");
ASSERT_EQUALS("", errout_str());
}

void memberFunctionCallInAssert() {
Expand Down
2 changes: 1 addition & 1 deletion test/testgarbage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1213,7 +1213,7 @@ class TestGarbage : public TestFixture {
" typedef S0 b[][1][1] != 0\n"
"};\n"
"b[K][0] S0 b[][1][1] != 4{ 0 };\n"
"b[0][0]"), SYNTAX);
"b[0][0]"), UNKNOWN_MACRO);
}

void garbageCode149() { // #7085
Expand Down
8 changes: 8 additions & 0 deletions test/testtokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7133,6 +7133,14 @@ class TestTokenizer : public TestFixture {
InternalError,
"There is an unknown macro here somewhere. Configuration is required. If MACRO is a macro then please configure it.");

ASSERT_THROW_EQUALS(tokenizeAndStringify("struct S { int a[2] PACKED; };\n"),
InternalError,
"There is an unknown macro here somewhere. Configuration is required. If PACKED is a macro then please configure it.");

ASSERT_THROW_EQUALS(tokenizeAndStringify("MACRO(a, b,,)\n"),
InternalError,
"There is an unknown macro here somewhere. Configuration is required. If MACRO is a macro then please configure it.");

ASSERT_THROW_INTERNAL(tokenizeAndStringify("{ for (()()) }"), SYNTAX); // #11643

ASSERT_NO_THROW(tokenizeAndStringify("S* g = ::new(ptr) S();")); // #12552
Expand Down
Loading

0 comments on commit 56207c8

Please sign in to comment.