[cfe-dev] Module macro semantics with #undef's

Richard Smith via cfe-dev cfe-dev at lists.llvm.org
Thu Sep 22 08:27:56 PDT 2016

On 21 Sep 2016 3:11 pm, "Manman via cfe-dev" <cfe-dev at lists.llvm.org> wrote:

> On Sep 21, 2016, at 10:48 AM, Tim Prince via cfe-dev <
cfe-dev at lists.llvm.org> wrote:
> Hi everyone,
> The modules documentation (http://clang.llvm.org/docs/Modules.html#macros)
says this about importing multiple definitions of the same macro:
>> For example, suppose:
>>  - <stdio.h> defines a macro getc (and exports its #define)
>>  - <cstdio> imports the <stdio.h> module and undefines the macro (and
exports its #undef)
>> The #undef overrides the #define, and a source file that imports both
modules in any order will not see getc defined as a macro.

In this specific case, #undef in cstdio overrides the #define in the
imported <stdio.h> module.
See the document:
        • A #define X or #undef X directive overrides all definitions of X
that are visible at the point of the directive.
        • A #define or #undef directive is active if it is visible and no
visible directive overrides it.

> I've been writing some test cases, and I've confirmed this behavior in a
trivial test case. However, when I import two modules that both define a
macro, that macro still seems to be defined even in the presence of another
macro that #undef's it.

The module has 3 macros, the macro owned by Module.UndefFoo overrides the
macro in Module.DefineFoo. The set of macros a given macro overrides
depends on the order in your module map file, I think. That is why the
macro in RedefineFoo is still active.

Right. In the default mode, names defined in an earlier header in a
top-level module are visible in later headers within that top-level module,
so the order matters. (With -fmodules-local-submodule-visibility, this name
leakage is turned off and each submodule starts with a clean slate, but
that's not well supported in C yet.)

> Here are two test cases that demonstrate the divergent behavior:
>> $ cat undef.c
>> #include "Module/UndefFoo.h"
>> #include "Module/DefineFoo.h”

Since the macro from Module.DefineFoo is overridden, FOO is undefined.
>> #ifdef FOO
>> #error FOO was defined
>> #endif
>> $ cat redef-undef.c
>> #include "Module/UndefFoo.h"
>> #include "Module/DefineFoo.h"
>> #include "Module/RedefineFoo.h”
The macro from RedefineFoo is active, and FOO is defined here.


>> #ifdef FOO
>> #error FOO was defined
>> #endif
>> $
> And here's the contents of the module itself:
>> $ ls Module/
>> DefineFoo.h  module.modulemap  RedefineFoo.h  UndefFoo.h
>> $ cat Module/module.modulemap
>> module Module {
>>  module DefineFoo {
>>    header "DefineFoo.h"
>>  }
>>  module UndefFoo {
>>    header "UndefFoo.h"
>>  }
>>  module RedefineFoo {
>>    header "RedefineFoo.h"
>>  }
>> }
>> $ cat Module/DefineFoo.h
>> #define FOO 1
>> $ cat Module/RedefineFoo.h
>> #define FOO 1
>> $ cat Module/UndefFoo.h
>> #undef FOO
>> $
> Now, when I run these test cases:
>> $ /opt/pkg/clang-3.9.0/bin/clang -fmodules -c undef.c
>> $ /opt/pkg/clang-3.9.0/bin/clang -fmodules -c redef-undef.c
>> redef-undef.c:6:2: error: FOO was defined
>> #error FOO was defined
>> ^
>> 1 error generated.
>> $
> The documentation seems to suggest that the latter case should also pass
without errors. Is this inconsistency a bug or is there some subtlety I'm
missing here?
> Thanks!
> - Tim
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

cfe-dev mailing list
cfe-dev at lists.llvm.org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20160922/96fa6d24/attachment.html>

More information about the cfe-dev mailing list