Functionality of __BASE_FILE__

Hello all. My question starts off touching on llvm, but then comes back to clang, so please let me know if any of this belongs on an llvm mailing list.

I am striving to avoid any paths from my hard drive ending up in the binary I am producing, and the code I am building uses __FILE__ for logging. When I researched solutions for avoiding the full paths from expansions of __FILE__, they all seemed to be performed at run-time even when the intent seems to have been for them to work at compile-time. This does not help, as my goal is to avoid any paths (above the project folder, at least) from being found in the binary on disk.

For instance, the suggestion to make a define like:

#define __FILE_NAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)

does not avoid full paths being stored in the binary because it does not optimize down to only the file name at compile-time, no matter how high I turn up the optimization. Nor does this simpler example optimize at compile-time:

const char* const THIS_FILE_NAME = strrchr(__FILE__, '/') + 1;

I can see that there are optimizations for string functions in llvm's SimplifyLibCalls.cpp, but they don’t seem to be used when I build at any -O level. If I’m not mistaken, the comment above InstCombiner::tryOptimizeCall() in InstCombineCalls.cpp explains why:

"// Try to fold some different type of calls here.
// Currently we're only working with the checking functions, memcpy_chk,
// mempcpy_chk, memmove_chk, memset_chk, strcpy_chk, stpcpy_chk, strncpy_chk,
// strcat_chk and strncat_chk.”

It seems that the optimization functions for strchr(), strcat(), etc. are simply never called by llvm, but I could be wrong.

That’s why I was excited to read about __BASE_FILE__... until I saw that it simply produces the same output as __FILE__. According to various Internet searches, __BASE_FILE__ simply uses the path passed in to clang, just like __FILE__ does. This is a problem, because according to what I’ve read, it doesn’t seem to be possible to get my IDE, Xcode, to pass relative paths to clang. There are various “relative path” settings that Xcode offers for storing file references in the project, but these always seem to be resolved to full paths when invoking clang.

However, clang’s PPMacroExpansion.cpp has this puzzling comment: "// __BASE_FILE__ is a GNU extension that returns the top of the presumed #include stack instead of the current file.” I’m not sure what that means; is it returning the file path relative to the highest common directory in the #include file tree? Why would it do that?

The documentation for GCC’s original __BASE_FILE__ is, in its entirety: "This macro expands to the name of the main input file, in the form of a C string constant. This is the source file that was specified on the command line of the preprocessor or C compiler.” That seems to be saying that the file name will be picked out from whatever path, relative or absolute, is used to pass the file to the compiler.

Shouldn’t clang follow this guideline? And if not, why isn’t there any macro for just getting a source file's name? Thanks in advance for any answers that you guys have for me.

__BASE_FILE__ does not mean "the basename of the current file"; it means what Clang calls "the main source file", i.e. your .c file, even when written in a .h file. So really it's back to optimization.


Thanks for the response. I completely failed to grasp what the “base” in __BASE_FILE__ meant, from all that I read on the Internet and in the clang docs, until I read your succinct definition. In my humble opinion, the docs for clang should not describe __BASE_FILE__ as "Defined to a string that contains the name of the main input file passed to Clang”, but rather “Defined to a string that contains the *path*…”.

Even though the file might get passed to clang with a relative path, __BASE_FILE__ is still returning that path, not just the name -- even if the path is "./foo.c" or even just "foo.c".

Anyway, as you said, it seems that I need to focus on the subject of optimization, so I suppose I should cross-post the llvm portion of my OP on an llvm mailing list.

- Iritscen