[cfe-dev] clang_parseTranslationUnit2(), "true", and libclang's header search path

W. Michael Petullo via cfe-dev cfe-dev at lists.llvm.org
Sat Jun 3 04:48:18 PDT 2017


I am writing a program which parses other programs written in C. When
I run my program, I find that it fails to find some key system headers
such as stdbool.h. When "true" is present in the parsed program, the
AST appears to be incomplete. When I replace "true" with "1" in the
parsed program, the AST is complete.

I have written a minimal example which follows at the end of this email. 

The "good" input program is:

1  #include <stdbool.h>
2  #include <stdio.h>
3
4  int
5  main(int argc, char *argv[])
6  {
7          while (1) {
8                  printf("Hello, world!\n");
9          }
10 }

For this, the attached program produces:

[...]
LINE 5
LINE 5
LINE 5
LINE 6
LINE 7
LINE 7
LINE 7
LINE 8
LINE 8
LINE 8
LINE 8
LINE 8
LINE 8
DONE

The "bad" input program is:

1  #include <stdbool.h>
2  #include <stdio.h>
3
4  int
5  main(int argc, char *argv[])
6  {
7          while (true) {
8                  printf("Hello, world!\n");
9          }
10  }

For this, the attached program produces:

[...]
LINE 5
LINE 5
LINE 5
LINE 6
DONE

All of this appears to follow from my program failing to find stdbool.h. I
used strace to discover that libclang seems to search

	/usr/local/include/,
	/usr/include/, and
	/include/

but not

	/usr/lib64/clang/3.9.1/include/.

The last directory is where clang installed its headers, so I am
surprised that libclang does not look there.

Is the expectation that I discover /usr/lib64/clang/3.9.1/include/
and pass -I/usr/lib64/clang/3.9.1/include/ to my program?

Why does libclang not search clang's header directory by default?


Here is the program:

#include <clang-c/Index.h>
#include <stdio.h>
#include <stdlib.h>

const char *program;
const char *filename;

void
usage(const char *program)
{
	fprintf(stderr, "usage: %s FILE.C\n", program);
	exit(EXIT_FAILURE);
}

enum CXChildVisitResult
visit_children_cb(CXCursor cursor,
                  CXCursor parent,
                  CXClientData client_data)
{
	CXFile file;
        unsigned int line, column, offset;
	unsigned int level = *(unsigned int *) client_data;
	unsigned int next = level + 1;

	clang_getSpellingLocation(clang_getCursorLocation(cursor),
                                 &file,
                                 &line,
                                 &column,
                                &offset);
	printf("LINE %d\n", line);

	clang_visitChildren(cursor, visit_children_cb, &next);

	return CXChildVisit_Continue;
}

int
main(int argc, const char * const* argv)
{
	unsigned int level = 0;
	CXIndex index;
	enum CXErrorCode error;
	CXTranslationUnit tu;
	CXCursor cursor;

	if (argc != 2) {
		usage(program);
	}

	program  = argv[0];
	filename = argv[1];

	index = clang_createIndex(1, 1);

	error = clang_parseTranslationUnit2(index,
	                                    NULL,
	                                    argv,
	                                    argc,
	                                    NULL,
	                                    0,
	                                    0,
	                                   &tu);
	if (CXError_Success != error) {
		fprintf(stderr, "Failure parsing %s\n", filename);
		exit(EXIT_FAILURE);
	}

	cursor = clang_getTranslationUnitCursor(tu);
	clang_visitChildren(cursor, visit_children_cb, &level);

	clang_disposeTranslationUnit(tu);
	clang_disposeIndex(index);

	printf("DONE\n");

	exit(EXIT_SUCCESS);
}

-- 
Mike

:wq



More information about the cfe-dev mailing list