[cfe-dev] libclang 3.5 C interface - cannot get to macro definitions/expansions with cursors

Juaristi Álamos, Ander via cfe-dev cfe-dev at lists.llvm.org
Mon Nov 30 04:52:29 PST 2015


Hi all,

I'm writing a libclang-based C application to get information about
functions, variables and macros, and should treat them all equally.

What I need is to be able to parse the macro definitions and expansions
(before they are expanded), as if they were functions.

To test libclang, I've written a sample application that walks over the
AST like this:

    error = clang_parseTranslationUnit2(index, 0, argv, argc, 0, 0,
             CXTranslationUnit_None,
             &tu);
    if (tu) {
        cursor = clang_getTranslationUnitCursor(tu);
        clang_visitChildren(cursor, cx_visit, NULL);
        ...

Where 'cx_visit' is my visitor function, which basically prints the
spelling and start and end offsets of the first child, and returns
CXChildVisit_Continue, so that only immediate siblings are printed. Such
an approach is proposed on [1], where the poster asks for guidance on a
similar problem.

Then I've run my sample application on the following test code,
intentionally omitting the initial #include <stdio.h> so as the output
not to be too noisy:

    int debug;

    #define BAR 20
    #define DEBUG(msg) \
        do { if (debug) printf("%s", msg); } while (0)

    void bar()
    {
        printf("Value of BAR is %d\n", BAR);
    }

    void foobar()
    {
        debug = 1;
        DEBUG("This is a debug test\n");
    }

    int main(int argc, char **argv)
    {
        int foo = 10;

        printf("Value of foo is %d\n", foo);
        bar();
        foobar();

        return 0;
    }

And the output of my sample application is the following:

Element: debug (test.c)[2,1; 2,10]
Element: bar (test.c)[8,1; 11,2]
Element: foobar (test.c)[13,1; 17,2]
Element: main (test.c)[19,1; 28,2]

The parent is the file itself ("test.c"), and those are the first level
siblings. Thus, it looks like the definitions of BAR and DEBUG are being
skipped, or put somewhere else.

What's more, 'cx_visit' explicitly checks for the following CursorKinds:

        cursorKind = clang_getCursorKind(child);
        ...
        switch (cursorKind)
	{
	case CXCursor_PreprocessingDirective:
		printf("[PREPROCESSING DIRECTIVE]");
		break;
	case CXCursor_MacroDefinition:
		printf("[MACRO DEFINITION]");
		break;
	case CXCursor_MacroExpansion:
		printf("[MACRO EXPANSION]");
		break;
	case CXCursor_InclusionDirective:
		printf("[INCLUSION DIRECTIVE]");
		break;
	default:
		break;
	}
And as you can see, any of those strings is ever printed.

If I change my 'cx_visit' callback to return CXChildVisit_Recurse to
walk recursively down all levels, things don't seem to change, because I
cannot see any spelling of the DEBUG macro anywhere, nor of the strings
mentioned above:

    <output trimmed>
    Element: foobar (test.c)[13,1; 17,2]
    Element:  (test.c)[14,1; 17,2]
    Element:  (test.c)[15,5; 15,14]
    Element: debug (test.c)[15,5; 15,10]
    Element:  (test.c)[15,13; 15,14]
    Element:  (test.c)[16,5; 16,36]
    Element:  (test.c)[16,5; 16,36]
    Element:  (test.c)[16,5; 16,36]
    Element: debug (test.c)[16,5; 16,36]
    Element: debug (test.c)[16,5; 16,36]
    Element: printf (test.c)[16,5; 16,36]
    Element: printf (test.c)[16,5; 16,36]
    Element: printf (test.c)[16,5; 16,36]
    Element:  (test.c)[16,5; 16,36]
    Element:  (test.c)[16,5; 16,36]
    Element: "%s" (test.c)[16,5; 16,36]
    Element:  (test.c)[16,11; 16,35]
    Element: "This is a debug test\n" (test.c)[16,11; 16,35]
    Element:  (test.c)[16,5; 16,36]
    <output trimmed>

Finally, I've seen a similar question was raised on this mailing list on
[2]. From that thread, one can infer that libclang lacks an API for
accessing macro information. So you have to use the C++ API, there is no
other way. However, the poster assured that he could at least handle
CXCursor_MacroDefinition, and get the macro name from the cursor
spelling, which is something I haven't been able to achieve so far.

I'd appreciate any guidance, or pointers to more specific information.
Maybe my libclang installation was somehow compiled without support for
walking over macros in the AST? Maybe I'm using a too old (or too new)
version?

I'm on Linux using libclang1-3.5 directly pulled from the Debian stable
repositories.

Regards,
- AJ

[1]http://stackoverflow.com/questions/16786767/obtain-original-unexpanded-macro-text-using-libclang
[2]http://lists.llvm.org/pipermail/cfe-dev/2014-November/040123.html



More information about the cfe-dev mailing list