diff --git a/Makefile b/Makefile index 17880bf29..60fe8edf6 100644 --- a/Makefile +++ b/Makefile @@ -452,7 +452,7 @@ test/testlibrary.o: test/testlibrary.cpp lib/library.h lib/config.h lib/path.h l test/testmathlib.o: test/testmathlib.cpp lib/mathlib.h lib/config.h test/testsuite.h lib/errorlogger.h lib/suppressions.h test/redirect.h lib/library.h lib/path.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CFG) $(CXXFLAGS) -std=c++0x -c -o test/testmathlib.o test/testmathlib.cpp -test/testmemleak.o: test/testmemleak.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkmemoryleak.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/settings.h lib/library.h lib/path.h lib/standards.h lib/timer.h test/testsuite.h test/redirect.h lib/symboldatabase.h +test/testmemleak.o: test/testmemleak.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkmemoryleak.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/settings.h lib/library.h lib/path.h lib/standards.h lib/timer.h test/testsuite.h test/redirect.h lib/symboldatabase.h lib/preprocessor.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CFG) $(CXXFLAGS) -std=c++0x -c -o test/testmemleak.o test/testmemleak.cpp test/testnonreentrantfunctions.o: test/testnonreentrantfunctions.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checknonreentrantfunctions.h lib/check.h lib/token.h lib/valueflow.h lib/mathlib.h lib/settings.h lib/library.h lib/path.h lib/standards.h lib/timer.h test/testsuite.h test/redirect.h diff --git a/cfg/gtk.cfg b/cfg/gtk.cfg index 4fa9044e1..5071aa3a7 100644 --- a/cfg/gtk.cfg +++ b/cfg/gtk.cfg @@ -1,6 +1,10 @@ + + + + g_thread_new g_thread_try_new diff --git a/lib/library.cpp b/lib/library.cpp index 61270e35b..5711d8296 100644 --- a/lib/library.cpp +++ b/lib/library.cpp @@ -127,6 +127,20 @@ bool Library::load(const tinyxml2::XMLDocument &doc) } } + else if (strcmp(node->Name(),"define")==0) { + const char *name = node->Attribute("name"); + if (name == NULL) + return false; + const char *value = node->Attribute("value"); + if (value == NULL) + return false; + defines.push_back(std::string("#define ") + + name + + " " + + value + + "\n"); + } + else if (strcmp(node->Name(),"function")==0) { const char *name = node->Attribute("name"); if (name == NULL) diff --git a/lib/library.h b/lib/library.h index 475e7cf3a..95bef7fb1 100644 --- a/lib/library.h +++ b/lib/library.h @@ -269,6 +269,7 @@ public: } std::set returnuninitdata; + std::vector defines; // to provide some library defines private: class ExportedFunctions { diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index ccd0491e1..6fe72091b 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -994,6 +994,13 @@ void Preprocessor::preprocess(std::istream &srcCodeStream, std::string &processe "#endfile\n" ; } + + for (std::vector::iterator it = _settings->library.defines.begin(); + it != _settings->library.defines.end(); + ++it) + { + forcedIncludes += *it; + } } if (!forcedIncludes.empty()) { diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index a80f3486e..63a94d045 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -23,6 +23,7 @@ #include "checkmemoryleak.h" #include "testsuite.h" #include "symboldatabase.h" +#include "preprocessor.h" #include extern std::ostringstream errout; @@ -6273,3 +6274,57 @@ private: } }; REGISTER_TEST(TestMemleakNoVar) + + + + + +class TestMemleakGLib : public TestFixture { +public: + TestMemleakGLib() : TestFixture("TestMemleakGLib") { + } + +private: + void check(const char code[]) { + // Clear the error buffer.. + errout.str(""); + + Settings settings; + LOAD_LIB("gtk.cfg"); + settings.library = _lib; + + // Preprocess... + Preprocessor preprocessor(&settings, this); + std::istringstream istrpreproc(code); + std::map actual; + preprocessor.preprocess(istrpreproc, actual, "test.c"); + + // Tokenize.. + Tokenizer tokenizer(&settings, this); + std::istringstream istr(actual[""]); + tokenizer.tokenize(istr, "test.c"); + tokenizer.simplifyTokenList2(); + + // Check for memory leaks.. + CheckMemoryLeakInFunction checkMemoryLeak(&tokenizer, &settings, this); + checkMemoryLeak.checkReallocUsage(); + checkMemoryLeak.check(); + } + + void run() { + TEST_CASE(glib1); + } + + void glib1() { + check("void f(gchar *_a, gchar *_b) {" + " g_return_if_fail(_a);" + " gchar *a = g_strdup(_a);" + " g_return_if_fail(_b);" + " gchar *b = g_strdup(_b);" + " g_free(a);" + " g_free(b);" + "}"); + ASSERT_EQUALS("[test.c:1]: (error) Memory leak: a\n", errout.str()); + } +}; +static TestMemleakGLib testMemleakGLib;