From 19a8cfd960d8abe59a2b530a7adbab309cf1edc7 Mon Sep 17 00:00:00 2001 From: Pavel Roschin Date: Thu, 6 Feb 2014 12:22:07 +0400 Subject: [PATCH] Library: add new "define" tag This tag will allow to add some preprocessor defs into library. It would be useful to provide more information about libraries implementation details. As example GLib's library include tag was added that helps to detect more memory leaks. --- Makefile | 2 +- cfg/gtk.cfg | 4 ++++ lib/library.cpp | 14 +++++++++++ lib/library.h | 1 + lib/preprocessor.cpp | 7 ++++++ test/testmemleak.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 82 insertions(+), 1 deletion(-) 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;