Search code examples
c++windowswinapidoxygensal

Using Microsoft's Source-Code Annotation Language (SAL) with Doxygen?


I am trying to use Doxygen to document some C++ code that uses Microsoft's Source-Code Annotation Language (SAL). However, Doxygen does not parse certain annotation macros, like _Success_, correctly. In the case of the example function annotation, _Success_, Doxygen misinterprets this macro as the function header/prototype.

Take the following example that contains the function annotation marker:

/**
 *    @file
 *    Example with function annotation.
 */

#include <windows.h>
#include <sal.h>

/**
 *    @brief This is a function.
 *    @param i a random variable
 *    @return TRUE on every call.
 */
_Success_(return) // The SAL function annotation.
BOOL function(_In_ int i) {
    return TRUE;
}

With the example above, Doxygen will interpret _Success_() as the function header/prototype and thereby, creates documentation that is absolutely wrong. Here is what the HTML Doxygen output appears like with and without the function annotation:

Comparison with and without function annotation

With the function annotation, Doxygen also says I have documented a parameter variable i that is not part of the list of arguments:

C:/.../Source.cpp:9: warning: argument 'i' of command @param is not found in the argument list of Success(return)

Am I missing a configuration setting in the main Doxygen configuration file?
Or is SAL and Doxygen simply just incompatible?


Solution

  • Ah ha! After some further research, I found a question on Stack Overflow that asked this same question, except it wasn't tagged correctly and did not explicitly say s/he was using "Microsoft's SAL." This is why it took me awhile to find it. (I have updated the corresponding question to correct these missteps.)

    The question's answer references the Doxygen manual section entitled: Preprocessing.

    A typically example where some help from the preprocessor is needed is when dealing with the language extension from Microsoft: __declspec. The same goes for GNU's __attribute__ extension. [...] When nothing is done, doxygen will be confused and see __declspec as some sort of function. [...]

    Therefore, as pertaining to my example above, the settings that need to be configured in the Doxygen configuration file are as follows:

    ENABLE_PREPROCESSING   = YES
    MACRO_EXPANSION        = YES
    EXPAND_ONLY_PREDEF     = YES
    PREDEFINED             = _Success_(x)= \
                             _In_=
    

    Basically, this set of configurations means that the macros defined in the PREDEFINED section will be fully expanded and evaluated "before the preprocessor [has] started." But, these macros will expand to nothing as we provide "nothing" for the definition side of the equation (i.e. format: name=definition). Therefore, they are essentially ignored/removed while Doxygen builds the documentation documents.

    Unfortunately, this does mean that one will need to continue to expand this PREDEFINED list to encapsulate, at least, all the SAL macros used in the source code. A better solution would to encapsulate all the SAL macros in this list, but future proofing is impossible as one will always be late at appending any new macros that are added later on. But, at least, there is a solution!