user58697 user58697 - 1 month ago 20
C Question

Preprocessor conditional distributed across `#include` files

Is this legal?

foo.h
:

#if 1
#include "bar.h"


bar.h
:

#endif


foo.c


#include "foo.h"


clang-700.1.81
complains in a kind of a funny way:

In file included from foo.c:1:
In file included from ./foo.h:2:
./bar.h:1:2: error: #endif without #if
#endif


(which means like it did
#include "bar.h"
)

# 3 "./foo.h" 2
In file included from foo.c:1:
./foo.h:1:2: error: unterminated conditional directive
#ifndef FOO


(which means like it didn't
#include "bar.h"
).

I have an uneasy feeling that the preprocessor cares about more than a Standard mandates it to. Please correct me if I am wrong, or prove otherwise if I am right.

Answer

It is not legal. All of the conditional directives which make up the conditional section must be in the same file, although the conditional groups may contain #include directives or nested conditional sections.

This constraint is made explicit by the grammar for preprocessing files (§ 6.10).

      preprocessing-file:
               group opt
      group:
               group-part
               group group-part
      group-part:
               if-section
               control-line
               text-line
               # non-directive
      if-section:
               if-group elif-groups opt else-group opt endif-line

The constraint is also implicit in §5.1.1.2 paragraph 4 which describes the functioning of the #include directive as a recursive execution of phases 1 through 4, rather than a simple textual inclusion:

A #include preprocessing directive causes the named header or source file to be processed from phase 1 through phase 4, recursively.