<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Sep 3, 2015, at 19:33 , 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" class=""><div class="gmail_extra"><div class="gmail_quote">On Thu, Sep 3, 2015 at 6:46 PM, Jordan Rose <span dir="ltr" class=""><<a href="mailto:jordan_rose@apple.com" target="_blank" class="">jordan_rose@apple.com</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word" class="">Hi, Richard. One of our Swift tests recently hit an interesting edge case involving modules and redefinitions. Take the following code:<div class=""><br class=""></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px" class=""><div class="">// Module A</div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px" class=""><div class="">struct Foo {</div><div class=""><span style="white-space:pre-wrap" class="">     </span>int x;</div><div class="">};</div><div class=""><br class=""></div><div class="">// Module B</div><div class="">struct Foo {</div><div class=""><span style="white-space:pre-wrap" class="">       </span>int x;</div><div class="">};</div><div class=""><br class=""></div><div class="">// Module C</div><div class="">typedef struct Foo *FooPtr;</div><div class=""><br class=""></div><div class="">// main.m</div><div class="">@import A;</div><div class="">@import B;</div><div class="">@import C;</div></blockquote><br class=""><div class="">If all of this was in one file, we'd have an invalid redefinition of Foo, but because A and B are separate modules (and supposedly self-contained) Clang just cheats and treat one of them as a mere declaration. Because Clang modules don't affect lookup, that's fine. In Swift, however, I can ask for "A.Foo" or "B.Foo", and ideally both would resolve to <i class="">some</i> declaration of Foo. "C.Foo", on the other hand, should say "there's no 'Foo' in C" (because Swift doesn't have forward declarations).</div><div class=""><br class=""></div><div class="">I tried using isCompleteDefinition to distinguish the B case from the C case, but of course Clang doesn't consider the second definition to <i class="">be</i> a definition. Do you have any ideas?</div></div></blockquote><div class=""><br class=""></div><div class="">It depends whether this is Objective C or Objective C++.</div><div class=""><br class=""></div><div class="">In C++, we take advantage of the ODR, which allows us to assume that those two 'struct Foo's are defining the same struct. We mostly make it look like one of the declarations was never a definition (so that AST consumers don't need to treat this as a special case), but in practice you can infer whether the declaration was once a definition by checking whether its decl context lexically contains any declarations (it just so happens that a current or former definition will always contain at least an injected class name decl, and a "pure" declaration will always be empty).</div><div class=""><br class=""></div><div class="">In C, there is no ODR, and the same struct name is permitted to have different definitions in different translation units in the same program. What we /should/ do is to keep decl chains for types from distinct modules separate, and implement C's "compatible type" structural typing rules to determine whether two 'Foo's can be used interchangeably. What we /actually/ do is to form a single redeclaration chain containing all the definitions, all of which think they are still "the" definition, and each use of the type will pick a semi-arbitrary definition. This case is easy for you: just ask the decl whether it's a complete definition (but I'm guessing you're in Objective C++ mode since you said that checking IsCompleteDefinition isn't working).</div></div></div></div>
</div></blockquote></div><br class=""><div class="">Huh. No, we're not in Objective-C++ mode. I guess I need to dig in more carefully to what's actually happening—I was definitely seeing Swift treat the definition as not being part of that module even after walking the redeclaration chain for other complete definitions. Thanks.</div><div class=""><br class=""></div><div class="">Jordan</div><div class=""><br class=""></div></body></html>