GNOME Bugzilla – Bug 608921
Preprocessor regression: Macro that are not used in file affect the file
Last modified: 2010-11-22 15:58:02 UTC
Created attachment 152961 [details] Example 1 in newer version of doxygen, all files are preprocessor only once, and already defined macro remain active throughout the run. The attached file DoxyPre.zip demonstrates that a macro not visible in file2.cpp so badly polutes the signatures that Doxygen cannot document a method- The attached file DoxyPre2.zip demonstrattes that a macro not visible in file2.cpp mask the correct method
Created attachment 152962 [details] Example 2
The issue originate in the fact that g_fileDefineDict->clear(); at the begin of preprocessFile() has been commented, and in the fact that readIncludeFile skips all files that are already known Kind Regards Gilles
Describing the issue via zip files is cumbersome for the reader. Therefore is a description of issue 1: Doxyfile contains: INPUT = header1.hpp file1.cpp file2.cpp ENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = YES SEARCH_INCLUDES = YES INCLUDE_PATH = INCLUDE_FILE_PATTERNS = PREDEFINED = "UNUSED(par)=par" EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES header1.hpp contains: /** * \file header1.hpp * define some usefull macros */ /** * \brief Decorate unused parameters in function/method declaration. * * The macro masks the parameter name from real compiler so that the compiler * does not produce warning about the unused paramter. * The doxy configuration file contains the definition * \verbatim PREDEFINED += "UNUSED(p)=p" \endverbatim * so that the parameters are visible to doxygen. This makes it possible to * document them */ #define UNUSED(par) File1.cpp contains: /** * \file file1.cpp * include 1 headers and pollute prepocessor */ #include "header1.hpp" /// \brief polute pre.l #define cat 42 File2.cpp contains: /** * \file file2.cpp * include 1 headers, and some code */ #include "header1.hpp" /** * \brief a test class */ class CTest { public: void methOk(int UNUSED(baz), CTest* UNUSED(foo), char* UNUSED(bar)) ; void methBroken(int UNUSED(cat), CTest* UNUSED(foo), char* UNUSED(bar)) ; }; /** * \brief demonstrate a working usage of the macro UNUSED. * * \param baz The BAZ param * \param foo The FOO param * \param bar The BAR param */ void CTest::methOk(int UNUSED(baz), CTest* UNUSED(foo), char* UNUSED(bar)) { } /** * \brief demonstrate a broken usage of the macro UNUSED. * * \param cat The CAT param. Alas because Doxygen already read * the file file1.cpp it already kows a macro "cat" defined as "42" * The problem is that Doxgen does no longer reset the dictionary of known macro * g_fileDefineDict->clear(); at the begin of preprocessFile() * \param foo The FOO param * \param bar The BAR param */ void CTest::methBroken(int UNUSED(cat), CTest* UNUSED(foo), char* UNUSED(bar)) { } Doxygen runs write to stdout C:/usr/gilbert/doxygen/DoxyPre/file2.cpp:30: Warning: argument 'cat' of command @param is not found in the argument list of CTest::methBroken(int 42, CTest *foo , char *bar) C:/usr/gilbert/doxygen/DoxyPre/file2.cpp:30: Warning: The following parameters o f CTest::methBroken(int 42, CTest *foo, char *bar) are not documented: parameter '42' The generated documentations says: void CTest::methBroken ( int 42, CTest * foo, char * bar ) demonstrate a broken usage of the macro UNUSED. ... Version 1.5.6 did not have the issue
Confirmed. I'll make doxygen check if a macro definition is "in scope" before it is resolved. Should be fixed in the next subversion update.
Hi Dimitri, I already tried to "check if a macro definition is in scope". This is just a small change in pre.l. I maintain a list of header that have been opened since preprocessFile() has been called. and i compare this list with the definition place returned by isDefined(). This attempt however revealed an other flaw in the preprocessor. This time a flaw that is also present in old Doxygen versions: Given /** * \file file1.cpp * * defines a first version of DUMP */ #if defined(DEBUG) || defined(DOXYGEN_MAKE) /** * \brief Dump an integer * * \param p The integer to dump */ # define DUMP(p) printf("%d\n", p) #else # define DUMP(p) #endif //!DEBUG and given /** * \file file2.cpp * * define an other version of dump */ /// Some structure struct Employe { int id; string name; }; #if defined(DEBUG) || defined(DOXYGEN_MAKE) /** * \brief Dump an instance of Employe * * \param p The empoyee instance to dump */ # define DUMP(p) printf("[%d] %s\n", p->id, p->name.c_str()) #else # define DUMP(p) #endif //!DEBUG #if defined(DEBUG) || defined(DOXYGEN_MAKE) /** * \brief Dump a list of Employe * * \param p The list */ # define DUMP_LIST(p) \ for(list<Employe> it(p.begin()), itEnd(p.end(); \ it != itEnd; \ ++it) \ DUMP(*it); #else # define DUMP_LIST(p) #endif //!DEBUG Doxygen generates for file2.cpp the following documentation: #define DUMP_LIST ( p ) Value: for(list<Employe> it(p.begin()), itEnd(p.end(); \ it != itEnd; \ ++it) \ DUMP(*it); Where DUMP has a tooltip saying "Dump an integer", and is a link to the DUMP macro within file1.cpp This is due to the fact that redefinition are ignored in: def=g_fileDefineDict->find(g_defName); if (def==0) // new define { //printf("new define!\n"); g_fileDefineDict->insert(g_defName,newDefine()); } else if (def)// name already exists { //printf("existing define!\n"); //printf("define found\n"); if (def->undef) // undefined name { def->undef = FALSE; def->name = g_defName; def->definition = g_defText.stripWhiteSpace(); def->nargs = g_defArgs; def->fileName = g_yyFileName.copy(); def->lineNr = g_yyLineNr; } else { //printf("Error: define %s is defined more than once!\n",g_defName.data()); } } What i would like to do if my wife was granting time for it would be to replace //printf("Error: define %s is defined more than once!\n",g_defName.data()); with building within "def" a link list of "Define*" and wind over this list in isDefined() (Together with the winding over the "active header" that i already added to isDefined() Kind Regards Gilles
Created attachment 153918 [details] Example for the wrong link I attached my test files that describe this further problem The issue if that if i test def->fileName in isDefined() against the list of headers that have been seen since the begining of preprocessFile() then I find that DUMP has been dedined in file1.cpp, and thus when i process file2.cpp my "fixed" isDefined states that DUMP is not defined. Thus the need to have a link list of all definitions of "DUMP" in this example Kind regards Gilles
This bug was previously marked ASSIGNED, which means it should be fixed in doxygen version 1.6.3. Please verify if this is indeed the case. Reopen the bug if you think it is not fixed and please include any additional information that you think can be relevant.
Hi Dimitri thanks for the quick resolution of the problem described in the attachment 1 [details] and 2. But it seems that you over read the issue described in Gilles [reporter] 2010-02-16 14:00:12 UTC Gilles [reporter] 2010-02-16 14:06:29 UTC When I run 1.6.3 against the third attachment the link in the definition of DUMP_LIST link to the wrong definition; an the tool tip is the title of the wrong definition Can you have a second look? Thanks Gilles
Can you try with the latest subversion snapshot? I see the link now pointing to the right definition.
ping Gilles?
Closing this bug report as no further information has been provided. Please feel free to reopen this bug if you can provide the information asked for. Thanks!