#include file derived from macro __FILE__? - c++

Observe the following program:
#include __FILE__
main(){}
The preprocessor gets stuck in infinite recursion including a copy of itself inside itself and complaining about main() already being defined.
If I can use macros to include files,
can I derive a file name based on __FILE__ and include it?
For example, I'd like to include "foo.h" whilst inside "foo.cpp", but derive it from __FILE__.
## will concatenate macros.
It is also possible to Stringify macros.
Can it be done with the preprocessor?

The C standard specifies three forms of #include:
#include <file>
#include "file"
#include ANYTHING ELSE
In the former two cases, no macro expansion takes place, so there's no way to vary the behavior. In the third case, C99 says (§6.10.2p4):
The preprocessing tokens after #include in the directive are [macro-expanded]. The directive resulting after all replacements shall match one of the two previous forms [footnote: Note that adjacent string literals are not concatenated into a single string literal]. The method by which a sequence of preprocessing tokens between a < and a > preprocessing token pair or a pair of " characters is combined into a single header name preprocessing token is implementation-defined.
Slightly different, but effectively equivalent, wording appears in C++98 §16.2p4.
Any sentence with "shall" in it imposes a hard requirement: in this case, the program is ill-formed if ANYTHING ELSE expands to anything but a sequence of tokens beginning with < and ending with >, or beginning and ending with ". The exact interpretation of that sequence of tokens is implementation defined, but note that the footnote specifically forbids string-literal concatenation.
So, as the expansion of __FILE__ is a string constant, the only ways to use it in an #include are
#include __FILE__
which, as you discovered, leads to infinite recursion, and
#define LT <
#define GT >
#include LT __FILE__ etc GT
which has amusing, but useless, effects on all the compilers I can conveniently test. Assuming that the above is in a file named test.c:
GCC attempts to open a file named "test.c" etc, with the quotation marks and space included verbatim.
clang is even more literal, and looks for that same filename but with leading and trailing spaces.
MSVC macro-expands only the LT (it is my considered opinion that this is a conformance violation), complains that there is no matching >, and then attempts to open a file named __FILE__ etc GT.
(GCC's behavior is documented here; you are on your own for anything else.)
tl;dr: There is no way to do what you want from inside the preprocessor. I recommend working out the name of the file-to-be-included from your build system and notifying the compiler of it with a -D switch (on a Unixy system you will need double quotation, -DINCLUDEME='"includeme.h"'; I don't speak CMD)

The best I've come up with is this:
#define foo(x) #x
#include foo(x)
prog.cpp:2:16: error: x: No such file or directory

Related

Condition inclusion through has-include-expression and has-attribute-expression behaves differently

#include <iostream>
#define Abc likely
# if __has_cpp_attribute(Abc)
#define Pn 0
#endif
#if __has_cpp_attribute(likely)
#ifndef Pn
#define Pn 1
#endif
#endif
int main(){
std::cout<< Pn;
}
For this example, GCC prints 0 while Clang prints 1. According to [cpp.cond] p5
Each has-attribute-expression is replaced by a non-zero pp-number matching the form of an integer-literal if the implementation supports an attribute with the name specified by interpreting the pp-tokens, after macro expansion, as an attribute-token, and by 0 otherwise. The program is ill-formed if the pp-tokens do not match the form of an attribute-token.
So, the directive # if __has_cpp_attribute(Abc) should behave the same as #if __has_cpp_attribute(likely). GCC has the right behavior. Again, consider this example
#include <iostream>
#define Head <iostream>
# if __has_include(Head)
#define Pn 0
#endif
#ifndef Pn
#define Pn 1
#endif
int main(){
std::cout<< Pn;
}
In this example, both compilers print 0. However, according to [cpp.cond] p4
The header or source file identified by the parenthesized preprocessing token sequence in each contained has-include-expression is searched for as if that preprocessing token sequence were the pp-tokens in a #include directive, except that no further macro expansion is performed. If such a directive would not satisfy the syntactic requirements of a #include directive, the program is ill-formed. The has-include-expression evaluates to 1 if the search for the source file succeeds, and to 0 if the search fails.
Note the bold wording, which means Head won't be replaced by <iostream>, there is no such a source file. Hence, Pn should be 1 instead. Could it be considered a bug of GCC and Clang?
I am not sure that the answer below is correct. I will leave it up for reference for now.
I think the second example does not fit the has-include-expression grammar. If you look at [cpp.cond] there are two forms mentioned, which are further subdivided into multiple cases, referring also to [lex.header].
Collecting the possible forms and combining them here for presentation, we get:
__has_include(<...>)
__has_include("...")
__has_include(string-literal)
with ... as some placeholder and string-literal any string literal. Your form __has_include(Head) is none of these, since Head neither starts with ", nor <, nor is it a string literal.
[cpp.cond]/3 does mention that if the first of the two syntax choices for has-include-expression does not match, the second is considered and the preprocessor tokens are processed like normal text, presumably meaning they are macro-expanded. However it is not clear to me whether this is supposed to reference all preprocessor tokens between ( and ) before the above-mentioned grammar rules are applied or just the h-pp-tokens in the __has_include(<h-pp-tokens>) form. In the former case, the compilers would be correct in returning 0.
However, the latter case makes more sense to me, especially when comparing e.g. to the grammar rule for #include, which uses similar forms, but instead of #include <h-pp-tokens> the last form is #include pp-tokens. [cpp.include]
[cpp.cond]/7 says that the identifier __has_include shall not appear in any context not mentioned in the subclause. I would think that shall not here means otherwise ill-formed, in which case the program should not compile without diagnostic. If it means otherwise undefined behavior, then all compilers are correct.
For the first example, I think you are right. Clang has a recently-fixed bug report regarding the macro expansion here and if you choose Clang trunk on compiler explorer, the result will coincide with GCC already now.

Why isn't this valid syntax?

#include ("/" "include/foo.h")
#include ("/" "include/bar.h")
I.e., I have gotten things like..
char* a = "/" "include/foo.h";
to work. So I'm wondering, why not add this as a feature for the preprocessor to?
Or maybe.. are there any preprocessors that support this syntax?
My thinking is that you could do something like..
// config.h
#define LIB1_PATH "/include"
and then..
// main.c
#include "config.h"
#include (LIB1_PATH "foo.h")
#include (LIB1_PATH "bar.h")
If you then were to move "lib1" elsewhere in your project, you would only need to adjust config.h.
Why isn't this valid syntax?
Because the syntax for #include preprocessing directive is cpp.include for example:
# include " q-char-sequence " new-line
The ( ) characters are not allowed there. Multiple " are also not allowed, and q-char is any member of the source character set **except** new-line and ".
why not add this as a feature for the preprocessor to?
Because it would require work. To implement it.
are there any preprocessors that support this syntax?
I very much doubt. No.
My thinking is that you could do something like..
And for limited cases you kind-of can, the form of preprocessing directive takes:
# include pp-tokens new-line
For the usages, see this question. However not everything is possible, see this answer.
If you then were to move "lib1" elsewhere in your project, you would only need to adjust config.h.
No, the typical solution is to add include paths to your compiler. Then if you were to move lib1, you would change your build and compiler options, without any modification to the source code.
Keep your #include very simple - they are a very crude way to raw include other files. There is no reason to generate #include paths.
Concatenation is defined for string literals, as you've illustrated. From cppreference on string literals :
String literals placed side-by-side are concatenated at translation phase 6 (after the preprocessor). That is, "Hello," " world!" yields the (single) string "Hello, world!"
But the "string" in an #include directive is not a technically a string literal. Looking at how #include is defined on cppreference : #include "filename" we can see that the filename is some token delimited by " characters. This looks a lot like a string literal, but this is a coincidence. A string literal defines an object. It has an address and a size and every other property an object can have. An #include does not define an object, it is a preprocessor directive.

how to concatenate strings in #include statement [duplicate]

I would like to have include file paths dynamically created by a macro for a target-configuration-dependent part of my program.
for example, I would like to construct a macro that would be invoked like this:
#include TARGET_PATH_OF(header.h)
Which will expand to a something like this:
#include "corefoundation/header.h"
when the source is configured (in this case) for OSX
So far all attempts have failed. I'm hoping someone out there has done this before?
example of what does not work:
#include <iostream>
#include <boost/preprocessor.hpp>
#define Dir directory/
#define File filename.h
#define MakePath(f) BOOST_PP_STRINGIZE(BOOST_PP_CAT(Dir,f))
#define MyPath MakePath(File)
using namespace std;
int main() {
// this is a test - yes I know I could just concatenate strings here
// but that is not the case for #include
cout << MyPath << endl;
}
errors:
./enableif.cpp:31:13: error: pasting formed '/filename', an invalid preprocessing token
cout << MyPath << endl;
^
./enableif.cpp:26:16: note: expanded from macro 'MyPath'
#define MyPath MakePath(File)
^
./enableif.cpp:25:40: note: expanded from macro 'MakePath'
#define MakePath(f) BOOST_PP_STRINGIZE(BOOST_PP_CAT(Dir,f))
^
/usr/local/include/boost/preprocessor/cat.hpp:22:32: note: expanded from macro 'BOOST_PP_CAT'
# define BOOST_PP_CAT(a, b) BOOST_PP_CAT_I(a, b)
^
/usr/local/include/boost/preprocessor/cat.hpp:29:36: note: expanded from macro 'BOOST_PP_CAT_I'
# define BOOST_PP_CAT_I(a, b) a ## b
^
1 error generated.
I tend to agree with the comment in utnapistim's answer that you shouldn't do this even though you can. But, in fact, you can, with standard-conformant C compilers. [Note 1]
There are two issues to overcome. The first one is that you cannot use the ## operator to create something which is not a valid preprocessor token, and pathnames do not qualify as valid preprocessor tokens because they include / and . characters. (The . would be ok if the token started with a digit, but the / will never work.)
You don't actually need to concatenate tokens in order to stringify them with the # operator, since that operator will stringify an entire macro argument, and the argument may consist of multiple tokens. However, stringify respects whitespace [Note 2], so STRINGIFY(Dir File) won't work; it will result in "directory/ filename.h" and the extraneous space in the filename will cause the #include to fail. So you need to concate Dir and File without any whitespace.
The following solves the second problem by using a function-like macro which just returns its argument:
#define IDENT(x) x
#define XSTR(x) #x
#define STR(x) XSTR(x)
#define PATH(x,y) STR(IDENT(x)IDENT(y))
#define Dir sys/
#define File socket.h
#include PATH(Dir,File)
Warning: (Thanks to #jed for passing on this issue.) If the strings being concatenated contain identifiers which are defined elsewhere as macros, then unexpected macro substitution will occur here. Caution should be taken to avoid this scenario, particularly if Dir and/or File are not controlled (for example, by being defined as a command-line parameter in the compiler invocation).
You need to also be aware than some implementations may define words which are likely to show up in a token-like fashion in a file path. For example, GCC may define macros with names like unix and linux unless it is invoked with an explicit C standard (which is not the default). That could be triggered by paths like platform/linux/my-header.h or even linux-specific/my-header.h.
To avoid these issues, I'd recommend that if you use this hack:
you use a C (or C11) standards-conformant compiler setting, and
you place the sequence very early in your source file, ideally before including any other header, or at least any header outside of the standard library.
Also, you wouldn't need the complication of the IDENT macro if you could write the concatenation without spaces. For example:
#define XSTR(x) #x
#define STR(x) XSTR(x)
#define Dir sys
#define File socket.h
#include STR(Dir/File)
Notes
I tried it with clang, gcc and icc, as available on godbolt. I don't know if it works with Visual Studio.
More accurately, it semi-respects whitespace: whitespace is converted to a single space character.
I would like to have include file paths dynamically created by a macro for a target-configuration-dependent part of my program.
You should be unable to (and if you are able to do so, you probably shouldn't do this).
You are effectively trying to do the compiler's job in a source file, which does not make much sense. If you want to change include paths based on the machine you compile on, this is a solved problem (but not solved in a header file).
Canonical solution:
Use an IF in your Makefile or CMakeLists.txt, use custom property pages depending on the build configuration in Visual Studio (or simply set the particular settings for your build in the OS environment for your user).
Then, write the include directive as:
#include <filename.h> // no path here
and rely on the environment/build system to make the path available when the compiler is invoked.
This works for VS2013. (It can be done easier, ofcourse.)
#define myIDENT(x) x
#define myXSTR(x) #x
#define mySTR(x) myXSTR(x)
#define myPATH(x,y) mySTR(myIDENT(x)myIDENT(y))
#define myLIBAEdir D:\\Georgy\\myprojects\\LibraryAE\\build\\native\\include\\ //here whitespace!
#define myFile libae.h
#include myPATH(myLIBAEdir,myFile)
From your description, it sound like you discovered that not every "" is a string. In particular, #include "corefoundation/header.h" looks like an ordinary string but it isn't. Grammatically, quoted text outside preprocessor directives are intended for the compiler, and compile to null terminated string literals. Quoted text in preprocessor directives is interpreted by the preprocessor in an implementation-defined way.
That said, the error in your example is because Boost pasted the second and third token : / and filename. The first, fourth and fifth token (directory, . and h) are left unchanged. This is not what you wanted, obviously.
It's a lot easier to rely on automatic string concatenation. "directory/" "filename" is the same string literal as "directory/filename" Note that there is no + between the two fragments.

Multiple preprocessor directives on one line in C++

A hypothetical question: Is it possible to have a C++ program, which includes preprocessor directives, entirely on one line?
Such a line would look like this:
#define foo #ifdef foo #define bar #endif
What are the semantics of such a line?
Further, are there any combinations of directives which are impossible to construct on one line?
If this is compiler-specific then both VC++ and GCC answers are welcome.
A preprocessing directive must be terminated by a newline, so this is actually a single preprocessing directive that defines an object-like macro, named foo, that expands to the following token sequence:
# ifdef foo # define bar # endif
Any later use of the name foo in the source (until it is #undefed) will expand to this, but after the macro is expanded, the resulting tokens are not evaluated as a preprocessing directive.
This is not compiler-specific; this behavior is defined by the C and C++ standards.
Preprocessor directives are somewhat different than language statements, which are terminated by ; and use whitespace to delimit tokens. In the case of the preprocessor, the directive is terminated by a newline so it's impossible to do what you're attempting using the C++ language itself.
One way you could kind of simulate this is to put your desired lines into a separate header file and then #include it where you want. The separate header still has to have each directive on one line, but the point where you include it is just a single line, effectively doing what you asked.
Another way to accomplish something like that is to have a pre-C++ file that you use an external process to process into a C++ source file prior to compiling with your C++ compiler. This is probably rather more trouble than it's worth.

Escaping a # symbol in a #define macro?

Without going into the gory details I want to use a #define macro that will expand to a #include but the '#' sign is confusing the preprocessor (as it thinks I want to quote an argument.)
For example, I want to do something like this:
#define MACRO(name) #include "name##foo"
And use it thus:
MACRO(Test)
Which will expand to:
#include "Testfoo"
The humble # sign is causing the preprocessor to barf. MinGW gives me the following error:
'#' is not followed by a macro parameter
I guess I need to escape the # sign but I don't if this is even possible.
Yes, macros are indeed evil...
It is possible to insert a hash token into the preprocessed token stream. You can do it as follows:
#define MACRO(hash, name) hash include name
MACRO(#,"hello")
—expands to:
# include "hello"
However, the standard explicitly rules out any further analysis of such line for the existence of preprocessing directives [cpp.rescan]:
The resulting completely macro-replaced preprocessing token sequence is not processed as a preprocessing directive even if it resembles one.
As far as I remember you cannot use another preprocessor directive in define.
The problem isn't actually getting a # symbol in the output of your preprocessor.
Apparently you want the preprocessor to reparse your file, to deal with newly created #include directives as part of macro expansion. It doesn't work that way. If a line starts with #, it's an instruction for the preprocessor and interpreted. If a line doesn't start with #, it's only subject to preprocessor transformation including macro substitution. This is a once-per-line test.
MACRO(Test)
does not start with #. Therefore it is not interpreted as a preprocessor directive; instead it's subject to macro replacement rules.
This is because the # has special meaning when used in a macro.
# means quote the following token (which should be a macro parameter name)
## means concatenate the preceding and following tokens.
In your situation the # is not followed by a proper token.
So in your situation we need to go through a level of indirection:
#define QUOTE(name) #name
#define TEST(name) QUOTE(name ## foo)
#include TEST(scot)
You can't do that. Preprocessor directives are recognized before macro expansion; if the macro expands into something that looks like a preprocessor directive, that directive will not be recognized. The best you can do is create a macro for the file name:
#define MACRO(name) "name##foo"
...
#include MACRO(Test)
This might work (it works for regular #define macros with no parameters, but I haven't tested it with macros with parameters).
#define MACRO(name) <name##foo>
#include MACRO(Test)
#define HASH_SIGN #
BOOST_PP_CAT(HASH_SIGN, include)
#define PARAM_NAME Param
#define GETNAME_(a) #a
#define GETNAME(a) GETNAME_(a)
int Param;
printf("%s = %i\n", GETNAME(PARAM_NAME), PARAM_NAME);