<html><head><meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Oct 6, 2017, at 15:06, Richard Smith <<a href="mailto:richard@metafoo.co.uk" class="">richard@metafoo.co.uk</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="gmail_extra"><div class="gmail_quote">Hey Jordan,</div><div class="gmail_quote"><br class=""></div><div class="gmail_quote">I wrote up an answer, then realised what you're probably seeing is what happens when -fmodules-local-submodule-visibility is turned off. In that mode, macros from, say, ConflictingA.h will leak into ConflictingB.h (as if ConflictingB.h started by performing a private import of ConflictingA.h), so ConflictingB.h's macro *does* override ConflictingA.h's macro, and from clang's perspective the Conflicting and Redefined modules would then have the same behavior -- if you import A and B, you get the macro from B.</div><div class="gmail_quote"><br class=""></div><div class="gmail_quote">So then I think the question is, what is the difference between the two cases that you want to detect? (The #undef? The import of A into B prior to the redefinition? Something else?) I think we retain sufficient information to do this, but it's not necessarily convenient, and some of it isn't ever read from the PCM file currently.</div></div></div></div></blockquote><div><br class=""></div><div>Hm, interesting. Yes, we're not using -fmodules-local-submodule-visibility; apart from Apple's SDK not yet being vetted with this option, it seems to break simple things like</div><div><br class=""></div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div><div>module X {</div></div><div><div> header "A.h"</div></div><div><div> header "B.h"</div><div> header "C.h"</div><div> export *</div></div><div><div>}</div></div></blockquote><div class=""><br class=""></div><div class="">with declarations from B.h not being visible to Swift at all. I suspect we'll have to rework our lookup logic in some way to do whatever's needed for this mode, but it's not an option for us at the moment.</div><div class=""><br class=""></div><div class="">I think the import of A into B would be a fair thing to look for. Another alternative that's not 100% correct but is likely to work in practice is to see if the macros are in different explicit submodules.</div><div class=""><br class=""></div><div class="">Any suggestions? Or is no-local-submodule-visibility just on its way out, and not something you're interested in spending time on?</div><div class=""><br class=""></div><div class="">Thanks, this has already been helpful.</div><div class="">Jordan</div><div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="gmail_extra"><div class="gmail_quote"><br class=""></div><div class="gmail_quote"><br class=""></div><div class="gmail_quote">If you<span class="Apple-converted-space"> </span><i class="">are</i><span class="Apple-converted-space"> </span>using -fmodules-local-submodule-visibility, then:<br class=""></div><div class="gmail_quote"><br class=""></div><div class="gmail_quote">On 6 October 2017 at 13:28, Jordan Rose via cfe-dev<span class="Apple-converted-space"> </span><span dir="ltr" class=""><<a href="mailto:cfe-dev@lists.llvm.org" target="_blank" class="">cfe-dev@lists.llvm.org</a>></span><span class="Apple-converted-space"> </span>wrote:<br class=""><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"><div style="word-wrap: break-word;" class="">Hi, Richard. Jordan's back with another annoying ModuleMacro question for Swift. Let's say I have these two modules:<div class=""><br class=""></div><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><div class="">module Conflicting {</div><div class=""> <span class="Apple-converted-space"> </span>explicit module A { header "ConflictingA.h" }</div><div class=""> <span class="Apple-converted-space"> </span>explicit module B { header "ConflictingB.h" }</div><div class="">}</div><div class=""><br class=""></div><div class="">module Redefined {</div><div class=""> <span class="Apple-converted-space"> </span>module A { header "RedefinedA.h" }</div><div class=""> <span class="Apple-converted-space"> </span>module B { header "RedefinedB.h" }</div><div class="">}</div></blockquote><div class=""><br class=""></div><div class="">Both headers in 'Conflicting' define a macro CONFLICTING, but with different values; a client is only supposed to import one of them. 'Redefined' is a little different: RedefinedB.h includes RedefinedA.h before defining the new value, and the client is probably going to import the entire top-level module. Let's say RedefinedB.h is even polite enough to use #undef.*</div><div class=""><br class=""></div><div class="">* If these examples sound bad, well, I agree, but the former is what the OpenGL framework on macOS has been doing for years, and the latter is how Clang's limits.h deals with a system limits.h.</div><div class=""><br class=""></div><div class="">The question: using ModuleMacro,<span class="Apple-converted-space"> </span><b class="">how can I distinguish these two cases</b> while building a PCM?</div></div></blockquote><div class=""><br class=""></div><div class="">When you say "while building a PCM", do you mean before you get to the end of one of the headers / submodules, or after? Depending on when you ask, you'd need to look at either the set of overridden module macros in the preprocessor (while we're still lexing within the overriding module, before we create a ModuleMacro) or the list of overridden module macros on the ModuleMacro (after it's created).</div><div class=""><br class=""></div><div class="">We build a chain of MacroDirectives while we parse, and then convert them to ModuleMacros at the end of each submodule. So, taking the example of Redefined.B:</div><div class=""><br class=""></div><div class="">// start of RedefinedB.h, preprocessor's MacroState for CONFLICTING will be that the ModuleMacro from Redefined.A is active and there is no MacroDirective</div><div class="">#undef CONFLICTING</div><div class="">// now the MacroState will have Redefined.A overridden, with the UndefMacroDirective being the current MacroDirective</div><div class="">#define CONFLICTING something_else</div><div class="">// now the MacroState will have Redefined.A overridden, with the DefMacroDirective being the current MacroDirective</div><div class=""><br class=""></div><div class="">At the end of Redefined.A, we convert the DefMacroDirective to a ModuleMacro for Redefined.B that overrides Redefined.A's macro.</div><div class=""><br class=""></div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;"><div style="word-wrap: break-word;" class=""><div class="">The obvious correct Clang answer is "don't bother, visibility will handle everything when the modules get imported", but unfortunately that doesn't fly for Swift, because of this third example:</div><div class=""><br class=""></div><blockquote style="margin: 0px 0px 0px 40px; border: none; padding: 0px;" class=""><div class="">module CrossModuleRedefinedCore {</div><div class=""> <span class="Apple-converted-space"> </span>header "CrossModuleRedefinedCore.h"</div><div class="">}</div><div class="">module CrossModuleRedefined {</div><div class=""> <span class="Apple-converted-space"> </span>// imports CrossModuleRedefinedCore</div><div class=""> <span class="Apple-converted-space"> </span>header "CrossModuleRedefined.h"</div><div class="">}</div></blockquote><br class=""><div class="">In Swift, I'm allowed to say `CrossModuleRedefinedCore.<wbr class="">REDEFINED` to get the old value, and `CrossModuleRedefined.<wbr class="">REDEFINED` to get the new value. I'm not<span class="Apple-converted-space"> </span><i class="">hugely</i> concerned about this use case if I can get the other two to work well, but I haven't given up on it yet.</div><div class=""><br class=""></div><div class="">Any ideas? I already tried looking at the overrides, but that seems like it's represented the same in both cases.</div></div></blockquote><div class=""><br class=""></div><div class="">That sounds wrong. Can you write a file that imports the modules and then does:</div><div class=""><br class=""></div><div class="">#pragma clang __debug macro REDEFINED</div></div></div></div></div></blockquote></div><br class=""></body></html>