Warning

I am not an adequate coder of C or C++, any information or thoughts provided here could have flaws. Moreover, I only use GNU Compiler Collection (GCC)1, some solutions may not be applicable. Please don’t hesitate to point out my mistakes.

[1]With GCC 4.8.4 on Gentoo Linux.

Finding the location of where a macro is defined isn’t hard, just need to know what options to use. I only use GNU Compiler Collection, so this post is only concerning the tools of GCC, in this case, the cpp2, however, you can still use gcc or g++, just put in -E option, which tells compiler to stop after the preprocessing stage.

1   cpp

The command goes like


cpp [-x<c|c++>] [-std=<standard>] -dCHARS <infile>

If input file is from standard input, -, with C++ standard specified, then you will need to include -xc++. Otherwise, the cpp treats the input file as C code and a warning will be thrown.

For the rest of options, from cpp(1):

-dCHARS

CHARS is a sequence of one or more of the following characters, […].

M
Instead of the normal output, generate a list of #define directives for all the macros defined during the execution of the preprocessor, including predefined macros. […]
D
Like M except in two respects: it does not include the predefined macros, and it outputs both the #define directives and the result of preprocessing. Both kinds of output go to the standard output file.
N
Like D, but emit only the macro names, not their expansions.
I
Output #include directives in addition to the result of preprocessing.
U
Like D except that only macros that are expanded, or […]

Basically, you probably only need to use M and D, more likely just D. Say, you want to find out how M_PI and other mathematical constants get defined in math.h with gnu99 through this condition:


#if defined __USE_MISC || defined __USE_XOPEN

So, you can run:


% cpp -xc -std=gnu99 -dD /usr/include/math.h | grep -B1 __USE_MISC
#undef __USE_FILE_OFFSET64
#undef __USE_MISC
--
# 311 "/usr/include/features.h" 3 4
#define __USE_MISC 1

It shows the __USE_MISC is defined in that header file, then you can work back up from that header.

You can also get a list of predefined macros in C99 by running


cpp -xc -std=c99 -dM /dev/null

2   Types of locations

If you run:


% cpp -xc -std=c99 - </dev/null
# 1 "<stdin>"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "<stdin>"

Other than the normal header files, you can see some in angle brackets, which have special meanings.

2.1   <command-line>

It’s what you manually define through command-line options -D, for example:


% cpp -xc -std=c99 -dD -Dfoo=bar /dev/null | grep -B1 foo
# 1 "<command-line>"
#define foo bar

There is a special case that I have seen GCC intentionally defines through command-line:


% cpp -xc++ -std=c++98 -dD /dev/null | grep -B1 GNU_SOURCE
# 1 "<command-line>"
#define _GNU_SOURCE 1

As you can see the standard is C++98 and the command has no manual definition, however, the macro shows up.

2.2   <stdin>

This shows macros are defined through standard input.


% echo '#define foo bar' | cpp -xc -std=c99 -dD - | grep -B1 foo
# 1 "<stdin>"
#define foo bar

2.3   <builtin>

As far as I can tell, they are the predefined macros3 and they could even come from GCC’s compile-time as how Gentoo Linux patches the c-cppbuiltin.c to force a macro defintion. That file name seems to confirm my guess.


[2]Whenever cpp pops out, the first assocation link my brain gets is to C++, not C preprocessor.
[3]diff <(cpp -xc -std=c99 -dM /dev/null | sort) <(cpp -xc -std=c99 -dD /dev/null | sort)